• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /**
2  * Copyright (c) 2024-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 #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     auto &nameToFunction = func.IsStatic() ? file->nameToFunctionStatic : file->nameToFunctionInstance;
615     ASSERT(nameToFunction.count(func.name) == 0);
616     nameToFunction[func.name] = namespaceFunc.get();
617 
618     auto n = std::make_unique<AbckitCoreNamespace>(m.get());
619     n->impl = std::make_unique<AbckitArktsNamespace>();
620     n->GetArkTSImpl()->core = n.get();
621     n->GetArkTSImpl()->f = std::move(namespaceFunc);
622     return n;
623 }
624 
GetScopeNamesArray(AbckitCoreModule * m)625 AbckitLiteralArray *GetScopeNamesArray(AbckitCoreModule *m)
626 {
627     switch (m->target) {
628         case ABCKIT_TARGET_JS:
629             return m->GetJsImpl()->impl.scopeNamesLiteralArray;
630         case ABCKIT_TARGET_ARK_TS_V1:
631             return m->GetArkTSImpl()->impl.GetDynModule().scopeNamesLiteralArray;
632         default:
633             LIBABCKIT_UNREACHABLE;
634     }
635 }
636 
AssignNamespacesToParent(std::vector<std::unique_ptr<AbckitCoreNamespace>> & namespaces,std::unordered_map<std::string,AbckitCoreNamespace * > & nameToNamespace)637 void AssignNamespacesToParent(std::vector<std::unique_ptr<AbckitCoreNamespace>> &namespaces,
638                               std::unordered_map<std::string, AbckitCoreNamespace *> &nameToNamespace)
639 {
640     for (auto &n : namespaces) {
641         ASSERT(n->owningModule->target == ABCKIT_TARGET_ARK_TS_V1);
642         panda::pandasm::Function *func = n->GetArkTSImpl()->f->GetArkTSImpl()->GetDynamicImpl();
643         auto [kind, parentName] = GetParentKindAndName(func->name, GetScopeNamesArray(n->owningModule));
644         switch (kind) {
645             case ParentKind::MODULE:
646                 n->owningModule->namespaces.emplace_back(std::move(n)).get();
647                 break;
648             case ParentKind::NAMESPACE: {
649                 ASSERT(nameToNamespace.count(parentName) == 1);
650                 auto *parentNamespace = nameToNamespace[parentName];
651                 n->parentNamespace = nameToNamespace[parentName];
652                 parentNamespace->namespaces.emplace_back(std::move(n)).get();
653                 break;
654             }
655             default:
656                 LIBABCKIT_UNREACHABLE;
657         }
658     }
659 }
660 
CreateClass(const std::string & functionName,panda::pandasm::Function & function,AbckitFile * file,std::unordered_map<std::string,AbckitCoreClass * > & nameToClass)661 std::unique_ptr<AbckitCoreClass> CreateClass(const std::string &functionName, panda::pandasm::Function &function,
662                                              AbckitFile *file,
663                                              std::unordered_map<std::string, AbckitCoreClass *> &nameToClass)
664 {
665     std::string moduleName = pandasm::GetOwnerName(functionName);
666     ASSERT(file->localModules.count(moduleName) != 0);
667     auto &m = file->localModules[moduleName];
668 
669     auto abckitFunction = &function;
670     std::unique_ptr<AbckitCoreClass> c;
671 
672     switch (m->target) {
673         case ABCKIT_TARGET_JS:
674             c = std::make_unique<AbckitCoreClass>(m.get(), AbckitJsClass(abckitFunction));
675             break;
676         case ABCKIT_TARGET_ARK_TS_V1:
677             c = std::make_unique<AbckitCoreClass>(m.get(), AbckitArktsClass(abckitFunction));
678             break;
679         default:
680             LIBABCKIT_UNREACHABLE;
681     }
682     ASSERT(nameToClass.count(functionName) == 0);
683     nameToClass[functionName] = c.get();
684     return c;
685 }
686 
AssignClassesToParent(std::vector<std::unique_ptr<AbckitCoreClass>> & klasses,std::unordered_map<std::string,AbckitCoreNamespace * > & nameToNamespace,std::unordered_map<std::string,AbckitCoreFunction * > & nameToFunction)687 void AssignClassesToParent(std::vector<std::unique_ptr<AbckitCoreClass>> &klasses,
688                            std::unordered_map<std::string, AbckitCoreNamespace *> &nameToNamespace,
689                            std::unordered_map<std::string, AbckitCoreFunction *> &nameToFunction)
690 {
691     for (auto &klass : klasses) {
692         std::string name;
693         switch (klass->owningModule->target) {
694             case ABCKIT_TARGET_JS:
695                 name = klass->GetJsImpl()->impl->name;
696                 break;
697             case ABCKIT_TARGET_ARK_TS_V1:
698                 name = klass->GetArkTSImpl()->impl.GetDynamicClass()->name;
699                 break;
700             default:
701                 LIBABCKIT_UNREACHABLE;
702         }
703         auto [kind, parentName] = GetParentKindAndName(name, GetScopeNamesArray(klass->owningModule));
704         switch (kind) {
705             case ParentKind::MODULE:
706                 klass->owningModule->InsertClass(name, std::move(klass));
707                 break;
708             case ParentKind::NAMESPACE: {
709                 ASSERT(nameToNamespace.count(parentName) != 0);
710                 auto *n = nameToNamespace[parentName];
711                 klass->parentNamespace = n;
712                 n->classes.emplace_back(std::move(klass));
713                 break;
714             }
715             case ParentKind::FUNCTION: {
716                 ASSERT(nameToFunction.count(parentName) != 0);
717                 auto *f = nameToFunction[parentName];
718                 klass->parentFunction = f;
719                 f->nestedClasses.emplace_back(std::move(klass));
720                 break;
721             }
722             case ParentKind::CLASS:
723                 klass->owningModule->InsertClass(name, std::move(klass));
724                 break;
725             default:
726                 LIBABCKIT_UNREACHABLE;
727         }
728     }
729 }
730 
CreateAnnotationInterface(AbckitFile * file,const std::string & recName,pandasm::Record & rec)731 void CreateAnnotationInterface(AbckitFile *file, const std::string &recName, pandasm::Record &rec)
732 {
733     auto ai = std::make_unique<AbckitCoreAnnotationInterface>();
734     std::string moduleName = pandasm::GetOwnerName(recName);
735     ASSERT(file->localModules.count(moduleName) != 0);
736     auto &module = file->localModules[moduleName];
737     ai->owningModule = module.get();
738     ai->impl = std::make_unique<AbckitArktsAnnotationInterface>();
739     ai->GetArkTSImpl()->impl = &rec;
740     ai->GetArkTSImpl()->core = ai.get();
741 
742     auto &fields = rec.field_list;
743     ASSERT(module->target != ABCKIT_TARGET_JS || fields.empty());
744     for (auto &field : fields) {
745         auto aiField = std::make_unique<AbckitCoreAnnotationInterfaceField>();
746         aiField->impl = std::make_unique<AbckitArktsAnnotationInterfaceField>();
747         aiField->GetArkTSImpl()->core = aiField.get();
748 
749         aiField->ai = ai.get();
750         aiField->name = CreateNameString(field.name, file);
751 
752         aiField->type = GetOrCreateType(file, PandaTypeToAbcKitTypeId(field.type), field.type.GetRank(), nullptr);
753 
754         if (field.metadata->GetValue().has_value()) {
755             aiField->value = FindOrCreateValueDynamic(file, field.metadata->GetValue().value());
756         }
757 
758         ai->fields.emplace_back(std::move(aiField));
759     }
760 
761     module->at.emplace(pandasm::GetItemName(recName), std::move(ai));
762 }
763 
SetImpl(std::unique_ptr<AbckitCoreFunction> & function,panda::pandasm::Function & functionImpl,std::unique_ptr<AbckitCoreModule> & m)764 void SetImpl(std::unique_ptr<AbckitCoreFunction> &function, panda::pandasm::Function &functionImpl,
765              std::unique_ptr<AbckitCoreModule> &m)
766 {
767     switch (m->target) {
768         case ABCKIT_TARGET_JS:
769             function->impl = std::make_unique<AbckitJsFunction>();
770             function->GetJsImpl()->impl = &functionImpl;
771             function->GetJsImpl()->core = function.get();
772             break;
773         case ABCKIT_TARGET_ARK_TS_V1:
774             function->impl = std::make_unique<AbckitArktsFunction>();
775             function->GetArkTSImpl()->impl = &functionImpl;
776             function->GetArkTSImpl()->core = function.get();
777             break;
778         default:
779             LIBABCKIT_UNREACHABLE;
780     }
781 }
782 
783 constexpr int REGULAR_IMPORT_SPAN = 3;
784 constexpr int NOT_REGULAR_IMPORT_SPAN = 2;
785 
CollectAnnotationModuleMap(AbckitCoreFunction * function,std::unordered_map<std::string,std::string> & importModules)786 void CollectAnnotationModuleMap(AbckitCoreFunction *function,
787                                 std::unordered_map<std::string, std::string> &importModules)
788 {
789     for (auto &id : function->owningModule->id) {
790         if (id->importingModule->GetArkTSImpl() == nullptr) {
791             continue;
792         }
793         std::string_view mName = id->importedModule->moduleName->impl;
794         auto mPayload = &id->importingModule->GetArkTSImpl()->impl.GetDynModule();
795         auto idPayload = &id->GetArkTSImpl()->payload.GetDynId();
796         const auto *moduleLitArr = mPayload->moduleLiteralArray;
797         auto sectionOffset =
798             idPayload->isRegularImport ? mPayload->regularImportsOffset : mPayload->namespaceImportsOffset;
799         if (idPayload->isRegularImport) {
800             sectionOffset = sectionOffset + idPayload->moduleRecordIndexOff * REGULAR_IMPORT_SPAN;
801         } else {
802             sectionOffset = sectionOffset + idPayload->moduleRecordIndexOff * NOT_REGULAR_IMPORT_SPAN;
803         }
804         std::string iName = std::get<std::string>(moduleLitArr->GetDynamicImpl()->literals_[sectionOffset].value_);
805         importModules[iName] = mName;
806     }
807 }
808 
CollectAnnotationCorrectInfo(AbckitFile * file,const panda::pandasm::AnnotationData & annoImpl,std::unordered_map<std::string,std::string> & importModules,std::vector<std::string> & removes,std::vector<panda::pandasm::AnnotationData> & inserts)809 AbckitCoreAnnotationInterface *CollectAnnotationCorrectInfo(AbckitFile *file,
810                                                             const panda::pandasm::AnnotationData &annoImpl,
811                                                             std::unordered_map<std::string, std::string> &importModules,
812                                                             std::vector<std::string> &removes,
813                                                             std::vector<panda::pandasm::AnnotationData> &inserts)
814 {
815     std::string aiModuleName = pandasm::GetOwnerName(annoImpl.GetName());
816     std::string aiName = pandasm::GetItemName(annoImpl.GetName());
817     std::string mName;
818     if (importModules.find(aiName) != importModules.end() && (mName = importModules[aiName]) != aiModuleName) {
819         auto &localModule = file->localModules[mName];
820         if (localModule.get() == nullptr) {
821             return nullptr;
822         }
823         auto &annotationInterface = localModule->at[aiName];
824         if (annotationInterface.get() != nullptr &&
825             libabckit::IsAnnotationInterfaceRecord(*(annotationInterface->GetArkTSImpl()->GetDynamicImpl()))) {
826             inserts.emplace_back(mName + "." + aiName, annoImpl.GetElements());
827             removes.emplace_back(annoImpl.GetName());
828             return annotationInterface.get();
829         }
830     }
831     return nullptr;
832 }
833 
CreateFunctionAnnotations(AbckitFile * file,panda::pandasm::Function & functionImpl,AbckitCoreFunction * function)834 void CreateFunctionAnnotations(AbckitFile *file, panda::pandasm::Function &functionImpl, AbckitCoreFunction *function)
835 {
836     std::vector<std::string> removes;
837     std::vector<panda::pandasm::AnnotationData> inserts;
838     std::unordered_map<std::string, std::string> importModules;
839     if (function->owningModule->target == ABCKIT_TARGET_ARK_TS_V1) {
840         CollectAnnotationModuleMap(function, importModules);
841     }
842 
843     for (auto &annoImpl : functionImpl.metadata->GetAnnotations()) {
844         if (libabckit::IsServiceRecord(annoImpl.GetName())) {
845             continue;
846         }
847         ASSERT(function->owningModule->target == ABCKIT_TARGET_ARK_TS_V1);
848         auto anno = std::make_unique<AbckitCoreAnnotation>();
849         std::string aiModuleName = pandasm::GetOwnerName(annoImpl.GetName());
850         std::string aiName = pandasm::GetItemName(annoImpl.GetName());
851         anno->name = CreateNameString(aiName, file);
852         anno->ai = file->localModules[aiModuleName]->at[aiName].get();
853         if (anno->ai == nullptr) {
854             anno->ai = CollectAnnotationCorrectInfo(file, annoImpl, importModules, removes, inserts);
855         }
856         anno->impl = std::make_unique<AbckitArktsAnnotation>();
857         anno->GetArkTSImpl()->core = anno.get();
858 
859         for (auto &annoElemImpl : annoImpl.GetElements()) {
860             auto annoElem = std::make_unique<AbckitCoreAnnotationElement>();
861             annoElem->ann = anno.get();
862             annoElem->name = CreateStringDynamic(file, annoElemImpl.GetName().data(), annoElemImpl.GetName().size());
863             annoElem->impl = std::make_unique<AbckitArktsAnnotationElement>();
864             annoElem->GetArkTSImpl()->core = annoElem.get();
865             auto value = FindOrCreateValueDynamic(file, *annoElemImpl.GetValue());
866             annoElem->value = value;
867 
868             anno->elements.emplace_back(std::move(annoElem));
869         }
870         anno->owner = function;
871         function->annotations.emplace_back(std::move(anno));
872     }
873 
874     if (function->owningModule->target == ABCKIT_TARGET_ARK_TS_V1) {
875         for (auto &remove : removes) {
876             functionImpl.metadata->DeleteAnnotationByName(remove);
877         }
878         functionImpl.metadata->AddAnnotations(inserts);
879     }
880 }
881 
CreateFunction(const std::string & functionName,panda::pandasm::Function & functionImpl,AbckitFile * file)882 std::unique_ptr<AbckitCoreFunction> CreateFunction(const std::string &functionName,
883                                                    panda::pandasm::Function &functionImpl, AbckitFile *file)
884 {
885     std::string moduleName = pandasm::GetOwnerName(functionName);
886     if (file->localModules.count(moduleName) == 0) {
887         return std::unique_ptr<AbckitCoreFunction> {};
888     }
889     auto &m = file->localModules[moduleName];
890 
891     auto function = std::make_unique<AbckitCoreFunction>();
892     function->owningModule = m.get();
893     if (m->target == ABCKIT_TARGET_ARK_TS_V1) {
894         auto functionKind = functionImpl.GetFunctionKind();
895         function->isAnonymous = functionKind == panda::panda_file::FunctionKind::NC_FUNCTION;
896     } else {
897         function->isAnonymous = IsAnonymousName(functionName);
898     }
899     SetImpl(function, functionImpl, m);
900     auto &nameToFunction = functionImpl.IsStatic() ? file->nameToFunctionStatic : file->nameToFunctionInstance;
901     ASSERT(nameToFunction.count(functionImpl.name) == 0);
902     nameToFunction[functionImpl.name] = function.get();
903 
904     CreateFunctionAnnotations(file, functionImpl, function.get());
905 
906     return function;
907 }
908 
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)909 void AssignFunction(std::unique_ptr<AbckitCoreFunction> &f, std::string &name,
910                     AbckitLiteralArray *scopeNamesLiteralArray,
911                     std::unordered_map<std::string, AbckitCoreNamespace *> &nameToNamespace,
912                     std::unordered_map<std::string, AbckitCoreClass *> &nameToClass,
913                     std::unordered_map<std::string, AbckitCoreFunction *> &nameToFunction)
914 {
915     auto [kind, parentName] = GetFunctionParentKindAndName(name, scopeNamesLiteralArray);
916     switch (kind) {
917         case ParentKind::MODULE:
918             f->owningModule->functions.emplace_back(std::move(f));
919             return;
920         case ParentKind::NAMESPACE: {
921             ASSERT(nameToNamespace.count(parentName) == 1);
922             auto *n = nameToNamespace[parentName];
923             f->parentNamespace = n;
924             n->functions.emplace_back(std::move(f));
925             return;
926         }
927         case ParentKind::CLASS: {
928             ASSERT(nameToClass.count(parentName) == 1);
929             auto *c = nameToClass[parentName];
930             f->parentClass = c;
931             c->methods.emplace_back(std::move(f));
932             return;
933         }
934         case ParentKind::FUNCTION: {
935             ASSERT(nameToFunction.count(parentName) == 1);
936             auto *parentF = nameToFunction[parentName];
937             f->parentFunction = parentF;
938             parentF->nestedFunction.emplace_back(std::move(f));
939             return;
940         }
941     }
942 }
943 
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)944 void AssignFunctionsToParent(std::vector<std::unique_ptr<AbckitCoreFunction>> &functions,
945                              std::unordered_map<std::string, AbckitCoreNamespace *> &nameToNamespace,
946                              std::unordered_map<std::string, AbckitCoreClass *> &nameToClass,
947                              std::unordered_map<std::string, AbckitCoreFunction *> &nameToFunction)
948 {
949     for (auto &f : functions) {
950         std::string name;
951         AbckitLiteralArray *scopeNamesLiteralArray;
952         switch (f->owningModule->target) {
953             case ABCKIT_TARGET_JS:
954                 name = f->GetJsImpl()->impl->name;
955                 scopeNamesLiteralArray = f->owningModule->GetJsImpl()->impl.scopeNamesLiteralArray;
956                 break;
957             case ABCKIT_TARGET_ARK_TS_V1:
958                 name = f->GetArkTSImpl()->GetDynamicImpl()->name;
959                 scopeNamesLiteralArray = f->owningModule->GetArkTSImpl()->impl.GetDynModule().scopeNamesLiteralArray;
960                 break;
961             default:
962                 LIBABCKIT_UNREACHABLE;
963         }
964 
965         if (f->isAnonymous) {
966             f->owningModule->functions.emplace_back(std::move(f));
967             continue;
968         }
969 
970         if (IsCtor(name)) {
971             ASSERT(nameToClass.count(name) == 1);
972             auto *c = nameToClass[name];
973             f->parentClass = c;
974             for (auto &anno : f->annotations) {
975                 anno->owner = c;
976                 c->annotations.emplace_back(std::move(anno));
977             }
978             f->annotations.clear();
979             c->methods.emplace_back(std::move(f));
980             continue;
981         }
982 
983         AssignFunction(f, name, scopeNamesLiteralArray, nameToNamespace, nameToClass, nameToFunction);
984     }
985 }
986 
DumpHierarchy(AbckitFile * file)987 void DumpHierarchy(AbckitFile *file)
988 {
989     std::function<void(AbckitCoreFunction * f, const std::string &indent)> dumpFunc;
990     std::function<void(AbckitCoreClass * c, const std::string &indent)> dumpClass;
991 
992     dumpFunc = [&dumpFunc, &dumpClass](AbckitCoreFunction *f, const std::string &indent = "") {
993         auto fName = GetDynFunction(f)->name;
994         LIBABCKIT_LOG_NO_FUNC(DEBUG) << indent << fName << std::endl;
995         for (auto &cNested : f->nestedClasses) {
996             dumpClass(cNested.get(), indent + "  ");
997         }
998         for (auto &fNested : f->nestedFunction) {
999             dumpFunc(fNested.get(), indent + "  ");
1000         }
1001     };
1002 
1003     dumpClass = [&dumpFunc](AbckitCoreClass *c, const std::string &indent = "") {
1004         auto cName = GetDynFunction(c)->name;
1005         LIBABCKIT_LOG_NO_FUNC(DEBUG) << indent << cName << std::endl;
1006         for (auto &f : c->methods) {
1007             dumpFunc(f.get(), indent + "  ");
1008         }
1009     };
1010 
1011     std::function<void(AbckitCoreNamespace * n, const std::string &indent)> dumpNamespace =
1012         [&dumpFunc, &dumpClass, &dumpNamespace](AbckitCoreNamespace *n, const std::string &indent = "") {
1013             ASSERT(n->owningModule->target == ABCKIT_TARGET_ARK_TS_V1);
1014             auto &nName = GetDynFunction(n->GetArkTSImpl()->f.get())->name;
1015             LIBABCKIT_LOG_NO_FUNC(DEBUG) << indent << nName << std::endl;
1016             for (auto &n : n->namespaces) {
1017                 dumpNamespace(n.get(), indent + "  ");
1018             }
1019             for (auto &c : n->classes) {
1020                 dumpClass(c.get(), indent + "  ");
1021             }
1022             for (auto &f : n->functions) {
1023                 dumpFunc(f.get(), indent + "  ");
1024             }
1025         };
1026 
1027     for (auto &[mName, m] : file->localModules) {
1028         LIBABCKIT_LOG_NO_FUNC(DEBUG) << mName << std::endl;
1029         for (auto &n : m->namespaces) {
1030             dumpNamespace(n.get(), "");
1031         }
1032         for (auto &[cName, c] : m->ct) {
1033             dumpClass(c.get(), "");
1034         }
1035         for (auto &f : m->functions) {
1036             dumpFunc(f.get(), "");
1037         }
1038     }
1039 }
1040 
ResolveUnfoundModule(AbckitCoreModule * m,AbckitFile * file,size_t offset)1041 AbckitCoreModule *ResolveUnfoundModule(AbckitCoreModule *m, AbckitFile *file, size_t offset)
1042 {
1043     auto mPayload = GetDynModulePayload(m);
1044     auto literalArr = mPayload->moduleLiteralArray->GetDynamicImpl();
1045     auto requestIdx = std::get<uint16_t>(literalArr->literals_[offset].value_);
1046     auto moduleName = std::get<std::string>(literalArr->literals_[requestIdx + 1].value_);
1047     if (moduleName.substr(0, 2U) == "./") {
1048         moduleName = moduleName.substr(2U);
1049     }
1050     auto foundModule = TryFindModule(moduleName, file);
1051     if (foundModule == nullptr) {
1052         auto md = std::make_unique<AbckitCoreModule>();
1053         md->target = ABCKIT_TARGET_UNKNOWN;
1054         md->isExternal = true;
1055         md->file = file;
1056         md->moduleName = CreateNameString(moduleName, file);
1057         file->externalModules.emplace(moduleName, std::move(md));
1058         foundModule = file->externalModules[moduleName].get();
1059     }
1060     if (m->md.at(requestIdx) == nullptr) {
1061         m->md.at(requestIdx) = foundModule;
1062     }
1063     ASSERT(m->md.at(requestIdx) == foundModule);
1064     return foundModule;
1065 }
1066 
ResolveImportedModule(AbckitFile * file,std::unique_ptr<AbckitCoreModule> & m,std::unique_ptr<AbckitCoreImportDescriptor> & id,AbckitModulePayloadDyn * mPayload)1067 void ResolveImportedModule(AbckitFile *file, std::unique_ptr<AbckitCoreModule> &m,
1068                            std::unique_ptr<AbckitCoreImportDescriptor> &id, AbckitModulePayloadDyn *mPayload)
1069 {
1070     AbckitDynamicImportDescriptorPayload *idDyn = GetDynImportDescriptorPayload(id.get());
1071     auto offset = idDyn->moduleRecordIndexOff;
1072     auto absOffset = idDyn->isRegularImport ? mPayload->regularImportsOffset + offset * 3U + 2U
1073                                             : mPayload->namespaceImportsOffset + offset * 2U + 1;
1074     auto importedModule = ResolveUnfoundModule(m.get(), file, absOffset);
1075     id->importedModule = importedModule;
1076 }
1077 
ResolveExportedModule(AbckitFile * file,std::unique_ptr<AbckitCoreModule> & m,std::unique_ptr<AbckitCoreExportDescriptor> & ed,AbckitModulePayloadDyn * mPayload)1078 void ResolveExportedModule(AbckitFile *file, std::unique_ptr<AbckitCoreModule> &m,
1079                            std::unique_ptr<AbckitCoreExportDescriptor> &ed, AbckitModulePayloadDyn *mPayload)
1080 {
1081     AbckitDynamicExportDescriptorPayload *edDyn = GetDynExportDescriptorPayload(ed.get());
1082     auto offset = edDyn->moduleRecordIndexOff;
1083     auto absOffset = 0;
1084     switch (edDyn->kind) {
1085         case ABCKIT_DYNAMIC_EXPORT_KIND_INDIRECT_EXPORT: {
1086             absOffset = mPayload->indirectExportsOffset + offset * 3U + 2U;
1087             break;
1088         }
1089         case ABCKIT_DYNAMIC_EXPORT_KIND_STAR_EXPORT: {
1090             if (edDyn->hasServiceImport) {
1091                 absOffset = mPayload->namespaceImportsOffset + edDyn->serviceNamespaceImportIdx * 2U + 1;
1092             } else {
1093                 absOffset = mPayload->starExportsOffset + offset;
1094             }
1095             break;
1096         }
1097         default:
1098             UNREACHABLE();
1099     }
1100     auto exportedModule = ResolveUnfoundModule(m.get(), file, absOffset);
1101     ed->exportedModule = exportedModule;
1102 }
1103 
ResolveUnfoundModules(AbckitFile * file)1104 void ResolveUnfoundModules(AbckitFile *file)
1105 {
1106     for (auto &[name, m] : file->localModules) {
1107         if (std::find(m->md.begin(), m->md.end(), nullptr) == m->md.end()) {
1108             continue;
1109         }
1110         auto mPayload = GetDynModulePayload(m.get());
1111         for (auto &id : m->id) {
1112             if (id->importedModule != nullptr) {
1113                 continue;
1114             }
1115             ResolveImportedModule(file, m, id, mPayload);
1116         }
1117         for (auto &ed : m->ed) {
1118             if (ed->exportedModule != nullptr) {
1119                 continue;
1120             }
1121             ResolveExportedModule(file, m, ed, mPayload);
1122         }
1123     }
1124 }
1125 
CollectModules(pandasm::Program * prog,AbckitFile * file)1126 void CollectModules(pandasm::Program *prog, AbckitFile *file)
1127 {
1128     for (const auto &[recName, rec] : prog->record_table) {
1129         LIBABCKIT_LOG(DEBUG) << "RECORD: " << recName << ' ' << rec.name << '\n';
1130         if (!libabckit::IsModuleDescriptorRecord(rec) || libabckit::IsExternalRecord(rec)) {
1131             continue;
1132         }
1133         auto m = CreateModule(prog, &rec, file);
1134         file->localModules.insert({rec.name, std::move(m)});
1135     }
1136     ResolveUnfoundModules(file);
1137 }
1138 
CollectAI(pandasm::Program * prog,AbckitFile * file)1139 void CollectAI(pandasm::Program *prog, AbckitFile *file)
1140 {
1141     for (auto &[recName, rec] : prog->record_table) {
1142         if (!libabckit::IsAnnotationInterfaceRecord(rec) || libabckit::IsServiceRecord(recName)) {
1143             continue;
1144         }
1145         LIBABCKIT_LOG(DEBUG) << "ANNOTATION: " << recName << ' ' << rec.name << '\n';
1146         CreateAnnotationInterface(file, recName, rec);
1147     }
1148 }
1149 
CollectNamespaces(pandasm::Program * prog,AbckitFile * file,std::vector<std::unique_ptr<AbckitCoreNamespace>> * namespaces,std::unordered_map<std::string,AbckitCoreNamespace * > * nameToNamespace)1150 void CollectNamespaces(pandasm::Program *prog, AbckitFile *file,
1151                        std::vector<std::unique_ptr<AbckitCoreNamespace>> *namespaces,
1152                        std::unordered_map<std::string, AbckitCoreNamespace *> *nameToNamespace)
1153 {
1154     for (auto &[functionName, function] : prog->function_table) {
1155         if (!IsNamespaceFunc(functionName)) {
1156             continue;
1157         }
1158         namespaces->emplace_back(CreateNamespace(function, file));
1159         ASSERT(nameToNamespace->count(function.name) == 0);
1160         (*nameToNamespace)[function.name] = namespaces->back().get();
1161     }
1162     AssignNamespacesToParent(*namespaces, *nameToNamespace);
1163 }
1164 
CreateWrappers(pandasm::Program * prog,AbckitFile * file)1165 void CreateWrappers(pandasm::Program *prog, AbckitFile *file)
1166 {
1167     file->program = prog;
1168 
1169     CollectModules(prog, file);
1170     CollectAI(prog, file);
1171     std::vector<std::unique_ptr<AbckitCoreNamespace>> namespaces;
1172     std::unordered_map<std::string, AbckitCoreNamespace *> nameToNamespace;
1173     CollectNamespaces(prog, file, &namespaces, &nameToNamespace);
1174 
1175     // Collect classes
1176     std::vector<std::unique_ptr<AbckitCoreClass>> classes;
1177     std::unordered_map<std::string, AbckitCoreClass *> nameToClass;
1178     for (auto &[functionName, function] : prog->function_table) {
1179         if (!libabckit::IsCtor(functionName)) {
1180             continue;
1181         }
1182         classes.emplace_back(CreateClass(functionName, function, file, nameToClass));
1183     }
1184 
1185     // Collect functions
1186     std::vector<std::unique_ptr<AbckitCoreFunction>> functions;
1187     std::unordered_map<std::string, AbckitCoreFunction *> nameToFunction;
1188     for (auto &[functionName, function] : prog->function_table) {
1189         LIBABCKIT_LOG(DEBUG) << "f: " << functionName << " ; " << function.name << '\n';
1190         if (!libabckit::IsFunction(functionName)) {
1191             continue;
1192         }
1193         auto abckitCoreFunction = CreateFunction(functionName, function, file);
1194         if (abckitCoreFunction == nullptr) {
1195             continue;
1196         }
1197         functions.emplace_back(std::move(abckitCoreFunction));
1198         ASSERT(nameToFunction.count(function.name) == 0);
1199         nameToFunction[function.name] = functions.back().get();
1200     }
1201 
1202     // Assign parents
1203     AssignClassesToParent(classes, nameToNamespace, nameToFunction);
1204     AssignFunctionsToParent(functions, nameToNamespace, nameToClass, nameToFunction);
1205 
1206     LIBABCKIT_LOG_DUMP(DumpHierarchy(file), DEBUG);
1207 
1208     // Strings
1209     for (auto &sImpl : prog->strings) {
1210         auto s = std::make_unique<AbckitString>();
1211         s->impl = sImpl;
1212         file->strings.insert({sImpl, std::move(s)});
1213     }
1214 }
1215 }  // namespace
1216 
1217 namespace libabckit {
1218 
1219 struct CtxIInternal {
1220     panda::abc2program::Abc2ProgramDriver *driver = nullptr;
1221 };
1222 
OpenAbcDynamic(const char * path,size_t len)1223 AbckitFile *OpenAbcDynamic(const char *path, size_t len)
1224 {
1225     LIBABCKIT_LOG_FUNC;
1226     auto spath = std::string(path, len);
1227     LIBABCKIT_LOG(DEBUG) << spath << '\n';
1228     auto *abc2program = new panda::abc2program::Abc2ProgramDriver();
1229     if (!abc2program->Compile(spath)) {
1230         LIBABCKIT_LOG(DEBUG) << "Failed to open " << spath << "\n";
1231         delete abc2program;
1232         return nullptr;
1233     }
1234     auto &prog = const_cast<pandasm::Program &>(abc2program->GetProgram());
1235     auto file = new AbckitFile();
1236     file->frontend = Mode::DYNAMIC;
1237     CreateWrappers(&prog, file);
1238 
1239     auto pf = panda_file::File::Open(spath);
1240     if (pf == nullptr) {
1241         LIBABCKIT_LOG(DEBUG) << "Failed to panda_file::File::Open\n";
1242         delete abc2program;
1243         delete file;
1244         return nullptr;
1245     }
1246 
1247     auto pandaFileVersion = pf->GetHeader()->version;
1248     uint8_t *fileVersion = pandaFileVersion.data();
1249 
1250     file->version = new uint8_t[ABCKIT_VERSION_SIZE];
1251     // NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic)
1252     std::copy(fileVersion, fileVersion + sizeof(uint8_t) * ABCKIT_VERSION_SIZE, file->version);
1253 
1254     file->internal = new CtxIInternal {abc2program};
1255     return file;
1256 }
1257 
WriteAbcDynamic(AbckitFile * file,const char * path,size_t len)1258 void WriteAbcDynamic(AbckitFile *file, const char *path, size_t len)
1259 {
1260     auto program = file->GetDynamicProgram();
1261 
1262     pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp = nullptr;
1263 
1264     EmitDynamicProgram(file, program, mapsp, false, std::string_view(path, len));
1265     if (statuses::GetLastError() != AbckitStatus::ABCKIT_STATUS_NO_ERROR) {
1266         return;
1267     }
1268 
1269     LIBABCKIT_LOG(DEBUG) << "SUCCESS\n";
1270 }
1271 
DestroyGraphDynamic(AbckitGraph * graph)1272 void DestroyGraphDynamic(AbckitGraph *graph)
1273 {
1274     LIBABCKIT_LOG_FUNC;
1275     GraphWrapper::DestroyGraphDynamic(graph);
1276 }
1277 
CloseFileDynamic(AbckitFile * file)1278 void CloseFileDynamic(AbckitFile *file)
1279 {
1280     LIBABCKIT_LOG_FUNC;
1281 
1282     auto *ctxIInternal = reinterpret_cast<struct CtxIInternal *>(file->internal);
1283     delete ctxIInternal->driver;
1284     delete ctxIInternal;
1285     delete[] file->version;
1286     delete file;
1287 }
1288 
1289 }  // namespace libabckit
1290