• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #ifndef PANDA_ASSEMBLER_ASSEMBLY_FUNCTION_H
17 #define PANDA_ASSEMBLER_ASSEMBLY_FUNCTION_H
18 
19 #include <memory>
20 #include <optional>
21 #include <string>
22 #include <string_view>
23 #include <unordered_map>
24 #include <vector>
25 
26 #include "assembly-ins.h"
27 #include "assembly-label.h"
28 #include "assembly-type.h"
29 #include "assembly-debug.h"
30 #include "assembly-file-location.h"
31 #include "bytecode_emitter.h"
32 #include "extensions/extensions.h"
33 #include "file_items.h"
34 #include "file_item_container.h"
35 #include "ide_helpers.h"
36 #include "meta.h"
37 
38 namespace panda::pandasm {
39 
40 // NOLINTBEGIN(misc-non-private-member-variables-in-classes)
41 struct Function {
42     struct CatchBlock {
43         std::string wholeLine;
44         std::string exceptionRecord;
45         std::string tryBeginLabel;
46         std::string tryEndLabel;
47         std::string catchBeginLabel;
48         std::string catchEndLabel;
49     };
50 
51     struct TryCatchInfo {
52         std::unordered_map<std::string_view, size_t> tryCatchLabels;
53         std::unordered_map<std::string, std::vector<const CatchBlock *>> tryCatchMap;
54         std::vector<std::string> tryCatchOrder;
TryCatchInfoFunction::TryCatchInfo55         TryCatchInfo(std::unordered_map<std::string_view, size_t> &labels,
56                      std::unordered_map<std::string, std::vector<const CatchBlock *>> &map,
57                      std::vector<std::string> &paramTryCatchOrder)
58             : tryCatchLabels(labels), tryCatchMap(map), tryCatchOrder(paramTryCatchOrder)
59         {
60         }
61     };
62 
63     struct Parameter {
64         Type type;
65         std::unique_ptr<ParamMetadata> metadata;
66 
ParameterFunction::Parameter67         Parameter(Type t, panda::panda_file::SourceLang lang)
68             : type(std::move(t)), metadata(extensions::MetadataExtension::CreateParamMetadata(lang))
69         {
70         }
71     };
72 
73     std::string name;
74     panda::panda_file::SourceLang language;
75     std::unique_ptr<FunctionMetadata> metadata;
76 
77     std::unordered_map<std::string, panda::pandasm::Label> labelTable;
78     std::vector<panda::pandasm::Ins> ins; /* function instruction list */
79     std::vector<panda::pandasm::debuginfo::LocalVariable> localVariableDebug;
80     std::string sourceFile; /* The file in which the function is defined or empty */
81     std::string sourceCode;
82     std::vector<CatchBlock> catchBlocks;
83     int64_t valueOfFirstParam = -1;
84     size_t regsNum = 0;
85     size_t profileSize {0};
86     std::vector<Parameter> params;
87     bool bodyPresence = false;
88     Type returnType;
89     SourceLocation bodyLocation;
90     std::optional<FileLocation> fileLocation;
91 
SetInsDebugFunction92     void SetInsDebug(const std::vector<debuginfo::Ins> &insDebug)
93     {
94         ASSERT(insDebug.size() == ins.size());
95         for (std::size_t i = 0; i < ins.size(); i++) {
96             ins[i].insDebug = insDebug[i];
97         }
98     }
99 
AddInstructionFunction100     void AddInstruction(const panda::pandasm::Ins &instruction)
101     {
102         ins.emplace_back(instruction);
103     }
104 
FunctionFunction105     Function(std::string s, panda::panda_file::SourceLang lang, size_t bL, size_t bR, std::string fC, bool d, size_t lN)
106         : name(std::move(s)),
107           language(lang),
108           metadata(extensions::MetadataExtension::CreateFunctionMetadata(lang)),
109           fileLocation({fC, bL, bR, lN, d})
110     {
111     }
112 
FunctionFunction113     Function(std::string s, panda::panda_file::SourceLang lang)
114         : name(std::move(s)), language(lang), metadata(extensions::MetadataExtension::CreateFunctionMetadata(lang))
115     {
116     }
117 
GetParamsNumFunction118     std::size_t GetParamsNum() const
119     {
120         return params.size();
121     }
122 
GetTotalRegsFunction123     std::size_t GetTotalRegs() const
124     {
125         return regsNum;
126     }
127 
IsStaticFunction128     bool IsStatic() const
129     {
130         return (metadata->GetAccessFlags() & ACC_STATIC) != 0;
131     }
132 
133     bool Emit(BytecodeEmitter &emitter, panda_file::MethodItem *method,
134               const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
135               const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
136               const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
137               const std::unordered_map<std::string_view, panda_file::StringItem *> &strings,
138               const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays) const;
139 
140     size_t GetLineNumber(size_t i) const;
141 
142     uint32_t GetColumnNumber(size_t i) const;
143 
144     void EmitLocalVariable(panda_file::LineNumberProgramItem *program, panda_file::ItemContainer *container,
145                            std::vector<uint8_t> *constantPool, uint32_t &pcInc, size_t instructionNumber) const;
146     void EmitNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constantPool, uint32_t pcInc,
147                     int32_t lineInc) const;
148     void EmitLineNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constantPool,
149                         int32_t &prevLineNumber, uint32_t &pcInc, size_t instructionNumber) const;
150 
151     // column number is only for dynamic language now
152     void EmitColumnNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constantPool,
153                           uint32_t &prevColumnNumber, uint32_t &pcInc, size_t instructionNumber) const;
154 
155     void BuildLineNumberProgram(panda_file::DebugInfoItem *debugItem, const std::vector<uint8_t> &bytecode,
156                                 panda_file::ItemContainer *container, std::vector<uint8_t> *constantPool,
157                                 bool emitDebugInfo) const;
158 
159     Function::TryCatchInfo MakeOrderAndOffsets(const std::vector<uint8_t> &bytecode) const;
160 
161     std::vector<panda_file::CodeItem::TryBlock> BuildTryBlocks(
162         panda_file::MethodItem *method, const std::unordered_map<std::string, panda_file::BaseClassItem *> &classItems,
163         const std::vector<uint8_t> &bytecode) const;
164 
HasImplementationFunction165     bool HasImplementation() const
166     {
167         return !metadata->IsForeign() && metadata->HasImplementation();
168     }
169 
IsParameterFunction170     bool IsParameter(uint32_t regNumber) const
171     {
172         return regNumber >= regsNum;
173     }
174 
CanThrowFunction175     bool CanThrow() const
176     {
177         return std::any_of(ins.cbegin(), ins.cend(), [](const Ins &insn) { return insn.CanThrow(); });
178     }
179 
HasDebugInfoFunction180     bool HasDebugInfo() const
181     {
182         return std::any_of(ins.cbegin(), ins.cend(), [](const Ins &insn) { return insn.HasDebugInfo(); });
183     }
184 
185     void DebugDump() const;
186 };
187 // NOLINTEND(misc-non-private-member-variables-in-classes)
188 
189 }  // namespace panda::pandasm
190 
191 #endif  // PANDA_ASSEMBLER_ASSEMBLY_FUNCTION_H
192