• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2025 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 {
ParameterFunction::Parameter64         Parameter(Type t, ark::panda_file::SourceLang sourceLang) : type(std::move(t)), lang(sourceLang) {}
65 
GetOrCreateMetadataFunction::Parameter66         ParamMetadata &GetOrCreateMetadata() const
67         {
68             if (!metadata_) {
69                 metadata_ = extensions::MetadataExtension::CreateParamMetadata(lang);
70             }
71             return *metadata_;
72         }
73 
74         Type type;
75         ark::panda_file::SourceLang lang;
76 
77     private:
78         mutable std::unique_ptr<ParamMetadata> metadata_;
79     };
80 
81     std::string name;
82     ark::panda_file::SourceLang language;
83     std::unique_ptr<FunctionMetadata> metadata;
84 
85     std::unordered_map<std::string, ark::pandasm::Label> labelTable;
86     std::vector<ark::pandasm::Ins> ins; /* function instruction list */
87     std::vector<ark::pandasm::debuginfo::LocalVariable> localVariableDebug;
88     std::string sourceFile; /* The file in which the function is defined or empty */
89     std::string sourceCode;
90     std::vector<CatchBlock> catchBlocks;
91     int64_t valueOfFirstParam = -1;
92     size_t regsNum = 0;
93     size_t profileSize {0};
94     std::vector<Parameter> params;
95     bool bodyPresence = false;
96     Type returnType;
97     SourceLocation bodyLocation;
98     std::optional<FileLocation> fileLocation;
99 
SetInsDebugFunction100     void SetInsDebug(const std::vector<debuginfo::Ins> &insDebug)
101     {
102         ASSERT(insDebug.size() == ins.size());
103         for (std::size_t i = 0; i < ins.size(); i++) {
104             ins[i].insDebug = insDebug[i];
105         }
106     }
107 
AddInstructionFunction108     void AddInstruction(const ark::pandasm::Ins &instruction)
109     {
110         ins.emplace_back(instruction);
111     }
112 
113     // CC-OFFNXT(G.FUN.01-CPP) solid logic
FunctionFunction114     Function(std::string s, ark::panda_file::SourceLang lang, size_t bL, size_t bR, std::string fC, bool d, size_t lN)
115         : name(std::move(s)),
116           language(lang),
117           metadata(extensions::MetadataExtension::CreateFunctionMetadata(lang)),
118           fileLocation({fC, bL, bR, lN, d})
119     {
120     }
121 
FunctionFunction122     Function(std::string s, ark::panda_file::SourceLang lang)
123         : name(std::move(s)), language(lang), metadata(extensions::MetadataExtension::CreateFunctionMetadata(lang))
124     {
125     }
126 
GetParamsNumFunction127     std::size_t GetParamsNum() const
128     {
129         return params.size();
130     }
131 
GetTotalRegsFunction132     std::size_t GetTotalRegs() const
133     {
134         return regsNum;
135     }
136 
IsStaticFunction137     bool IsStatic() const
138     {
139         return (metadata->GetAccessFlags() & ACC_STATIC) != 0;
140     }
141 
142     // CC-OFFNXT(G.FUN.01-CPP) solid logic
143     bool Emit(BytecodeEmitter &emitter, panda_file::MethodItem *method,
144               const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
145               const std::unordered_map<std::string, panda_file::BaseMethodItem *> &staticMethods,
146               const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
147               const std::unordered_map<std::string, panda_file::BaseFieldItem *> &staticFields,
148               const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
149               const std::unordered_map<std::string_view, panda_file::StringItem *> &strings,
150               const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays) const;
151 
152     size_t GetLineNumber(size_t i) const;
153 
154     uint32_t GetColumnNumber(size_t i) const;
155 
156     void EmitLocalVariable(panda_file::LineNumberProgramItem *program, panda_file::ItemContainer *container,
157                            std::vector<uint8_t> *constantPool, uint32_t &pcInc, size_t instructionNumber) const;
158     void EmitNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constantPool, uint32_t pcInc,
159                     int32_t lineInc) const;
160     void EmitLineNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constantPool,
161                         uint32_t &prevLineNumber, uint32_t &pcInc, size_t instructionNumber) const;
162 
163     // column number is only for dynamic language now
164     void EmitColumnNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constantPool,
165                           uint32_t &prevColumnNumber, uint32_t &pcInc, size_t instructionNumber) const;
166 
167     void BuildLineNumberProgram(panda_file::DebugInfoItem *debugItem, const std::vector<uint8_t> &bytecode,
168                                 panda_file::ItemContainer *container, std::vector<uint8_t> *constantPool,
169                                 bool emitDebugInfo) const;
170 
171     Function::TryCatchInfo MakeOrderAndOffsets(const std::vector<uint8_t> &bytecode) const;
172 
173     std::vector<panda_file::CodeItem::TryBlock> BuildTryBlocks(
174         panda_file::MethodItem *method, const std::unordered_map<std::string, panda_file::BaseClassItem *> &classItems,
175         const std::vector<uint8_t> &bytecode) const;
176 
HasImplementationFunction177     bool HasImplementation() const
178     {
179         return !metadata->IsForeign() && metadata->HasImplementation();
180     }
181 
IsParameterFunction182     bool IsParameter(uint32_t regNumber) const
183     {
184         return regNumber >= regsNum;
185     }
186 
CanThrowFunction187     bool CanThrow() const
188     {
189         return std::any_of(ins.cbegin(), ins.cend(), [](const Ins &insn) { return insn.CanThrow(); });
190     }
191 
HasDebugInfoFunction192     bool HasDebugInfo() const
193     {
194         return std::any_of(ins.cbegin(), ins.cend(), [](const Ins &insn) { return insn.HasDebugInfo(); });
195     }
196 
197     PANDA_PUBLIC_API void DebugDump() const;
198 };
199 // NOLINTEND(misc-non-private-member-variables-in-classes)
200 
201 }  // namespace ark::pandasm
202 
203 #endif  // PANDA_ASSEMBLER_ASSEMBLY_FUNCTION_H
204