• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 ASSEMBLER_ASSEMBLY_FUNCTION_H
17 #define 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 struct Function {
41     struct CatchBlock {
42         std::string whole_line;
43         std::string exception_record;
44         std::string try_begin_label;
45         std::string try_end_label;
46         std::string catch_begin_label;
47         std::string catch_end_label;
48     };
49 
50     struct TryCatchInfo {
51         std::unordered_map<std::string_view, size_t> try_catch_labels;
52         std::unordered_map<std::string, std::vector<const CatchBlock *>> try_catch_map;
53         std::vector<std::string> try_catch_order;
TryCatchInfoFunction::TryCatchInfo54         TryCatchInfo(std::unordered_map<std::string_view, size_t> &labels,
55                      std::unordered_map<std::string, std::vector<const CatchBlock *>> &map,
56                      std::vector<std::string> &param_try_catch_order)
57             : try_catch_labels(labels), try_catch_map(map), try_catch_order(param_try_catch_order)
58         {
59         }
60     };
61 
62     struct Parameter {
63         Type type;
64 
ParameterFunction::Parameter65         Parameter(Type t, panda::panda_file::SourceLang lang)
66             : type(std::move(t))
67         {
68         }
69     };
70 
71     std::string name = "";
72     panda::panda_file::SourceLang language;
73     std::unique_ptr<FunctionMetadata> metadata;
74 
75     std::unordered_map<std::string, panda::pandasm::Label> label_table;
76     std::vector<panda::pandasm::Ins> ins; /* function instruction list */
77     std::vector<panda::pandasm::debuginfo::LocalVariable> local_variable_debug;
78     std::string source_file; /* The file in which the function is defined or empty */
79     std::string source_code;
80     std::vector<CatchBlock> catch_blocks;
81     int64_t value_of_first_param = -1;
82     size_t regs_num = 0;
83     std::vector<Parameter> params;
84     bool body_presence = false;
85     Type return_type;
86     SourceLocation body_location;
87     std::optional<FileLocation> file_location;
88     panda::panda_file::FunctionKind function_kind = panda::panda_file::FunctionKind::NONE;
89     size_t slots_num = 0;
90     std::vector<int> concurrent_module_requests;
91     size_t expected_property_count = 0;
92 
SetSlotsNumFunction93     void SetSlotsNum(size_t num)
94     {
95         slots_num = num;
96     }
97 
GetSlotsNumFunction98     size_t GetSlotsNum() const
99     {
100         return slots_num;
101     }
102 
SetFunctionKindFunction103     void SetFunctionKind(panda::panda_file::FunctionKind kind)
104     {
105         function_kind = kind;
106     }
107 
GetFunctionKindFunction108     panda::panda_file::FunctionKind GetFunctionKind() const
109     {
110         return function_kind;
111     }
112 
SetExpectedPropertyCountFunction113     void SetExpectedPropertyCount(size_t count)
114     {
115         expected_property_count = count;
116     }
117 
GetExpectedPropertyCountFunction118     size_t GetExpectedPropertyCount() const
119     {
120         return expected_property_count;
121     }
122 
SetInsDebugFunction123     void SetInsDebug(const std::vector<debuginfo::Ins> &ins_debug)
124     {
125         ASSERT(ins_debug.size() == ins.size());
126         for (std::size_t i = 0; i < ins.size(); i++) {
127             ins[i].ins_debug = ins_debug[i];
128         }
129     }
130 
AddInstructionFunction131     void AddInstruction(const panda::pandasm::Ins &instruction)
132     {
133         ins.emplace_back(instruction);
134     }
135 
FunctionFunction136     Function(std::string s, panda::panda_file::SourceLang lang, size_t b_l, size_t b_r, std::string f_c, bool d,
137              size_t l_n)
138         : name(std::move(s)),
139           language(lang),
140           metadata(extensions::MetadataExtension::CreateFunctionMetadata(lang)),
141           file_location({f_c, b_l, b_r, l_n, d})
142     {
143     }
144 
FunctionFunction145     Function(std::string s, panda::panda_file::SourceLang lang)
146         : name(std::move(s)), language(lang), metadata(extensions::MetadataExtension::CreateFunctionMetadata(lang))
147     {
148     }
149 
GetParamsNumFunction150     std::size_t GetParamsNum() const
151     {
152         return params.size();
153     }
154 
GetTotalRegsFunction155     std::size_t GetTotalRegs() const
156     {
157         return regs_num;
158     }
159 
IsStaticFunction160     bool IsStatic() const
161     {
162         return (metadata->GetAccessFlags() & ACC_STATIC) != 0;
163     }
164 
165     bool Emit(BytecodeEmitter &emitter, panda_file::MethodItem *method,
166               const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods,
167               const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
168               const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
169               const std::unordered_map<std::string, panda_file::StringItem *> &strings,
170               const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays) const;
171 
172     size_t GetLineNumber(size_t i) const;
173 
174     uint32_t GetColumnNumber(size_t i) const;
175 
176     struct LocalVariablePair {
177         size_t insn_order;
178         size_t variable_index;
LocalVariablePairFunction::LocalVariablePair179         LocalVariablePair(size_t order, size_t index) : insn_order(order), variable_index(index) {}
180     };
181     void CollectLocalVariable(std::vector<LocalVariablePair> &local_variable_info) const;
182     void EmitLocalVariable(panda_file::LineNumberProgramItem *program, panda_file::ItemContainer *container,
183                            std::vector<uint8_t> *constant_pool, uint32_t &pc_inc, size_t instruction_number,
184                            size_t variable_index) const;
185     void EmitNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constant_pool, uint32_t pc_inc,
186                     int32_t line_inc) const;
187     void EmitLineNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constant_pool,
188                         int32_t &prev_line_number, uint32_t &pc_inc, size_t instruction_number) const;
189 
190     // column number is only for dynamic language now
191     void EmitColumnNumber(panda_file::LineNumberProgramItem *program, std::vector<uint8_t> *constant_pool,
192                           uint32_t &prev_column_number, uint32_t &pc_inc, size_t instruction_number) const;
193 
194     void BuildLineNumberProgram(panda_file::DebugInfoItem *debug_item, const std::vector<uint8_t> &bytecode,
195                                 panda_file::ItemContainer *container, std::vector<uint8_t> *constant_pool,
196                                 bool emit_debug_info) const;
197 
198     Function::TryCatchInfo MakeOrderAndOffsets(const std::vector<uint8_t> &bytecode) const;
199 
200     std::vector<panda_file::CodeItem::TryBlock> BuildTryBlocks(
201         panda_file::MethodItem *method, const std::unordered_map<std::string, panda_file::BaseClassItem *> &class_items,
202         const std::vector<uint8_t> &bytecode) const;
203 
HasImplementationFunction204     bool HasImplementation() const
205     {
206         return !metadata->IsForeign();
207     }
208 
IsParameterFunction209     bool IsParameter(uint32_t reg_number) const
210     {
211         return reg_number >= regs_num;
212     }
213 
CanThrowFunction214     bool CanThrow() const
215     {
216         return std::any_of(ins.cbegin(), ins.cend(), [](const Ins &insn) { return insn.CanThrow(); });
217     }
218 
HasDebugInfoFunction219     bool HasDebugInfo() const
220     {
221         return std::any_of(ins.cbegin(), ins.cend(), [](const Ins &insn) { return insn.HasDebugInfo(); });
222     }
223 
224     void DebugDump() const;
225 
226     std::set<std::string> CollectStringsFromFunctionInsns() const;
227 };
228 
229 }  // namespace panda::pandasm
230 
231 #endif  // ASSEMBLER_ASSEMBLY_FUNCTION_H
232