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