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