• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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