1b1994897Sopenharmony_ci/** 2b1994897Sopenharmony_ci * Copyright (c) 2021-2022 Huawei Device Co., Ltd. 3b1994897Sopenharmony_ci * Licensed under the Apache License, Version 2.0 (the "License"); 4b1994897Sopenharmony_ci * you may not use this file except in compliance with the License. 5b1994897Sopenharmony_ci * You may obtain a copy of the License at 6b1994897Sopenharmony_ci * 7b1994897Sopenharmony_ci * http://www.apache.org/licenses/LICENSE-2.0 8b1994897Sopenharmony_ci * 9b1994897Sopenharmony_ci * Unless required by applicable law or agreed to in writing, software 10b1994897Sopenharmony_ci * distributed under the License is distributed on an "AS IS" BASIS, 11b1994897Sopenharmony_ci * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12b1994897Sopenharmony_ci * See the License for the specific language governing permissions and 13b1994897Sopenharmony_ci * limitations under the License. 14b1994897Sopenharmony_ci */ 15b1994897Sopenharmony_ci 16b1994897Sopenharmony_ci#ifndef ASSEMBLER_ASSEMBLY_EMITTER_H 17b1994897Sopenharmony_ci#define ASSEMBLER_ASSEMBLY_EMITTER_H 18b1994897Sopenharmony_ci 19b1994897Sopenharmony_ci#include <memory> 20b1994897Sopenharmony_ci#include <type_traits> 21b1994897Sopenharmony_ci#include <vector> 22b1994897Sopenharmony_ci#include <unordered_map> 23b1994897Sopenharmony_ci 24b1994897Sopenharmony_ci#include "assembly-ins.h" 25b1994897Sopenharmony_ci#include "assembly-literals.h" 26b1994897Sopenharmony_ci#include "assembly-program.h" 27b1994897Sopenharmony_ci#include "assembly-type.h" 28b1994897Sopenharmony_ci#include "assembly-function.h" 29b1994897Sopenharmony_ci#include "bytecode_emitter.h" 30b1994897Sopenharmony_ci#include "file_item_container.h" 31b1994897Sopenharmony_ci#include "pgo.h" 32b1994897Sopenharmony_ci 33b1994897Sopenharmony_cinamespace panda::pandasm { 34b1994897Sopenharmony_ciclass AsmEmitter { 35b1994897Sopenharmony_cipublic: 36b1994897Sopenharmony_ci struct PandaFileToPandaAsmMaps { 37b1994897Sopenharmony_ci std::unordered_map<uint32_t, std::string> methods; 38b1994897Sopenharmony_ci std::unordered_map<uint32_t, std::string> fields; 39b1994897Sopenharmony_ci std::unordered_map<uint32_t, std::string> classes; 40b1994897Sopenharmony_ci std::unordered_map<uint32_t, std::string> strings; 41b1994897Sopenharmony_ci std::unordered_map<uint32_t, std::string> literalarrays; 42b1994897Sopenharmony_ci }; 43b1994897Sopenharmony_ci 44b1994897Sopenharmony_ci struct AsmEntityCollections { 45b1994897Sopenharmony_ci std::unordered_map<std::string, panda_file::BaseMethodItem *> method_items; 46b1994897Sopenharmony_ci std::unordered_map<std::string, panda_file::BaseFieldItem *> field_items; 47b1994897Sopenharmony_ci std::unordered_map<std::string, panda_file::BaseClassItem *> class_items; 48b1994897Sopenharmony_ci std::unordered_map<std::string, panda_file::StringItem *> string_items; 49b1994897Sopenharmony_ci std::unordered_map<std::string, panda_file::LiteralArrayItem *> literalarray_items; 50b1994897Sopenharmony_ci }; 51b1994897Sopenharmony_ci 52b1994897Sopenharmony_ci static bool Emit(panda_file::ItemContainer *items, const Program &program, PandaFileToPandaAsmMaps *maps = nullptr, 53b1994897Sopenharmony_ci bool emit_debug_info = true, panda::panda_file::pgo::ProfileOptimizer *profile_opt = nullptr); 54b1994897Sopenharmony_ci 55b1994897Sopenharmony_ci static bool Emit(panda_file::Writer *writer, const Program &program, std::map<std::string, size_t> *stat = nullptr, 56b1994897Sopenharmony_ci PandaFileToPandaAsmMaps *maps = nullptr, bool debug_info = true, 57b1994897Sopenharmony_ci panda::panda_file::pgo::ProfileOptimizer *profile_opt = nullptr, 58b1994897Sopenharmony_ci uint8_t api = 0, std::string subApi = panda_file::DEFAULT_SUB_API_VERSION); 59b1994897Sopenharmony_ci 60b1994897Sopenharmony_ci static bool Emit(const std::string &filename, const Program &program, std::map<std::string, size_t> *stat = nullptr, 61b1994897Sopenharmony_ci PandaFileToPandaAsmMaps *maps = nullptr, bool debug_info = true, 62b1994897Sopenharmony_ci panda::panda_file::pgo::ProfileOptimizer *profile_opt = nullptr, 63b1994897Sopenharmony_ci uint8_t api = 0, std::string subApi = panda_file::DEFAULT_SUB_API_VERSION); 64b1994897Sopenharmony_ci 65b1994897Sopenharmony_ci static bool EmitPrograms(const std::string &filename, const std::vector<Program *> &progs, bool emit_debug_info, 66b1994897Sopenharmony_ci uint8_t api = 0, std::string subApi = panda_file::DEFAULT_SUB_API_VERSION); 67b1994897Sopenharmony_ci 68b1994897Sopenharmony_ci static std::unique_ptr<const panda_file::File> Emit(const Program &program, 69b1994897Sopenharmony_ci PandaFileToPandaAsmMaps *maps = nullptr, 70b1994897Sopenharmony_ci uint8_t api = 0, 71b1994897Sopenharmony_ci std::string subApi = panda_file::DEFAULT_SUB_API_VERSION); 72b1994897Sopenharmony_ci 73b1994897Sopenharmony_ci static std::string GetLastError() 74b1994897Sopenharmony_ci { 75b1994897Sopenharmony_ci return last_error; 76b1994897Sopenharmony_ci } 77b1994897Sopenharmony_ci 78b1994897Sopenharmony_ciprivate: 79b1994897Sopenharmony_ci static bool FillFields(panda_file::ItemContainer *items, const Program &program, 80b1994897Sopenharmony_ci const panda::pandasm::Record &record, const AsmEmitter::AsmEntityCollections &entities); 81b1994897Sopenharmony_ci static bool CheckDuplicateField(panda_file::ValueItem &value_item, panda_file::FieldItem &field_item, 82b1994897Sopenharmony_ci std::string &field_name); 83b1994897Sopenharmony_ci static void MakeStringItems(panda_file::ItemContainer *items, const Program &program, 84b1994897Sopenharmony_ci AsmEntityCollections &entities); 85b1994897Sopenharmony_ci static void MakeLiteralItems(panda_file::ItemContainer *items, const Program &program, 86b1994897Sopenharmony_ci AsmEmitter::AsmEntityCollections &entities); 87b1994897Sopenharmony_ci static void MakeArrayTypeItems(panda_file::ItemContainer *items, const Program &program, 88b1994897Sopenharmony_ci AsmEntityCollections &entities); 89b1994897Sopenharmony_ci static bool HandleRecordAsForeign( 90b1994897Sopenharmony_ci panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, 91b1994897Sopenharmony_ci const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types, 92b1994897Sopenharmony_ci const std::string &name, const Record &rec); 93b1994897Sopenharmony_ci static bool HandleBaseRecord(panda_file::ItemContainer *items, const Program &program, const std::string &name, 94b1994897Sopenharmony_ci const Record &base_rec, panda_file::ClassItem *record); 95b1994897Sopenharmony_ci static bool HandleInterfaces(panda_file::ItemContainer *items, const Program &program, const std::string &name, 96b1994897Sopenharmony_ci const Record &rec, panda_file::ClassItem *record); 97b1994897Sopenharmony_ci static bool HandleFields( 98b1994897Sopenharmony_ci panda_file::ItemContainer *items, const Program &program, AsmEmitter::AsmEntityCollections &entities, 99b1994897Sopenharmony_ci const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types, 100b1994897Sopenharmony_ci const std::string &name, const Record &rec, panda_file::ClassItem *record); 101b1994897Sopenharmony_ci static bool HandleRecord( 102b1994897Sopenharmony_ci panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, 103b1994897Sopenharmony_ci const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types, 104b1994897Sopenharmony_ci const std::string &name, const Record &rec); 105b1994897Sopenharmony_ci static bool MakeRecordItems( 106b1994897Sopenharmony_ci panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, 107b1994897Sopenharmony_ci const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types); 108b1994897Sopenharmony_ci static panda_file::StringItem *GetMethodName(panda_file::ItemContainer *items, const Function &func, 109b1994897Sopenharmony_ci const std::string &name); 110b1994897Sopenharmony_ci static bool HandleAreaForInner(panda_file::ItemContainer *items, const Program &program, 111b1994897Sopenharmony_ci panda_file::ClassItem **area, panda_file::ForeignClassItem **foreign_area, 112b1994897Sopenharmony_ci const std::string &name, const std::string &record_owner_name); 113b1994897Sopenharmony_ci static bool HandleRecordOnwer(panda_file::ItemContainer *items, const Program &program, 114b1994897Sopenharmony_ci panda_file::ClassItem **area, panda_file::ForeignClassItem **foreign_area, 115b1994897Sopenharmony_ci const std::string &name, const std::string &record_owner_name); 116b1994897Sopenharmony_ci static bool HandleFunctionParams( 117b1994897Sopenharmony_ci panda_file::ItemContainer *items, const Program &program, size_t idx, const std::string &name, 118b1994897Sopenharmony_ci const Function &func, 119b1994897Sopenharmony_ci const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types, 120b1994897Sopenharmony_ci std::vector<panda_file::MethodParamItem> ¶ms); 121b1994897Sopenharmony_ci static bool HandleFunctionLocalVariables(panda_file::ItemContainer *items, const Function &func, 122b1994897Sopenharmony_ci const std::string &name); 123b1994897Sopenharmony_ci static bool CreateMethodItem(panda_file::ItemContainer *items, AsmEmitter::AsmEntityCollections &entities, 124b1994897Sopenharmony_ci const Function &func, panda_file::TypeItem *type_item, panda_file::ClassItem *area, 125b1994897Sopenharmony_ci panda_file::ForeignClassItem *foreign_area, uint32_t access_flags, 126b1994897Sopenharmony_ci panda_file::StringItem *method_name, const std::string &mangled_name, 127b1994897Sopenharmony_ci const std::string &name, std::vector<panda_file::MethodParamItem> ¶ms); 128b1994897Sopenharmony_ci static bool MakeFunctionItems( 129b1994897Sopenharmony_ci panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, 130b1994897Sopenharmony_ci const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types, 131b1994897Sopenharmony_ci bool emit_debug_info); 132b1994897Sopenharmony_ci static bool MakeRecordAnnotations(panda_file::ItemContainer *items, const Program &program, 133b1994897Sopenharmony_ci const AsmEntityCollections &entities); 134b1994897Sopenharmony_ci static void SetCodeAndDebugInfo(panda_file::ItemContainer *items, panda_file::MethodItem *method, 135b1994897Sopenharmony_ci const Function &func, bool emit_debug_info); 136b1994897Sopenharmony_ci static bool AddMethodAndParamsAnnotations(panda_file::ItemContainer *items, const Program &program, 137b1994897Sopenharmony_ci const AsmEmitter::AsmEntityCollections &entities, 138b1994897Sopenharmony_ci panda_file::MethodItem *method, const Function &func); 139b1994897Sopenharmony_ci static bool MakeFunctionDebugInfoAndAnnotations(panda_file::ItemContainer *items, const Program &program, 140b1994897Sopenharmony_ci const AsmEntityCollections &entities, bool emit_debug_info); 141b1994897Sopenharmony_ci static void FillMap(PandaFileToPandaAsmMaps *maps, AsmEntityCollections &entities); 142b1994897Sopenharmony_ci static void EmitDebugInfo(panda_file::ItemContainer *items, const Program &program, 143b1994897Sopenharmony_ci const std::vector<uint8_t> *bytes, const panda_file::MethodItem *method, 144b1994897Sopenharmony_ci const Function &func, const std::string &name, bool emit_debug_info); 145b1994897Sopenharmony_ci static bool EmitFunctions(panda_file::ItemContainer *items, const Program &program, 146b1994897Sopenharmony_ci const AsmEntityCollections &entities, bool emit_debug_info); 147b1994897Sopenharmony_ci 148b1994897Sopenharmony_ci static panda_file::TypeItem *GetTypeItem( 149b1994897Sopenharmony_ci panda_file::ItemContainer *items, 150b1994897Sopenharmony_ci const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types, 151b1994897Sopenharmony_ci const Type &type, const Program &program); 152b1994897Sopenharmony_ci 153b1994897Sopenharmony_ci static void SetLastError(const std::string &message) 154b1994897Sopenharmony_ci { 155b1994897Sopenharmony_ci last_error = message; 156b1994897Sopenharmony_ci } 157b1994897Sopenharmony_ci 158b1994897Sopenharmony_ci static bool MakeItemsForSingleProgram(panda_file::ItemContainer *items, const Program &program, 159b1994897Sopenharmony_ci bool emit_debug_info, AsmEntityCollections &entities, 160b1994897Sopenharmony_ci std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> primitive_types); 161b1994897Sopenharmony_ci 162b1994897Sopenharmony_ci static std::string GetMethodSignatureFromProgram(const std::string &name, const Program &program); 163b1994897Sopenharmony_ci 164b1994897Sopenharmony_ci static panda_file::LiteralItem *CreateLiteralItem( 165b1994897Sopenharmony_ci panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::LiteralItem> *out, 166b1994897Sopenharmony_ci const AsmEmitter::AsmEntityCollections &entities); 167b1994897Sopenharmony_ci 168b1994897Sopenharmony_ci template <class PrimType> 169b1994897Sopenharmony_ci static panda_file::ScalarValueItem *CreateScalarPrimValueItem(panda_file::ItemContainer *container, 170b1994897Sopenharmony_ci const Value *value, 171b1994897Sopenharmony_ci std::vector<panda_file::ScalarValueItem> *out) 172b1994897Sopenharmony_ci { 173b1994897Sopenharmony_ci static_assert(std::is_arithmetic<PrimType>::value); 174b1994897Sopenharmony_ci auto v = value->GetAsScalar()->GetValue<PrimType>(); 175b1994897Sopenharmony_ci if (out != nullptr) { 176b1994897Sopenharmony_ci out->emplace_back(v, container); 177b1994897Sopenharmony_ci return &out->back(); 178b1994897Sopenharmony_ci } 179b1994897Sopenharmony_ci 180b1994897Sopenharmony_ci if constexpr (std::is_same<PrimType, uint32_t>::value) { 181b1994897Sopenharmony_ci return container->GetOrCreateIntegerValueItem(v); 182b1994897Sopenharmony_ci } else if constexpr (std::is_same<PrimType, uint64_t>::value) { 183b1994897Sopenharmony_ci return container->GetOrCreateLongValueItem(v); 184b1994897Sopenharmony_ci } else if constexpr (std::is_same<PrimType, float>::value) { 185b1994897Sopenharmony_ci return container->GetOrCreateFloatValueItem(v); 186b1994897Sopenharmony_ci } else if constexpr (std::is_same<PrimType, double>::value) { 187b1994897Sopenharmony_ci return container->GetOrCreateDoubleValueItem(v); 188b1994897Sopenharmony_ci } else { 189b1994897Sopenharmony_ci UNREACHABLE(); 190b1994897Sopenharmony_ci return nullptr; 191b1994897Sopenharmony_ci } 192b1994897Sopenharmony_ci } 193b1994897Sopenharmony_ci 194b1994897Sopenharmony_ci static panda_file::ScalarValueItem *CreateScalarStringValueItem(panda_file::ItemContainer *container, 195b1994897Sopenharmony_ci const Value *value, 196b1994897Sopenharmony_ci std::vector<panda_file::ScalarValueItem> *out); 197b1994897Sopenharmony_ci static panda_file::ScalarValueItem *CreateScalarRecordValueItem( 198b1994897Sopenharmony_ci panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 199b1994897Sopenharmony_ci const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes); 200b1994897Sopenharmony_ci static panda_file::ScalarValueItem *CreateScalarMethodValueItem( 201b1994897Sopenharmony_ci panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 202b1994897Sopenharmony_ci const Program &program, const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods); 203b1994897Sopenharmony_ci static panda_file::ScalarValueItem *CreateScalarLiteralArrayItem( 204b1994897Sopenharmony_ci panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 205b1994897Sopenharmony_ci const Program &program, const std::unordered_map<std::string, panda_file::LiteralArrayItem *> &literalarrays); 206b1994897Sopenharmony_ci static panda_file::ScalarValueItem *CreateScalarEnumValueItem( 207b1994897Sopenharmony_ci panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 208b1994897Sopenharmony_ci const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields); 209b1994897Sopenharmony_ci static panda_file::ScalarValueItem *CreateScalarAnnotationValueItem( 210b1994897Sopenharmony_ci panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 211b1994897Sopenharmony_ci const Program &program, const AsmEmitter::AsmEntityCollections &entities); 212b1994897Sopenharmony_ci 213b1994897Sopenharmony_ci static panda_file::ScalarValueItem *CreateScalarValueItem( 214b1994897Sopenharmony_ci panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out, 215b1994897Sopenharmony_ci const Program &program, const AsmEmitter::AsmEntityCollections &entities); 216b1994897Sopenharmony_ci 217b1994897Sopenharmony_ci static panda_file::ValueItem *CreateValueItem( 218b1994897Sopenharmony_ci panda_file::ItemContainer *container, const Value *value, const Program &program, 219b1994897Sopenharmony_ci const AsmEmitter::AsmEntityCollections &entities); 220b1994897Sopenharmony_ci 221b1994897Sopenharmony_ci static panda_file::AnnotationItem *CreateAnnotationItem( 222b1994897Sopenharmony_ci panda_file::ItemContainer *container, const AnnotationData &annotation, const Program &program, 223b1994897Sopenharmony_ci const AsmEmitter::AsmEntityCollections &entities); 224b1994897Sopenharmony_ci 225b1994897Sopenharmony_ci static panda_file::MethodHandleItem *CreateMethodHandleItem( 226b1994897Sopenharmony_ci panda_file::ItemContainer *container, const MethodHandle &mh, 227b1994897Sopenharmony_ci const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields, 228b1994897Sopenharmony_ci const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods); 229b1994897Sopenharmony_ci 230b1994897Sopenharmony_ci template <class T> 231b1994897Sopenharmony_ci static bool AddAnnotations(T *item, panda_file::ItemContainer *container, const AnnotationMetadata &metadata, 232b1994897Sopenharmony_ci const Program &program, const AsmEmitter::AsmEntityCollections &entities); 233b1994897Sopenharmony_ci 234b1994897Sopenharmony_ci // TODO(mgonopolsky): Refactor to introduce a single error-processing mechanism for parser and emitter 235b1994897Sopenharmony_ci static std::string last_error; 236b1994897Sopenharmony_ci}; 237b1994897Sopenharmony_ci 238b1994897Sopenharmony_cistd::string GetOwnerName(std::string name); 239b1994897Sopenharmony_cistd::string GetItemName(std::string name); 240b1994897Sopenharmony_ci 241b1994897Sopenharmony_ci} // namespace panda::pandasm 242b1994897Sopenharmony_ci 243b1994897Sopenharmony_ci#endif // ASSEMBLER_ASSEMBLY_EMITTER_H 244