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