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 "helpers_static.h"
17 #include "libabckit/src/adapter_static/metadata_inspect_static.h"
18 #include "assembler/annotation.h"
19 #include "libabckit/include/c/statuses.h"
20 #include "libabckit/src/helpers_common.h"
21 #include "libabckit/src/macros.h"
22 #include "libabckit/src/metadata_inspect_impl.h"
23 #include "libabckit/src/ir_impl.h"
24 #include "libabckit/src/adapter_static/runtime_adapter_static.h"
25 #include "libabckit/src/adapter_static/metadata_modify_static.h"
26 #include "libabckit/src/adapter_static/ir_static.h"
27
28 #include "libabckit/src/wrappers/graph_wrapper/graph_wrapper.h"
29
30 #include "mem/arena_allocator.h"
31 #include "modifiers.h"
32 #include "src/logger.h"
33 #include "static_core/assembler/assembly-program.h"
34 #include "static_core/assembler/mangling.h"
35 #include "static_core/assembler/assembly-emitter.h"
36
37 #include "static_core/compiler/compiler_options.h"
38 #include "static_core/compiler/optimizer/ir/graph.h"
39 #include "static_core/compiler/optimizer/ir_builder/ir_builder.h"
40 #include "static_core/compiler/optimizer/optimizations/cleanup.h"
41 #include "static_core/bytecode_optimizer/check_resolver.h"
42
43 #include <cstdint>
44 #include <iostream>
45
46 // CC-OFFNXT(WordsTool.95) sensitive word conflict
47 // NOLINTNEXTLINE(google-build-using-namespace)
48 using namespace ark;
49
50 namespace libabckit {
51
52 // ========================================
53 // Module
54 // ========================================
55
ModuleEnumerateAnonymousFunctionsStatic(AbckitCoreModule * m,void * data,bool (* cb)(AbckitCoreFunction * function,void * data))56 bool ModuleEnumerateAnonymousFunctionsStatic(AbckitCoreModule *m, void *data,
57 bool (*cb)(AbckitCoreFunction *function, void *data))
58 {
59 LIBABCKIT_LOG_FUNC;
60 LIBABCKIT_BAD_ARGUMENT(m, false)
61 LIBABCKIT_BAD_ARGUMENT(cb, false)
62 for (auto &function : m->functions) {
63 if (!FunctionIsAnonymousStatic(function.get())) {
64 continue;
65 }
66 if (!cb(function.get(), data)) {
67 return false;
68 }
69 }
70 return true;
71 }
72
73 // ========================================
74 // Namespace
75 // ========================================
76
77 // ========================================
78 // Class
79 // ========================================
80
ClassGetNameStatic(AbckitCoreClass * klass)81 AbckitString *ClassGetNameStatic(AbckitCoreClass *klass)
82 {
83 LIBABCKIT_LOG_FUNC;
84 auto *record = klass->GetArkTSImpl()->impl.GetStaticClass();
85 auto [moduleName, className] = ClassGetNames(record->name);
86
87 return CreateStringStatic(klass->owningModule->file, className.data(), className.size());
88 }
89
90 // ========================================
91 // Function
92 // ========================================
FunctionGetNameStatic(AbckitCoreFunction * function)93 AbckitString *FunctionGetNameStatic(AbckitCoreFunction *function)
94 {
95 LIBABCKIT_LOG_FUNC;
96 auto *functionImpl = function->GetArkTSImpl()->GetStaticImpl();
97
98 auto functionName = pandasm::MangleFunctionName(functionImpl->name, functionImpl->params, functionImpl->returnType);
99 auto croppedName = FuncNameCropModule(functionName);
100 return CreateStringStatic(function->owningModule->file, croppedName.data(), croppedName.size());
101 }
102
GetMethodOffset(pandasm::Function * func,pandasm::AsmEmitter::PandaFileToPandaAsmMaps * maps,uint32_t * methodOffset)103 bool GetMethodOffset(pandasm::Function *func, pandasm::AsmEmitter::PandaFileToPandaAsmMaps *maps,
104 uint32_t *methodOffset)
105 {
106 auto funcFullName = pandasm::MangleFunctionName(func->name, func->params, func->returnType);
107 for (auto &[id, s] : maps->methods) {
108 if (s == funcFullName) {
109 *methodOffset = id;
110 }
111 }
112 if (*methodOffset == 0) {
113 LIBABCKIT_LOG(DEBUG) << "methodOffset == 0\n";
114 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
115 return false;
116 }
117 return true;
118 }
119
RemoveInsts(compiler::Graph * graphImpl)120 void RemoveInsts(compiler::Graph *graphImpl)
121 {
122 graphImpl->RunPass<ark::bytecodeopt::CheckResolver>();
123 graphImpl->RunPass<compiler::Cleanup>(false);
124 std::vector<std::pair<compiler::BasicBlock *, compiler::Inst *>> instsToRemove;
125 for (auto bb : graphImpl->GetBlocksRPO()) {
126 for ([[maybe_unused]] auto inst : bb->AllInsts()) {
127 if (inst->IsSaveState() || (inst->GetOpcode() == compiler::Opcode::SaveStateDeoptimize)) {
128 ASSERT(!inst->HasUsers());
129 /*
130 * NOTE(nsizov): find out why we still have non-movable
131 * SaveStates with no users
132 */
133 instsToRemove.emplace_back(bb, inst);
134 }
135 }
136 }
137 for (auto &[bb, inst] : instsToRemove) {
138 bb->RemoveInst(inst);
139 }
140 }
141
DeleteGraphArgs(ArenaAllocator * allocator,ArenaAllocator * localAllocator,AbckitRuntimeAdapterStatic * adapter,AbckitIrInterface * irInterface)142 static void DeleteGraphArgs(ArenaAllocator *allocator, ArenaAllocator *localAllocator,
143 AbckitRuntimeAdapterStatic *adapter, AbckitIrInterface *irInterface)
144 {
145 delete allocator;
146 delete localAllocator;
147 delete adapter;
148 delete irInterface;
149 }
150
CreateGraph(AbckitCoreFunction * function,AbckitIrInterface * irInterface,ark::compiler::Graph * graphImpl,AbckitRuntimeAdapterStatic * adapter)151 static AbckitGraph *CreateGraph(AbckitCoreFunction *function, AbckitIrInterface *irInterface,
152 ark::compiler::Graph *graphImpl, AbckitRuntimeAdapterStatic *adapter)
153 {
154 auto graph = new AbckitGraph;
155 graph->file = function->owningModule->file;
156 graph->function = function;
157 graph->irInterface = irInterface;
158 graph->impl = graphImpl;
159 GraphWrapper::CreateGraphWrappers(graph);
160
161 auto *ctxGInternal =
162 new CtxGInternal {graphImpl->GetAllocator(), graphImpl->GetLocalAllocator(), irInterface, adapter};
163 graph->internal = ctxGInternal;
164 LIBABCKIT_LOG_DUMP(GdumpStatic(graph, STDERR_FILENO), DEBUG);
165 return graph;
166 }
167
CreateGraphFromFunctionStatic(AbckitCoreFunction * function)168 AbckitGraph *CreateGraphFromFunctionStatic(AbckitCoreFunction *function)
169 {
170 LIBABCKIT_LOG_FUNC;
171
172 ark::compiler::g_options.SetCompilerFrameSize("default");
173 ark::compiler::g_options.SetCompilerUseSafepoint(false);
174 auto *func = function->GetArkTSImpl()->GetStaticImpl();
175
176 LIBABCKIT_LOG_DUMP(func->DebugDump(), DEBUG);
177 LIBABCKIT_LOG(DEBUG) << func->name << '\n';
178
179 auto program = function->owningModule->file->GetStaticProgram();
180
181 auto maps = std::make_unique<pandasm::AsmEmitter::PandaFileToPandaAsmMaps>();
182 auto pf = pandasm::AsmEmitter::Emit(*program, maps.get()).release();
183 if (pf == nullptr) {
184 LIBABCKIT_LOG(DEBUG) << "FAILURE: " << pandasm::AsmEmitter::GetLastError() << '\n';
185 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
186 return nullptr;
187 }
188
189 uint32_t methodOffset = 0;
190 if (!GetMethodOffset(func, maps.get(), &methodOffset)) {
191 return nullptr;
192 }
193
194 auto *irInterface =
195 new AbckitIrInterface(maps->methods, maps->fields, maps->classes, maps->strings, maps->literalarrays);
196
197 auto *allocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER);
198 auto *localAllocator = new ArenaAllocator(SpaceType::SPACE_TYPE_COMPILER, nullptr, true);
199 auto *adapter = new AbckitRuntimeAdapterStatic(*pf);
200
201 auto methodPtr = reinterpret_cast<compiler::RuntimeInterface::MethodPtr>(methodOffset); // NOTE
202 auto graphImpl = allocator->New<compiler::Graph>(
203 compiler::Graph::GraphArgs {allocator, localAllocator, Arch::NONE, methodPtr, adapter}, nullptr, false, false,
204 true);
205 if (graphImpl == nullptr) {
206 DeleteGraphArgs(allocator, localAllocator, adapter, irInterface);
207 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_MEMORY_ALLOCATION);
208 return nullptr;
209 }
210 graphImpl->SetLanguage(SourceLanguage::ETS);
211 graphImpl->SetAbcKit();
212 #ifndef NDEBUG
213 graphImpl->SetLowLevelInstructionsEnabled();
214 #endif
215
216 bool irBuilderRes = graphImpl->RunPass<ark::compiler::IrBuilder>();
217 if (!irBuilderRes) {
218 DeleteGraphArgs(allocator, localAllocator, adapter, irInterface);
219 statuses::SetLastError(AbckitStatus::ABCKIT_STATUS_INTERNAL_ERROR);
220 return nullptr;
221 }
222
223 RemoveInsts(graphImpl);
224 graphImpl->RemoveUnreachableBlocks();
225 GraphInvalidateAnalyses(graphImpl);
226 CheckInvalidOpcodes(graphImpl, false);
227
228 return CreateGraph(function, irInterface, graphImpl, adapter);
229 }
230
FunctionIsStaticStatic(AbckitCoreFunction * function)231 bool FunctionIsStaticStatic(AbckitCoreFunction *function)
232 {
233 LIBABCKIT_LOG_FUNC;
234 auto *func = function->GetArkTSImpl()->GetStaticImpl();
235 return (func->metadata->GetAccessFlags() & ACC_STATIC) != 0x0;
236 }
237
FunctionIsCtorStatic(AbckitCoreFunction * function)238 bool FunctionIsCtorStatic(AbckitCoreFunction *function)
239 {
240 LIBABCKIT_LOG_FUNC;
241 auto *func = function->GetArkTSImpl()->GetStaticImpl();
242 size_t pos = func->name.rfind('.');
243 ASSERT(pos != std::string::npos);
244 std::string name = func->name.substr(pos + 1);
245 return name == "_ctor_"; // NOTE(ivagin)
246 }
247
FunctionIsAnonymousStatic(AbckitCoreFunction * function)248 bool FunctionIsAnonymousStatic(AbckitCoreFunction *function)
249 {
250 LIBABCKIT_LOG_FUNC;
251 auto *func = function->GetArkTSImpl()->GetStaticImpl();
252 size_t pos = func->name.rfind('.');
253 ASSERT(pos != std::string::npos);
254 std::string name = func->name.substr(pos + 1);
255 return name.find("lambda$invoke$") == 0;
256 }
257
FunctionIsNativeStatic(AbckitCoreFunction * function)258 bool FunctionIsNativeStatic(AbckitCoreFunction *function)
259 {
260 LIBABCKIT_LOG_FUNC;
261 auto *func = function->GetArkTSImpl()->GetStaticImpl();
262 return (func->metadata->GetAccessFlags() & ACC_NATIVE) != 0x0;
263 }
264
265 // ========================================
266 // Annotation
267 // ========================================
268
269 // ========================================
270 // ImportDescriptor
271 // ========================================
272
273 // ========================================
274 // ExportDescriptor
275 // ========================================
276
277 // ========================================
278 // Literal
279 // ========================================
280
LiteralGetBoolStatic(AbckitLiteral * lit)281 bool LiteralGetBoolStatic(AbckitLiteral *lit)
282 {
283 LIBABCKIT_LOG_FUNC;
284 auto *literal = reinterpret_cast<pandasm::LiteralArray::Literal *>(lit->val.get());
285 if (!literal->IsBoolValue()) {
286 statuses::SetLastError(ABCKIT_STATUS_WRONG_LITERAL_TYPE);
287 return false;
288 }
289 return std::get<bool>(literal->value);
290 }
291
LiteralGetU8Static(AbckitLiteral * lit)292 uint8_t LiteralGetU8Static(AbckitLiteral *lit)
293 {
294 LIBABCKIT_LOG_FUNC;
295 auto *literal = reinterpret_cast<pandasm::LiteralArray::Literal *>(lit->val.get());
296 if (!literal->IsByteValue()) {
297 statuses::SetLastError(ABCKIT_STATUS_WRONG_LITERAL_TYPE);
298 return 0;
299 }
300 return std::get<uint8_t>(literal->value);
301 }
302
LiteralGetU16Static(AbckitLiteral * lit)303 uint16_t LiteralGetU16Static(AbckitLiteral *lit)
304 {
305 LIBABCKIT_LOG_FUNC;
306 auto *literal = reinterpret_cast<pandasm::LiteralArray::Literal *>(lit->val.get());
307 if (!literal->IsShortValue()) {
308 statuses::SetLastError(ABCKIT_STATUS_WRONG_LITERAL_TYPE);
309 return 0;
310 }
311 return std::get<uint16_t>(literal->value);
312 }
313
LiteralGetMethodAffiliateStatic(AbckitLiteral * lit)314 uint16_t LiteralGetMethodAffiliateStatic(AbckitLiteral *lit)
315 {
316 LIBABCKIT_LOG_FUNC;
317 auto *literal = reinterpret_cast<pandasm::LiteralArray::Literal *>(lit->val.get());
318 if (literal->tag != panda_file::LiteralTag::METHODAFFILIATE) {
319 statuses::SetLastError(ABCKIT_STATUS_WRONG_LITERAL_TYPE);
320 return 0;
321 }
322 return std::get<uint16_t>(literal->value);
323 }
324
LiteralGetU32Static(AbckitLiteral * lit)325 uint32_t LiteralGetU32Static(AbckitLiteral *lit)
326 {
327 LIBABCKIT_LOG_FUNC;
328 auto *literal = reinterpret_cast<pandasm::LiteralArray::Literal *>(lit->val.get());
329 if (!literal->IsIntegerValue()) {
330 statuses::SetLastError(ABCKIT_STATUS_WRONG_LITERAL_TYPE);
331 return 0;
332 }
333 return std::get<uint32_t>(literal->value);
334 }
335
LiteralGetU64Static(AbckitLiteral * lit)336 uint64_t LiteralGetU64Static(AbckitLiteral *lit)
337 {
338 LIBABCKIT_LOG_FUNC;
339 auto *literal = reinterpret_cast<pandasm::LiteralArray::Literal *>(lit->val.get());
340 if (!literal->IsLongValue()) {
341 statuses::SetLastError(ABCKIT_STATUS_WRONG_LITERAL_TYPE);
342 return 0;
343 }
344 return std::get<uint64_t>(literal->value);
345 }
346
LiteralGetFloatStatic(AbckitLiteral * lit)347 float LiteralGetFloatStatic(AbckitLiteral *lit)
348 {
349 LIBABCKIT_LOG_FUNC;
350 auto *literal = reinterpret_cast<pandasm::LiteralArray::Literal *>(lit->val.get());
351 if (!literal->IsFloatValue()) {
352 statuses::SetLastError(ABCKIT_STATUS_WRONG_LITERAL_TYPE);
353 return 0;
354 }
355 return std::get<float>(literal->value);
356 }
357
LiteralGetDoubleStatic(AbckitLiteral * lit)358 double LiteralGetDoubleStatic(AbckitLiteral *lit)
359 {
360 LIBABCKIT_LOG_FUNC;
361 auto *literal = reinterpret_cast<pandasm::LiteralArray::Literal *>(lit->val.get());
362 if (!literal->IsDoubleValue()) {
363 statuses::SetLastError(ABCKIT_STATUS_WRONG_LITERAL_TYPE);
364 return 0;
365 }
366 return std::get<double>(literal->value);
367 }
368
LiteralGetStringStatic(AbckitLiteral * lit)369 AbckitString *LiteralGetStringStatic(AbckitLiteral *lit)
370 {
371 LIBABCKIT_LOG_FUNC;
372 auto s = std::make_unique<AbckitString>();
373 auto *literal = reinterpret_cast<pandasm::LiteralArray::Literal *>(lit->val.get());
374 if (!literal->IsStringValue()) {
375 statuses::SetLastError(ABCKIT_STATUS_WRONG_LITERAL_TYPE);
376 return nullptr;
377 }
378
379 auto &strings = lit->file->strings;
380
381 auto &val = std::get<std::string>(literal->value);
382 if (strings.find(val) != strings.end()) {
383 return strings[val].get();
384 }
385 s->impl = val;
386 strings.insert({val, std::move(s)});
387
388 return strings[val].get();
389 }
390
LiteralGetTagStatic(AbckitLiteral * lit)391 AbckitLiteralTag LiteralGetTagStatic(AbckitLiteral *lit)
392 {
393 LIBABCKIT_LOG_FUNC;
394 auto *litImpl = reinterpret_cast<pandasm::LiteralArray::Literal *>(lit->val.get());
395 switch (litImpl->tag) {
396 case panda_file::LiteralTag::ARRAY_U1:
397 case panda_file::LiteralTag::BOOL:
398 return ABCKIT_LITERAL_TAG_BOOL;
399 case panda_file::LiteralTag::ARRAY_U8:
400 case panda_file::LiteralTag::ARRAY_I8:
401 return ABCKIT_LITERAL_TAG_BYTE;
402 case panda_file::LiteralTag::ARRAY_U16:
403 case panda_file::LiteralTag::ARRAY_I16:
404 return ABCKIT_LITERAL_TAG_SHORT;
405 case panda_file::LiteralTag::ARRAY_U32:
406 case panda_file::LiteralTag::ARRAY_I32:
407 case panda_file::LiteralTag::INTEGER:
408 return ABCKIT_LITERAL_TAG_INTEGER;
409 case panda_file::LiteralTag::ARRAY_U64:
410 case panda_file::LiteralTag::ARRAY_I64:
411 return ABCKIT_LITERAL_TAG_LONG;
412 case panda_file::LiteralTag::ARRAY_F32:
413 case panda_file::LiteralTag::FLOAT:
414 return ABCKIT_LITERAL_TAG_FLOAT;
415 case panda_file::LiteralTag::ARRAY_F64:
416 case panda_file::LiteralTag::DOUBLE:
417 return ABCKIT_LITERAL_TAG_DOUBLE;
418 case panda_file::LiteralTag::ARRAY_STRING:
419 case panda_file::LiteralTag::STRING:
420 return ABCKIT_LITERAL_TAG_STRING;
421 case panda_file::LiteralTag::NULLVALUE:
422 return ABCKIT_LITERAL_TAG_NULLVALUE;
423 case panda_file::LiteralTag::TAGVALUE:
424 return ABCKIT_LITERAL_TAG_TAGVALUE;
425 case panda_file::LiteralTag::METHOD:
426 case panda_file::LiteralTag::GENERATORMETHOD:
427 case panda_file::LiteralTag::ASYNCGENERATORMETHOD:
428 return ABCKIT_LITERAL_TAG_METHOD;
429 case panda_file::LiteralTag::METHODAFFILIATE:
430 return ABCKIT_LITERAL_TAG_METHODAFFILIATE;
431 default:
432 return ABCKIT_LITERAL_TAG_INVALID;
433 }
434 }
435
436 // ========================================
437 // Value
438 // ========================================
439
ValueGetTypeStatic(AbckitValue * value)440 AbckitType *ValueGetTypeStatic(AbckitValue *value)
441 {
442 LIBABCKIT_LOG_FUNC;
443 auto *pVal = reinterpret_cast<pandasm::ScalarValue *>(value->val.get());
444 AbckitTypeId id;
445 switch (pVal->GetType()) {
446 case pandasm::Value::Type::U1:
447 id = ABCKIT_TYPE_ID_U1;
448 break;
449 case pandasm::Value::Type::U8:
450 id = ABCKIT_TYPE_ID_U8;
451 break;
452 case pandasm::Value::Type::U16:
453 id = ABCKIT_TYPE_ID_U16;
454 break;
455 case pandasm::Value::Type::U32:
456 id = ABCKIT_TYPE_ID_U32;
457 break;
458 case pandasm::Value::Type::U64:
459 id = ABCKIT_TYPE_ID_U64;
460 break;
461 case pandasm::Value::Type::F64:
462 id = ABCKIT_TYPE_ID_F64;
463 break;
464 case pandasm::Value::Type::STRING:
465 id = ABCKIT_TYPE_ID_STRING;
466 break;
467 default:
468 LIBABCKIT_UNIMPLEMENTED;
469 }
470 // NOTE implement logic for classes
471 return GetOrCreateType(value->file, id, 0, nullptr);
472 }
473
ValueGetU1Static(AbckitValue * value)474 bool ValueGetU1Static(AbckitValue *value)
475 {
476 LIBABCKIT_LOG_FUNC;
477 if (ValueGetTypeStatic(value)->id != ABCKIT_TYPE_ID_U1) {
478 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
479 return false;
480 }
481
482 auto *pVal = reinterpret_cast<pandasm::ScalarValue *>(value->val.get());
483 return pVal->GetValue<bool>();
484 }
485
ValueGetDoubleStatic(AbckitValue * value)486 double ValueGetDoubleStatic(AbckitValue *value)
487 {
488 LIBABCKIT_LOG_FUNC;
489 if (ValueGetTypeStatic(value)->id != ABCKIT_TYPE_ID_F64) {
490 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
491 return 0.0;
492 }
493
494 auto *pVal = reinterpret_cast<pandasm::ScalarValue *>(value->val.get());
495 return pVal->GetValue<double>();
496 }
497
ValueGetStringStatic(AbckitValue * value)498 AbckitString *ValueGetStringStatic(AbckitValue *value)
499 {
500 LIBABCKIT_LOG_FUNC;
501 if (ValueGetTypeStatic(value)->id != ABCKIT_TYPE_ID_STRING) {
502 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
503 return nullptr;
504 }
505
506 auto *pVal = reinterpret_cast<pandasm::ScalarValue *>(value->val.get());
507 auto valImpl = pVal->GetValue<std::string>();
508 return CreateStringStatic(value->file, valImpl.data(), valImpl.size());
509 }
510
ArrayValueGetLiteralArrayStatic(AbckitValue *)511 AbckitLiteralArray *ArrayValueGetLiteralArrayStatic(AbckitValue * /*value*/)
512 {
513 LIBABCKIT_LOG_FUNC;
514 statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED);
515 return nullptr;
516 }
517
518 } // namespace libabckit
519