• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2024 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 ark::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, ark::panda_file::SourceLang lang)
68             : type(std::move(t)), metadata(extensions::MetadataExtension::CreateParamMetadata(lang))
69         {
70         }
71     };
72 
73     std::string name;
74     ark::panda_file::SourceLang language;
75     std::unique_ptr<FunctionMetadata> metadata;
76 
77     std::unordered_map<std::string, ark::pandasm::Label> labelTable;
78     std::vector<ark::pandasm::Ins> ins; /* function instruction list */
79     std::vector<ark::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 ark::pandasm::Ins &instruction)
101     {
102         ins.emplace_back(instruction);
103     }
104 
105     // CC-OFFNXT(G.FUN.01-CPP) solid logic
FunctionFunction106     Function(std::string s, ark::panda_file::SourceLang lang, size_t bL, size_t bR, std::string fC, bool d, size_t lN)
107         : name(std::move(s)),
108           language(lang),
109           metadata(extensions::MetadataExtension::CreateFunctionMetadata(lang)),
110           fileLocation({fC, bL, bR, lN, d})
111     {
112     }
113 
FunctionFunction114     Function(std::string s, ark::panda_file::SourceLang lang)
115         : name(std::move(s)), language(lang), metadata(extensions::MetadataExtension::CreateFunctionMetadata(lang))
116     {
117     }
118 
GetParamsNumFunction119     std::size_t GetParamsNum() const
120     {
121         return params.size();
122     }
123 
GetTotalRegsFunction124     std::size_t GetTotalRegs() const
125     {
126         return regsNum;
127     }
128 
IsStaticFunction129     bool IsStatic() const
130     {
131         return (metadata->GetAccessFlags() & ACC_STATIC) != 0;
132     }
133 
134     // CC-OFFNXT(G.FUN.01-CPP) solid logic
135     bool Emit(BytecodeEmitter &emitter, panda_file::MethodItem *method,
136               const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
137               const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
138               const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
139               const std::unordered_map<std::string_view, panda_file::StringItem *> &strings,
140               const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays) const;
141 
142     size_t GetLineNumber(size_t i) const;
143 
144     uint32_t GetColumnNumber(size_t i) const;
145 
146     void EmitLocalVariable(panda_file::LineNumberProgramItem *program, panda_file::ItemContainer *container,
147                            std::vector<uint8_t> *constantPool, uint32_t &pcInc, size_t instructionNumber) const;
148     void EmitNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constantPool, uint32_t pcInc,
149                     int32_t lineInc) const;
150     void EmitLineNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constantPool,
151                         uint32_t &prevLineNumber, uint32_t &pcInc, size_t instructionNumber) const;
152 
153     // column number is only for dynamic language now
154     void EmitColumnNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constantPool,
155                           uint32_t &prevColumnNumber, uint32_t &pcInc, size_t instructionNumber) const;
156 
157     void BuildLineNumberProgram(panda_file::DebugInfoItem *debugItem, const std::vector<uint8_t> &bytecode,
158                                 panda_file::ItemContainer *container, std::vector<uint8_t> *constantPool,
159                                 bool emitDebugInfo) const;
160 
161     Function::TryCatchInfo MakeOrderAndOffsets(const std::vector<uint8_t> &bytecode) const;
162 
163     std::vector<panda_file::CodeItem::TryBlock> BuildTryBlocks(
164         panda_file::MethodItem *method, const std::unordered_map<std::string, panda_file::BaseClassItem *> &classItems,
165         const std::vector<uint8_t> &bytecode) const;
166 
HasImplementationFunction167     bool HasImplementation() const
168     {
169         return !metadata->IsForeign() && metadata->HasImplementation();
170     }
171 
IsParameterFunction172     bool IsParameter(uint32_t regNumber) const
173     {
174         return regNumber >= regsNum;
175     }
176 
CanThrowFunction177     bool CanThrow() const
178     {
179         return std::any_of(ins.cbegin(), ins.cend(), [](const Ins &insn) { return insn.CanThrow(); });
180     }
181 
HasDebugInfoFunction182     bool HasDebugInfo() const
183     {
184         return std::any_of(ins.cbegin(), ins.cend(), [](const Ins &insn) { return insn.HasDebugInfo(); });
185     }
186 
187     PANDA_PUBLIC_API void DebugDump() const;
188 };
189 // NOLINTEND(misc-non-private-member-variables-in-classes)
190 
191 }  // namespace ark::pandasm
192 
193 #endif  // PANDA_ASSEMBLER_ASSEMBLY_FUNCTION_H
194