• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 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 #include "libabckit/include/c/metadata_core.h"
17 #include "libabckit/src/adapter_dynamic/abckit_dynamic.h"
18 #include "libabckit/src/adapter_dynamic/convert.h"
19 #include "libabckit/src/adapter_dynamic/helpers_dynamic.h"
20 #include "libabckit/src/helpers_common.h"
21 #include "libabckit/src/logger.h"
22 #include "libabckit/src/statuses_impl.h"
23 #include "libabckit/src/ir_impl.h"
24 #include "libabckit/src/metadata_inspect_impl.h"
25 #include "libabckit/src/wrappers/graph_wrapper/graph_wrapper.h"
26 #include "libabckit/src/adapter_dynamic/metadata_modify_dynamic.h"
27 
28 #include "abc2program/abc2program_driver.h"
29 #include "assembler/annotation.h"
30 #include "assembler/assembly-program.h"
31 #include "assembler/assembly-function.h"
32 #include "assembler/assembly-record.h"
33 #include "assembler/assembly-emitter.h"
34 #include "libpandabase/os/filesystem.h"
35 #include "libpandafile/file.h"
36 
37 #include <cstdint>
38 #include <cstring>
39 #include <string>
40 #include <type_traits>
41 
42 #if __has_include(<filesystem>)
43 #include <filesystem>
44 namespace fs = std::filesystem;
45 #elif __has_include(<experimental/filesystem>)
46 #include <experimental/filesystem>
47 #define STD_FILESYSTEM_EXPERIMENTAL
48 namespace fs = std::experimental::filesystem;
49 #endif
50 
51 // NOLINTNEXTLINE(google-build-using-namespace)
52 using namespace panda;
53 // CC-OFFNXT(WordsTool.95) sensitive word conflict
54 // NOLINTNEXTLINE(google-build-using-namespace)
55 using namespace libabckit;
56 
57 namespace {
58 
PandaTypeToAbcKitTypeId(const pandasm::Type & type)59 AbckitTypeId PandaTypeToAbcKitTypeId(const pandasm::Type &type)
60 {
61     switch (type.GetId()) {
62         case panda_file::Type::TypeId::VOID:
63             return ABCKIT_TYPE_ID_VOID;
64         case panda_file::Type::TypeId::U1:
65             return ABCKIT_TYPE_ID_U1;
66         case panda_file::Type::TypeId::I8:
67             return ABCKIT_TYPE_ID_I8;
68         case panda_file::Type::TypeId::U8:
69             return ABCKIT_TYPE_ID_U8;
70         case panda_file::Type::TypeId::I16:
71             return ABCKIT_TYPE_ID_I16;
72         case panda_file::Type::TypeId::U16:
73             return ABCKIT_TYPE_ID_U16;
74         case panda_file::Type::TypeId::I32:
75             return ABCKIT_TYPE_ID_I32;
76         case panda_file::Type::TypeId::U32:
77             return ABCKIT_TYPE_ID_U32;
78         case panda_file::Type::TypeId::F32:
79             return ABCKIT_TYPE_ID_F32;
80         case panda_file::Type::TypeId::F64:
81             return ABCKIT_TYPE_ID_F64;
82         case panda_file::Type::TypeId::I64:
83             return ABCKIT_TYPE_ID_I64;
84         case panda_file::Type::TypeId::U64:
85             return ABCKIT_TYPE_ID_U64;
86         case panda_file::Type::TypeId::REFERENCE:
87             if (type.IsArray()) {
88                 return PandaTypeToAbcKitTypeId(type.GetComponentType());
89             }
90             return ABCKIT_TYPE_ID_REFERENCE;
91         default:
92             return AbckitTypeId::ABCKIT_TYPE_ID_INVALID;
93     }
94 }
95 
CreateNameString(std::string & name,AbckitFile * file)96 AbckitString *CreateNameString(std::string &name, AbckitFile *file)
97 {
98     return CreateStringDynamic(file, name.data(), name.size());
99 }
100 
TryFindModule(const std::string & name,AbckitFile * file)101 AbckitCoreModule *TryFindModule(const std::string &name, AbckitFile *file)
102 {
103     auto tryFindLocal = file->localModules.find(name);
104     if (tryFindLocal != file->localModules.end()) {
105         return tryFindLocal->second.get();
106     }
107     auto tryFindExternal = file->externalModules.find(name);
108     if (tryFindExternal != file->externalModules.end()) {
109         return tryFindExternal->second.get();
110     }
111     return nullptr;
112 }
113 
GetModuleRequestName(uint16_t moduleRequestsOffset,const pandasm::LiteralArray * litArr)114 std::string GetModuleRequestName(uint16_t moduleRequestsOffset, const pandasm::LiteralArray *litArr)
115 {
116     ASSERT(litArr->literals_[moduleRequestsOffset + 1].IsStringValue());
117     std::string name = std::get<std::string>(litArr->literals_[moduleRequestsOffset + 1].value_);
118     if (name.substr(0, 2U) == "./") {
119         std::string newName = name.substr(2U);
120         return newName;
121     }
122     return name;
123 }
124 
FillExportDescriptor(ModuleIterateData * data,uint16_t idx,size_t recordIndexOff,bool hasServiceImport=false,size_t serviceNamespaceImportIdx=0)125 bool FillExportDescriptor(ModuleIterateData *data, uint16_t idx, size_t recordIndexOff, bool hasServiceImport = false,
126                           size_t serviceNamespaceImportIdx = 0)
127 {
128     auto ed = std::make_unique<AbckitCoreExportDescriptor>();
129     switch (data->m->target) {
130         case ABCKIT_TARGET_JS:
131             ed->impl = std::make_unique<AbckitJsExportDescriptor>();
132             ed->GetJsImpl()->core = ed.get();
133             ed->GetJsImpl()->kind = AbckitImportExportDescriptorKind::UNTYPED;
134             break;
135         case ABCKIT_TARGET_ARK_TS_V1:
136             ed->impl = std::make_unique<AbckitArktsExportDescriptor>();
137             ed->GetArkTSImpl()->core = ed.get();
138             ed->GetArkTSImpl()->kind = AbckitImportExportDescriptorKind::UNTYPED;
139             break;
140         default:
141             LIBABCKIT_UNREACHABLE;
142     }
143     ed->exportingModule = data->m;
144     if (data->kind == ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT) {
145         ed->exportedModule = data->m;
146     } else {
147         auto moduleRequestIdx = std::get<uint16_t>(data->moduleLitArr->literals_[idx].value_);
148         auto exportedModuleName = GetModuleRequestName(moduleRequestIdx, data->moduleLitArr);
149         auto tryFindModule = TryFindModule(exportedModuleName, data->m->file);
150         ed->exportedModule = tryFindModule;
151     }
152     auto payloadDyn = AbckitDynamicExportDescriptorPayload();
153     payloadDyn.kind = data->kind;
154     payloadDyn.hasServiceImport = hasServiceImport;
155     payloadDyn.serviceNamespaceImportIdx = serviceNamespaceImportIdx;
156     payloadDyn.moduleRecordIndexOff = recordIndexOff;
157     auto payload = AbckitCoreExportDescriptorPayload();
158     payload.impl = payloadDyn;
159     switch (data->m->target) {
160         case ABCKIT_TARGET_JS:
161             ed->GetJsImpl()->payload = payload;
162             break;
163         case ABCKIT_TARGET_ARK_TS_V1:
164             ed->GetArkTSImpl()->payload = payload;
165             break;
166         default:
167             LIBABCKIT_UNREACHABLE;
168     }
169     data->m->ed.push_back(std::move(ed));
170     return true;
171 }
172 
SetIdImpl(ModuleIterateData * data,std::unique_ptr<AbckitCoreImportDescriptor> & id)173 void SetIdImpl(ModuleIterateData *data, std::unique_ptr<AbckitCoreImportDescriptor> &id)
174 {
175     switch (data->m->target) {
176         case ABCKIT_TARGET_JS:
177             id->impl = std::make_unique<AbckitJsImportDescriptor>();
178             id->GetJsImpl()->core = id.get();
179             break;
180         case ABCKIT_TARGET_ARK_TS_V1:
181             id->impl = std::make_unique<AbckitArktsImportDescriptor>();
182             id->GetArkTSImpl()->core = id.get();
183             break;
184         default:
185             LIBABCKIT_UNREACHABLE;
186     }
187 }
188 
SetIdModule(ModuleIterateData * data,std::unique_ptr<AbckitCoreImportDescriptor> & id,uint16_t moduleRequestIdx)189 void SetIdModule(ModuleIterateData *data, std::unique_ptr<AbckitCoreImportDescriptor> &id, uint16_t moduleRequestIdx)
190 {
191     id->importingModule = data->m;
192     auto importedModuleName = GetModuleRequestName(moduleRequestIdx, data->moduleLitArr);
193     id->importedModule = TryFindModule(importedModuleName, data->m->file);
194     switch (data->m->target) {
195         case ABCKIT_TARGET_JS:
196             id->GetJsImpl()->kind = AbckitImportExportDescriptorKind::UNTYPED;
197             break;
198         case ABCKIT_TARGET_ARK_TS_V1:
199             id->GetArkTSImpl()->kind = AbckitImportExportDescriptorKind::UNTYPED;
200             break;
201         default:
202             LIBABCKIT_UNREACHABLE;
203     }
204 }
205 
SetRegularImport(ModuleIterateData * data,size_t * idx,size_t & fieldNum,size_t * importRecordIndexOff,size_t * recordIndexOff,bool * skipFilling)206 bool SetRegularImport(ModuleIterateData *data, size_t *idx, size_t &fieldNum, size_t *importRecordIndexOff,
207                       size_t *recordIndexOff, bool *skipFilling)
208 {
209     for (size_t i = 0; i < (fieldNum - 1); i++) {
210         auto name = std::get<std::string>(data->moduleLitArr->literals_[(*idx)++].value_);
211         if ((i == 0) && !(data->isRegularImport.second) && (name.find("=ens") != std::string::npos)) {
212             auto tmp = data->isRegularImport.second;
213             data->isRegularImport.second = false;
214             data->kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_STAR_EXPORT;
215             if (!FillExportDescriptor(data, (*idx)++, (*importRecordIndexOff)++, true, *recordIndexOff)) {
216                 return true;
217             }
218             data->isRegularImport.second = tmp;
219             *skipFilling = true;
220             (*recordIndexOff)++;
221             break;
222         }
223     }
224     return false;
225 }
226 
FillImportSection(ModuleIterateData * data,size_t idx,size_t fieldNum)227 std::pair<size_t, size_t> FillImportSection(ModuleIterateData *data, size_t idx, size_t fieldNum)
228 {
229     size_t recordIndexOff = 0;
230     size_t importRecordIndexOff = 0;
231     size_t numImports = std::get<uint32_t>(data->moduleLitArr->literals_[idx++].value_);
232     size_t sectionOffset = idx;
233     bool skipFilling = false;
234     while (idx < sectionOffset + numImports * fieldNum) {
235         if (SetRegularImport(data, &idx, fieldNum, &importRecordIndexOff, &recordIndexOff, &skipFilling)) {
236             return {0, 0};
237         }
238         if (skipFilling) {
239             skipFilling = false;
240             continue;
241         }
242         auto id = std::make_unique<AbckitCoreImportDescriptor>();
243         SetIdImpl(data, id);
244         auto moduleRequestIdx = std::get<uint16_t>(data->moduleLitArr->literals_[idx++].value_);
245         SetIdModule(data, id, moduleRequestIdx);
246 
247         auto payloadDyn = AbckitDynamicImportDescriptorPayload();
248         payloadDyn.isRegularImport = data->isRegularImport.second;
249         payloadDyn.moduleRecordIndexOff = recordIndexOff++;
250         auto payload = AbckitCoreImportDescriptorPayload();
251         payload.impl = payloadDyn;
252         switch (data->m->target) {
253             case ABCKIT_TARGET_JS:
254                 id->GetJsImpl()->payload = payload;
255                 break;
256             case ABCKIT_TARGET_ARK_TS_V1:
257                 id->GetArkTSImpl()->payload = payload;
258                 break;
259             default:
260                 LIBABCKIT_UNREACHABLE;
261         }
262         data->m->id.push_back(std::move(id));
263     }
264 
265     return {idx, sectionOffset};
266 }
267 
FindJSTarget(const std::unique_ptr<AbckitCoreExportDescriptor> & ed,ModuleIterateData * data,const std::string & serviceName)268 bool FindJSTarget(const std::unique_ptr<AbckitCoreExportDescriptor> &ed, ModuleIterateData *data,
269                   const std::string &serviceName)
270 {
271     if (ed->GetJsImpl()->payload.GetDynamicPayload().hasServiceImport) {
272         auto offset = data->payload->namespaceImportsOffset +
273                       ed->GetJsImpl()->payload.GetDynamicPayload().serviceNamespaceImportIdx * 2;
274         auto namespaceLocalName = std::get<std::string>(data->moduleLitArr->literals_[offset].value_);
275         if (serviceName == namespaceLocalName) {
276             return true;
277         }
278     }
279     return false;
280 }
281 
FindTSTarget(const std::unique_ptr<AbckitCoreExportDescriptor> & ed,ModuleIterateData * data,const std::string & serviceName)282 bool FindTSTarget(const std::unique_ptr<AbckitCoreExportDescriptor> &ed, ModuleIterateData *data,
283                   const std::string &serviceName)
284 {
285     if (ed->GetArkTSImpl()->payload.GetDynamicPayload().hasServiceImport) {
286         auto offset = data->payload->namespaceImportsOffset +
287                       ed->GetArkTSImpl()->payload.GetDynamicPayload().serviceNamespaceImportIdx * 2;
288         auto namespaceLocalName = std::get<std::string>(data->moduleLitArr->literals_[offset].value_);
289         if (serviceName == namespaceLocalName) {
290             return true;
291         }
292     }
293     return false;
294 }
295 
FindStarExport(ModuleIterateData * data,const std::string & serviceName)296 AbckitCoreExportDescriptor *FindStarExport(ModuleIterateData *data, const std::string &serviceName)
297 {
298     for (const auto &ed : data->m->ed) {
299         switch (ed->exportingModule->target) {
300             case ABCKIT_TARGET_JS:
301                 if (FindJSTarget(ed, data, serviceName)) {
302                     return ed.get();
303                 }
304                 break;
305             case ABCKIT_TARGET_ARK_TS_V1:
306                 if (FindTSTarget(ed, data, serviceName)) {
307                     return ed.get();
308                 }
309                 break;
310             default:
311                 LIBABCKIT_UNREACHABLE;
312         }
313     }
314     LIBABCKIT_LOG(DEBUG) << "Appropriate StarExport was not found for service namespace import '" << serviceName << "'"
315                          << std::endl;
316     libabckit::statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
317     return nullptr;
318 }
319 
SetRecordIndexOff(size_t & i,ModuleIterateData * data,std::basic_string<char> & name,size_t * recordIndexOff,bool * skipFilling)320 bool SetRecordIndexOff(size_t &i, ModuleIterateData *data, std::basic_string<char> &name, size_t *recordIndexOff,
321                        bool *skipFilling)
322 {
323     if ((i == 0) && (data->kind == ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT) &&
324         (name.find("=ens") != std::string::npos)) {
325         auto *starExport = FindStarExport(data, name);
326         switch (starExport->exportingModule->target) {
327             case ABCKIT_TARGET_JS: {
328                 starExport->GetJsImpl()->payload.GetDynamicPayload().moduleRecordIndexOff = (*recordIndexOff)++;
329                 break;
330             }
331             case ABCKIT_TARGET_ARK_TS_V1: {
332                 starExport->GetArkTSImpl()->payload.GetDynamicPayload().moduleRecordIndexOff = (*recordIndexOff)++;
333                 break;
334             }
335             default:
336                 LIBABCKIT_UNREACHABLE;
337         }
338         *skipFilling = true;
339         return true;
340     }
341     return false;
342 }
343 
FillExportSection(ModuleIterateData * data,size_t idx,size_t fieldNum)344 std::pair<size_t, size_t> FillExportSection(ModuleIterateData *data, size_t idx, size_t fieldNum)
345 {
346     size_t recordIndexOff = 0;
347     size_t numExports = std::get<uint32_t>(data->moduleLitArr->literals_[idx++].value_);
348     size_t sectionOffset = idx;
349     bool skipFilling = false;
350     while (idx < sectionOffset + numExports * fieldNum) {
351         for (size_t i = 0; i < (fieldNum - 1); i++) {
352             auto name = std::get<std::string>(data->moduleLitArr->literals_[idx++].value_);
353             if (SetRecordIndexOff(i, data, name, &recordIndexOff, &skipFilling)) {
354                 break;
355             }
356         }
357         if (skipFilling) {
358             skipFilling = false;
359             idx++;
360             continue;
361         }
362         if (!FillExportDescriptor(data, idx++, recordIndexOff++)) {
363             return {0, 0};
364         }
365     }
366 
367     return {idx, sectionOffset};
368 }
369 
FillRequestIdxSection(ModuleIterateData * data)370 size_t FillRequestIdxSection(ModuleIterateData *data)
371 {
372     auto *file = data->m->file;
373     size_t idx = 0;
374     auto numModuleRequests = std::get<uint32_t>(data->moduleLitArr->literals_[idx++].value_);
375     data->payload->moduleRequestsOffset = idx;
376     auto moduleBasePath = fs::path("./" + std::string(data->m->moduleName->impl)).remove_filename().string();
377     while (idx < data->payload->moduleRequestsOffset + numModuleRequests) {
378         auto relativePathStr = std::get<std::string>(data->moduleLitArr->literals_[idx].value_);
379         if (relativePathStr[0] == '@') {
380             data->moduleLitArr->literals_[idx++].value_ = relativePathStr;
381             data->m->md.push_back(TryFindModule(relativePathStr, file));
382         } else {
383 #ifdef STD_FILESYSTEM_EXPERIMENTAL
384             auto moduleAbsPath = fs::absolute(fs::path(moduleBasePath).append(relativePathStr));
385 #else
386             auto moduleAbsPath = fs::weakly_canonical(fs::path(moduleBasePath).append(relativePathStr));
387 #endif
388             auto moduleName = Relative(moduleAbsPath, fs::current_path()).string();
389             data->moduleLitArr->literals_[idx++].value_ = fs::path("./").append(moduleName).string();
390             data->m->md.push_back(TryFindModule(moduleName, file));
391         }
392     }
393     return idx;
394 }
395 
FillLiteralArraySection(ModuleIterateData * data,size_t idx,size_t fieldNum)396 std::pair<size_t, size_t> FillLiteralArraySection(ModuleIterateData *data, size_t idx, size_t fieldNum)
397 {
398     if (data->isRegularImport.first) {
399         return FillImportSection(data, idx, fieldNum);
400     }
401     return FillExportSection(data, idx, fieldNum);
402 }
403 
GetRecordFieldValue(const pandasm::Record * rec,const std::string & fieldName)404 std::string GetRecordFieldValue(const pandasm::Record *rec, const std::string &fieldName)
405 {
406     for (const auto &field : rec->field_list) {
407         if (field.name == fieldName) {
408             return field.metadata->GetValue()->GetAsScalar()->GetValue<std::string>();
409         }
410     }
411     LIBABCKIT_LOG(DEBUG) << "'" << fieldName << "' field was not found for record " << rec->name << std::endl;
412     LIBABCKIT_UNREACHABLE;
413 }
414 
GetLiteralArray(const pandasm::Program * prog,const std::string & arrName)415 pandasm::LiteralArray *GetLiteralArray(const pandasm::Program *prog, const std::string &arrName)
416 {
417     auto it = prog->literalarray_table.find(arrName);
418     if (it != prog->literalarray_table.end()) {
419         return const_cast<pandasm::LiteralArray *>(&it->second);
420     }
421     LIBABCKIT_LOG(DEBUG) << "'" << arrName << "' array was not found in program" << std::endl;
422     LIBABCKIT_UNREACHABLE;
423 }
424 
CreateModuleImpl(AbckitCoreModule * m)425 void CreateModuleImpl(AbckitCoreModule *m)
426 {
427     switch (m->target) {
428         case ABCKIT_TARGET_JS:
429             m->impl = std::make_unique<AbckitJsModule>();
430             m->GetJsImpl()->core = m;
431             break;
432         case ABCKIT_TARGET_ARK_TS_V1:
433             m->impl = std::make_unique<AbckitArktsModule>();
434             m->GetArkTSImpl()->core = m;
435             break;
436         default:
437             LIBABCKIT_UNREACHABLE;
438     }
439     LIBABCKIT_LOG(DEBUG) << m->moduleName->impl << std::endl;
440 }
441 
CreateModule(pandasm::Program * prog,const pandasm::Record * record,AbckitFile * file)442 std::unique_ptr<AbckitCoreModule> CreateModule(pandasm::Program *prog, const pandasm::Record *record, AbckitFile *file)
443 {
444     auto m = std::make_unique<AbckitCoreModule>();
445     m->file = file;
446     m->moduleName = CreateStringDynamic(file, record->name.data(), record->name.size());
447     m->target = convert::ToTargetDynamic(record->language);
448     LIBABCKIT_LOG(DEBUG) << "name=" << m->moduleName << " target=" << convert::ToString(m->target)
449                          << " lang=" << record->language << "\n";
450 
451     CreateModuleImpl(m.get());
452 
453     auto modulePayloadDyn = AbckitModulePayloadDyn();
454     modulePayloadDyn.record = record;
455 
456     pandasm::LiteralArray *moduleLitArr = GetLiteralArray(prog, GetRecordFieldValue(record, "moduleRecordIdx"));
457     LIBABCKIT_LOG_DUMP(DumpModuleArray(moduleLitArr, m->moduleName->impl), DEBUG);
458     auto moduleLiteralArray = std::make_unique<AbckitLiteralArray>(file, moduleLitArr);
459     modulePayloadDyn.moduleLiteralArray = file->litarrs.emplace_back(std::move(moduleLiteralArray)).get();
460 
461     auto scopeNamesLiteralArray =
462         std::make_unique<AbckitLiteralArray>(file, GetLiteralArray(prog, GetRecordFieldValue(record, "scopeNames")));
463     modulePayloadDyn.scopeNamesLiteralArray = file->litarrs.emplace_back(std::move(scopeNamesLiteralArray)).get();
464 
465     ModuleIterateData iterData;
466     iterData.m = m.get();
467     iterData.payload = &modulePayloadDyn;
468     iterData.moduleLitArr = moduleLitArr;
469 
470     auto res = IterateModuleSections(
471         iterData, FillRequestIdxSection, FillLiteralArraySection,
472         [](ModuleIterateData * /*data*/, std::pair<size_t, size_t> res) { return res.first != 0; });
473     if (!res) {
474         return nullptr;
475     }
476 
477     modulePayloadDyn.absPaths = true;
478     switch (m->target) {
479         case ABCKIT_TARGET_JS:
480             m->GetJsImpl()->impl = modulePayloadDyn;
481             break;
482         case ABCKIT_TARGET_ARK_TS_V1:
483             m->GetArkTSImpl()->impl.impl = modulePayloadDyn;
484             break;
485         default:
486             LIBABCKIT_UNREACHABLE;
487     }
488     return m;
489 }
490 
IsNamespaceFunc(const std::string & name)491 bool IsNamespaceFunc(const std::string &name)
492 {
493     return name.find("&#") != std::string::npos;
494 }
495 
496 enum class ParentKind {
497     MODULE,
498     NAMESPACE,
499     CLASS,
500     FUNCTION,
501 };
502 
503 /*
504  * For example:
505  * - @1 -> M0N0
506  * - A -> A
507  */
DemangleScope(const std::string & mangledName,const AbckitLiteralArray * scopeNames,bool isClass)508 std::string DemangleScope(const std::string &mangledName, const AbckitLiteralArray *scopeNames, bool isClass)
509 {
510     if (mangledName.empty()) {
511         return mangledName;
512     }
513 
514     if (mangledName[0] != '@') {
515         if (isClass) {
516             size_t caretPos = mangledName.find('^');
517             if (caretPos != std::string::npos) {
518                 return mangledName.substr(0, caretPos);
519             }
520         }
521         return mangledName;
522     }
523 
524     const int base = 16;
525     size_t scopeIdx = std::stoul(mangledName.substr(1, mangledName.size() - 1), nullptr, base);
526     auto *litArr = scopeNames->GetDynamicImpl();
527     const size_t two = 2;
528     ASSERT(litArr->literals_.size() % two == 0);
529     size_t litIdx = scopeIdx * two + 1;
530     ASSERT(litIdx < litArr->literals_.size());
531     auto &lit = litArr->literals_[litIdx];
532     ASSERT(lit.tag_ == panda_file::LiteralTag::STRING);
533     return std::get<std::string>(lit.value_);
534 }
535 
536 /*
537  * This function consumes full mangled name and returns full parent name, for example:
538  * - module.#&@2&A&B~C>D*E*#F -> module.#&@2&A&B~C>D*#E
539  * - module.#&@2&A&B~C>D*#E -> module.#&@2&A&B~C>#D
540  * - module.#&@2&A&B~C>#D -> module.#&@2&A&B~C=#C
541  * - module.#&@2&A&B~C=#C -> module.#&@2&A&#B
542  * - module.#&@2&A&#B -> module.#&@2&#A
543  * - module.#&@2&#A -> module.#&#M0N0
544  * - module.#&#M0N0 -> module
545  * NOTE: There is single function name for both constructor and class (for example "module.#~C=#C")
546  *       For class parent is scope where this class was declared ("module")
547  *       For constructor parent is class itself ("module.#~C=#C"))
548  *       So for functions "GetFunctionParentKindAndName" should be used instead of "GetParentKindAndName" to handle this
549  * case
550  */
GetParentKindAndName(const std::string & name,const AbckitLiteralArray * scopeNames)551 std::pair<ParentKind, std::string> GetParentKindAndName(const std::string &name, const AbckitLiteralArray *scopeNames)
552 {
553     size_t dotPos = name.rfind('.');
554     std::string moduleName = name.substr(0, dotPos);
555     size_t sharpPos1 = name.find('#', dotPos);
556     if (sharpPos1 == std::string::npos) {
557         ASSERT(name.substr(dotPos + 1) == "func_main_0");
558         return {ParentKind::MODULE, moduleName};
559     }
560     size_t sharpPos2 = name.find('#', sharpPos1 + 1);
561     ASSERT(sharpPos2 != std::string::npos);
562 
563     std::string parentName;
564     auto getParentName = [](std::string &parentName, const AbckitLiteralArray *scopeNames, const std::string &prefix,
565                             bool isClass = false) {
566         return prefix + '#' + DemangleScope(parentName, scopeNames, isClass);
567     };
568     bool isCtor = IsCtor(name);
569     size_t startPos = isCtor ? (name.rfind('~', sharpPos2) - 1) : (sharpPos2 - 2);
570     for (size_t idx = startPos; name[idx] != '#'; idx--) {
571         auto c = name[idx];
572         switch (c) {
573             case '&':
574                 return {ParentKind::NAMESPACE, getParentName(parentName, scopeNames, name.substr(0, idx + 1))};
575             case '~':
576                 return {ParentKind::CLASS,
577                         getParentName(parentName, scopeNames,
578                                       name.substr(0, isCtor ? (name.rfind('~', sharpPos2)) : (sharpPos2 - 1)) + '=',
579                                       true)};
580             case '*':
581             case '>':
582             case '<':
583             case '=':
584                 return {ParentKind::FUNCTION, getParentName(parentName, scopeNames, name.substr(0, idx + 1))};
585             default:
586                 parentName.insert(0, 1, c);
587         }
588     }
589     return {ParentKind::MODULE, moduleName};
590 }
591 
GetFunctionParentKindAndName(const std::string & name,const AbckitLiteralArray * scopeNames)592 std::pair<ParentKind, std::string> GetFunctionParentKindAndName(const std::string &name,
593                                                                 const AbckitLiteralArray *scopeNames)
594 {
595     if (IsCtor(name)) {
596         return {ParentKind::CLASS, name};
597     }
598     return GetParentKindAndName(name, scopeNames);
599 }
600 
CreateNamespace(pandasm::Function & func,AbckitFile * file)601 std::unique_ptr<AbckitCoreNamespace> CreateNamespace(pandasm::Function &func, AbckitFile *file)
602 {
603     std::string &functionName = func.name;
604     std::string moduleName = pandasm::GetOwnerName(functionName);
605     ASSERT(file->localModules.count(moduleName) != 0);
606     auto &m = file->localModules[moduleName];
607     ASSERT(m->target == ABCKIT_TARGET_ARK_TS_V1);
608 
609     auto namespaceFunc = std::make_unique<AbckitCoreFunction>();
610     namespaceFunc->owningModule = m.get();
611     namespaceFunc->impl = std::make_unique<AbckitArktsFunction>();
612     namespaceFunc->GetArkTSImpl()->impl = &func;
613     namespaceFunc->GetArkTSImpl()->core = namespaceFunc.get();
614     ASSERT(file->nameToFunction.count(func.name) == 0);
615     file->nameToFunction[func.name] = namespaceFunc.get();
616 
617     auto n = std::make_unique<AbckitCoreNamespace>(m.get());
618     n->impl = std::make_unique<AbckitArktsNamespace>();
619     n->GetArkTSImpl()->core = n.get();
620     n->GetArkTSImpl()->f = std::move(namespaceFunc);
621     return n;
622 }
623 
GetScopeNamesArray(AbckitCoreModule * m)624 AbckitLiteralArray *GetScopeNamesArray(AbckitCoreModule *m)
625 {
626     switch (m->target) {
627         case ABCKIT_TARGET_JS:
628             return m->GetJsImpl()->impl.scopeNamesLiteralArray;
629         case ABCKIT_TARGET_ARK_TS_V1:
630             return m->GetArkTSImpl()->impl.GetDynModule().scopeNamesLiteralArray;
631         default:
632             LIBABCKIT_UNREACHABLE;
633     }
634 }
635 
AssignNamespacesToParent(std::vector<std::unique_ptr<AbckitCoreNamespace>> & namespaces,std::unordered_map<std::string,AbckitCoreNamespace * > & nameToNamespace)636 void AssignNamespacesToParent(std::vector<std::unique_ptr<AbckitCoreNamespace>> &namespaces,
637                               std::unordered_map<std::string, AbckitCoreNamespace *> &nameToNamespace)
638 {
639     for (auto &n : namespaces) {
640         ASSERT(n->owningModule->target == ABCKIT_TARGET_ARK_TS_V1);
641         panda::pandasm::Function *func = n->GetArkTSImpl()->f->GetArkTSImpl()->GetDynamicImpl();
642         auto [kind, parentName] = GetParentKindAndName(func->name, GetScopeNamesArray(n->owningModule));
643         switch (kind) {
644             case ParentKind::MODULE:
645                 n->owningModule->namespaces.emplace_back(std::move(n)).get();
646                 break;
647             case ParentKind::NAMESPACE: {
648                 ASSERT(nameToNamespace.count(parentName) == 1);
649                 auto *parentNamespace = nameToNamespace[parentName];
650                 n->parentNamespace = nameToNamespace[parentName];
651                 parentNamespace->namespaces.emplace_back(std::move(n)).get();
652                 break;
653             }
654             default:
655                 LIBABCKIT_UNREACHABLE;
656         }
657     }
658 }
659 
CreateClass(const std::string & functionName,panda::pandasm::Function & function,AbckitFile * file,std::unordered_map<std::string,AbckitCoreClass * > & nameToClass)660 std::unique_ptr<AbckitCoreClass> CreateClass(const std::string &functionName, panda::pandasm::Function &function,
661                                              AbckitFile *file,
662                                              std::unordered_map<std::string, AbckitCoreClass *> &nameToClass)
663 {
664     std::string moduleName = pandasm::GetOwnerName(functionName);
665     ASSERT(file->localModules.count(moduleName) != 0);
666     auto &m = file->localModules[moduleName];
667 
668     auto abckitFunction = &function;
669     std::unique_ptr<AbckitCoreClass> c;
670 
671     switch (m->target) {
672         case ABCKIT_TARGET_JS:
673             c = std::make_unique<AbckitCoreClass>(m.get(), AbckitJsClass(abckitFunction));
674             break;
675         case ABCKIT_TARGET_ARK_TS_V1:
676             c = std::make_unique<AbckitCoreClass>(m.get(), AbckitArktsClass(abckitFunction));
677             break;
678         default:
679             LIBABCKIT_UNREACHABLE;
680     }
681     ASSERT(nameToClass.count(functionName) == 0);
682     nameToClass[functionName] = c.get();
683     return c;
684 }
685 
AssignClassesToParent(std::vector<std::unique_ptr<AbckitCoreClass>> & klasses,std::unordered_map<std::string,AbckitCoreNamespace * > & nameToNamespace,std::unordered_map<std::string,AbckitCoreFunction * > & nameToFunction)686 void AssignClassesToParent(std::vector<std::unique_ptr<AbckitCoreClass>> &klasses,
687                            std::unordered_map<std::string, AbckitCoreNamespace *> &nameToNamespace,
688                            std::unordered_map<std::string, AbckitCoreFunction *> &nameToFunction)
689 {
690     for (auto &klass : klasses) {
691         std::string name;
692         switch (klass->owningModule->target) {
693             case ABCKIT_TARGET_JS:
694                 name = klass->GetJsImpl()->impl->name;
695                 break;
696             case ABCKIT_TARGET_ARK_TS_V1:
697                 name = klass->GetArkTSImpl()->impl.GetDynamicClass()->name;
698                 break;
699             default:
700                 LIBABCKIT_UNREACHABLE;
701         }
702         auto [kind, parentName] = GetParentKindAndName(name, GetScopeNamesArray(klass->owningModule));
703         switch (kind) {
704             case ParentKind::MODULE:
705                 klass->owningModule->InsertClass(name, std::move(klass));
706                 break;
707             case ParentKind::NAMESPACE: {
708                 ASSERT(nameToNamespace.count(parentName) != 0);
709                 auto *n = nameToNamespace[parentName];
710                 klass->parentNamespace = n;
711                 n->classes.emplace_back(std::move(klass));
712                 break;
713             }
714             case ParentKind::FUNCTION: {
715                 ASSERT(nameToFunction.count(parentName) != 0);
716                 auto *f = nameToFunction[parentName];
717                 klass->parentFunction = f;
718                 f->nestedClasses.emplace_back(std::move(klass));
719                 break;
720             }
721             case ParentKind::CLASS:
722                 klass->owningModule->InsertClass(name, std::move(klass));
723                 break;
724             default:
725                 LIBABCKIT_UNREACHABLE;
726         }
727     }
728 }
729 
CreateAnnotationInterface(AbckitFile * file,const std::string & recName,pandasm::Record & rec)730 void CreateAnnotationInterface(AbckitFile *file, const std::string &recName, pandasm::Record &rec)
731 {
732     auto ai = std::make_unique<AbckitCoreAnnotationInterface>();
733     std::string moduleName = pandasm::GetOwnerName(recName);
734     ASSERT(file->localModules.count(moduleName) != 0);
735     auto &module = file->localModules[moduleName];
736     ai->owningModule = module.get();
737     ai->impl = std::make_unique<AbckitArktsAnnotationInterface>();
738     ai->GetArkTSImpl()->impl = &rec;
739     ai->GetArkTSImpl()->core = ai.get();
740 
741     auto &fields = rec.field_list;
742     ASSERT(module->target != ABCKIT_TARGET_JS || fields.empty());
743     for (auto &field : fields) {
744         auto aiField = std::make_unique<AbckitCoreAnnotationInterfaceField>();
745         aiField->impl = std::make_unique<AbckitArktsAnnotationInterfaceField>();
746         aiField->GetArkTSImpl()->core = aiField.get();
747 
748         aiField->ai = ai.get();
749         aiField->name = CreateNameString(field.name, file);
750 
751         aiField->type = GetOrCreateType(file, PandaTypeToAbcKitTypeId(field.type), field.type.GetRank(), nullptr);
752 
753         if (field.metadata->GetValue().has_value()) {
754             aiField->value = FindOrCreateValueDynamic(file, field.metadata->GetValue().value());
755         }
756 
757         ai->fields.emplace_back(std::move(aiField));
758     }
759 
760     module->at.emplace(pandasm::GetItemName(recName), std::move(ai));
761 }
762 
SetImpl(std::unique_ptr<AbckitCoreFunction> & function,panda::pandasm::Function & functionImpl,std::unique_ptr<AbckitCoreModule> & m)763 void SetImpl(std::unique_ptr<AbckitCoreFunction> &function, panda::pandasm::Function &functionImpl,
764              std::unique_ptr<AbckitCoreModule> &m)
765 {
766     switch (m->target) {
767         case ABCKIT_TARGET_JS:
768             function->impl = std::make_unique<AbckitJsFunction>();
769             function->GetJsImpl()->impl = &functionImpl;
770             function->GetJsImpl()->core = function.get();
771             break;
772         case ABCKIT_TARGET_ARK_TS_V1:
773             function->impl = std::make_unique<AbckitArktsFunction>();
774             function->GetArkTSImpl()->impl = &functionImpl;
775             function->GetArkTSImpl()->core = function.get();
776             break;
777         default:
778             LIBABCKIT_UNREACHABLE;
779     }
780 }
781 
CreateFunctionAnnotations(AbckitFile * file,panda::pandasm::Function & functionImpl,AbckitCoreFunction * function)782 void CreateFunctionAnnotations(AbckitFile *file, panda::pandasm::Function &functionImpl, AbckitCoreFunction *function)
783 {
784     for (auto &annoImpl : functionImpl.metadata->GetAnnotations()) {
785         if (libabckit::IsServiceRecord(annoImpl.GetName())) {
786             continue;
787         }
788         ASSERT(function->owningModule->target == ABCKIT_TARGET_ARK_TS_V1);
789         auto anno = std::make_unique<AbckitCoreAnnotation>();
790         std::string aiModuleName = pandasm::GetOwnerName(annoImpl.GetName());
791         std::string aiName = pandasm::GetItemName(annoImpl.GetName());
792         anno->name = CreateNameString(aiName, file);
793         anno->ai = file->localModules[aiModuleName]->at[aiName].get();
794         anno->impl = std::make_unique<AbckitArktsAnnotation>();
795         anno->GetArkTSImpl()->core = anno.get();
796 
797         for (auto &annoElemImpl : annoImpl.GetElements()) {
798             auto annoElem = std::make_unique<AbckitCoreAnnotationElement>();
799             annoElem->ann = anno.get();
800             annoElem->name = CreateStringDynamic(file, annoElemImpl.GetName().data(), annoElemImpl.GetName().size());
801             annoElem->impl = std::make_unique<AbckitArktsAnnotationElement>();
802             annoElem->GetArkTSImpl()->core = annoElem.get();
803             auto value = FindOrCreateValueDynamic(file, *annoElemImpl.GetValue());
804             annoElem->value = value;
805 
806             anno->elements.emplace_back(std::move(annoElem));
807         }
808         anno->owner = function;
809         function->annotations.emplace_back(std::move(anno));
810     }
811 }
812 
CreateFunction(const std::string & functionName,panda::pandasm::Function & functionImpl,AbckitFile * file)813 std::unique_ptr<AbckitCoreFunction> CreateFunction(const std::string &functionName,
814                                                    panda::pandasm::Function &functionImpl, AbckitFile *file)
815 {
816     std::string moduleName = pandasm::GetOwnerName(functionName);
817     ASSERT(file->localModules.count(moduleName) != 0);
818     auto &m = file->localModules[moduleName];
819 
820     auto function = std::make_unique<AbckitCoreFunction>();
821     function->owningModule = m.get();
822     auto [kind, _] = GetFunctionParentKindAndName(functionName, GetScopeNamesArray(function->owningModule));
823     if (m->target == ABCKIT_TARGET_ARK_TS_V1) {
824         function->isAnonymous = kind == ParentKind::FUNCTION;
825     } else {
826         function->isAnonymous = IsAnonymousName(functionName);
827     }
828     SetImpl(function, functionImpl, m);
829     ASSERT(file->nameToFunction.count(functionImpl.name) == 0);
830     file->nameToFunction[functionImpl.name] = function.get();
831 
832     CreateFunctionAnnotations(file, functionImpl, function.get());
833 
834     return function;
835 }
836 
AssignFunction(std::unique_ptr<AbckitCoreFunction> & f,std::string & name,AbckitLiteralArray * scopeNamesLiteralArray,std::unordered_map<std::string,AbckitCoreNamespace * > & nameToNamespace,std::unordered_map<std::string,AbckitCoreClass * > & nameToClass,std::unordered_map<std::string,AbckitCoreFunction * > & nameToFunction)837 void AssignFunction(std::unique_ptr<AbckitCoreFunction> &f, std::string &name,
838                     AbckitLiteralArray *scopeNamesLiteralArray,
839                     std::unordered_map<std::string, AbckitCoreNamespace *> &nameToNamespace,
840                     std::unordered_map<std::string, AbckitCoreClass *> &nameToClass,
841                     std::unordered_map<std::string, AbckitCoreFunction *> &nameToFunction)
842 {
843     auto [kind, parentName] = GetFunctionParentKindAndName(name, scopeNamesLiteralArray);
844     switch (kind) {
845         case ParentKind::MODULE:
846             f->owningModule->functions.emplace_back(std::move(f));
847             return;
848         case ParentKind::NAMESPACE: {
849             ASSERT(nameToNamespace.count(parentName) == 1);
850             auto *n = nameToNamespace[parentName];
851             f->parentNamespace = n;
852             n->functions.emplace_back(std::move(f));
853             return;
854         }
855         case ParentKind::CLASS: {
856             ASSERT(nameToClass.count(parentName) == 1);
857             auto *c = nameToClass[parentName];
858             f->parentClass = c;
859             c->methods.emplace_back(std::move(f));
860             return;
861         }
862         case ParentKind::FUNCTION: {
863             ASSERT(nameToFunction.count(parentName) == 1);
864             auto *parentF = nameToFunction[parentName];
865             f->parentFunction = parentF;
866             parentF->nestedFunction.emplace_back(std::move(f));
867             return;
868         }
869     }
870 }
871 
AssignFunctionsToParent(std::vector<std::unique_ptr<AbckitCoreFunction>> & functions,std::unordered_map<std::string,AbckitCoreNamespace * > & nameToNamespace,std::unordered_map<std::string,AbckitCoreClass * > & nameToClass,std::unordered_map<std::string,AbckitCoreFunction * > & nameToFunction)872 void AssignFunctionsToParent(std::vector<std::unique_ptr<AbckitCoreFunction>> &functions,
873                              std::unordered_map<std::string, AbckitCoreNamespace *> &nameToNamespace,
874                              std::unordered_map<std::string, AbckitCoreClass *> &nameToClass,
875                              std::unordered_map<std::string, AbckitCoreFunction *> &nameToFunction)
876 {
877     for (auto &f : functions) {
878         std::string name;
879         AbckitLiteralArray *scopeNamesLiteralArray;
880         switch (f->owningModule->target) {
881             case ABCKIT_TARGET_JS:
882                 name = f->GetJsImpl()->impl->name;
883                 scopeNamesLiteralArray = f->owningModule->GetJsImpl()->impl.scopeNamesLiteralArray;
884                 break;
885             case ABCKIT_TARGET_ARK_TS_V1:
886                 name = f->GetArkTSImpl()->GetDynamicImpl()->name;
887                 scopeNamesLiteralArray = f->owningModule->GetArkTSImpl()->impl.GetDynModule().scopeNamesLiteralArray;
888                 break;
889             default:
890                 LIBABCKIT_UNREACHABLE;
891         }
892 
893         if (f->isAnonymous) {
894             f->owningModule->functions.emplace_back(std::move(f));
895             continue;
896         }
897 
898         if (IsCtor(name)) {
899             ASSERT(nameToClass.count(name) == 1);
900             auto *c = nameToClass[name];
901             f->parentClass = c;
902             for (auto &anno : f->annotations) {
903                 anno->owner = c;
904                 c->annotations.emplace_back(std::move(anno));
905             }
906             f->annotations.clear();
907             c->methods.emplace_back(std::move(f));
908             continue;
909         }
910 
911         AssignFunction(f, name, scopeNamesLiteralArray, nameToNamespace, nameToClass, nameToFunction);
912     }
913 }
914 
DumpHierarchy(AbckitFile * file)915 void DumpHierarchy(AbckitFile *file)
916 {
917     std::function<void(AbckitCoreFunction * f, const std::string &indent)> dumpFunc;
918     std::function<void(AbckitCoreClass * c, const std::string &indent)> dumpClass;
919 
920     dumpFunc = [&dumpFunc, &dumpClass](AbckitCoreFunction *f, const std::string &indent = "") {
921         auto fName = GetDynFunction(f)->name;
922         LIBABCKIT_LOG_NO_FUNC(DEBUG) << indent << fName << std::endl;
923         for (auto &cNested : f->nestedClasses) {
924             dumpClass(cNested.get(), indent + "  ");
925         }
926         for (auto &fNested : f->nestedFunction) {
927             dumpFunc(fNested.get(), indent + "  ");
928         }
929     };
930 
931     dumpClass = [&dumpFunc](AbckitCoreClass *c, const std::string &indent = "") {
932         auto cName = GetDynFunction(c)->name;
933         LIBABCKIT_LOG_NO_FUNC(DEBUG) << indent << cName << std::endl;
934         for (auto &f : c->methods) {
935             dumpFunc(f.get(), indent + "  ");
936         }
937     };
938 
939     std::function<void(AbckitCoreNamespace * n, const std::string &indent)> dumpNamespace =
940         [&dumpFunc, &dumpClass, &dumpNamespace](AbckitCoreNamespace *n, const std::string &indent = "") {
941             ASSERT(n->owningModule->target == ABCKIT_TARGET_ARK_TS_V1);
942             auto &nName = GetDynFunction(n->GetArkTSImpl()->f.get())->name;
943             LIBABCKIT_LOG_NO_FUNC(DEBUG) << indent << nName << std::endl;
944             for (auto &n : n->namespaces) {
945                 dumpNamespace(n.get(), indent + "  ");
946             }
947             for (auto &c : n->classes) {
948                 dumpClass(c.get(), indent + "  ");
949             }
950             for (auto &f : n->functions) {
951                 dumpFunc(f.get(), indent + "  ");
952             }
953         };
954 
955     for (auto &[mName, m] : file->localModules) {
956         LIBABCKIT_LOG_NO_FUNC(DEBUG) << mName << std::endl;
957         for (auto &n : m->namespaces) {
958             dumpNamespace(n.get(), "");
959         }
960         for (auto &[cName, c] : m->ct) {
961             dumpClass(c.get(), "");
962         }
963         for (auto &f : m->functions) {
964             dumpFunc(f.get(), "");
965         }
966     }
967 }
968 
ResolveUnfoundModule(AbckitCoreModule * m,AbckitFile * file,size_t offset)969 AbckitCoreModule *ResolveUnfoundModule(AbckitCoreModule *m, AbckitFile *file, size_t offset)
970 {
971     auto mPayload = GetDynModulePayload(m);
972     auto literalArr = mPayload->moduleLiteralArray->GetDynamicImpl();
973     auto requestIdx = std::get<uint16_t>(literalArr->literals_[offset].value_);
974     auto moduleName = std::get<std::string>(literalArr->literals_[requestIdx + 1].value_);
975     if (moduleName.substr(0, 2U) == "./") {
976         moduleName = moduleName.substr(2U);
977     }
978     auto foundModule = TryFindModule(moduleName, file);
979     if (foundModule == nullptr) {
980         auto md = std::make_unique<AbckitCoreModule>();
981         md->target = ABCKIT_TARGET_UNKNOWN;
982         md->isExternal = true;
983         md->file = file;
984         md->moduleName = CreateNameString(moduleName, file);
985         file->externalModules.emplace(moduleName, std::move(md));
986         foundModule = file->externalModules[moduleName].get();
987     }
988     if (m->md.at(requestIdx) == nullptr) {
989         m->md.at(requestIdx) = foundModule;
990     }
991     ASSERT(m->md.at(requestIdx) == foundModule);
992     return foundModule;
993 }
994 
ResolveImportedModule(AbckitFile * file,std::unique_ptr<AbckitCoreModule> & m,std::unique_ptr<AbckitCoreImportDescriptor> & id,AbckitModulePayloadDyn * mPayload)995 void ResolveImportedModule(AbckitFile *file, std::unique_ptr<AbckitCoreModule> &m,
996                            std::unique_ptr<AbckitCoreImportDescriptor> &id, AbckitModulePayloadDyn *mPayload)
997 {
998     AbckitDynamicImportDescriptorPayload *idDyn = GetDynImportDescriptorPayload(id.get());
999     auto offset = idDyn->moduleRecordIndexOff;
1000     auto absOffset = idDyn->isRegularImport ? mPayload->regularImportsOffset + offset * 3U + 2U
1001                                             : mPayload->namespaceImportsOffset + offset * 2U + 1;
1002     auto importedModule = ResolveUnfoundModule(m.get(), file, absOffset);
1003     id->importedModule = importedModule;
1004 }
1005 
ResolveExportedModule(AbckitFile * file,std::unique_ptr<AbckitCoreModule> & m,std::unique_ptr<AbckitCoreExportDescriptor> & ed,AbckitModulePayloadDyn * mPayload)1006 void ResolveExportedModule(AbckitFile *file, std::unique_ptr<AbckitCoreModule> &m,
1007                            std::unique_ptr<AbckitCoreExportDescriptor> &ed, AbckitModulePayloadDyn *mPayload)
1008 {
1009     AbckitDynamicExportDescriptorPayload *edDyn = GetDynExportDescriptorPayload(ed.get());
1010     auto offset = edDyn->moduleRecordIndexOff;
1011     auto absOffset = 0;
1012     switch (edDyn->kind) {
1013         case ABCKIT_DYNAMIC_EXPORT_KIND_INDIRECT_EXPORT: {
1014             absOffset = mPayload->indirectExportsOffset + offset * 3U + 2U;
1015             break;
1016         }
1017         case ABCKIT_DYNAMIC_EXPORT_KIND_STAR_EXPORT: {
1018             if (edDyn->hasServiceImport) {
1019                 absOffset = mPayload->namespaceImportsOffset + edDyn->serviceNamespaceImportIdx * 2U + 1;
1020             } else {
1021                 absOffset = mPayload->starExportsOffset + offset;
1022             }
1023             break;
1024         }
1025         default:
1026             UNREACHABLE();
1027     }
1028     auto exportedModule = ResolveUnfoundModule(m.get(), file, absOffset);
1029     ed->exportedModule = exportedModule;
1030 }
1031 
ResolveUnfoundModules(AbckitFile * file)1032 void ResolveUnfoundModules(AbckitFile *file)
1033 {
1034     for (auto &[name, m] : file->localModules) {
1035         if (std::find(m->md.begin(), m->md.end(), nullptr) == m->md.end()) {
1036             continue;
1037         }
1038         auto mPayload = GetDynModulePayload(m.get());
1039         for (auto &id : m->id) {
1040             if (id->importedModule != nullptr) {
1041                 continue;
1042             }
1043             ResolveImportedModule(file, m, id, mPayload);
1044         }
1045         for (auto &ed : m->ed) {
1046             if (ed->exportedModule != nullptr) {
1047                 continue;
1048             }
1049             ResolveExportedModule(file, m, ed, mPayload);
1050         }
1051     }
1052 }
1053 
CollectModules(pandasm::Program * prog,AbckitFile * file)1054 void CollectModules(pandasm::Program *prog, AbckitFile *file)
1055 {
1056     for (const auto &[recName, rec] : prog->record_table) {
1057         LIBABCKIT_LOG(DEBUG) << "RECORD: " << recName << ' ' << rec.name << '\n';
1058         if (!libabckit::IsModuleDescriptorRecord(rec) || libabckit::IsExternalRecord(rec)) {
1059             continue;
1060         }
1061         auto m = CreateModule(prog, &rec, file);
1062         file->localModules.insert({rec.name, std::move(m)});
1063     }
1064     ResolveUnfoundModules(file);
1065 }
1066 
CollectAI(pandasm::Program * prog,AbckitFile * file)1067 void CollectAI(pandasm::Program *prog, AbckitFile *file)
1068 {
1069     for (auto &[recName, rec] : prog->record_table) {
1070         if (!libabckit::IsAnnotationInterfaceRecord(rec) || libabckit::IsServiceRecord(recName)) {
1071             continue;
1072         }
1073         LIBABCKIT_LOG(DEBUG) << "ANNOTATION: " << recName << ' ' << rec.name << '\n';
1074         CreateAnnotationInterface(file, recName, rec);
1075     }
1076 }
1077 
CollectNamespaces(pandasm::Program * prog,AbckitFile * file,std::vector<std::unique_ptr<AbckitCoreNamespace>> * namespaces,std::unordered_map<std::string,AbckitCoreNamespace * > * nameToNamespace)1078 void CollectNamespaces(pandasm::Program *prog, AbckitFile *file,
1079                        std::vector<std::unique_ptr<AbckitCoreNamespace>> *namespaces,
1080                        std::unordered_map<std::string, AbckitCoreNamespace *> *nameToNamespace)
1081 {
1082     for (auto &[functionName, function] : prog->function_table) {
1083         if (!IsNamespaceFunc(functionName)) {
1084             continue;
1085         }
1086         namespaces->emplace_back(CreateNamespace(function, file));
1087         ASSERT(nameToNamespace->count(function.name) == 0);
1088         (*nameToNamespace)[function.name] = namespaces->back().get();
1089     }
1090     AssignNamespacesToParent(*namespaces, *nameToNamespace);
1091 }
1092 
CreateWrappers(pandasm::Program * prog,AbckitFile * file)1093 void CreateWrappers(pandasm::Program *prog, AbckitFile *file)
1094 {
1095     file->program = prog;
1096 
1097     CollectModules(prog, file);
1098     CollectAI(prog, file);
1099     std::vector<std::unique_ptr<AbckitCoreNamespace>> namespaces;
1100     std::unordered_map<std::string, AbckitCoreNamespace *> nameToNamespace;
1101     CollectNamespaces(prog, file, &namespaces, &nameToNamespace);
1102 
1103     // Collect classes
1104     std::vector<std::unique_ptr<AbckitCoreClass>> classes;
1105     std::unordered_map<std::string, AbckitCoreClass *> nameToClass;
1106     for (auto &[functionName, function] : prog->function_table) {
1107         if (!libabckit::IsCtor(functionName)) {
1108             continue;
1109         }
1110         classes.emplace_back(CreateClass(functionName, function, file, nameToClass));
1111     }
1112 
1113     // Collect functions
1114     std::vector<std::unique_ptr<AbckitCoreFunction>> functions;
1115     std::unordered_map<std::string, AbckitCoreFunction *> nameToFunction;
1116     for (auto &[functionName, function] : prog->function_table) {
1117         LIBABCKIT_LOG(DEBUG) << "f: " << functionName << " ; " << function.name << '\n';
1118         if (!libabckit::IsFunction(functionName)) {
1119             continue;
1120         }
1121         functions.emplace_back(CreateFunction(functionName, function, file));
1122         ASSERT(nameToFunction.count(function.name) == 0);
1123         nameToFunction[function.name] = functions.back().get();
1124     }
1125 
1126     // Assign parents
1127     AssignClassesToParent(classes, nameToNamespace, nameToFunction);
1128     AssignFunctionsToParent(functions, nameToNamespace, nameToClass, nameToFunction);
1129 
1130     LIBABCKIT_LOG_DUMP(DumpHierarchy(file), DEBUG);
1131 
1132     // Strings
1133     for (auto &sImpl : prog->strings) {
1134         auto s = std::make_unique<AbckitString>();
1135         s->impl = sImpl;
1136         file->strings.insert({sImpl, std::move(s)});
1137     }
1138 }
1139 }  // namespace
1140 
1141 namespace libabckit {
1142 
1143 struct CtxIInternal {
1144     panda::abc2program::Abc2ProgramDriver *driver = nullptr;
1145 };
1146 
OpenAbcDynamic(const char * path,size_t len)1147 AbckitFile *OpenAbcDynamic(const char *path, size_t len)
1148 {
1149     LIBABCKIT_LOG_FUNC;
1150     auto spath = std::string(path, len);
1151     LIBABCKIT_LOG(DEBUG) << spath << '\n';
1152     auto *abc2program = new panda::abc2program::Abc2ProgramDriver();
1153     if (!abc2program->Compile(spath)) {
1154         LIBABCKIT_LOG(DEBUG) << "Failed to open " << spath << "\n";
1155         delete abc2program;
1156         return nullptr;
1157     }
1158     auto &prog = const_cast<pandasm::Program &>(abc2program->GetProgram());
1159     auto file = new AbckitFile();
1160     file->frontend = Mode::DYNAMIC;
1161     CreateWrappers(&prog, file);
1162 
1163     auto pf = panda_file::File::Open(spath);
1164     if (pf == nullptr) {
1165         LIBABCKIT_LOG(DEBUG) << "Failed to panda_file::File::Open\n";
1166         delete abc2program;
1167         delete file;
1168         return nullptr;
1169     }
1170 
1171     auto pandaFileVersion = pf->GetHeader()->version;
1172     uint8_t *fileVersion = pandaFileVersion.data();
1173 
1174     file->version = new uint8_t[ABCKIT_VERSION_SIZE];
1175     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1176     std::copy(fileVersion, fileVersion + sizeof(uint8_t) * ABCKIT_VERSION_SIZE, file->version);
1177 
1178     file->internal = new CtxIInternal {abc2program};
1179     return file;
1180 }
1181 
WriteAbcDynamic(AbckitFile * file,const char * path,size_t len)1182 void WriteAbcDynamic(AbckitFile *file, const char *path, size_t len)
1183 {
1184     auto program = file->GetDynamicProgram();
1185 
1186     pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = nullptr;
1187 
1188     EmitDynamicProgram(file, program, mapsp, false, std::string_view(path, len));
1189     if (statuses::GetLastError() != AbckitStatus::ABCKIT_STATUS_NO_ERROR) {
1190         return;
1191     }
1192 
1193     LIBABCKIT_LOG(DEBUG) << "SUCCESS\n";
1194 }
1195 
DestroyGraphDynamic(AbckitGraph * graph)1196 void DestroyGraphDynamic(AbckitGraph *graph)
1197 {
1198     LIBABCKIT_LOG_FUNC;
1199     GraphWrapper::DestroyGraphDynamic(graph);
1200 }
1201 
CloseFileDynamic(AbckitFile * file)1202 void CloseFileDynamic(AbckitFile *file)
1203 {
1204     LIBABCKIT_LOG_FUNC;
1205 
1206     auto *ctxIInternal = reinterpret_cast<struct CtxIInternal *>(file->internal);
1207     delete ctxIInternal->driver;
1208     delete ctxIInternal;
1209     delete[] file->version;
1210     delete file;
1211 }
1212 
1213 }  // namespace libabckit
1214