• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2021-2022 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 ASSEMBLER_ASSEMBLY_EMITTER_H
17 #define 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 panda::pandasm {
34 
35 constexpr size_t DEFAULT_ITEM_THREAD_COUNT = 8;;
36 struct EmitterConfig {
37     uint8_t api = 0;
38     std::string subApi = panda_file::DEFAULT_SUB_API_VERSION;
39     bool isDebug = false;
40     size_t fileThreadCount = DEFAULT_ITEM_THREAD_COUNT;
41 };
42 
43 class AsmEmitter {
44 public:
45     struct PandaFileToPandaAsmMaps {
46         std::unordered_map<uint32_t, std::string> methods;
47         std::unordered_map<uint32_t, std::string> fields;
48         std::unordered_map<uint32_t, std::string> classes;
49         std::unordered_map<uint32_t, std::string> strings;
50         std::unordered_map<uint32_t, std::string> literalarrays;
51     };
52 
53     struct AsmEntityCollections {
54         std::unordered_map<std::string, panda_file::BaseMethodItem *> method_items;
55         std::unordered_map<std::string, panda_file::BaseFieldItem *> field_items;
56         std::unordered_map<std::string, panda_file::BaseClassItem *> class_items;
57         std::unordered_map<std::string, panda_file::StringItem *> string_items;
58         std::unordered_map<std::string, panda_file::LiteralArrayItem *> literalarray_items;
59     };
60 
61     static bool Emit(panda_file::ItemContainer *items, const Program &program, PandaFileToPandaAsmMaps *maps = nullptr,
62                      bool emit_debug_info = true, panda::panda_file::pgo::ProfileOptimizer *profile_opt = nullptr);
63 
64     static bool Emit(panda_file::Writer *writer, const Program &program, std::map<std::string, size_t> *stat = nullptr,
65                      PandaFileToPandaAsmMaps *maps = nullptr, bool debug_info = true,
66                      panda::panda_file::pgo::ProfileOptimizer *profile_opt = nullptr,
67                      uint8_t api = 0, std::string subApi = panda_file::DEFAULT_SUB_API_VERSION);
68 
69     static bool Emit(const std::string &filename, const Program &program, std::map<std::string, size_t> *stat = nullptr,
70                      PandaFileToPandaAsmMaps *maps = nullptr, bool debug_info = true,
71                      panda::panda_file::pgo::ProfileOptimizer *profile_opt = nullptr,
72                      uint8_t api = 0, std::string subApi = panda_file::DEFAULT_SUB_API_VERSION);
73 
74     // The function releases the data in progs in advance for the sake of the peak memory at compiler time.
75     static bool EmitPrograms(const std::string &filename, const std::vector<Program *> &progs, bool emit_debug_info,
76                              const EmitterConfig &emitterConfig = EmitterConfig {});
77 
78     static std::unique_ptr<const panda_file::File> Emit(const Program &program,
79                                                         PandaFileToPandaAsmMaps *maps = nullptr,
80                                                         uint8_t api = 0,
81                                                         std::string subApi = panda_file::DEFAULT_SUB_API_VERSION);
82 
GetLastError()83     static std::string GetLastError()
84     {
85         return last_error;
86     }
87 
SetLastError(const std::string & message)88     static void SetLastError(const std::string &message)
89     {
90         last_error = message;
91     }
92 
93 private:
94     static bool FillFields(panda_file::ItemContainer *items, const Program &program,
95                            const panda::pandasm::Record &record, const AsmEmitter::AsmEntityCollections &entities);
96     static bool CheckDuplicateField(panda_file::ValueItem &value_item, panda_file::FieldItem &field_item,
97                                     std::string &field_name);
98     static void MakeStringItems(panda_file::ItemContainer *items, const Program &program,
99                                 AsmEntityCollections &entities);
100     static void MakeLiteralItems(panda_file::ItemContainer *items, const Program &program,
101                                  AsmEmitter::AsmEntityCollections &entities);
102     static void MakeArrayTypeItems(panda_file::ItemContainer *items, const Program &program,
103                                    AsmEntityCollections &entities);
104     static bool HandleRecordAsForeign(
105         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
106         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
107         const std::string &name, const Record &rec);
108     static bool HandleBaseRecord(panda_file::ItemContainer *items, const Program &program, const std::string &name,
109                                  const Record &base_rec, panda_file::ClassItem *record);
110     static bool HandleInterfaces(panda_file::ItemContainer *items, const Program &program, const std::string &name,
111                                  const Record &rec, panda_file::ClassItem *record);
112     static bool HandleFields(
113         panda_file::ItemContainer *items, const Program &program, AsmEmitter::AsmEntityCollections &entities,
114         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
115         const std::string &name, const Record &rec, panda_file::ClassItem *record);
116     static bool HandleRecord(
117         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
118         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
119         const std::string &name, const Record &rec);
120     static bool MakeRecordItems(
121         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
122         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types);
123     static panda_file::StringItem *GetMethodName(panda_file::ItemContainer *items, const Function &func,
124                                                  const std::string &name);
125     static bool HandleAreaForInner(panda_file::ItemContainer *items, const Program &program,
126                                    panda_file::ClassItem **area, panda_file::ForeignClassItem **foreign_area,
127                                    const std::string &name, const std::string &record_owner_name);
128     static bool HandleRecordOnwer(panda_file::ItemContainer *items, const Program &program,
129                                   panda_file::ClassItem **area, panda_file::ForeignClassItem **foreign_area,
130                                   const std::string &name, const std::string &record_owner_name);
131     static bool HandleFunctionParams(
132         panda_file::ItemContainer *items, const Program &program, size_t idx, const std::string &name,
133         const Function &func,
134         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
135         std::vector<panda_file::MethodParamItem> &params);
136     static bool HandleFunctionLocalVariables(panda_file::ItemContainer *items, const Function &func,
137                                              const std::string &name);
138     static bool CreateMethodItem(panda_file::ItemContainer *items, AsmEmitter::AsmEntityCollections &entities,
139                                  const Function &func, panda_file::TypeItem *type_item, panda_file::ClassItem *area,
140                                  panda_file::ForeignClassItem *foreign_area, uint32_t access_flags,
141                                  panda_file::StringItem *method_name, const std::string &mangled_name,
142                                  const std::string &name, std::vector<panda_file::MethodParamItem> &params);
143     static bool MakeFunctionItems(
144         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
145         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
146         bool emit_debug_info);
147     static bool MakeRecordAnnotations(panda_file::ItemContainer *items, const Program &program,
148                                       const AsmEntityCollections &entities);
149     static void SetCodeAndDebugInfo(panda_file::ItemContainer *items, panda_file::MethodItem *method,
150                                     const Function &func, bool emit_debug_info);
151     static bool AddMethodAndParamsAnnotations(panda_file::ItemContainer *items, const Program &program,
152                                               const AsmEmitter::AsmEntityCollections &entities,
153                                               panda_file::MethodItem *method, const Function &func);
154     static bool MakeFunctionDebugInfoAndAnnotations(panda_file::ItemContainer *items, const Program &program,
155                                                     const AsmEntityCollections &entities, bool emit_debug_info);
156     static void FillMap(PandaFileToPandaAsmMaps *maps, AsmEntityCollections &entities);
157     static void EmitDebugInfo(panda_file::ItemContainer *items, const Program &program,
158                               const std::vector<uint8_t> *bytes, const panda_file::MethodItem *method,
159                               const Function &func, const std::string &name, bool emit_debug_info);
160     static bool EmitFunctions(panda_file::ItemContainer *items, const Program &program,
161                               const AsmEntityCollections &entities, bool emit_debug_info);
162 
163     static panda_file::TypeItem *GetTypeItem(
164         panda_file::ItemContainer *items,
165         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
166         const Type &type, const Program &program);
167 
168     static bool MakeItemsForSingleProgram(panda_file::ItemContainer *items, const Program &program,
169         bool emit_debug_info, AsmEntityCollections &entities,
170         std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> primitive_types);
171 
172     static std::string GetMethodSignatureFromProgram(const std::string &name, const Program &program);
173 
174     static panda_file::LiteralItem *CreateLiteralItem(
175         panda_file::ItemContainer *container, const Value *value, 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, container);
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 Program &program, 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     static panda_file::ScalarValueItem *CreateScalarAnnotationValueItem(
220         panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out,
221         const Program &program, const AsmEmitter::AsmEntityCollections &entities);
222 
223     static panda_file::ScalarValueItem *CreateScalarValueItem(
224         panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out,
225         const Program &program, const AsmEmitter::AsmEntityCollections &entities);
226 
227     static panda_file::ValueItem *CreateValueItem(
228         panda_file::ItemContainer *container, const Value *value, const Program &program,
229         const AsmEmitter::AsmEntityCollections &entities);
230 
231     static panda_file::AnnotationItem *CreateAnnotationItem(
232         panda_file::ItemContainer *container, const AnnotationData &annotation, const Program &program,
233         const AsmEmitter::AsmEntityCollections &entities);
234 
235     static panda_file::MethodHandleItem *CreateMethodHandleItem(
236         panda_file::ItemContainer *container, const MethodHandle &mh,
237         const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
238         const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods);
239 
240     template <class T>
241     static bool AddAnnotations(T *item, panda_file::ItemContainer *container, const AnnotationMetadata &metadata,
242                                const Program &program, const AsmEmitter::AsmEntityCollections &entities);
243 
244     // TODO(mgonopolsky): Refactor to introduce a single error-processing mechanism for parser and emitter
245     static std::string last_error;
246 };
247 
248 std::string GetOwnerName(std::string name);
249 std::string GetItemName(std::string name);
250 
251 }  // namespace panda::pandasm
252 
253 #endif  // ASSEMBLER_ASSEMBLY_EMITTER_H
254