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