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> ¶mTryCatchOrder) 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