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