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