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> ¶m_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