• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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 
32 namespace panda::pandasm {
33 
34 class AsmEmitter {
35 public:
36     struct PandaFileToPandaAsmMaps {
37         std::unordered_map<uint32_t, std::string> methods;
38         std::unordered_map<uint32_t, std::string> fields;
39         std::unordered_map<uint32_t, std::string> classes;
40         std::unordered_map<uint32_t, std::string> strings;
41         std::unordered_map<uint32_t, std::string> literalarrays;
42     };
43 
44     struct AsmEntityCollections {
45         std::unordered_map<std::string, panda_file::BaseMethodItem *> method_items;
46         std::unordered_map<std::string, panda_file::BaseFieldItem *> field_items;
47         std::unordered_map<std::string, panda_file::BaseClassItem *> class_items;
48         std::unordered_map<std::string_view, panda_file::StringItem *> string_items;
49         std::unordered_map<std::string, panda_file::LiteralArrayItem *> literalarray_items;
50     };
51 
52     static bool Emit(panda_file::ItemContainer *items, const Program &program, PandaFileToPandaAsmMaps *maps = nullptr,
53                      bool emit_debug_info = true);
54 
55     static bool Emit(panda_file::Writer *writer, const Program &program, std::map<std::string, size_t> *stat = nullptr,
56                      PandaFileToPandaAsmMaps *maps = nullptr, bool debug_info = true);
57 
58     static bool Emit(const std::string &filename, const Program &program, std::map<std::string, size_t> *stat = nullptr,
59                      PandaFileToPandaAsmMaps *maps = nullptr, bool debug_info = true);
60 
61     static std::unique_ptr<const panda_file::File> Emit(const Program &program,
62                                                         PandaFileToPandaAsmMaps *maps = nullptr);
63 
GetLastError()64     static std::string GetLastError()
65     {
66         return last_error;
67     }
68 
69 private:
70     static void MakeStringItems(panda_file::ItemContainer *items, const Program &program,
71                                 AsmEntityCollections &entities);
72     static void MakeLiteralItems(panda_file::ItemContainer *items, const Program &program,
73                                  AsmEmitter::AsmEntityCollections &entities);
74     static void MakeArrayTypeItems(panda_file::ItemContainer *items, const Program &program,
75                                    AsmEntityCollections &entities);
76     static bool HandleRecordAsForeign(
77         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
78         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
79         const std::string &name, const Record &rec);
80     static bool HandleBaseRecord(panda_file::ItemContainer *items, const Program &program, const std::string &name,
81                                  const Record &rec, panda_file::ClassItem *record);
82     static bool HandleInterfaces(panda_file::ItemContainer *items, const Program &program, const std::string &name,
83                                  const Record &rec, panda_file::ClassItem *record);
84     static bool HandleFields(
85         panda_file::ItemContainer *items, const Program &program, AsmEmitter::AsmEntityCollections &entities,
86         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
87         const std::string &name, const Record &rec, panda_file::ClassItem *record);
88     static bool HandleRecord(
89         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
90         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
91         const std::string &name, const Record &rec);
92     static bool MakeRecordItems(
93         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
94         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types);
95     static panda_file::StringItem *GetMethodName(panda_file::ItemContainer *items, const Function &func,
96                                                  const std::string &name);
97     static bool HandleAreaForInner(panda_file::ItemContainer *items, const Program &program,
98                                    panda_file::ClassItem **area, panda_file::ForeignClassItem **foreign_area,
99                                    const std::string &name, const std::string &record_owner_name);
100     static bool HandleRecordOnwer(panda_file::ItemContainer *items, const Program &program,
101                                   panda_file::ClassItem **area, panda_file::ForeignClassItem **foreign_area,
102                                   const std::string &name, const std::string &record_owner_name);
103     static bool HandleFunctionParams(
104         panda_file::ItemContainer *items, const Program &program, size_t idx, const std::string &name,
105         const Function &func,
106         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
107         std::vector<panda_file::MethodParamItem> &params);
108     static bool HandleFunctionLocalVariables(panda_file::ItemContainer *items, const Function &func,
109                                              const std::string &name);
110     static bool CreateMethodItem(panda_file::ItemContainer *items, AsmEmitter::AsmEntityCollections &entities,
111                                  const Function &func, panda_file::TypeItem *type_item, panda_file::ClassItem *area,
112                                  panda_file::ForeignClassItem *foreign_area, uint32_t access_flags,
113                                  panda_file::StringItem *method_name, const std::string &mangled_name,
114                                  const std::string &name, std::vector<panda_file::MethodParamItem> &params);
115     static bool MakeFunctionItems(
116         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
117         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
118         bool emit_debug_info);
119     static bool MakeRecordAnnotations(panda_file::ItemContainer *items, const Program &program,
120                                       const AsmEntityCollections &entities);
121     static void SetCodeAndDebugInfo(panda_file::ItemContainer *items, panda_file::MethodItem *method,
122                                     const Function &func, bool emit_debug_info);
123     static void SetMethodSourceLang(const Program &program, panda_file::MethodItem *method, const Function &func,
124                                     const std::string &name);
125     static bool AddMethodAndParamsAnnotations(panda_file::ItemContainer *items, const Program &program,
126                                               const AsmEmitter::AsmEntityCollections &entities,
127                                               panda_file::MethodItem *method, const Function &func);
128     static bool MakeFunctionDebugInfoAndAnnotations(panda_file::ItemContainer *items, const Program &program,
129                                                     const AsmEntityCollections &entities, bool emit_debug_info);
130     static void FillMap(PandaFileToPandaAsmMaps *maps, const AsmEntityCollections &entities);
131     static void EmitDebugInfo(panda_file::ItemContainer *items, const Program &program,
132                               const std::vector<uint8_t> *bytes, const panda_file::MethodItem *method,
133                               const Function &func, const std::string &name, bool emit_debug_info);
134     static bool EmitFunctions(panda_file::ItemContainer *items, const Program &program,
135                               const AsmEntityCollections &entities, bool emit_debug_info);
136 
137     static panda_file::TypeItem *GetTypeItem(
138         panda_file::ItemContainer *items,
139         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitive_types,
140         const Type &type, const Program &program);
141 
SetLastError(const std::string & message)142     static void SetLastError(const std::string &message)
143     {
144         last_error = message;
145     }
146 
147     static bool CheckValueType(Value::Type value_type, Type type, const Program &program);
148 
149     static bool CheckValueEnumCase(const Value *value, Type type, const Program &program);
150     static bool CheckValueArrayCase(const Value *value, Type type, const Program &program);
151     static bool CheckValueMethodCase(const Value *value, const Program &program);
152     static bool CheckValueRecordCase(const Value *value, const Program &program);
153     static bool CheckValue(const Value *value, Type type, const Program &program);
154 
155     static panda_file::LiteralItem *CreateLiteralItem(
156         panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::LiteralItem> *out,
157         const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods);
158 
159     template <class PrimType>
CreateScalarPrimValueItem(panda_file::ItemContainer * container,const Value * value,std::vector<panda_file::ScalarValueItem> * out)160     static panda_file::ScalarValueItem *CreateScalarPrimValueItem(panda_file::ItemContainer *container,
161                                                                   const Value *value,
162                                                                   std::vector<panda_file::ScalarValueItem> *out)
163     {
164         static_assert(std::is_arithmetic<PrimType>::value);
165         auto v = value->GetAsScalar()->GetValue<PrimType>();
166         if (out != nullptr) {
167             out->emplace_back(v);
168             return &out->back();
169         }
170 
171         if constexpr (std::is_same<PrimType, uint32_t>::value) {
172             return container->GetOrCreateIntegerValueItem(v);
173         } else if constexpr (std::is_same<PrimType, uint64_t>::value) {
174             return container->GetOrCreateLongValueItem(v);
175         } else if constexpr (std::is_same<PrimType, float>::value) {
176             return container->GetOrCreateFloatValueItem(v);
177         } else if constexpr (std::is_same<PrimType, double>::value) {
178             return container->GetOrCreateDoubleValueItem(v);
179         } else {
180             UNREACHABLE();
181             return nullptr;
182         }
183     }
184 
185     static panda_file::ScalarValueItem *CreateScalarStringValueItem(panda_file::ItemContainer *container,
186                                                                     const Value *value,
187                                                                     std::vector<panda_file::ScalarValueItem> *out);
188     static panda_file::ScalarValueItem *CreateScalarRecordValueItem(
189         panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out,
190         const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes);
191     static panda_file::ScalarValueItem *CreateScalarMethodValueItem(
192         panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out,
193         const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods);
194     static panda_file::ScalarValueItem *CreateScalarEnumValueItem(
195         panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out,
196         const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields);
197     static panda_file::ScalarValueItem *CreateScalarAnnotationValueItem(
198         panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out,
199         const Program &program, const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
200         const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
201         const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods);
202 
203     static panda_file::ScalarValueItem *CreateScalarValueItem(
204         panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out,
205         const Program &program, const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
206         const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
207         const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods);
208 
209     static panda_file::ValueItem *CreateValueItem(
210         panda_file::ItemContainer *container, const Value *value, const Program &program,
211         const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
212         const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
213         const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods);
214 
215     static panda_file::AnnotationItem *CreateAnnotationItem(
216         panda_file::ItemContainer *container, const AnnotationData &annotation, const Program &program,
217         const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
218         const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
219         const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods);
220 
221     static panda_file::MethodHandleItem *CreateMethodHandleItem(
222         panda_file::ItemContainer *container, const MethodHandle &mh,
223         const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
224         const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods);
225 
226     template <class T>
227     static bool AddAnnotations(T *item, panda_file::ItemContainer *container, const AnnotationMetadata &metadata,
228                                const Program &program,
229                                const std::unordered_map<std::string, panda_file::BaseClassItem *> &classes,
230                                const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
231                                const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods);
232 
233     static std::string last_error;
234 };
235 
236 std::string GetOwnerName(const std::string &name);
237 std::string GetItemName(const std::string &name);
238 
239 }  // namespace panda::pandasm
240 
241 #endif  // PANDA_ASSEMBLER_ASSEMBLY_EMITTER_H_
242