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
17 #include "libabckit/src/metadata_inspect_impl.h"
18 #include "libabckit/src/adapter_dynamic/helpers_dynamic.h"
19 #include "libabckit/src/logger.h"
20 #include "libabckit/src/statuses_impl.h"
21 #include "assembler/assembly-program.h"
22 #include "assembler/assembly-record.h"
23
24 #if defined(_WIN32)
25 #include <cwchar>
26 #include <codecvt>
27 #include <locale>
28 #endif
29 #include <cstdint>
30 #include <memory>
31
32 // CC-OFFNXT(WordsTool.95) sensitive word conflict
33 // NOLINTNEXTLINE(google-build-using-namespace)
34 using namespace panda;
35 // CC-OFFNXT(WordsTool.95) sensitive word conflict
36 // NOLINTNEXTLINE(google-build-using-namespace)
37 using namespace libabckit;
38
39 namespace {
40
41 // CC-OFFNXT(G.NAM.03) project code style
UpdateLitArrSectionPostAction(ModuleIterateData * data,std::pair<size_t,size_t> res)42 bool UpdateLitArrSectionPostAction(ModuleIterateData *data, std::pair<size_t, size_t> res)
43 {
44 bool *isChangeField {nullptr};
45 size_t *offset {nullptr};
46 if (data->isRegularImport.first) {
47 if (data->isRegularImport.second) {
48 ASSERT(data->payload->regularImportsOffset == res.second);
49 isChangeField = &(data->updateData.isRegularImportsChange);
50 offset = &(data->payload->regularImportsOffset);
51 } else {
52 offset = &(data->payload->namespaceImportsOffset);
53 }
54 } else {
55 switch (data->kind) {
56 case AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT: {
57 isChangeField = &(data->updateData.isLocalExportsChange);
58 offset = &(data->payload->localExportsOffset);
59 break;
60 }
61 case AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_INDIRECT_EXPORT: {
62 offset = &(data->payload->indirectExportsOffset);
63 break;
64 }
65 case AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_STAR_EXPORT: {
66 offset = &(data->payload->starExportsOffset);
67 break;
68 }
69 }
70 }
71
72 auto prevNum = std::get<uint32_t>(data->moduleLitArr->literals_[*offset - 1].value_);
73 auto newNum = std::get<uint32_t>((data->updateData.newLiterals)[res.second - 1].value_);
74 if (prevNum != newNum && (isChangeField != nullptr)) {
75 *isChangeField = true;
76 }
77 return true;
78 }
79
UpdateLitArrSection(ModuleIterateData * data,size_t idx,size_t fieldNum)80 std::pair<size_t, size_t> UpdateLitArrSection(ModuleIterateData *data, size_t idx, size_t fieldNum)
81 {
82 auto &newLiterals = data->updateData.newLiterals;
83 auto *idxMap =
84 data->isRegularImport.first ? &data->updateData.regularImportsIdxMap : &data->updateData.localExportsIdxMap;
85
86 auto num = std::get<uint32_t>(data->moduleLitArr->literals_[idx].value_);
87 newLiterals.push_back(std::move(data->moduleLitArr->literals_[idx++]));
88 auto newOffset = newLiterals.size();
89 auto prevOffset = idx;
90 uint32_t oldIdx = 0;
91 uint32_t actualNumber = 0;
92 while (idx < prevOffset + num * fieldNum) {
93 if (data->moduleLitArr->literals_[idx].tag_ == panda_file::LiteralTag::NULLVALUE) {
94 for (size_t i = 0; i < fieldNum; i++) {
95 idx++;
96 }
97 oldIdx++;
98 continue;
99 }
100 idxMap->emplace(oldIdx, actualNumber);
101 actualNumber++;
102 oldIdx++;
103 for (size_t i = 0; i < fieldNum; i++) {
104 newLiterals.push_back(std::move(data->moduleLitArr->literals_[idx++]));
105 }
106 }
107 if (actualNumber != num) {
108 newLiterals[newOffset - 1].value_ = actualNumber;
109 }
110 return {idx, newOffset};
111 }
112
IterateRequestIdxSectionBeforeUpdate(ModuleIterateData * data)113 size_t IterateRequestIdxSectionBeforeUpdate(ModuleIterateData *data)
114 {
115 auto &newLiterals = data->updateData.newLiterals;
116 size_t idx = 0;
117 while (idx < (data->payload->regularImportsOffset - 1)) {
118 newLiterals.push_back(std::move(data->moduleLitArr->literals_[idx++]));
119 }
120 return idx;
121 }
122
CheckRegularImport(ModuleUpdateData * updateData,panda::pandasm::Ins * inst)123 bool CheckRegularImport(ModuleUpdateData *updateData, panda::pandasm::Ins *inst)
124 {
125 if (updateData->isRegularImportsChange) {
126 if (inst->opcode == pandasm::Opcode::LDEXTERNALMODULEVAR ||
127 inst->opcode == pandasm::Opcode::WIDE_LDEXTERNALMODULEVAR) {
128 auto imm = static_cast<uint32_t>(std::get<int64_t>(inst->imms[0]));
129 auto foundIdx = updateData->regularImportsIdxMap.find(imm);
130 if (foundIdx == updateData->regularImportsIdxMap.end()) {
131 LIBABCKIT_LOG(DEBUG) << "There is an instruction '" << inst->ToString()
132 << "' with an unknown regular import index '" << std::hex << imm << "'\n";
133 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
134 return false;
135 }
136 inst->imms[0] = (int64_t)foundIdx->second;
137 }
138 }
139 return true;
140 }
141
CheckLocalExports(ModuleUpdateData * updateData,panda::pandasm::Ins * inst)142 bool CheckLocalExports(ModuleUpdateData *updateData, panda::pandasm::Ins *inst)
143 {
144 if (updateData->isLocalExportsChange) {
145 auto op = inst->opcode;
146 if (op == pandasm::Opcode::LDLOCALMODULEVAR || op == pandasm::Opcode::WIDE_LDLOCALMODULEVAR ||
147 op == pandasm::Opcode::STMODULEVAR || op == pandasm::Opcode::WIDE_STMODULEVAR) {
148 auto imm = static_cast<uint32_t>(std::get<int64_t>(inst->imms[0]));
149 auto foundIdx = updateData->localExportsIdxMap.find(imm);
150 if (foundIdx == updateData->localExportsIdxMap.end()) {
151 LIBABCKIT_LOG(DEBUG) << "There is an instruction '" << inst->ToString()
152 << "' with an unknown local export index '" << std::hex << imm << "'\n";
153 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
154 return false;
155 }
156 inst->imms[0] = (int64_t)foundIdx->second;
157 }
158 }
159 return true;
160 }
161
UpdateInsImms(pandasm::Program * program,ModuleUpdateData * updateData,const std::string & mainRecordName)162 bool UpdateInsImms(pandasm::Program *program, ModuleUpdateData *updateData, const std::string &mainRecordName)
163 {
164 for (auto &[name, func] : program->function_table) {
165 if (pandasm::GetOwnerName(name) != mainRecordName) {
166 continue;
167 }
168 for (auto &inst : func.ins) {
169 if (!CheckRegularImport(updateData, &inst)) {
170 return false;
171 }
172
173 if (!CheckLocalExports(updateData, &inst)) {
174 return false;
175 }
176 }
177 }
178 return true;
179 }
180
GetModulePayload(AbckitCoreModule * module)181 AbckitModulePayloadDyn *GetModulePayload(AbckitCoreModule *module)
182 {
183 switch (module->target) {
184 case ABCKIT_TARGET_JS:
185 return &(module->GetJsImpl()->impl);
186 break;
187 case ABCKIT_TARGET_ARK_TS_V1:
188 return &(module->GetArkTSImpl()->impl.GetDynModule());
189 default:
190 LIBABCKIT_UNREACHABLE;
191 }
192 }
193
UpdateModuleLiteralArray(AbckitFile * file,const std::string & recName)194 bool UpdateModuleLiteralArray(AbckitFile *file, const std::string &recName)
195 {
196 auto program = file->GetDynamicProgram();
197 auto module = file->localModules.find(recName);
198 if (module == file->localModules.end()) {
199 LIBABCKIT_LOG(DEBUG) << "Can not find module with name '" << recName << "'\n";
200 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
201 return false;
202 }
203 AbckitModulePayloadDyn *mPayload = GetModulePayload(module->second.get());
204 auto moduleLitArr = mPayload->moduleLiteralArray->GetDynamicImpl();
205 if (mPayload->absPaths) {
206 size_t idx = 1;
207 auto moduleBasePath = fs::path("./" + recName).remove_filename();
208 while (idx < (mPayload->regularImportsOffset - 1)) {
209 auto moduleAbsPath = std::get<std::string>(moduleLitArr->literals_[idx].value_);
210 if (moduleAbsPath[0] == '@') {
211 moduleLitArr->literals_[idx++].value_ = moduleAbsPath;
212 } else {
213 auto relativePath = Relative(moduleAbsPath, moduleBasePath).string();
214 moduleLitArr->literals_[idx++].value_ = fs::path("./").append(relativePath).string();
215 }
216 }
217 mPayload->absPaths = false;
218 }
219
220 bool modified = std::any_of(
221 moduleLitArr->literals_.cbegin(), moduleLitArr->literals_.cend(),
222 [](const pandasm::LiteralArray::Literal &lit) { return lit.tag_ == panda_file::LiteralTag::NULLVALUE; });
223 if (!modified) {
224 return true;
225 }
226
227 ModuleIterateData iterData;
228 iterData.m = module->second.get();
229 iterData.payload = mPayload;
230 iterData.moduleLitArr = moduleLitArr;
231
232 if (!IterateModuleSections(iterData, IterateRequestIdxSectionBeforeUpdate, UpdateLitArrSection,
233 UpdateLitArrSectionPostAction)) {
234 return false;
235 }
236
237 if (iterData.updateData.isRegularImportsChange || iterData.updateData.isLocalExportsChange) {
238 if (!UpdateInsImms(program, &iterData.updateData, recName)) {
239 return false;
240 }
241 }
242
243 moduleLitArr->literals_ = std::move(iterData.updateData.newLiterals);
244
245 LIBABCKIT_LOG_DUMP(DumpModuleArray(moduleLitArr, iterData.m->moduleName->impl), DEBUG);
246 return true;
247 }
248
249 } // namespace
250
251 namespace libabckit {
252
253 // CC-OFFNXT(G.FUN.01-CPP) helper function
EmitDynamicProgram(AbckitFile * file,pandasm::Program * program,pandasm::AsmEmitter::PandaFileToPandaAsmMaps * mapsp,bool getFile,std::string_view path)254 const panda_file::File *EmitDynamicProgram(AbckitFile *file, pandasm::Program *program,
255 pandasm::AsmEmitter::PandaFileToPandaAsmMaps *mapsp, bool getFile,
256 std::string_view path)
257 {
258 for (auto &[recName, rec] : program->record_table) {
259 if (!IsModuleDescriptorRecord(rec) || IsExternalRecord(rec)) {
260 continue;
261 }
262 if (!UpdateModuleLiteralArray(file, recName)) {
263 return nullptr;
264 }
265 }
266
267 const panda_file::File *pf = [&]() {
268 const panda_file::File *res {nullptr};
269 if (!getFile) {
270 std::map<std::string, size_t> *statp = nullptr;
271 if (!pandasm::AsmEmitter::Emit(std::string(path), *program, statp, mapsp)) {
272 LIBABCKIT_LOG_NO_FUNC(DEBUG)
273 << "[EmitDynamicProgram] FAILURE: " << pandasm::AsmEmitter::GetLastError() << '\n';
274 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
275 }
276 return res;
277 }
278 return pandasm::AsmEmitter::Emit(*program, mapsp, 1U).release();
279 }();
280 if (getFile && pf == nullptr) {
281 LIBABCKIT_LOG(DEBUG) << "FAILURE: " << pandasm::AsmEmitter::GetLastError() << '\n';
282 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
283 return nullptr;
284 }
285
286 return pf;
287 }
288
Relative(const fs::path & src,const fs::path & base)289 fs::path Relative(const fs::path &src, const fs::path &base)
290 {
291 #ifdef STD_FILESYSTEM_EXPERIMENTAL
292 fs::path tmpPath = src;
293 fs::path relPath;
294 while (fs::abcolute(tmpPath) != fs::absolute(base)) {
295 relPath = relPath.empty() ? tmpPath.filename() : tmpPath.filename() / relPath;
296 if (tmpPath == tmpPath.parent_path()) {
297 return "";
298 }
299 tmpPath = tmpPath.parent_path();
300 }
301 return relPath;
302 #else
303 return fs::relative(src, base);
304 #endif
305 }
306
IterateModuleSections(ModuleIterateData & data,const std::function<size_t (ModuleIterateData *)> & requestIdxSectionModifier,const std::function<std::pair<size_t,size_t> (ModuleIterateData *,size_t,size_t)> & sectionModifier,const std::function<bool (ModuleIterateData *,std::pair<size_t,size_t>)> & postAction)307 bool IterateModuleSections(
308 ModuleIterateData &data, const std::function<size_t(ModuleIterateData *)> &requestIdxSectionModifier,
309 const std::function<std::pair<size_t, size_t>(ModuleIterateData *, size_t, size_t)> §ionModifier,
310 const std::function<bool(ModuleIterateData *, std::pair<size_t, size_t>)> &postAction)
311 {
312 auto idx = requestIdxSectionModifier(&data);
313
314 data.isRegularImport = {true, true};
315 auto r = sectionModifier(&data, idx, 3U);
316 if (!postAction(&data, r)) {
317 return false;
318 }
319 idx = r.first;
320 data.payload->regularImportsOffset = r.second;
321
322 data.isRegularImport = {true, false};
323 r = sectionModifier(&data, idx, 2U);
324 if (!postAction(&data, r)) {
325 return false;
326 }
327 idx = r.first;
328 data.payload->namespaceImportsOffset = r.second;
329
330 data.isRegularImport = {false, false};
331 data.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT;
332 r = sectionModifier(&data, idx, 2U);
333 if (!postAction(&data, r)) {
334 return false;
335 }
336 idx = r.first;
337 data.payload->localExportsOffset = r.second;
338
339 data.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_INDIRECT_EXPORT;
340 r = sectionModifier(&data, idx, 3U);
341 if (!postAction(&data, r)) {
342 return false;
343 }
344 idx = r.first;
345 data.payload->indirectExportsOffset = r.second;
346
347 data.kind = AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_STAR_EXPORT;
348 r = sectionModifier(&data, idx, 1);
349 if (!postAction(&data, r)) {
350 return false;
351 }
352 data.payload->starExportsOffset = r.second;
353
354 return true;
355 }
356
DumpModuleRequests(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)357 void DumpModuleRequests(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
358 {
359 auto numModuleRequests = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
360 auto moduleRequestsOffset = idx;
361 ss << "\n numModuleRequests " << numModuleRequests << " | offset " << idx << std::endl;
362 while (idx < moduleRequestsOffset + numModuleRequests) {
363 ss << " [\n";
364 ss << " module_request: " << std::get<std::string>(moduleLitArr->literals_[idx].value_) << std::endl;
365 idx++;
366 ss << " ]\n";
367 }
368 }
369
DumpRegularImports(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)370 void DumpRegularImports(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
371 {
372 auto numRegularImports = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
373 auto regularImportsOffset = idx;
374 ss << " numRegularImports " << numRegularImports << " | offset " << idx << std::endl;
375 while (idx < regularImportsOffset + numRegularImports * 3U) {
376 ss << " [\n";
377 ss << " localNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
378 << std::endl;
379 idx++;
380 ss << " importNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
381 << std::endl;
382 idx++;
383 ss << " moduleRequestIdx: " << std::get<uint16_t>(moduleLitArr->literals_[idx].value_) << std::endl;
384 idx++;
385 ss << " ]\n";
386 }
387 }
388
DumpNamespaceImports(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)389 void DumpNamespaceImports(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
390 {
391 auto numNamespaceImports = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
392 auto namespaceImportsOffset = idx;
393 ss << " numNamespaceImports " << numNamespaceImports << " | offset " << idx << std::endl;
394 while (idx < namespaceImportsOffset + numNamespaceImports * 2U) {
395 ss << " [\n";
396 ss << " localNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
397 << std::endl;
398 idx++;
399 ss << " moduleRequestIdx: " << std::get<uint16_t>(moduleLitArr->literals_[idx].value_) << std::endl;
400 idx++;
401 ss << " ]\n";
402 }
403 }
404
DumpLocalExports(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)405 void DumpLocalExports(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
406 {
407 auto numLocalExports = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
408 auto localExportsOffset = idx;
409 ss << " numLocalExports " << numLocalExports << " | offset " << idx << std::endl;
410 while (idx < localExportsOffset + numLocalExports * 2U) {
411 ss << " [\n";
412 ss << " localNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
413 << std::endl;
414 idx++;
415 ss << " exportNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
416 << std::endl;
417 idx++;
418 ss << " ]\n";
419 }
420 }
421
DumpIndirectExports(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)422 void DumpIndirectExports(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
423 {
424 auto numIndirectExports = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
425 auto indirectExportsOffset = idx;
426 ss << " numIndirectExports " << numIndirectExports << " | offset " << idx << std::endl;
427 while (idx < indirectExportsOffset + numIndirectExports * 3U) {
428 ss << " [\n";
429 ss << " exportNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
430 << std::endl;
431 idx++;
432 ss << " importNameOffset: " << std::get<std::string>(moduleLitArr->literals_[idx].value_)
433 << std::endl;
434 idx++;
435 ss << " moduleRequestIdx: " << std::get<uint16_t>(moduleLitArr->literals_[idx].value_) << std::endl;
436 idx++;
437 ss << " ]\n";
438 }
439 }
440
DumpStarExports(const pandasm::LiteralArray * moduleLitArr,size_t & idx,std::stringstream & ss)441 void DumpStarExports(const pandasm::LiteralArray *moduleLitArr, size_t &idx, std::stringstream &ss)
442 {
443 auto numStarExports = std::get<uint32_t>(moduleLitArr->literals_[idx++].value_);
444 auto starExportsOffset = idx;
445 ss << " numStarExports " << numStarExports << " | offset " << idx << std::endl;
446 while (idx < starExportsOffset + numStarExports) {
447 ss << " [\n";
448 ss << " moduleRequestIdx: " << std::get<uint16_t>(moduleLitArr->literals_[idx].value_) << std::endl;
449 idx++;
450 ss << " ]\n";
451 }
452 ss << "]\n";
453 }
454
DumpModuleArray(const pandasm::LiteralArray * moduleLitArr,std::string_view name)455 void DumpModuleArray(const pandasm::LiteralArray *moduleLitArr, std::string_view name)
456 {
457 std::stringstream ss;
458 ss << "ModuleLiteralArray " << name << " \n[";
459 size_t idx = 0;
460
461 DumpModuleRequests(moduleLitArr, idx, ss);
462 DumpRegularImports(moduleLitArr, idx, ss);
463 DumpNamespaceImports(moduleLitArr, idx, ss);
464 DumpLocalExports(moduleLitArr, idx, ss);
465 DumpIndirectExports(moduleLitArr, idx, ss);
466 DumpStarExports(moduleLitArr, idx, ss);
467 LIBABCKIT_LOG(DEBUG) << ss.str();
468 }
469
IsServiceRecord(const std::string & name)470 bool IsServiceRecord(const std::string &name)
471 {
472 constexpr const std::string_view TSTYPE_ANNO_RECORD_NAME = "_TestAnnotation";
473 return name == TSTYPE_ANNO_RECORD_NAME || name == "_ESConcurrentModuleRequestsAnnotation" ||
474 name == "L_ESSlotNumberAnnotation" || name == "_ESSlotNumberAnnotation" ||
475 name == "_ESExpectedPropertyCountAnnotation";
476 }
477
IsModuleDescriptorRecord(const pandasm::Record & rec)478 bool IsModuleDescriptorRecord(const pandasm::Record &rec)
479 {
480 constexpr std::array<std::string_view, 2> REQUIRED_FIELDS = {
481 "moduleRecordIdx",
482 "scopeNames",
483 };
484
485 for (const auto &fieldName : REQUIRED_FIELDS) {
486 auto it = std::find_if(rec.field_list.begin(), rec.field_list.end(),
487 [&fieldName](const auto &field) { return fieldName == field.name; });
488 if (it == rec.field_list.end()) {
489 return false;
490 }
491 }
492
493 return true;
494 }
495
IsAnnotationInterfaceRecord(const pandasm::Record & rec)496 bool IsAnnotationInterfaceRecord(const pandasm::Record &rec)
497 {
498 return (rec.metadata->GetAccessFlags() & ACC_ANNOTATION) != 0;
499 }
500
IsExternalRecord(const pandasm::Record & rec)501 bool IsExternalRecord(const pandasm::Record &rec)
502 {
503 return rec.metadata->IsForeign();
504 }
505
IsMain(const std::string & funcName)506 bool IsMain(const std::string &funcName)
507 {
508 size_t dotPos = funcName.rfind('.');
509 ASSERT(dotPos != std::string::npos);
510 return funcName.substr(dotPos + 1) == "func_main_0";
511 }
512
IsFunction(const std::string & fullFuncName)513 bool IsFunction(const std::string &fullFuncName)
514 {
515 if (IsMain(fullFuncName)) {
516 return true;
517 }
518 size_t dotPos = fullFuncName.rfind('.');
519 ASSERT(dotPos != std::string::npos);
520 std::string funcName = fullFuncName.substr(dotPos);
521 for (auto &sub : {"<#", ">#", "=#", "*#"}) {
522 if (funcName.find(sub) != std::string::npos) {
523 return true;
524 }
525 }
526 return false;
527 }
528
IsCtor(const std::string & funcName)529 bool IsCtor(const std::string &funcName)
530 {
531 return funcName.find("=#") != std::string::npos;
532 }
533
IsStatic(const std::string & funcName)534 bool IsStatic(const std::string &funcName)
535 {
536 if (IsMain(funcName)) {
537 return true;
538 }
539 if (funcName.find("<#") != std::string::npos) {
540 return true;
541 }
542 return funcName.find("*#") != std::string::npos;
543 }
544
IsAnonymousName(const std::string & funcName)545 bool IsAnonymousName(const std::string &funcName)
546 {
547 if (IsMain(funcName)) {
548 return false;
549 }
550 size_t pos = funcName.rfind('#');
551 ASSERT(pos != std::string::npos);
552 std::string name = funcName.substr(pos + 1);
553 return name.empty() || name.find('^') == 0;
554 }
555
DemangleScopeName(const std::string & mangled,const AbckitLiteralArray * scopeNames)556 static std::string DemangleScopeName(const std::string &mangled, const AbckitLiteralArray *scopeNames)
557 {
558 size_t scopeIdx = stoi(mangled);
559 auto *litArr = scopeNames->GetDynamicImpl();
560 ASSERT(litArr->literals_.size() % 2U == 0);
561 ASSERT(scopeIdx < litArr->literals_.size());
562 auto &lit = litArr->literals_[scopeIdx * 2 + 1];
563 ASSERT(lit.tag_ == panda_file::LiteralTag::STRING);
564 return std::get<std::string>(lit.value_);
565 }
566
GetDynFunction(AbckitCoreFunction * function)567 panda::pandasm::Function *GetDynFunction(AbckitCoreFunction *function)
568 {
569 switch (function->owningModule->target) {
570 case ABCKIT_TARGET_JS:
571 return function->GetJsImpl()->impl;
572 case ABCKIT_TARGET_ARK_TS_V1:
573 return function->GetArkTSImpl()->GetDynamicImpl();
574 default:
575 LIBABCKIT_UNREACHABLE;
576 }
577 }
578
GetDynFunction(AbckitCoreClass * klass)579 panda::pandasm::Function *GetDynFunction(AbckitCoreClass *klass)
580 {
581 switch (klass->owningModule->target) {
582 case ABCKIT_TARGET_JS:
583 return klass->GetJsImpl()->impl;
584 case ABCKIT_TARGET_ARK_TS_V1:
585 return klass->GetArkTSImpl()->impl.GetDynamicClass();
586 default:
587 LIBABCKIT_UNREACHABLE;
588 }
589 }
590
GetDynModulePayload(AbckitCoreModule * mod)591 AbckitModulePayloadDyn *GetDynModulePayload(AbckitCoreModule *mod)
592 {
593 switch (mod->target) {
594 case ABCKIT_TARGET_JS:
595 return &mod->GetJsImpl()->impl;
596 case ABCKIT_TARGET_ARK_TS_V1:
597 return &mod->GetArkTSImpl()->impl.GetDynModule();
598 default:
599 LIBABCKIT_UNREACHABLE;
600 }
601 }
602
GetDynImportDescriptorPayload(AbckitCoreImportDescriptor * id)603 AbckitDynamicImportDescriptorPayload *GetDynImportDescriptorPayload(AbckitCoreImportDescriptor *id)
604 {
605 switch (id->importingModule->target) {
606 case ABCKIT_TARGET_JS:
607 return &id->GetJsImpl()->payload.GetDynId();
608 case ABCKIT_TARGET_ARK_TS_V1:
609 return &id->GetArkTSImpl()->payload.GetDynId();
610 default:
611 LIBABCKIT_UNREACHABLE;
612 }
613 }
614
GetDynExportDescriptorPayload(AbckitCoreExportDescriptor * ed)615 AbckitDynamicExportDescriptorPayload *GetDynExportDescriptorPayload(AbckitCoreExportDescriptor *ed)
616 {
617 AbckitDynamicExportDescriptorPayload *edPayload = nullptr;
618 switch (ed->exportingModule->target) {
619 case ABCKIT_TARGET_JS:
620 edPayload = &ed->GetJsImpl()->payload.GetDynamicPayload();
621 break;
622 case ABCKIT_TARGET_ARK_TS_V1:
623 edPayload = &ed->GetArkTSImpl()->payload.GetDynamicPayload();
624 break;
625 default:
626 LIBABCKIT_UNREACHABLE;
627 }
628 return edPayload;
629 }
630
GetClassNameFromCtor(const std::string & ctorName,const AbckitLiteralArray * scopeNames)631 std::string GetClassNameFromCtor(const std::string &ctorName, const AbckitLiteralArray *scopeNames)
632 {
633 ASSERT(IsCtor(ctorName));
634 auto className = ctorName.substr(ctorName.find('~') + 1);
635 className = className.substr(0, className.find("=#"));
636 if (className[0] != '@') {
637 return className;
638 }
639 return DemangleScopeName(className.substr(1), scopeNames);
640 }
641
642 template <class T>
FindOrCreateLiteral(AbckitFile * file,std::unordered_map<T,std::unique_ptr<AbckitLiteral>> & cache,T value,panda_file::LiteralTag tagImpl)643 static AbckitLiteral *FindOrCreateLiteral(AbckitFile *file,
644 std::unordered_map<T, std::unique_ptr<AbckitLiteral>> &cache, T value,
645 panda_file::LiteralTag tagImpl)
646 {
647 if (cache.count(value) == 1) {
648 return cache[value].get();
649 }
650
651 auto literalDeleter = [](pandasm_Literal *p) -> void {
652 delete reinterpret_cast<pandasm::LiteralArray::Literal *>(p);
653 };
654
655 auto *literal = new pandasm::LiteralArray::Literal();
656 literal->tag_ = tagImpl;
657 literal->value_ = value;
658 auto abcLit = std::make_unique<AbckitLiteral>(
659 file, AbckitLiteralImplT(reinterpret_cast<pandasm_Literal *>(literal), literalDeleter));
660 cache.insert({value, std::move(abcLit)});
661 return cache[value].get();
662 }
663
FindOrCreateLiteralBoolDynamicImpl(AbckitFile * file,bool value)664 AbckitLiteral *FindOrCreateLiteralBoolDynamicImpl(AbckitFile *file, bool value)
665 {
666 return FindOrCreateLiteral(file, file->literals.boolLits, value, panda_file::LiteralTag::BOOL);
667 }
668
FindOrCreateLiteralU8DynamicImpl(AbckitFile * file,uint8_t value)669 AbckitLiteral *FindOrCreateLiteralU8DynamicImpl(AbckitFile *file, uint8_t value)
670 {
671 return FindOrCreateLiteral(file, file->literals.u8Lits, value, panda_file::LiteralTag::ARRAY_U8);
672 }
673
FindOrCreateLiteralU16DynamicImpl(AbckitFile * file,uint16_t value)674 AbckitLiteral *FindOrCreateLiteralU16DynamicImpl(AbckitFile *file, uint16_t value)
675 {
676 return FindOrCreateLiteral(file, file->literals.u16Lits, value, panda_file::LiteralTag::ARRAY_U16);
677 }
678
FindOrCreateLiteralMethodAffiliateDynamicImpl(AbckitFile * file,uint16_t value)679 AbckitLiteral *FindOrCreateLiteralMethodAffiliateDynamicImpl(AbckitFile *file, uint16_t value)
680 {
681 return FindOrCreateLiteral(file, file->literals.methodAffilateLits, value, panda_file::LiteralTag::METHODAFFILIATE);
682 }
683
FindOrCreateLiteralU32DynamicImpl(AbckitFile * file,uint32_t value)684 AbckitLiteral *FindOrCreateLiteralU32DynamicImpl(AbckitFile *file, uint32_t value)
685 {
686 return FindOrCreateLiteral(file, file->literals.u32Lits, value, panda_file::LiteralTag::INTEGER);
687 }
688
FindOrCreateLiteralU64DynamicImpl(AbckitFile * file,uint64_t value)689 AbckitLiteral *FindOrCreateLiteralU64DynamicImpl(AbckitFile *file, uint64_t value)
690 {
691 return FindOrCreateLiteral(file, file->literals.u64Lits, value, panda_file::LiteralTag::ARRAY_U64);
692 }
693
FindOrCreateLiteralFloatDynamicImpl(AbckitFile * file,float value)694 AbckitLiteral *FindOrCreateLiteralFloatDynamicImpl(AbckitFile *file, float value)
695 {
696 return FindOrCreateLiteral(file, file->literals.floatLits, value, panda_file::LiteralTag::FLOAT);
697 }
698
FindOrCreateLiteralDoubleDynamicImpl(AbckitFile * file,double value)699 AbckitLiteral *FindOrCreateLiteralDoubleDynamicImpl(AbckitFile *file, double value)
700 {
701 return FindOrCreateLiteral(file, file->literals.doubleLits, value, panda_file::LiteralTag::DOUBLE);
702 }
703
FindOrCreateLiteralLiteralArrayDynamicImpl(AbckitFile * file,const std::string & value)704 AbckitLiteral *FindOrCreateLiteralLiteralArrayDynamicImpl(AbckitFile *file, const std::string &value)
705 {
706 return FindOrCreateLiteral(file, file->literals.litArrLits, value, panda_file::LiteralTag::LITERALARRAY);
707 }
708
FindOrCreateLiteralStringDynamicImpl(AbckitFile * file,const std::string & value)709 AbckitLiteral *FindOrCreateLiteralStringDynamicImpl(AbckitFile *file, const std::string &value)
710 {
711 return FindOrCreateLiteral(file, file->literals.stringLits, value, panda_file::LiteralTag::STRING);
712 }
713
FindOrCreateLiteralMethodDynamicImpl(AbckitFile * file,const std::string & value)714 AbckitLiteral *FindOrCreateLiteralMethodDynamicImpl(AbckitFile *file, const std::string &value)
715 {
716 return FindOrCreateLiteral(file, file->literals.methodLits, value, panda_file::LiteralTag::METHOD);
717 }
718
FindOrCreateLiteralDynamic(AbckitFile * file,const pandasm::LiteralArray::Literal & value)719 AbckitLiteral *FindOrCreateLiteralDynamic(AbckitFile *file, const pandasm::LiteralArray::Literal &value)
720 {
721 switch (value.tag_) {
722 case panda_file::LiteralTag::ARRAY_U1:
723 case panda_file::LiteralTag::BOOL:
724 return FindOrCreateLiteralBoolDynamicImpl(file, std::get<bool>(value.value_));
725 case panda_file::LiteralTag::ARRAY_U8:
726 case panda_file::LiteralTag::ARRAY_I8:
727 return FindOrCreateLiteralU8DynamicImpl(file, std::get<uint8_t>(value.value_));
728 case panda_file::LiteralTag::ARRAY_U16:
729 case panda_file::LiteralTag::ARRAY_I16:
730 return FindOrCreateLiteralU16DynamicImpl(file, std::get<uint16_t>(value.value_));
731 case panda_file::LiteralTag::ARRAY_U32:
732 case panda_file::LiteralTag::ARRAY_I32:
733 case panda_file::LiteralTag::INTEGER:
734 return FindOrCreateLiteralU32DynamicImpl(file, std::get<uint32_t>(value.value_));
735 case panda_file::LiteralTag::ARRAY_U64:
736 case panda_file::LiteralTag::ARRAY_I64:
737 return FindOrCreateLiteralU64DynamicImpl(file, std::get<uint64_t>(value.value_));
738 case panda_file::LiteralTag::ARRAY_F32:
739 case panda_file::LiteralTag::FLOAT:
740 return FindOrCreateLiteralFloatDynamicImpl(file, std::get<float>(value.value_));
741 case panda_file::LiteralTag::ARRAY_F64:
742 case panda_file::LiteralTag::DOUBLE:
743 return FindOrCreateLiteralDoubleDynamicImpl(file, std::get<double>(value.value_));
744 case panda_file::LiteralTag::ARRAY_STRING:
745 case panda_file::LiteralTag::STRING:
746 return FindOrCreateLiteralStringDynamicImpl(file, std::get<std::string>(value.value_));
747 case panda_file::LiteralTag::METHOD:
748 case panda_file::LiteralTag::GETTER:
749 case panda_file::LiteralTag::SETTER:
750 case panda_file::LiteralTag::GENERATORMETHOD:
751 case panda_file::LiteralTag::ASYNCGENERATORMETHOD:
752 return FindOrCreateLiteralMethodDynamicImpl(file, std::get<std::string>(value.value_));
753 case panda_file::LiteralTag::METHODAFFILIATE:
754 return FindOrCreateLiteralMethodAffiliateDynamicImpl(file, std::get<uint16_t>(value.value_));
755 case panda_file::LiteralTag::LITERALARRAY:
756 return FindOrCreateLiteralLiteralArrayDynamicImpl(file, std::get<std::string>(value.value_));
757 default:
758 LIBABCKIT_UNREACHABLE;
759 }
760 }
761
762 template <class T, pandasm::Value::Type PANDASM_VALUE_TYPE>
FindOrCreateScalarValue(AbckitFile * file,std::unordered_map<T,std::unique_ptr<AbckitValue>> & cache,T value)763 static AbckitValue *FindOrCreateScalarValue(AbckitFile *file,
764 std::unordered_map<T, std::unique_ptr<AbckitValue>> &cache, T value)
765 {
766 if (cache.count(value) == 1) {
767 return cache[value].get();
768 }
769
770 auto valueDeleter = [](pandasm_Value *val) -> void { delete reinterpret_cast<panda::pandasm::ScalarValue *>(val); };
771
772 auto *pval = new pandasm::ScalarValue(pandasm::ScalarValue::Create<PANDASM_VALUE_TYPE>(value));
773 auto abcVal =
774 std::make_unique<AbckitValue>(file, AbckitValueImplT(reinterpret_cast<pandasm_Value *>(pval), valueDeleter));
775 cache.insert({value, std::move(abcVal)});
776 return cache[value].get();
777 }
778
FindOrCreateValueU1DynamicImpl(AbckitFile * file,bool value)779 AbckitValue *FindOrCreateValueU1DynamicImpl(AbckitFile *file, bool value)
780 {
781 return FindOrCreateScalarValue<bool, panda::pandasm::Value::Type::U1>(file, file->values.boolVals, value);
782 }
783
FindOrCreateValueDoubleDynamicImpl(AbckitFile * file,double value)784 AbckitValue *FindOrCreateValueDoubleDynamicImpl(AbckitFile *file, double value)
785 {
786 return FindOrCreateScalarValue<double, panda::pandasm::Value::Type::F64>(file, file->values.doubleVals, value);
787 }
788
FindOrCreateValueStringDynamicImpl(AbckitFile * file,const std::string & value)789 AbckitValue *FindOrCreateValueStringDynamicImpl(AbckitFile *file, const std::string &value)
790 {
791 return FindOrCreateScalarValue<std::string, panda::pandasm::Value::Type::STRING>(file, file->values.stringVals,
792 value);
793 }
794
FindOrCreateLiteralArrayValueDynamicImpl(AbckitFile * file,const std::string & value)795 AbckitValue *FindOrCreateLiteralArrayValueDynamicImpl(AbckitFile *file, const std::string &value)
796 {
797 return FindOrCreateScalarValue<std::string, panda::pandasm::Value::Type::LITERALARRAY>(
798 file, file->values.litarrVals, value);
799 }
800
FindOrCreateValueDynamic(AbckitFile * file,const pandasm::Value & value)801 AbckitValue *FindOrCreateValueDynamic(AbckitFile *file, const pandasm::Value &value)
802 {
803 switch (value.GetType()) {
804 case pandasm::Value::Type::U1:
805 return FindOrCreateValueU1DynamicImpl(file, value.GetAsScalar()->GetValue<bool>());
806 case pandasm::Value::Type::F64:
807 return FindOrCreateValueDoubleDynamicImpl(file, value.GetAsScalar()->GetValue<double>());
808 case pandasm::Value::Type::STRING:
809 return FindOrCreateValueStringDynamicImpl(file, value.GetAsScalar()->GetValue<std::string>());
810 case pandasm::Value::Type::LITERALARRAY:
811 return FindOrCreateLiteralArrayValueDynamicImpl(file, value.GetAsScalar()->GetValue<std::string>());
812 case pandasm::Value::Type::I8:
813 case pandasm::Value::Type::U8:
814 case pandasm::Value::Type::I16:
815 case pandasm::Value::Type::U16:
816 case pandasm::Value::Type::I32:
817 case pandasm::Value::Type::U32:
818 case pandasm::Value::Type::I64:
819 case pandasm::Value::Type::U64:
820 case pandasm::Value::Type::F32:
821 case pandasm::Value::Type::STRING_NULLPTR:
822 case pandasm::Value::Type::RECORD:
823 case pandasm::Value::Type::METHOD:
824 case pandasm::Value::Type::ENUM:
825 case pandasm::Value::Type::ANNOTATION:
826 case pandasm::Value::Type::ARRAY:
827 case pandasm::Value::Type::VOID:
828 case pandasm::Value::Type::METHOD_HANDLE:
829 case pandasm::Value::Type::UNKNOWN:
830 default:
831 LIBABCKIT_UNREACHABLE;
832 }
833 }
834
835 } // namespace libabckit
836