• 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     // CC-OFFNXT(G.FUN.01-CPP) solid logic
58     PANDA_PUBLIC_API static bool Emit(panda_file::Writer *writer, const Program &program,
59                                       std::map<std::string, size_t> *stat = nullptr,
60                                       PandaFileToPandaAsmMaps *maps = nullptr, bool debugInfo = true,
61                                       ark::panda_file::pgo::ProfileOptimizer *profileOpt = nullptr);
62 
63     // CC-OFFNXT(G.FUN.01-CPP) solid logic
64     PANDA_PUBLIC_API static bool Emit(const std::string &filename, const Program &program,
65                                       std::map<std::string, size_t> *stat = nullptr,
66                                       PandaFileToPandaAsmMaps *maps = nullptr, bool debugInfo = true,
67                                       ark::panda_file::pgo::ProfileOptimizer *profileOpt = nullptr);
68 
69     PANDA_PUBLIC_API static std::unique_ptr<const panda_file::File> Emit(const Program &program,
70                                                                          PandaFileToPandaAsmMaps *maps = nullptr);
71 
72     PANDA_PUBLIC_API static bool AssignProfileInfo(Program *program);
73 
GetLastError()74     PANDA_PUBLIC_API static std::string GetLastError()
75     {
76         return lastError_;
77     }
78 
79 private:
80     static void MakeStringItems(panda_file::ItemContainer *items, const Program &program,
81                                 AsmEntityCollections &entities);
82     static void MakeLiteralItems(panda_file::ItemContainer *items, const Program &program,
83                                  AsmEmitter::AsmEntityCollections &entities);
84     static void MakeArrayTypeItems(panda_file::ItemContainer *items, const Program &program,
85                                    AsmEntityCollections &entities);
86     // CC-OFFNXT(G.FUN.01-CPP) solid logic
87     static bool HandleRecordAsForeign(
88         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
89         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes,
90         const std::string &name, const Record &rec);
91     static bool HandleBaseRecord(panda_file::ItemContainer *items, const Program &program, const std::string &name,
92                                  const Record &rec, panda_file::ClassItem *record);
93     static bool HandleInterfaces(panda_file::ItemContainer *items, const Program &program, const std::string &name,
94                                  const Record &rec, panda_file::ClassItem *record);
95     // CC-OFFNXT(G.FUN.01-CPP) solid logic
96     static bool HandleFields(
97         panda_file::ItemContainer *items, const Program &program, AsmEmitter::AsmEntityCollections &entities,
98         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes,
99         const std::string &name, const Record &rec, panda_file::ClassItem *record);
100     // CC-OFFNXT(G.FUN.01-CPP) solid logic
101     static bool HandleRecord(
102         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
103         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes,
104         const std::string &name, const Record &rec);
105     static bool MakeRecordItems(
106         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
107         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes);
108     static panda_file::StringItem *GetMethodName(panda_file::ItemContainer *items, const Function &func,
109                                                  const std::string &name);
110     // CC-OFFNXT(G.FUN.01-CPP) solid logic
111     static bool HandleAreaForInner(panda_file::ItemContainer *items, const Program &program,
112                                    panda_file::ClassItem **area, panda_file::ForeignClassItem **foreignArea,
113                                    const std::string &name, const std::string &recordOwnerName);
114     // CC-OFFNXT(G.FUN.01-CPP) solid logic
115     static bool HandleRecordOnwer(panda_file::ItemContainer *items, const Program &program,
116                                   panda_file::ClassItem **area, panda_file::ForeignClassItem **foreignArea,
117                                   const std::string &name, const std::string &recordOwnerName);
118     // CC-OFFNXT(G.FUN.01-CPP) solid logic
119     static bool HandleFunctionParams(
120         panda_file::ItemContainer *items, const Program &program, size_t idx, const std::string &name,
121         const Function &func,
122         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes,
123         std::vector<panda_file::MethodParamItem> &params);
124     static bool HandleFunctionLocalVariables(panda_file::ItemContainer *items, const Function &func,
125                                              const std::string &name);
126     // CC-OFFNXT(G.FUN.01-CPP) solid logic
127     static bool CreateMethodItem(panda_file::ItemContainer *items, AsmEmitter::AsmEntityCollections &entities,
128                                  const Function &func, panda_file::TypeItem *typeItem, panda_file::ClassItem *area,
129                                  panda_file::ForeignClassItem *foreignArea, uint32_t accessFlags,
130                                  panda_file::StringItem *methodName, const std::string &mangledName,
131                                  const std::string &name, std::vector<panda_file::MethodParamItem> &params);
132     static bool MakeFunctionItems(
133         panda_file::ItemContainer *items, const Program &program, AsmEntityCollections &entities,
134         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes,
135         bool emitDebugInfo);
136     static bool MakeRecordAnnotations(panda_file::ItemContainer *items, const Program &program,
137                                       const AsmEntityCollections &entities);
138     static void SetCodeAndDebugInfo(panda_file::ItemContainer *items, panda_file::MethodItem *method,
139                                     const Function &func, bool emitDebugInfo);
140     static void SetMethodSourceLang(const Program &program, panda_file::MethodItem *method, const Function &func,
141                                     const std::string &name);
142     static bool AddMethodAndParamsAnnotations(panda_file::ItemContainer *items, const Program &program,
143                                               const AsmEmitter::AsmEntityCollections &entities,
144                                               panda_file::MethodItem *method, const Function &func);
145     static bool MakeFunctionDebugInfoAndAnnotations(panda_file::ItemContainer *items, const Program &program,
146                                                     const AsmEntityCollections &entities, bool emitDebugInfo);
147     static void FillMap(PandaFileToPandaAsmMaps *maps, AsmEntityCollections &entities);
148     // CC-OFFNXT(G.FUN.01-CPP) solid logic
149     static void EmitDebugInfo(panda_file::ItemContainer *items, const Program &program,
150                               const std::vector<uint8_t> *bytes, const panda_file::MethodItem *method,
151                               const Function &func, const std::string &name, bool emitDebugInfo);
152     static bool EmitFunctions(panda_file::ItemContainer *items, const Program &program,
153                               const AsmEntityCollections &entities, bool emitDebugInfo);
154 
155     static panda_file::TypeItem *GetTypeItem(
156         panda_file::ItemContainer *items,
157         const std::unordered_map<panda_file::Type::TypeId, panda_file::PrimitiveTypeItem *> &primitiveTypes,
158         const Type &type, const Program &program);
159 
SetLastError(const std::string & message)160     PANDA_PUBLIC_API static void SetLastError(const std::string &message)
161     {
162         lastError_ = message;
163     }
164 
165     static bool CheckValueType(Value::Type valueType, const Type &type, const Program &program);
166 
167     static bool CheckValueEnumCase(const Value *value, const Type &type, const Program &program);
168     static bool CheckValueArrayCase(const Value *value, const Type &type, const Program &program);
169     static bool CheckValueMethodCase(const Value *value, const Program &program);
170     static bool CheckValueRecordCase(const Value *value, const Program &program);
171     static bool CheckValue(const Value *value, const Type &type, const Program &program);
172     static std::string GetMethodSignatureFromProgram(const std::string &name, const Program &program);
173 
174     static panda_file::LiteralItem *CreateLiteralItem(panda_file::ItemContainer *container, const Value *value,
175                                                       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);
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 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     // CC-OFFNXT(G.FUN.01-CPP) solid logic
220     static panda_file::ScalarValueItem *CreateScalarAnnotationValueItem(
221         panda_file::ItemContainer *container, const Value *value, std::vector<panda_file::ScalarValueItem> *out,
222         const Program &program, const AsmEmitter::AsmEntityCollections &entities);
223 
224     // CC-OFFNXT(G.FUN.01-CPP) solid logic
225     static panda_file::ScalarValueItem *CreateScalarValueItem(panda_file::ItemContainer *container, const Value *value,
226                                                               std::vector<panda_file::ScalarValueItem> *out,
227                                                               const Program &program,
228                                                               const AsmEmitter::AsmEntityCollections &entities);
229 
230     // CC-OFFNXT(G.FUN.01-CPP) solid logic
231     static panda_file::ValueItem *CreateValueItem(panda_file::ItemContainer *container, const Value *value,
232                                                   const Program &program,
233                                                   const AsmEmitter::AsmEntityCollections &entities);
234 
235     // CC-OFFNXT(G.FUN.01-CPP) solid logic
236     static panda_file::AnnotationItem *CreateAnnotationItem(panda_file::ItemContainer *container,
237                                                             const AnnotationData &annotation, const Program &program,
238                                                             const AsmEmitter::AsmEntityCollections &entities);
239 
240     static panda_file::MethodHandleItem *CreateMethodHandleItem(
241         panda_file::ItemContainer *container, const MethodHandle &mh,
242         const std::unordered_map<std::string, panda_file::BaseFieldItem *> &fields,
243         const std::unordered_map<std::string, panda_file::BaseMethodItem *> &methods);
244 
245     template <class T>
246     // CC-OFFNXT(G.FUN.01-CPP) solid logic
247     static bool AddAnnotations(T *item, panda_file::ItemContainer *container, const AnnotationMetadata &metadata,
248                                const Program &program, const AsmEmitter::AsmEntityCollections &entities);
249 
250     // NOTE(mgonopolsky): Refactor to introduce a single error-processing mechanism for parser and emitter
251     // NOLINTNEXTLINE(fuchsia-statically-constructed-objects)
252     PANDA_PUBLIC_API static std::string lastError_;
253 };
254 
255 std::string GetOwnerName(std::string name);
256 std::string GetItemName(std::string name);
257 
258 }  // namespace ark::pandasm
259 
260 #endif  // PANDA_ASSEMBLER_ASSEMBLY_EMITTER_H
261