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> &params);
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> &params);
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