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