/** * Copyright (c) 2021-2022 Huawei Device Co., Ltd. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #ifndef ASSEMBLER_ASSEMBLY_EMITTER_H #define ASSEMBLER_ASSEMBLY_EMITTER_H #include #include #include #include #include "assembly-ins.h" #include "assembly-literals.h" #include "assembly-program.h" #include "assembly-type.h" #include "assembly-function.h" #include "bytecode_emitter.h" #include "file_item_container.h" #include "pgo.h" namespace panda::pandasm { class AsmEmitter { public: struct PandaFileToPandaAsmMaps { std::unordered_map methods; std::unordered_map fields; std::unordered_map classes; std::unordered_map strings; std::unordered_map literalarrays; }; struct AsmEntityCollections { std::unordered_map method_items; std::unordered_map field_items; std::unordered_map class_items; std::unordered_map string_items; std::unordered_map literalarray_items; }; static bool Emit(panda_file::ItemContainer *items, const Program &program, PandaFileToPandaAsmMaps *maps = nullptr, bool emit_debug_info = true, panda::panda_file::pgo::ProfileOptimizer *profile_opt = nullptr); static bool Emit(panda_file::Writer *writer, const Program &program, std::map *stat = nullptr, PandaFileToPandaAsmMaps *maps = nullptr, bool debug_info = true, panda::panda_file::pgo::ProfileOptimizer *profile_opt = nullptr); static bool Emit(const std::string &filename, const Program &program, std::map *stat = nullptr, PandaFileToPandaAsmMaps *maps = nullptr, bool debug_info = true, panda::panda_file::pgo::ProfileOptimizer *profile_opt = nullptr); static bool EmitPrograms(const std::string &filename, const std::vector &progs, bool emit_debug_info); static std::unique_ptr Emit(const Program &program, PandaFileToPandaAsmMaps *maps = nullptr); static std::string GetLastError() { return last_error; } private: static void MakeStringItems(panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities); static void MakeLiteralItems(panda_file::ItemContainer *items, const Program &program, AsmEmitter::AsmEntityCollections &entities); static void MakeArrayTypeItems(panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities); static bool HandleRecordAsForeign( panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, const std::unordered_map &primitive_types, const std::string &name, const Record &rec); static bool HandleBaseRecord(panda_file::ItemContainer *items, const Program &program, const std::string &name, const Record &base_rec, panda_file::ClassItem *record); static bool HandleInterfaces(panda_file::ItemContainer *items, const Program &program, const std::string &name, const Record &rec, panda_file::ClassItem *record); static bool HandleFields( panda_file::ItemContainer *items, const Program &program, AsmEmitter::AsmEntityCollections &entities, const std::unordered_map &primitive_types, const std::string &name, const Record &rec, panda_file::ClassItem *record); static bool HandleRecord( panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, const std::unordered_map &primitive_types, const std::string &name, const Record &rec); static bool MakeRecordItems( panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, const std::unordered_map &primitive_types); static panda_file::StringItem *GetMethodName(panda_file::ItemContainer *items, const Function &func, const std::string &name); static bool HandleAreaForInner(panda_file::ItemContainer *items, const Program &program, panda_file::ClassItem **area, panda_file::ForeignClassItem **foreign_area, const std::string &name, const std::string &record_owner_name); static bool HandleRecordOnwer(panda_file::ItemContainer *items, const Program &program, panda_file::ClassItem **area, panda_file::ForeignClassItem **foreign_area, const std::string &name, const std::string &record_owner_name); static bool HandleFunctionParams( panda_file::ItemContainer *items, const Program &program, size_t idx, const std::string &name, const Function &func, const std::unordered_map &primitive_types, std::vector ¶ms); static bool HandleFunctionLocalVariables(panda_file::ItemContainer *items, const Function &func, const std::string &name); static bool CreateMethodItem(panda_file::ItemContainer *items, AsmEmitter::AsmEntityCollections &entities, const Function &func, panda_file::TypeItem *type_item, panda_file::ClassItem *area, panda_file::ForeignClassItem *foreign_area, uint32_t access_flags, panda_file::StringItem *method_name, const std::string &mangled_name, const std::string &name, std::vector ¶ms); static bool MakeFunctionItems( panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities, const std::unordered_map &primitive_types, bool emit_debug_info); static bool MakeRecordAnnotations(panda_file::ItemContainer *items, const Program &program, const AsmEntityCollections &entities); static void SetCodeAndDebugInfo(panda_file::ItemContainer *items, panda_file::MethodItem *method, const Function &func, bool emit_debug_info); static bool AddMethodAndParamsAnnotations(panda_file::ItemContainer *items, const Program &program, const AsmEmitter::AsmEntityCollections &entities, panda_file::MethodItem *method, const Function &func); static bool MakeFunctionDebugInfoAndAnnotations(panda_file::ItemContainer *items, const Program &program, const AsmEntityCollections &entities, bool emit_debug_info); static void FillMap(PandaFileToPandaAsmMaps *maps, AsmEntityCollections &entities); static void EmitDebugInfo(panda_file::ItemContainer *items, const Program &program, const std::vector *bytes, const panda_file::MethodItem *method, const Function &func, const std::string &name, bool emit_debug_info); static bool EmitFunctions(panda_file::ItemContainer *items, const Program &program, const AsmEntityCollections &entities, bool emit_debug_info); static panda_file::TypeItem *GetTypeItem( panda_file::ItemContainer *items, const std::unordered_map &primitive_types, const Type &type, const Program &program); static void SetLastError(const std::string &message) { last_error = message; } static bool MakeItemsForSingleProgram(panda_file::ItemContainer *items, const Program &program, bool emit_debug_info, AsmEntityCollections &entities, std::unordered_map primitive_types); static std::string GetMethodSignatureFromProgram(const std::string &name, const Program &program); static panda_file::LiteralItem *CreateLiteralItem( panda_file::ItemContainer *container, const Value *value, std::vector *out, const AsmEmitter::AsmEntityCollections &entities); template static panda_file::ScalarValueItem *CreateScalarPrimValueItem(panda_file::ItemContainer *container, const Value *value, std::vector *out) { static_assert(std::is_arithmetic::value); auto v = value->GetAsScalar()->GetValue(); if (out != nullptr) { out->emplace_back(v, container); return &out->back(); } if constexpr (std::is_same::value) { return container->GetOrCreateIntegerValueItem(v); } else if constexpr (std::is_same::value) { return container->GetOrCreateLongValueItem(v); } else if constexpr (std::is_same::value) { return container->GetOrCreateFloatValueItem(v); } else if constexpr (std::is_same::value) { return container->GetOrCreateDoubleValueItem(v); } else { UNREACHABLE(); return nullptr; } } static panda_file::ScalarValueItem *CreateScalarStringValueItem(panda_file::ItemContainer *container, const Value *value, std::vector *out); static panda_file::ScalarValueItem *CreateScalarRecordValueItem( panda_file::ItemContainer *container, const Value *value, std::vector *out, const std::unordered_map &classes); static panda_file::ScalarValueItem *CreateScalarMethodValueItem( panda_file::ItemContainer *container, const Value *value, std::vector *out, const Program &program, const std::unordered_map &methods); static panda_file::ScalarValueItem *CreateScalarLiteralArrayItem( panda_file::ItemContainer *container, const Value *value, std::vector *out, const Program &program, const std::unordered_map &literalarrays); static panda_file::ScalarValueItem *CreateScalarEnumValueItem( panda_file::ItemContainer *container, const Value *value, std::vector *out, const std::unordered_map &fields); static panda_file::ScalarValueItem *CreateScalarAnnotationValueItem( panda_file::ItemContainer *container, const Value *value, std::vector *out, const Program &program, const AsmEmitter::AsmEntityCollections &entities); static panda_file::ScalarValueItem *CreateScalarValueItem( panda_file::ItemContainer *container, const Value *value, std::vector *out, const Program &program, const AsmEmitter::AsmEntityCollections &entities); static panda_file::ValueItem *CreateValueItem( panda_file::ItemContainer *container, const Value *value, const Program &program, const AsmEmitter::AsmEntityCollections &entities); static panda_file::AnnotationItem *CreateAnnotationItem( panda_file::ItemContainer *container, const AnnotationData &annotation, const Program &program, const AsmEmitter::AsmEntityCollections &entities); static panda_file::MethodHandleItem *CreateMethodHandleItem( panda_file::ItemContainer *container, const MethodHandle &mh, const std::unordered_map &fields, const std::unordered_map &methods); template static bool AddAnnotations(T *item, panda_file::ItemContainer *container, const AnnotationMetadata &metadata, const Program &program, const AsmEmitter::AsmEntityCollections &entities); // TODO(mgonopolsky): Refactor to introduce a single error-processing mechanism for parser and emitter static std::string last_error; }; std::string GetOwnerName(std::string name); std::string GetItemName(std::string name); } // namespace panda::pandasm #endif // ASSEMBLER_ASSEMBLY_EMITTER_H