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