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_EMITTER_H 17 #define PANDA_ASSEMBLER_ASSEMBLY_EMITTER_H 18 19 #include <memory> 20 #include <type_traits> 21 #include <vector> 22 #include <unordered_map> 23 24 #include "assembly-ins.h" 25 #include "assembly-literals.h" 26 #include "assembly-program.h" 27 #include "assembly-type.h" 28 #include "assembly-function.h" 29 #include "bytecode_emitter.h" 30 #include "file_item_container.h" 31 #include "pgo.h" 32 33 namespace ark::pandasm { 34 35 class AsmEmitter { 36 public: 37 struct PandaFileToPandaAsmMaps { 38 std::unordered_map<uint32_t, std::string> methods; 39 std::unordered_map<uint32_t, std::string> fields; 40 std::unordered_map<uint32_t, std::string> classes; 41 std::unordered_map<uint32_t, std::string> strings; 42 std::unordered_map<uint32_t, std::string> literalarrays; 43 }; 44 45 struct AsmEntityCollections { 46 std::unordered_map<std::string, panda_file::BaseMethodItem *> methodItems; 47 std::unordered_map<std::string, panda_file::BaseMethodItem *> staticMethodItems; 48 std::unordered_map<std::string, panda_file::BaseFieldItem *> fieldItems; 49 std::unordered_map<std::string, panda_file::BaseFieldItem *> staticFieldItems; 50 std::unordered_map<std::string, panda_file::BaseClassItem *> classItems; 51 std::unordered_map<std::string_view, panda_file::StringItem *> stringItems; 52 std::unordered_map<std::string, panda_file::LiteralArrayItem *> literalarrayItems; 53 }; 54 55 PANDA_PUBLIC_API static bool Emit(panda_file::ItemContainer *items, Program &program, 56 PandaFileToPandaAsmMaps *maps = nullptr, bool emitDebugInfo = true, 57 ark::panda_file::pgo::ProfileOptimizer *profileOpt = nullptr); 58 59 // CC-OFFNXT(G.FUN.01-CPP) solid logic 60 PANDA_PUBLIC_API static bool Emit(panda_file::Writer *writer, Program &program, 61 std::map<std::string, size_t> *stat = nullptr, 62 PandaFileToPandaAsmMaps *maps = nullptr, bool debugInfo = true, 63 ark::panda_file::pgo::ProfileOptimizer *profileOpt = nullptr); 64 65 // CC-OFFNXT(G.FUN.01-CPP) solid logic 66 PANDA_PUBLIC_API static bool Emit(const std::string &filename, Program &program, 67 std::map<std::string, size_t> *stat = nullptr, 68 PandaFileToPandaAsmMaps *maps = nullptr, bool debugInfo = true, 69 ark::panda_file::pgo::ProfileOptimizer *profileOpt = nullptr); 70 71 PANDA_PUBLIC_API static std::unique_ptr<const panda_file::File> Emit(Program &program, 72 PandaFileToPandaAsmMaps *maps = nullptr); 73 74 PANDA_PUBLIC_API static bool AssignProfileInfo(Program *program); 75 GetLastError()76 PANDA_PUBLIC_API static std::string GetLastError() 77 { 78 return lastError_; 79 } 80 81 private: 82 static void MakeStringItems(panda_file::ItemContainer *items, const Program &program, 83 AsmEntityCollections &entities); 84 static void MakeLiteralItems(panda_file::ItemContainer *items, const Program &program, 85 AsmEmitter::AsmEntityCollections &entities); 86 static void MakeArrayTypeItems(panda_file::ItemContainer *items, const Program &program, 87 AsmEntityCollections &entities); 88 // CC-OFFNXT(G.FUN.01-CPP) solid logic 89 static bool HandleRecordAsForeign( 90 panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, 91 const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes, 92 const std::string &name, const Record &rec); 93 static bool HandleBaseRecord(panda_file::ItemContainer *items, const Program &program, const std::string &name, 94 const Record &rec, panda_file::ClassItem *record); 95 static bool HandleInterfaces(panda_file::ItemContainer *items, const Program &program, const std::string &name, 96 const Record &rec, panda_file::ClassItem *record); 97 static void UpdateFieldList(AsmEmitter::AsmEntityCollections &entities, const std::string &fullFieldName, 98 panda_file::BaseFieldItem *field); 99 static panda_file::MethodItem *FindMethod(const Function &func, const std::string &name, 100 const AsmEmitter::AsmEntityCollections &entities); 101 static panda_file::MethodItem *FindAmongAllMethods(const std::string &name, 102 const AsmEmitter::AsmEntityCollections &entities, 103 const Value *value); 104 // CC-OFFNXT(G.FUN.01-CPP) solid logic 105 static bool HandleFields( 106 panda_file::ItemContainer *items, const Program &program, AsmEmitter::AsmEntityCollections &entities, 107 const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes, 108 const std::string &name, const Record &rec, panda_file::ClassItem *record); 109 // CC-OFFNXT(G.FUN.01-CPP) solid logic 110 static bool HandleRecord( 111 panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, 112 const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes, 113 const std::string &name, const Record &rec); 114 static bool MakeRecordItems( 115 panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, 116 const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes); 117 static panda_file::StringItem *GetMethodName(panda_file::ItemContainer *items, const Function &func, 118 const std::string &name); 119 // CC-OFFNXT(G.FUN.01-CPP) solid logic 120 static bool HandleAreaForInner(panda_file::ItemContainer *items, const Program &program, 121 panda_file::ClassItem **area, panda_file::ForeignClassItem **foreignArea, 122 const std::string &name, const std::string &recordOwnerName); 123 // CC-OFFNXT(G.FUN.01-CPP) solid logic 124 static bool HandleRecordOnwer(panda_file::ItemContainer *items, const Program &program, 125 panda_file::ClassItem **area, panda_file::ForeignClassItem **foreignArea, 126 const std::string &name, const std::string &recordOwnerName); 127 // CC-OFFNXT(G.FUN.01-CPP) solid logic 128 static bool HandleFunctionParams( 129 panda_file::ItemContainer *items, const Program &program, size_t idx, const std::string &name, 130 const Function &func, 131 const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes, 132 std::vector<panda_file::MethodParamItem> ¶ms); 133 static bool HandleFunctionLocalVariables(panda_file::ItemContainer *items, const Function &func, 134 const std::string &name); 135 // CC-OFFNXT(G.FUN.01-CPP) solid logic 136 static bool CreateMethodItem(panda_file::ItemContainer *items, AsmEmitter::AsmEntityCollections &entities, 137 const Function &func, panda_file::TypeItem *typeItem, panda_file::ClassItem *area, 138 panda_file::ForeignClassItem *foreignArea, panda_file::StringItem *methodName, 139 const std::string &mangledName, const std::string &name, 140 std::vector<panda_file::MethodParamItem> ¶ms); 141 static bool MakeFunctionItems( 142 panda_file::ItemContainer *items, Program &program, AsmEntityCollections &entities, 143 const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes, 144 bool emitDebugInfo); 145 // CC-OFFNXT(G.FUN.01-CPP) solid logic 146 static bool MakeFunctionItems( 147 panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, 148 const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes, 149 bool emitDebugInfo, bool isStatic); 150 static bool MakeRecordAnnotations(panda_file::ItemContainer *items, const Program &program, 151 const AsmEntityCollections &entities); 152 static void SetCodeAndDebugInfo(panda_file::ItemContainer *items, panda_file::MethodItem *method, 153 const Function &func, bool emitDebugInfo); 154 static void SetMethodSourceLang(const Program &program, panda_file::MethodItem *method, const Function &func, 155 const std::string &name); 156 static bool AddMethodAndParamsAnnotations(panda_file::ItemContainer *items, const Program &program, 157 const AsmEmitter::AsmEntityCollections &entities, 158 panda_file::MethodItem *method, const Function &func); 159 static bool MakeFunctionDebugInfoAndAnnotations(panda_file::ItemContainer *items, const Program &program, 160 const AsmEntityCollections &entities, bool emitDebugInfo); 161 static bool MakeFunctionDebugInfoAndAnnotations(panda_file::ItemContainer *items, const Program &program, 162 const std::map<std::string, Function> &functionTable, 163 const AsmEmitter::AsmEntityCollections &entities, 164 bool emitDebugInfo); 165 static void FillMap(PandaFileToPandaAsmMaps *maps, AsmEntityCollections &entities); 166 // CC-OFFNXT(G.FUN.01-CPP) solid logic 167 static void EmitDebugInfo(panda_file::ItemContainer *items, const Program &program, 168 const std::vector<uint8_t> *bytes, const panda_file::MethodItem *method, 169 const Function &func, const std::string &name, bool emitDebugInfo); 170 static bool EmitFunctions(panda_file::ItemContainer *items, const Program &program, 171 const AsmEntityCollections &entities, bool emitDebugInfo); 172 static bool EmitFunctions(panda_file::ItemContainer *items, const Program &program, 173 const AsmEntityCollections &entities, bool emitDebugInfo, bool isStatic); 174 175 static panda_file::TypeItem *GetTypeItem( 176 panda_file::ItemContainer *items, 177 const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes, 178 const Type &type, const Program &program); 179 SetLastError(const std::string & message)180 PANDA_PUBLIC_API static void SetLastError(const std::string &message) 181 { 182 lastError_ = message; 183 } 184 185 static bool CheckValueType(Value::Type valueType, const Type &type, const Program &program); 186 187 static bool CheckValueEnumCase(const Value *value, const Type &type, const Program &program); 188 static bool CheckValueArrayCase(const Value *value, const Type &type, const Program &program); 189 static bool CheckValueMethodCase(const Value *value, const Program &program); 190 static bool CheckValueRecordCase(const Value *value, const Program &program); 191 static bool CheckValue(const Value *value, const Type &type, const Program &program); 192 static std::string GetMethodSignatureFromProgram(const std::string &name, const Program &program); 193 194 static panda_file::LiteralItem *CreateLiteralItem(panda_file::ItemContainer *container, const Value *value, 195 std::vector<panda_file::LiteralItem> *out, 196 const AsmEmitter::AsmEntityCollections &entities); 197 static panda_file::LiteralItem *CreateLiteralItemFromMethod(const Value *value, 198 std::vector<panda_file::LiteralItem> *out, 199 const AsmEmitter::AsmEntityCollections &entities); 200 201 template <class PrimType> CreateScalarPrimValueItem(panda_file::ItemContainer * container,const Value * value,std::vector<panda_file::ScalarValueItem> * out)202 static panda_file::ScalarValueItem *CreateScalarPrimValueItem(panda_file::ItemContainer *container, 203 const Value *value, 204 std::vector<panda_file::ScalarValueItem> *out) 205 { 206 static_assert(std::is_arithmetic<PrimType>::value); 207 auto v = value->GetAsScalar()->GetValue<PrimType>(); 208 if (out != nullptr) { 209 out->emplace_back(v); 210 return &out->back(); 211 } 212 213 if constexpr (std::is_same<PrimType, uint32_t>::value) { 214 return container->GetOrCreateIntegerValueItem(v); 215 } else if constexpr (std::is_same<PrimType, uint64_t>::value) { 216 return container->GetOrCreateLongValueItem(v); 217 } else if constexpr (std::is_same<PrimType, float>::value) { 218 return container->GetOrCreateFloatValueItem(v); 219 } else if constexpr (std::is_same<PrimType, double>::value) { 220 return container->GetOrCreateDoubleValueItem(v); 221 } else { 222 UNREACHABLE(); 223 return nullptr; 224 } 225 } 226 227 static panda_file::ScalarValueItem *CreateScalarStringValueItem(panda_file::ItemContainer *container, 228 const Value *value, 229 std::vector<panda_file::ScalarValueItem> *out); 230 static panda_file::ScalarValueItem *CreateScalarRecordValueItem( 231 panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 232 const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes); 233 // CC-OFFNXT(G.FUN.01-CPP) solid logic 234 static panda_file::ScalarValueItem *CreateScalarMethodValueItem( 235 panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 236 const Program &program, const AsmEmitter::AsmEntityCollections &entities, std::pair<bool, bool> searchInfo); 237 static panda_file::ScalarValueItem *CreateScalarLiteralArrayItem( 238 panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 239 const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays); 240 static panda_file::ScalarValueItem *CreateScalarEnumValueItem( 241 panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 242 const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields); 243 // CC-OFFNXT(G.FUN.01-CPP) solid logic 244 static panda_file::ScalarValueItem *CreateScalarAnnotationValueItem( 245 panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 246 const Program &program, const AsmEmitter::AsmEntityCollections &entities); 247 248 // CC-OFFNXT(G.FUN.01-CPP) solid logic 249 static panda_file::ScalarValueItem *CreateScalarValueItem(panda_file::ItemContainer *container, const Value *value, 250 std::vector<panda_file::ScalarValueItem> *out, 251 const Program &program, 252 const AsmEmitter::AsmEntityCollections &entities, 253 std::pair<bool, bool> searchInfo); 254 255 // CC-OFFNXT(G.FUN.01-CPP) solid logic 256 static panda_file::ValueItem *CreateValueItem(panda_file::ItemContainer *container, const Value *value, 257 const Program &program, 258 const AsmEmitter::AsmEntityCollections &entities, 259 std::pair<bool, bool> searchInfo = {false, false}); 260 261 // CC-OFFNXT(G.FUN.01-CPP) solid logic 262 static panda_file::AnnotationItem *CreateAnnotationItem(panda_file::ItemContainer *container, 263 const AnnotationData &annotation, const Program &program, 264 const AsmEmitter::AsmEntityCollections &entities); 265 static std::optional<std::map<std::basic_string<char>, ark::pandasm::Function>::const_iterator> 266 GetMethodForAnnotationElement(const std::string &functionName, const Value *value, const Program &program); 267 static panda_file::MethodHandleItem *CreateMethodHandleItem( 268 panda_file::ItemContainer *container, const MethodHandle &mh, 269 const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields, 270 const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods); 271 272 template <class T> 273 // CC-OFFNXT(G.FUN.01-CPP) solid logic 274 static bool AddAnnotations(T *item, panda_file::ItemContainer *container, const AnnotationMetadata &metadata, 275 const Program &program, const AsmEmitter::AsmEntityCollections &entities); 276 277 static bool AssignProfileInfo(std::unordered_map<size_t, std::vector<Ins *>> &instMap, 278 const std::map<std::string, pandasm::Function> &functionTable); 279 280 // NOTE(mgonopolsky): Refactor to introduce a single error-processing mechanism for parser and emitter 281 // NOLINTNEXTLINE(fuchsia-statically-constructed-objects) 282 PANDA_PUBLIC_API static std::string lastError_; 283 }; 284 285 std::string GetOwnerName(std::string name); 286 std::string GetItemName(std::string name); 287 288 } // namespace ark::pandasm 289 290 #endif // PANDA_ASSEMBLER_ASSEMBLY_EMITTER_H 291