1 /**
2 * Copyright (c) 2024-2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "ir_static.h"
17
18 #include "datatype.h"
19 #include "libabckit/include/c/ir_core.h"
20 #include "libabckit/include/c/statuses.h"
21 #include "libabckit/src/adapter_static/helpers_static.h"
22
23 #include "libabckit/include/c/metadata_core.h"
24 #include "libabckit/src/statuses_impl.h"
25 #include "libabckit/src/macros.h"
26 #include "libabckit/src/metadata_inspect_impl.h"
27 #include "libabckit/src/helpers_common.h"
28 #include "libabckit/src/ir_impl.h"
29 #include "libabckit/src/wrappers/pandasm_wrapper.h"
30
31 #include "static_core/assembler/assembly-program.h"
32 #include "static_core/assembler/mangling.h"
33
34 #include "static_core/compiler/optimizer/ir/graph.h"
35 #include "static_core/compiler/optimizer/ir/basicblock.h"
36 #include "static_core/compiler/optimizer/ir/inst.h"
37 #include "static_core/compiler/optimizer/analysis/loop_analyzer.h"
38
39 #include "generated/insn_info.h"
40
41 #include "abckit_intrinsics_opcodes.inc"
42
43 #include <cstdarg>
44 #include <cstdint>
45
46 namespace libabckit {
47
48 #include "inst_props_helpers_dynamic.inc"
49
50 // helpers for getting inst operand's info
51 // for dynamic insts helpers are autogenerated by inst_props_helpers_dynamic.inc.erb
HasMethodIdOperandStatic(AbckitIsaApiStaticOpcode opcode)52 static bool HasMethodIdOperandStatic(AbckitIsaApiStaticOpcode opcode)
53 {
54 switch (opcode) {
55 case ABCKIT_ISA_API_STATIC_OPCODE_INITOBJECT:
56 case ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC:
57 case ABCKIT_ISA_API_STATIC_OPCODE_CALL_VIRTUAL:
58 return true;
59 default:
60 return false;
61 }
62 }
63
GetMethodIdOperandIndexStatic(AbckitIsaApiStaticOpcode opcode)64 static int GetMethodIdOperandIndexStatic(AbckitIsaApiStaticOpcode opcode)
65 {
66 switch (opcode) {
67 case ABCKIT_ISA_API_STATIC_OPCODE_INITOBJECT:
68 case ABCKIT_ISA_API_STATIC_OPCODE_CALL_STATIC:
69 case ABCKIT_ISA_API_STATIC_OPCODE_CALL_VIRTUAL:
70 return 0;
71 default:
72 return 0;
73 }
74 }
75
HasStringIdOperandStatic(AbckitIsaApiStaticOpcode opcode)76 static bool HasStringIdOperandStatic(AbckitIsaApiStaticOpcode opcode)
77 {
78 switch (opcode) {
79 case ABCKIT_ISA_API_STATIC_OPCODE_LOADSTRING:
80 return true;
81 default:
82 return false;
83 }
84 }
85
GetStringIdOperandIndexStatic(AbckitIsaApiStaticOpcode opcode)86 static int GetStringIdOperandIndexStatic(AbckitIsaApiStaticOpcode opcode)
87 {
88 switch (opcode) {
89 case ABCKIT_ISA_API_STATIC_OPCODE_LOADSTRING:
90 return 0;
91 default:
92 return 0;
93 }
94 }
95
HasLiteralArrayIdOperandStatic(AbckitIsaApiStaticOpcode opcode)96 static bool HasLiteralArrayIdOperandStatic(AbckitIsaApiStaticOpcode opcode)
97 {
98 switch (opcode) {
99 case ABCKIT_ISA_API_STATIC_OPCODE_LOADCONSTARRAY:
100 return true;
101 default:
102 return false;
103 }
104 }
105
GetLiteralArrayIdOperandIndexStatic(AbckitIsaApiStaticOpcode opcode)106 static int GetLiteralArrayIdOperandIndexStatic(AbckitIsaApiStaticOpcode opcode)
107 {
108 switch (opcode) {
109 case ABCKIT_ISA_API_STATIC_OPCODE_LOADCONSTARRAY:
110 return 0;
111 default:
112 return 0;
113 }
114 }
115
HasTypeIdOperandStatic(AbckitIsaApiStaticOpcode opcode)116 [[maybe_unused]] static bool HasTypeIdOperandStatic(AbckitIsaApiStaticOpcode opcode)
117 {
118 switch (opcode) {
119 case ABCKIT_ISA_API_STATIC_OPCODE_NEWARRAY:
120 case ABCKIT_ISA_API_STATIC_OPCODE_NEWOBJECT:
121 case ABCKIT_ISA_API_STATIC_OPCODE_CHECKCAST:
122 case ABCKIT_ISA_API_STATIC_OPCODE_ISINSTANCE:
123 return true;
124 default:
125 return false;
126 }
127 }
128
GetTypeIdOperandIndexStatic(AbckitIsaApiStaticOpcode opcode)129 [[maybe_unused]] static int GetTypeIdOperandIndexStatic(AbckitIsaApiStaticOpcode opcode)
130 {
131 switch (opcode) {
132 case ABCKIT_ISA_API_STATIC_OPCODE_NEWARRAY:
133 case ABCKIT_ISA_API_STATIC_OPCODE_NEWOBJECT:
134 case ABCKIT_ISA_API_STATIC_OPCODE_CHECKCAST:
135 case ABCKIT_ISA_API_STATIC_OPCODE_ISINSTANCE:
136 return 0;
137 default:
138 return -1;
139 }
140 }
141
142 // ========================================
143 // Api for Graph manipulation
144 // ========================================
145
GfindOrCreateConstantI64Static(AbckitGraph * graph,int64_t value)146 AbckitInst *GfindOrCreateConstantI64Static(AbckitGraph *graph, int64_t value)
147 {
148 LIBABCKIT_LOG_FUNC;
149 if (graph == nullptr) {
150 LIBABCKIT_LOG(DEBUG) << "nullptr argument\n";
151 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
152 return nullptr;
153 }
154 auto constantI64Impl = graph->impl->FindOrCreateConstant(value);
155 return CreateInstFromImpl(graph, constantI64Impl);
156 }
157
GfindOrCreateConstantI32Static(AbckitGraph * graph,int32_t value)158 AbckitInst *GfindOrCreateConstantI32Static(AbckitGraph *graph, int32_t value)
159 {
160 LIBABCKIT_LOG_FUNC;
161 if (graph == nullptr) {
162 LIBABCKIT_LOG(DEBUG) << "nullptr argument\n";
163 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
164 return nullptr;
165 }
166 auto constantI32Impl = graph->impl->FindOrCreateConstant(value);
167 return CreateInstFromImpl(graph, constantI32Impl);
168 }
169
GfindOrCreateConstantU64Static(AbckitGraph * graph,uint64_t value)170 AbckitInst *GfindOrCreateConstantU64Static(AbckitGraph *graph, uint64_t value)
171 {
172 LIBABCKIT_LOG_FUNC;
173 if (graph == nullptr) {
174 LIBABCKIT_LOG(DEBUG) << "nullptr argument\n";
175 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
176 return nullptr;
177 }
178 auto constantU64Impl = graph->impl->FindOrCreateConstant(value);
179 return CreateInstFromImpl(graph, constantU64Impl);
180 }
181
GfindOrCreateConstantF64Static(AbckitGraph * graph,double value)182 AbckitInst *GfindOrCreateConstantF64Static(AbckitGraph *graph, double value)
183 {
184 LIBABCKIT_LOG_FUNC;
185 // check inputs are valid
186 if (graph == nullptr) {
187 LIBABCKIT_LOG(DEBUG) << "nullptr argument\n";
188 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
189 return nullptr;
190 }
191 auto constantF64Impl = graph->impl->FindOrCreateConstant(value);
192 return CreateInstFromImpl(graph, constantF64Impl);
193 }
194
GgetNumberOfBasicBlocksStatic(AbckitGraph * graph)195 uint32_t GgetNumberOfBasicBlocksStatic(AbckitGraph *graph)
196 {
197 LIBABCKIT_LOG_FUNC;
198 if (graph == nullptr) {
199 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
200 return 0;
201 }
202 return graph->impl->GetVectorBlocks().size();
203 }
204
GgetBasicBlockStatic(AbckitGraph * graph,uint32_t id)205 AbckitBasicBlock *GgetBasicBlockStatic(AbckitGraph *graph, uint32_t id)
206 {
207 LIBABCKIT_LOG_FUNC;
208 if (graph == nullptr) {
209 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
210 return nullptr;
211 }
212 if (id >= graph->impl->GetVectorBlocks().size()) {
213 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
214 return nullptr;
215 }
216 auto *bbImpl = graph->impl->GetVectorBlocks()[id];
217 return graph->implToBB.at(bbImpl);
218 }
219
GgetNumberOfParametersStatic(AbckitGraph * graph)220 uint32_t GgetNumberOfParametersStatic(AbckitGraph *graph)
221 {
222 auto list = graph->impl->GetParameters();
223 auto ins = list.begin();
224 uint32_t size = 0;
225 while (ins != list.end()) {
226 ++ins;
227 ++size;
228 }
229 return size;
230 }
231
GgetParameterStatic(AbckitGraph * graph,uint32_t index)232 AbckitInst *GgetParameterStatic(AbckitGraph *graph, uint32_t index)
233 {
234 LIBABCKIT_LOG_FUNC;
235 if (graph == nullptr) {
236 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
237 return nullptr;
238 }
239
240 if (index >= GgetNumberOfParametersStatic(graph)) {
241 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
242 return nullptr;
243 }
244
245 auto list = graph->impl->GetParameters();
246 auto ins = list.begin();
247 for (uint32_t i = 0; i < index; i++) {
248 if (ins != list.end()) {
249 ++ins;
250 }
251 }
252 return graph->implToInst.at(*ins);
253 }
254
SetTryBlocks(AbckitGraph * graph,AbckitBasicBlock * tryLastBB,AbckitBasicBlock * tryBeginBB,AbckitBasicBlock * tryEndBB)255 void SetTryBlocks(AbckitGraph *graph, AbckitBasicBlock *tryLastBB, AbckitBasicBlock *tryBeginBB,
256 AbckitBasicBlock *tryEndBB)
257 {
258 tryBeginBB->impl->SetTryBegin(true);
259 tryBeginBB->impl->SetTryId(tryBeginBB->impl->GetId());
260 graph->impl->AppendTryBeginBlock(tryBeginBB->impl);
261 AbckitInst *tryInst = IcreateTryStatic(graph);
262 BBaddInstFrontStatic(tryBeginBB, tryInst);
263
264 tryEndBB->impl->SetTryEnd(true);
265 tryEndBB->impl->SetTryId(tryBeginBB->impl->GetTryId());
266 // NOTE(nsizov): NOTE, calculate guest pc for new created blocks (abckit-wise problem)
267 tryEndBB->impl->SetGuestPc(tryLastBB->impl->GetGuestPc() - 1);
268 tryInst->impl->CastToTry()->SetTryEndBlock(tryEndBB->impl);
269 // NOTE(nsizov): NOTE, set proper typeid for catch blocks (abckit-wise problem)
270 tryInst->impl->CastToTry()->AppendCatchTypeId(0, 1);
271 }
272
273 struct VisitorData {
274 AbckitBasicBlock *cur;
275 AbckitBasicBlock *tryBegin;
276 AbckitBasicBlock *tryEnd;
277 AbckitBasicBlock *catchEnd;
278 std::unordered_set<AbckitBasicBlock *> *visited;
279 std::queue<AbckitBasicBlock *> *toVisit;
280 };
281
VisitBbs(AbckitBasicBlock * tryFirstBB,AbckitBasicBlock * tryLastBB,AbckitBasicBlock * catchBeginBB,AbckitBasicBlock * tryBeginBB,std::unordered_set<AbckitBasicBlock * > * visited,std::queue<AbckitBasicBlock * > * toVisit,VisitorData visitorData)282 void VisitBbs(AbckitBasicBlock *tryFirstBB, AbckitBasicBlock *tryLastBB, AbckitBasicBlock *catchBeginBB,
283 AbckitBasicBlock *tryBeginBB, std::unordered_set<AbckitBasicBlock *> *visited,
284 std::queue<AbckitBasicBlock *> *toVisit, VisitorData visitorData)
285 {
286 visitorData.cur = tryFirstBB;
287
288 // A data to pass into visitors traverse
289
290 BBvisitPredBlocksStatic(tryFirstBB, &visitorData, [](AbckitBasicBlock *predBasicBlock, void *data) {
291 AbckitBasicBlock *curBasicBlock = static_cast<struct VisitorData *>(data)->cur;
292 AbckitBasicBlock *tryBeginBB = static_cast<struct VisitorData *>(data)->tryBegin;
293
294 predBasicBlock->impl->ReplaceSucc(curBasicBlock->impl, tryBeginBB->impl);
295 curBasicBlock->impl->RemovePred(predBasicBlock->impl);
296 return true;
297 });
298
299 BBappendSuccBlockStatic(tryBeginBB, tryFirstBB);
300 BBappendSuccBlockStatic(tryBeginBB, catchBeginBB);
301
302 visitorData.cur = tryLastBB;
303
304 BBvisitPredBlocksStatic(tryLastBB, &visitorData, [](AbckitBasicBlock *predBasicBlock, void *data) {
305 AbckitBasicBlock *curBasicBlock = static_cast<struct VisitorData *>(data)->cur;
306 AbckitBasicBlock *tryEndBB = static_cast<struct VisitorData *>(data)->tryEnd;
307
308 predBasicBlock->impl->ReplaceSucc(curBasicBlock->impl, tryEndBB->impl);
309 curBasicBlock->impl->RemovePred(predBasicBlock->impl);
310 return true;
311 });
312
313 toVisit->push(tryBeginBB);
314
315 while (!(*toVisit).empty()) {
316 AbckitBasicBlock *curBB = toVisit->front();
317 visitorData.cur = curBB;
318 toVisit->pop();
319 visited->insert(curBB);
320 curBB->impl->SetTry(true);
321 curBB->impl->SetTryId(tryBeginBB->impl->GetTryId());
322 BBvisitSuccBlocksStatic(curBB, &visitorData, [](AbckitBasicBlock *succBasicBlock, void *data) {
323 if (succBasicBlock->impl->IsTryEnd() || succBasicBlock->impl->IsCatchBegin() ||
324 succBasicBlock->impl->IsEndBlock()) {
325 return false;
326 }
327
328 auto *visited = static_cast<struct VisitorData *>(data)->visited;
329 auto *toVisit = static_cast<struct VisitorData *>(data)->toVisit;
330
331 auto it = visited->find(succBasicBlock);
332 if (it == visited->end()) {
333 toVisit->push(succBasicBlock);
334 }
335 return true;
336 });
337 }
338 }
339
CheckCatchEnv(AbckitBasicBlock * tryFirstBB,AbckitBasicBlock * tryLastBB)340 bool CheckCatchEnv(AbckitBasicBlock *tryFirstBB, AbckitBasicBlock *tryLastBB)
341 {
342 // NOTE(nsizov): check input for dominance tryFirstBB -> tryLastBB
343 // and catchBeginBB -> catchEndBB
344
345 if (BBisStartStatic(tryFirstBB) || BBisEndStatic(tryFirstBB)) {
346 LIBABCKIT_LOG(DEBUG) << "tryFirstBB cannot be niether 'start' nor 'end' block";
347 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
348 return false;
349 }
350
351 if (BBisStartStatic(tryLastBB) || BBisEndStatic(tryLastBB)) {
352 LIBABCKIT_LOG(DEBUG) << "tryLastBB cannot be niether 'start' nor 'end' block";
353 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
354 return false;
355 }
356 return true;
357 }
358
GinsertTryCatchStatic(AbckitBasicBlock * tryFirstBB,AbckitBasicBlock * tryLastBB,AbckitBasicBlock * catchBeginBB,AbckitBasicBlock * catchEndBB)359 void GinsertTryCatchStatic(AbckitBasicBlock *tryFirstBB, AbckitBasicBlock *tryLastBB, AbckitBasicBlock *catchBeginBB,
360 AbckitBasicBlock *catchEndBB)
361 {
362 LIBABCKIT_LOG_FUNC;
363 if (!CheckCatchEnv(tryFirstBB, tryLastBB)) {
364 return;
365 }
366
367 AbckitGraph *graph = tryFirstBB->graph;
368
369 // NOTE(nsizov): implement for static mode as well
370 if (!IsDynamic(graph->function->owningModule->target)) {
371 libabckit::statuses::SetLastError(ABCKIT_STATUS_WRONG_TARGET);
372 return;
373 }
374
375 if ((graph != tryLastBB->graph) || (graph != catchBeginBB->graph) || (graph != catchEndBB->graph)) {
376 SetLastError(ABCKIT_STATUS_WRONG_CTX);
377 return;
378 }
379
380 AbckitBasicBlock *tryBeginBB = BBcreateEmptyStatic(graph);
381 AbckitBasicBlock *tryEndBB = BBcreateEmptyStatic(graph);
382 SetTryBlocks(graph, tryLastBB, tryBeginBB, tryEndBB);
383
384 catchBeginBB->impl->SetCatchBegin(true);
385 if (catchBeginBB != catchEndBB) {
386 catchEndBB->impl->SetCatch(true);
387 }
388
389 std::unordered_set<AbckitBasicBlock *> visited;
390 std::queue<AbckitBasicBlock *> toVisit;
391
392 auto visitorData = VisitorData {nullptr, tryBeginBB, tryEndBB, catchEndBB, &visited, &toVisit};
393
394 VisitBbs(tryFirstBB, tryLastBB, catchBeginBB, tryBeginBB, &visited, &toVisit, visitorData);
395
396 visited.erase(visited.begin(), visited.end());
397 std::queue<AbckitBasicBlock *>().swap(toVisit);
398
399 while (!toVisit.empty()) {
400 AbckitBasicBlock *curBB = toVisit.front();
401 toVisit.pop();
402 visited.insert(curBB);
403 curBB->impl->SetCatch(true);
404 curBB->impl->SetTryId(tryBeginBB->impl->GetTryId());
405 BBvisitSuccBlocksStatic(curBB, &visitorData, [](AbckitBasicBlock *succBasicBlock, void *data) {
406 auto catchEndBB = static_cast<struct VisitorData *>(data)->catchEnd;
407
408 // NOTE(ivagin) if (succBasicBlock->impl->IsCatchEnd()
409 if (succBasicBlock == catchEndBB || succBasicBlock->impl->IsTry()) {
410 return false;
411 }
412
413 auto *visited = static_cast<struct VisitorData *>(data)->visited;
414 auto *toVisit = static_cast<struct VisitorData *>(data)->toVisit;
415
416 if (visited->find(succBasicBlock) == visited->end()) {
417 toVisit->push(succBasicBlock);
418 }
419 return true;
420 });
421 }
422
423 BBappendSuccBlockStatic(tryEndBB, tryLastBB);
424 BBappendSuccBlockStatic(tryEndBB, catchBeginBB);
425 BBappendSuccBlockStatic(catchEndBB, tryLastBB);
426 }
427
GgetStartBasicBlockStatic(AbckitGraph * graph)428 AbckitBasicBlock *GgetStartBasicBlockStatic(AbckitGraph *graph)
429 {
430 LIBABCKIT_LOG_FUNC;
431 LIBABCKIT_BAD_ARGUMENT(graph, nullptr);
432 ark::compiler::BasicBlock *bbImpl = graph->impl->GetStartBlock();
433 auto *bb = graph->implToBB.at(bbImpl);
434
435 return bb;
436 }
437
GgetEndBasicBlockStatic(AbckitGraph * graph)438 AbckitBasicBlock *GgetEndBasicBlockStatic(AbckitGraph *graph)
439 {
440 LIBABCKIT_LOG_FUNC;
441 LIBABCKIT_BAD_ARGUMENT(graph, nullptr);
442 ark::compiler::BasicBlock *bbImpl = graph->impl->GetEndBlock();
443 auto *bb = graph->implToBB.at(bbImpl);
444
445 return bb;
446 }
447
IdumpStatic(AbckitInst * inst,int fd)448 void IdumpStatic(AbckitInst *inst, int fd)
449 {
450 LIBABCKIT_LOG_FUNC;
451 std::stringstream ss;
452 inst->impl->Dump(&ss);
453 write(fd, ss.str().data(), ss.str().size());
454 }
455
GdumpStatic(AbckitGraph * graph,int fd)456 void GdumpStatic(AbckitGraph *graph, int fd)
457 {
458 LIBABCKIT_LOG_FUNC;
459 if (GraphHasUnreachableBlocks(graph->impl)) {
460 LIBABCKIT_LOG(DEBUG) << "Cannot dump, there are unreachable blocks in graph\n";
461 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
462 return;
463 }
464 std::stringstream ss;
465 graph->impl->Dump(&ss);
466 write(fd, ss.str().data(), ss.str().size());
467 }
468
GrunPassRemoveUnreachableBlocksStatic(AbckitGraph * graph)469 void GrunPassRemoveUnreachableBlocksStatic(AbckitGraph *graph)
470 {
471 LIBABCKIT_LOG_FUNC;
472 graph->impl->RemoveUnreachableBlocks();
473 GraphInvalidateAnalyses(graph->impl);
474 }
475
GvisitBlocksRPOStatic(AbckitGraph * graph,void * data,bool (* cb)(AbckitBasicBlock * bb,void * data))476 bool GvisitBlocksRPOStatic(AbckitGraph *graph, void *data, bool (*cb)(AbckitBasicBlock *bb, void *data))
477 {
478 LIBABCKIT_LOG_FUNC;
479 LIBABCKIT_BAD_ARGUMENT(graph, false)
480 LIBABCKIT_BAD_ARGUMENT(cb, false)
481
482 if (GraphHasUnreachableBlocks(graph->impl)) {
483 LIBABCKIT_LOG(DEBUG) << "Cannot get blocks RPO, there are unreachable blocks in graph\n";
484 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
485 return false;
486 }
487
488 std::stringstream ss;
489 for (auto *bbImpl : graph->impl->GetBlocksRPO()) {
490 auto *bb = graph->implToBB.at(bbImpl);
491 if (!cb(bb, data)) {
492 return false;
493 }
494 }
495 return true;
496 }
497
498 // ========================================
499 // Api for basic block manipulation
500 // ========================================
501
BBvisitSuccBlocksStatic(AbckitBasicBlock * curBasicBlock,void * data,bool (* cb)(AbckitBasicBlock * succBasicBlock,void * data))502 bool BBvisitSuccBlocksStatic(AbckitBasicBlock *curBasicBlock, void *data,
503 bool (*cb)(AbckitBasicBlock *succBasicBlock, void *data))
504 {
505 LIBABCKIT_LOG_FUNC;
506 LIBABCKIT_BAD_ARGUMENT(curBasicBlock, false)
507 LIBABCKIT_BAD_ARGUMENT(cb, false)
508
509 auto *graph = curBasicBlock->graph;
510 auto *bbImpl = curBasicBlock->impl;
511 auto succImpls = bbImpl->GetSuccsBlocks();
512 for (auto *succImpl : succImpls) {
513 auto *succ = graph->implToBB.at(succImpl);
514 if (!cb(succ, data)) {
515 return false;
516 }
517 }
518 return true;
519 }
520
BBvisitPredBlocksStatic(AbckitBasicBlock * curBasicBlock,void * data,bool (* cb)(AbckitBasicBlock * succBasicBlock,void * data))521 bool BBvisitPredBlocksStatic(AbckitBasicBlock *curBasicBlock, void *data,
522 bool (*cb)(AbckitBasicBlock *succBasicBlock, void *data))
523 {
524 LIBABCKIT_LOG_FUNC;
525 LIBABCKIT_BAD_ARGUMENT(curBasicBlock, false)
526 LIBABCKIT_BAD_ARGUMENT(cb, false)
527
528 auto *graph = curBasicBlock->graph;
529 auto *bbImpl = curBasicBlock->impl;
530 auto predImpls = bbImpl->GetPredsBlocks();
531 for (auto *predImpl : predImpls) {
532 auto *pred = graph->implToBB.at(predImpl);
533 if (!cb(pred, data)) {
534 return false;
535 }
536 }
537 return true;
538 }
539
BBcreateEmptyStatic(AbckitGraph * graph)540 AbckitBasicBlock *BBcreateEmptyStatic(AbckitGraph *graph)
541 {
542 LIBABCKIT_LOG_FUNC;
543 LIBABCKIT_BAD_ARGUMENT(graph, nullptr);
544
545 auto *bbImpl = graph->impl->CreateEmptyBlock(0U);
546 auto *bb = graph->impl->GetLocalAllocator()->New<AbckitBasicBlock>();
547 bb->graph = graph;
548 bb->impl = bbImpl;
549 graph->implToBB.insert({bbImpl, bb});
550 GraphInvalidateAnalyses(graph->impl);
551 return bb;
552 }
553
BBaddInstFrontStatic(AbckitBasicBlock * basicBlock,AbckitInst * inst)554 void BBaddInstFrontStatic(AbckitBasicBlock *basicBlock, AbckitInst *inst)
555 {
556 LIBABCKIT_LOG_FUNC;
557 LIBABCKIT_BAD_ARGUMENT_VOID(basicBlock)
558 LIBABCKIT_BAD_ARGUMENT_VOID(inst)
559
560 LIBABCKIT_WRONG_CTX_VOID(basicBlock->graph, inst->graph);
561
562 if (inst->impl->IsConst()) {
563 LIBABCKIT_LOG(DEBUG) << "can't use constant instruction as an argument";
564 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
565 return;
566 }
567
568 basicBlock->impl->PrependInst(inst->impl);
569 }
570
BBsplitBlockAfterInstructionStatic(AbckitBasicBlock * basicBlock,AbckitInst * inst,bool makeEdge)571 AbckitBasicBlock *BBsplitBlockAfterInstructionStatic(AbckitBasicBlock *basicBlock, AbckitInst *inst, bool makeEdge)
572 {
573 LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr);
574 LIBABCKIT_BAD_ARGUMENT(inst, nullptr);
575
576 auto *bbImpl = inst->impl->GetBasicBlock();
577 auto *newBbImpl = bbImpl->SplitBlockAfterInstruction(inst->impl, makeEdge);
578
579 auto *iBb = IgetBasicBlockStatic(inst);
580 if (iBb != basicBlock) {
581 LIBABCKIT_LOG(DEBUG) << "Instruction should be in basic block";
582 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
583 return nullptr;
584 }
585
586 auto *bb = inst->graph->impl->GetLocalAllocator()->New<AbckitBasicBlock>();
587 bb->graph = inst->graph;
588 bb->impl = newBbImpl;
589 inst->graph->implToBB.insert({newBbImpl, bb});
590 GraphInvalidateAnalyses(basicBlock->graph->impl);
591 return bb;
592 }
593
BBaddInstBackStatic(AbckitBasicBlock * basicBlock,AbckitInst * inst)594 void BBaddInstBackStatic(AbckitBasicBlock *basicBlock, AbckitInst *inst)
595 {
596 LIBABCKIT_LOG_FUNC;
597 LIBABCKIT_BAD_ARGUMENT_VOID(basicBlock)
598 LIBABCKIT_BAD_ARGUMENT_VOID(inst)
599
600 LIBABCKIT_WRONG_CTX_VOID(basicBlock->graph, inst->graph);
601
602 if (inst->impl->IsConst()) {
603 LIBABCKIT_LOG(DEBUG) << "can't use constant instruction as an argument";
604 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
605 return;
606 }
607
608 basicBlock->impl->AppendInst(inst->impl);
609 }
610
BBgetLastInstStatic(AbckitBasicBlock * basicBlock)611 AbckitInst *BBgetLastInstStatic(AbckitBasicBlock *basicBlock)
612 {
613 LIBABCKIT_LOG_FUNC;
614 LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr);
615
616 auto *bb = basicBlock->impl;
617 auto *inst = bb->GetLastInst();
618 if (inst == nullptr) {
619 return nullptr;
620 }
621 return basicBlock->graph->implToInst.at(inst);
622 }
623
BBgetGraphStatic(AbckitBasicBlock * basicBlock)624 AbckitGraph *BBgetGraphStatic(AbckitBasicBlock *basicBlock)
625 {
626 LIBABCKIT_LOG_FUNC;
627 LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr);
628
629 return basicBlock->graph;
630 }
631
BBgetFirstInstStatic(AbckitBasicBlock * basicBlock)632 AbckitInst *BBgetFirstInstStatic(AbckitBasicBlock *basicBlock)
633 {
634 LIBABCKIT_LOG_FUNC;
635 LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr);
636
637 auto *bbImpl = basicBlock->impl;
638
639 ark::compiler::Inst *instImpl = bbImpl->GetFirstPhi();
640 if (instImpl == nullptr) {
641 instImpl = bbImpl->GetFirstInst();
642 }
643 if (instImpl == nullptr) {
644 return nullptr;
645 }
646
647 auto *inst = basicBlock->graph->implToInst.at(instImpl);
648 return inst;
649 }
650
BBdisconnectSuccBlockStatic(AbckitBasicBlock * bb,size_t index)651 void BBdisconnectSuccBlockStatic(AbckitBasicBlock *bb, size_t index)
652 {
653 LIBABCKIT_LOG_FUNC;
654 LIBABCKIT_BAD_ARGUMENT_VOID(bb)
655
656 if (index >= bb->impl->GetSuccsBlocks().size()) {
657 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
658 return;
659 }
660
661 auto succ = bb->impl->GetSuccessor(index);
662 succ->RemovePred(bb->impl);
663 bb->impl->RemoveSucc(succ);
664 GraphInvalidateAnalyses(bb->graph->impl);
665 }
666
BBremoveAllInstsStatic(AbckitBasicBlock * basicBlock)667 void BBremoveAllInstsStatic(AbckitBasicBlock *basicBlock)
668 {
669 LIBABCKIT_LOG_FUNC;
670 basicBlock->impl->Clear();
671 }
672
BBgetSuccBlockStatic(AbckitBasicBlock * basicBlock,uint32_t index)673 AbckitBasicBlock *BBgetSuccBlockStatic(AbckitBasicBlock *basicBlock, uint32_t index)
674 {
675 LIBABCKIT_LOG_FUNC;
676 LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr);
677 if (index >= basicBlock->impl->GetSuccsBlocks().size()) {
678 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
679 return nullptr;
680 }
681
682 auto *succImpl = basicBlock->impl->GetSuccsBlocks()[index];
683
684 return basicBlock->graph->implToBB.at(succImpl);
685 }
686
BBgetSuccBlockCountStatic(AbckitBasicBlock * basicBlock)687 uint64_t BBgetSuccBlockCountStatic(AbckitBasicBlock *basicBlock)
688 {
689 LIBABCKIT_LOG_FUNC;
690 LIBABCKIT_BAD_ARGUMENT(basicBlock, 0);
691
692 return basicBlock->impl->GetSuccsBlocks().size();
693 }
694
BBgetIdStatic(AbckitBasicBlock * basicBlock)695 uint32_t BBgetIdStatic([[maybe_unused]] AbckitBasicBlock *basicBlock)
696 {
697 LIBABCKIT_LOG_FUNC;
698 LIBABCKIT_BAD_ARGUMENT(basicBlock, 0);
699
700 return basicBlock->impl->GetId();
701 }
702
BBgetPredBlockStatic(AbckitBasicBlock * basicBlock,uint32_t index)703 AbckitBasicBlock *BBgetPredBlockStatic(AbckitBasicBlock *basicBlock, uint32_t index)
704 {
705 LIBABCKIT_LOG_FUNC;
706 LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr);
707
708 if (index >= basicBlock->impl->GetPredsBlocks().size()) {
709 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
710 return nullptr;
711 }
712
713 auto *predImpl = basicBlock->impl->GetPredsBlocks()[index];
714
715 return basicBlock->graph->implToBB.at(predImpl);
716 }
717
BBgetPredBlockCountStatic(AbckitBasicBlock * basicBlock)718 uint64_t BBgetPredBlockCountStatic(AbckitBasicBlock *basicBlock)
719 {
720 LIBABCKIT_LOG_FUNC;
721 LIBABCKIT_BAD_ARGUMENT(basicBlock, 0);
722
723 return basicBlock->impl->GetPredsBlocks().size();
724 }
725
BBisStartStatic(AbckitBasicBlock * basicBlock)726 bool BBisStartStatic(AbckitBasicBlock *basicBlock)
727 {
728 LIBABCKIT_LOG_FUNC;
729 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
730
731 return basicBlock->impl->IsStartBlock();
732 }
733
BBisEndStatic(AbckitBasicBlock * basicBlock)734 bool BBisEndStatic(AbckitBasicBlock *basicBlock)
735 {
736 LIBABCKIT_LOG_FUNC;
737 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
738
739 return basicBlock->impl->IsEndBlock();
740 }
741
BBgetNumberOfInstructionsStatic(AbckitBasicBlock * basicBlock)742 uint32_t BBgetNumberOfInstructionsStatic(AbckitBasicBlock *basicBlock)
743 {
744 LIBABCKIT_LOG_FUNC;
745 LIBABCKIT_BAD_ARGUMENT(basicBlock, 0);
746
747 return basicBlock->impl->CountInsts();
748 }
749
BBisLoopHeadStatic(AbckitBasicBlock * basicBlock)750 bool BBisLoopHeadStatic(AbckitBasicBlock *basicBlock)
751 {
752 LIBABCKIT_LOG_FUNC;
753 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
754
755 return basicBlock->impl->IsLoopHeader();
756 }
757
BBisLoopPreheadStatic(AbckitBasicBlock * basicBlock)758 bool BBisLoopPreheadStatic(AbckitBasicBlock *basicBlock)
759 {
760 LIBABCKIT_LOG_FUNC;
761 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
762
763 return basicBlock->impl->IsLoopPreHeader();
764 }
765
BBisTryBeginStatic(AbckitBasicBlock * basicBlock)766 bool BBisTryBeginStatic(AbckitBasicBlock *basicBlock)
767 {
768 LIBABCKIT_LOG_FUNC;
769 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
770
771 return basicBlock->impl->IsTryBegin();
772 }
773
BBisTryStatic(AbckitBasicBlock * basicBlock)774 bool BBisTryStatic(AbckitBasicBlock *basicBlock)
775 {
776 LIBABCKIT_LOG_FUNC;
777 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
778
779 return basicBlock->impl->IsTry();
780 }
781
BBisTryEndStatic(AbckitBasicBlock * basicBlock)782 bool BBisTryEndStatic(AbckitBasicBlock *basicBlock)
783 {
784 LIBABCKIT_LOG_FUNC;
785 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
786
787 return basicBlock->impl->IsTryEnd();
788 }
789
BBisCatchBeginStatic(AbckitBasicBlock * basicBlock)790 bool BBisCatchBeginStatic(AbckitBasicBlock *basicBlock)
791 {
792 LIBABCKIT_LOG_FUNC;
793 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
794
795 return basicBlock->impl->IsCatchBegin();
796 }
797
BBisCatchStatic(AbckitBasicBlock * basicBlock)798 bool BBisCatchStatic(AbckitBasicBlock *basicBlock)
799 {
800 LIBABCKIT_LOG_FUNC;
801 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
802
803 return basicBlock->impl->IsCatch();
804 }
805
BBdumpStatic(AbckitBasicBlock * basicBlock,int fd)806 void BBdumpStatic(AbckitBasicBlock *basicBlock, int fd)
807 {
808 LIBABCKIT_LOG_FUNC;
809 LIBABCKIT_BAD_ARGUMENT_VOID(basicBlock)
810
811 std::stringstream ss;
812 basicBlock->impl->Dump(&ss);
813 write(fd, ss.str().data(), ss.str().size());
814 }
815
BBcheckDominanceStatic(AbckitBasicBlock * basicBlock,AbckitBasicBlock * dominator)816 bool BBcheckDominanceStatic(AbckitBasicBlock *basicBlock, AbckitBasicBlock *dominator)
817 {
818 LIBABCKIT_LOG_FUNC;
819 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
820 LIBABCKIT_BAD_ARGUMENT(dominator, false);
821
822 LIBABCKIT_WRONG_CTX(basicBlock->graph, dominator->graph, false);
823
824 if (!GraphDominatorsTreeAnalysisIsValid(basicBlock->graph->impl)) {
825 LIBABCKIT_LOG(DEBUG) << "DominatorsTree analysis is not valid\n";
826 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
827 return false;
828 }
829
830 return dominator->impl->IsDominate(basicBlock->impl);
831 }
832
BBgetImmediateDominatorStatic(AbckitBasicBlock * basicBlock)833 AbckitBasicBlock *BBgetImmediateDominatorStatic(AbckitBasicBlock *basicBlock)
834 {
835 LIBABCKIT_LOG_FUNC;
836 LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr);
837
838 if (!GraphDominatorsTreeAnalysisIsValid(basicBlock->graph->impl)) {
839 LIBABCKIT_LOG(DEBUG) << "DominatorsTree analysis is not valid\n";
840 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
841 return nullptr;
842 }
843
844 auto *bb = basicBlock->impl->GetDominator();
845 if (bb == nullptr) {
846 return nullptr;
847 }
848 return basicBlock->graph->implToBB.at(bb);
849 }
850
BBvisitDominatedBlocksStatic(AbckitBasicBlock * basicBlock,void * data,bool (* cb)(AbckitBasicBlock * dominatedBasicBlock,void * data))851 bool BBvisitDominatedBlocksStatic(AbckitBasicBlock *basicBlock, void *data,
852 bool (*cb)(AbckitBasicBlock *dominatedBasicBlock, void *data))
853 {
854 LIBABCKIT_LOG_FUNC;
855 LIBABCKIT_BAD_ARGUMENT(basicBlock, false)
856 LIBABCKIT_BAD_ARGUMENT(cb, false)
857
858 if (!GraphDominatorsTreeAnalysisIsValid(basicBlock->graph->impl)) {
859 LIBABCKIT_LOG(DEBUG) << "DominatorsTree analysis is not valid\n";
860 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
861 return false;
862 }
863
864 for (auto *bbImpl : basicBlock->impl->GetDominatedBlocks()) {
865 auto *bb = basicBlock->graph->implToBB.at(bbImpl);
866 if (!cb(bb, data)) {
867 return false;
868 }
869 }
870 return true;
871 }
872
BBinsertSuccBlockStatic(AbckitBasicBlock * basicBlock,AbckitBasicBlock * succBlock,uint32_t index)873 void BBinsertSuccBlockStatic(AbckitBasicBlock *basicBlock, AbckitBasicBlock *succBlock, uint32_t index)
874 {
875 LIBABCKIT_LOG_FUNC;
876 LIBABCKIT_BAD_ARGUMENT_VOID(basicBlock)
877 LIBABCKIT_BAD_ARGUMENT_VOID(succBlock)
878
879 LIBABCKIT_WRONG_CTX_VOID(basicBlock->graph, succBlock->graph);
880
881 auto &bbs = basicBlock->impl->GetSuccsBlocks();
882 if (index > bbs.size()) {
883 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
884 return;
885 }
886
887 if (index == bbs.size()) {
888 bbs.emplace_back(succBlock->impl);
889 } else {
890 bbs.resize(bbs.size() + 1);
891 for (size_t i = index + 1; i < bbs.size(); i++) {
892 bbs[i] = bbs[i - 1];
893 }
894 bbs[index] = succBlock->impl;
895 }
896
897 succBlock->impl->GetPredsBlocks().emplace_back(basicBlock->impl);
898 GraphInvalidateAnalyses(basicBlock->graph->impl);
899 }
900
BBappendSuccBlockStatic(AbckitBasicBlock * basicBlock,AbckitBasicBlock * succBlock)901 void BBappendSuccBlockStatic(AbckitBasicBlock *basicBlock, AbckitBasicBlock *succBlock)
902 {
903 LIBABCKIT_LOG_FUNC;
904 LIBABCKIT_BAD_ARGUMENT_VOID(basicBlock)
905 LIBABCKIT_BAD_ARGUMENT_VOID(succBlock)
906
907 LIBABCKIT_WRONG_CTX_VOID(basicBlock->graph, succBlock->graph);
908
909 basicBlock->impl->GetSuccsBlocks().emplace_back(succBlock->impl);
910 succBlock->impl->GetPredsBlocks().emplace_back(basicBlock->impl);
911 GraphInvalidateAnalyses(basicBlock->graph->impl);
912 }
913
BBgetTrueBranchStatic(AbckitBasicBlock * bb)914 AbckitBasicBlock *BBgetTrueBranchStatic(AbckitBasicBlock *bb)
915 {
916 LIBABCKIT_LOG_FUNC;
917 LIBABCKIT_BAD_ARGUMENT(bb, nullptr);
918
919 if (bb->impl->GetSuccsBlocks().empty()) {
920 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
921 return nullptr;
922 }
923 auto *tb = bb->impl->GetTrueSuccessor();
924 ASSERT(tb != nullptr);
925
926 return bb->graph->implToBB.at(tb);
927 }
928
BBgetFalseBranchStatic(AbckitBasicBlock * bb)929 AbckitBasicBlock *BBgetFalseBranchStatic(AbckitBasicBlock *bb)
930 {
931 LIBABCKIT_LOG_FUNC;
932 LIBABCKIT_BAD_ARGUMENT(bb, nullptr);
933
934 if (bb->impl->GetSuccsBlocks().size() < 2U) {
935 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
936 return nullptr;
937 }
938 auto *fb = bb->impl->GetFalseSuccessor();
939 ASSERT(fb != nullptr);
940
941 return bb->graph->implToBB.at(fb);
942 }
943
BBcreatePhiStatic(AbckitBasicBlock * bb,size_t argCount,std::va_list args)944 AbckitInst *BBcreatePhiStatic(AbckitBasicBlock *bb, size_t argCount, std::va_list args)
945 {
946 LIBABCKIT_LOG_FUNC;
947
948 LIBABCKIT_LOG(DEBUG) << argCount << '\n';
949 if (argCount < 1) {
950 LIBABCKIT_LOG(DEBUG) << "not enough inputs\n";
951 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
952 return nullptr;
953 }
954
955 std::vector<AbckitInst *> inputs;
956
957 for (size_t index = 0; index < argCount; ++index) {
958 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
959 AbckitInst *input = va_arg(args, AbckitInst *);
960 LIBABCKIT_BAD_ARGUMENT(input, nullptr);
961 inputs.emplace_back(input);
962 }
963
964 ark::compiler::DataType::Type type = inputs[0]->impl->GetType();
965 if (IsDynamic(bb->graph->function->owningModule->target)) {
966 type = ark::compiler::DataType::ANY;
967 }
968
969 for (auto *inst : inputs) {
970 if (IsDynamic(bb->graph->function->owningModule->target)) {
971 if (inst->impl->GetType() != ark::compiler::DataType::INT64 &&
972 inst->impl->GetType() != ark::compiler::DataType::ANY) {
973 LIBABCKIT_LOG(DEBUG) << "inconsistent input types\n";
974 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
975 return nullptr;
976 }
977 } else {
978 if (type != inst->impl->GetType()) {
979 LIBABCKIT_LOG(DEBUG) << "inconsistent input types\n";
980 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
981 return nullptr;
982 }
983 }
984 }
985
986 auto phiImpl = bb->graph->impl->CreateInstPhi(type, 0);
987 bb->impl->AppendPhi(phiImpl);
988 auto *phi = CreateInstFromImpl(bb->graph, phiImpl);
989 for (auto *inst : inputs) {
990 phiImpl->AppendInput(inst->impl);
991 }
992 return phi;
993 }
994
BBcreateCatchPhiStatic(AbckitBasicBlock * catchBegin,size_t argCount,std::va_list args)995 AbckitInst *BBcreateCatchPhiStatic(AbckitBasicBlock *catchBegin, size_t argCount, std::va_list args)
996 {
997 auto *instImpl = catchBegin->graph->impl->CreateInstCatchPhi();
998 auto *catchPhi = CreateInstFromImpl(catchBegin->graph, instImpl);
999
1000 BBaddInstFrontStatic(catchBegin, catchPhi);
1001
1002 if (argCount == 0) {
1003 auto type = IsDynamic(catchBegin->graph->function->owningModule->target) ? ark::compiler::DataType::ANY
1004 : ark::compiler::DataType::REFERENCE;
1005 instImpl->SetIsAcc();
1006 instImpl->SetType(type);
1007 return catchPhi;
1008 }
1009
1010 std::vector<ark::compiler::DataType::Type> types;
1011
1012 for (size_t index = 0; index < argCount; ++index) {
1013 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
1014 AbckitInst *inputOrThrowable = va_arg(args, AbckitInst *);
1015 if (index % 2U == 0) {
1016 types.push_back(inputOrThrowable->impl->GetType());
1017 catchPhi->impl->AppendInput(inputOrThrowable->impl);
1018 } else {
1019 catchPhi->impl->CastToCatchPhi()->AppendThrowableInst(inputOrThrowable->impl);
1020 }
1021 }
1022
1023 ASSERT(!types.empty());
1024
1025 if (IsDynamic(catchBegin->graph->function->owningModule->target)) {
1026 catchPhi->impl->SetType(ark::compiler::DataType::ANY);
1027 } else {
1028 for (int i = 1, j = types.size(); i < j; ++i) {
1029 if (types[0] != types[i]) {
1030 LIBABCKIT_LOG(DEBUG) << "All inputs of a catchPhi should be of the same type " << '\n';
1031 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1032 catchBegin->impl->EraseInst(instImpl, true);
1033 return nullptr;
1034 }
1035 }
1036 catchPhi->impl->SetType(types[0]);
1037 }
1038
1039 return catchPhi;
1040 }
1041
1042 // ========================================
1043 // Api for instruction manipulation
1044 // ========================================
1045
IremoveStatic(AbckitInst * inst)1046 void IremoveStatic(AbckitInst *inst)
1047 {
1048 LIBABCKIT_LOG_FUNC;
1049
1050 auto bbImpl = inst->impl->GetBasicBlock();
1051 LIBABCKIT_BAD_ARGUMENT_VOID(bbImpl)
1052
1053 bbImpl->RemoveInst(inst->impl);
1054 }
1055
IgetIdStatic(AbckitInst * inst)1056 uint32_t IgetIdStatic(AbckitInst *inst)
1057 {
1058 LIBABCKIT_LOG_FUNC;
1059 auto id = inst->impl->GetId();
1060 LIBABCKIT_LOG(DEBUG) << id << '\n';
1061 return id;
1062 }
1063
IgetLiteralArrayStatic(AbckitInst * inst)1064 AbckitLiteralArray *IgetLiteralArrayStatic(AbckitInst *inst)
1065 {
1066 LIBABCKIT_LOG_FUNC;
1067 size_t idx = 0;
1068 if (IsDynamic(inst->graph->function->owningModule->target)) {
1069 auto instOpcode = GetDynamicOpcode(inst->impl);
1070 if (!HasLiteralArrayIdOperandDynamic(instOpcode)) {
1071 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1072 return nullptr;
1073 }
1074 idx = GetLiteralArrayIdOperandIndexDynamic(instOpcode);
1075 } else {
1076 auto instOpcode = GetStaticOpcode(inst->impl);
1077 if (!HasLiteralArrayIdOperandStatic(instOpcode)) {
1078 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1079 return nullptr;
1080 }
1081 idx = GetLiteralArrayIdOperandIndexStatic(instOpcode);
1082 }
1083 auto &imms = inst->impl->CastToIntrinsic()->GetImms();
1084 ASSERT(!imms.empty());
1085 auto arrName = inst->graph->irInterface->literalarrays.at(imms[idx]);
1086 std::variant<ark::pandasm::LiteralArray *, panda::pandasm::LiteralArray *> arrImpl {
1087 (panda::pandasm::LiteralArray *)nullptr};
1088 if (IsDynamic(inst->graph->function->owningModule->target)) {
1089 arrImpl = reinterpret_cast<panda::pandasm::LiteralArray *>(
1090 PandasmWrapper::GetUnwrappedLiteralArrayTable(inst->graph->file->GetDynamicProgram()).at(arrName));
1091 } else {
1092 arrImpl = &inst->graph->file->GetStaticProgram()->literalarrayTable.at(arrName);
1093 }
1094
1095 // Search through already created litarrs
1096 auto &abckitLitArrs = inst->graph->file->litarrs;
1097 for (auto &item : abckitLitArrs) {
1098 if (item->impl == arrImpl) {
1099 return item.get();
1100 }
1101 }
1102
1103 // Create new litarr
1104 auto litarr = std::make_unique<AbckitLiteralArray>();
1105 litarr->file = inst->graph->file;
1106 litarr->impl = arrImpl;
1107 return abckitLitArrs.emplace_back(std::move(litarr)).get();
1108 }
1109
IsetLiteralArrayStatic(AbckitInst * inst,AbckitLiteralArray * la)1110 void IsetLiteralArrayStatic(AbckitInst *inst, AbckitLiteralArray *la)
1111 {
1112 LIBABCKIT_LOG_FUNC;
1113 size_t idx = 0;
1114 if (IsDynamic(inst->graph->function->owningModule->target)) {
1115 auto instOpcode = GetDynamicOpcode(inst->impl);
1116 if (!HasLiteralArrayIdOperandDynamic(instOpcode)) {
1117 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1118 return;
1119 }
1120 idx = GetLiteralArrayIdOperandIndexDynamic(instOpcode);
1121 } else {
1122 auto instOpcode = GetStaticOpcode(inst->impl);
1123 if (!HasLiteralArrayIdOperandStatic(instOpcode)) {
1124 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1125 return;
1126 }
1127 idx = GetLiteralArrayIdOperandIndexStatic(instOpcode);
1128 }
1129
1130 auto &imms = inst->impl->CastToIntrinsic()->GetImms();
1131 ASSERT(imms.size() == 2U);
1132 imms[idx] = GetLiteralArrayOffset(inst->graph, la);
1133 }
1134
IgetStringStatic(AbckitInst * inst)1135 AbckitString *IgetStringStatic(AbckitInst *inst)
1136 {
1137 LIBABCKIT_LOG_FUNC;
1138 size_t idx = 0;
1139 if (IsDynamic(inst->graph->function->owningModule->target)) {
1140 auto instOpcode = GetDynamicOpcode(inst->impl);
1141 if (!HasStringIdOperandDynamic(instOpcode)) {
1142 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1143 return nullptr;
1144 }
1145 idx = GetStringIdOperandIndexDynamic(instOpcode);
1146 } else {
1147 auto instOpcode = GetStaticOpcode(inst->impl);
1148 if (!HasStringIdOperandStatic(instOpcode)) {
1149 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1150 return nullptr;
1151 }
1152 idx = GetStringIdOperandIndexStatic(instOpcode);
1153 }
1154
1155 auto &imms = inst->impl->CastToIntrinsic()->GetImms();
1156 auto strName = inst->graph->irInterface->strings.at(imms[idx]);
1157 auto strImpl = inst->graph->file->strings.at(strName).get();
1158 return strImpl;
1159 }
1160
IsetStringStatic(AbckitInst * inst,AbckitString * str)1161 void IsetStringStatic(AbckitInst *inst, AbckitString *str)
1162 {
1163 LIBABCKIT_LOG_FUNC;
1164 size_t idx = 0;
1165 if (IsDynamic(inst->graph->function->owningModule->target)) {
1166 auto instOpcode = GetDynamicOpcode(inst->impl);
1167 if (!HasStringIdOperandDynamic(instOpcode)) {
1168 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1169 return;
1170 }
1171 idx = GetStringIdOperandIndexDynamic(instOpcode);
1172 } else {
1173 auto instOpcode = GetStaticOpcode(inst->impl);
1174 if (!HasStringIdOperandStatic(instOpcode)) {
1175 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1176 return;
1177 }
1178 idx = GetStringIdOperandIndexStatic(instOpcode);
1179 }
1180
1181 auto &imms = inst->impl->CastToIntrinsic()->GetImms();
1182 imms[idx] = GetStringOffset(inst->graph, str);
1183 }
1184
IgetOpcodeStaticStatic(AbckitInst * inst)1185 AbckitIsaApiStaticOpcode IgetOpcodeStaticStatic(AbckitInst *inst)
1186 {
1187 LIBABCKIT_LOG_FUNC;
1188 auto opc = inst->impl->GetOpcode();
1189 if (opc == ark::compiler::Opcode::Intrinsic) {
1190 return GetStaticIntrinsicOpcode(inst->impl->CastToIntrinsic());
1191 }
1192 return GetStaticOpcode(inst->impl);
1193 }
1194
IgetOpcodeDynamicStatic(AbckitInst * inst)1195 AbckitIsaApiDynamicOpcode IgetOpcodeDynamicStatic(AbckitInst *inst)
1196 {
1197 LIBABCKIT_LOG_FUNC;
1198 auto opc = inst->impl->GetOpcode();
1199 if (opc == ark::compiler::Opcode::Intrinsic) {
1200 switch (inst->impl->CastToIntrinsic()->GetIntrinsicId()) {
1201 case ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_ABCKIT_LOAD_STRING:
1202 return ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING;
1203 default:
1204 break;
1205 }
1206 return GetDynamicIntrinsicOpcode(inst->impl->CastToIntrinsic());
1207 }
1208 return GetDynamicOpcode(inst->impl);
1209 }
1210
IgetNextStatic(AbckitInst * inst)1211 AbckitInst *IgetNextStatic(AbckitInst *inst)
1212 {
1213 LIBABCKIT_LOG_FUNC;
1214
1215 auto *nextInstImpl = inst->impl->GetNext();
1216 if (nextInstImpl == nullptr) {
1217 return nullptr;
1218 }
1219 auto *nextInst = inst->graph->implToInst.at(nextInstImpl);
1220 return nextInst;
1221 }
1222
IgetPrevStatic(AbckitInst * inst)1223 AbckitInst *IgetPrevStatic(AbckitInst *inst)
1224 {
1225 LIBABCKIT_LOG_FUNC;
1226 auto *nextInstImpl = inst->impl->GetPrev();
1227 if (nextInstImpl == nullptr) {
1228 return nullptr;
1229 }
1230 auto *nextInst = inst->graph->implToInst.at(nextInstImpl);
1231 return nextInst;
1232 }
1233
IinsertAfterStatic(AbckitInst * inst,AbckitInst * next)1234 void IinsertAfterStatic(AbckitInst *inst, AbckitInst *next)
1235 {
1236 LIBABCKIT_LOG_FUNC;
1237 LIBABCKIT_BAD_ARGUMENT_VOID(inst)
1238 LIBABCKIT_BAD_ARGUMENT_VOID(next)
1239
1240 LIBABCKIT_WRONG_CTX_VOID(inst->graph, next->graph);
1241
1242 auto *bb = IgetBasicBlockStatic(next);
1243 LIBABCKIT_BAD_ARGUMENT_VOID(bb)
1244
1245 if (inst->impl->IsConst() || next->impl->IsConst()) {
1246 LIBABCKIT_LOG(DEBUG) << "can't use constant instruction as an argument";
1247 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1248 return;
1249 }
1250
1251 bb->impl->InsertAfter(inst->impl, next->impl);
1252 }
1253
IinsertBeforeStatic(AbckitInst * inst,AbckitInst * prev)1254 void IinsertBeforeStatic(AbckitInst *inst, AbckitInst *prev)
1255 {
1256 LIBABCKIT_LOG_FUNC;
1257 LIBABCKIT_BAD_ARGUMENT_VOID(inst)
1258 LIBABCKIT_BAD_ARGUMENT_VOID(prev)
1259
1260 LIBABCKIT_WRONG_CTX_VOID(inst->graph, prev->graph);
1261
1262 auto *bb = IgetBasicBlockStatic(prev);
1263 LIBABCKIT_BAD_ARGUMENT_VOID(bb)
1264
1265 if (inst->impl->IsConst() || prev->impl->IsConst()) {
1266 LIBABCKIT_LOG(DEBUG) << "can't use constant instruction as an argument";
1267 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1268 return;
1269 }
1270 bb->impl->InsertBefore(inst->impl, prev->impl);
1271 }
1272
IcheckDominanceStatic(AbckitInst * inst,AbckitInst * dominator)1273 bool IcheckDominanceStatic(AbckitInst *inst, AbckitInst *dominator)
1274 {
1275 LIBABCKIT_LOG_FUNC;
1276
1277 LIBABCKIT_WRONG_CTX(inst->graph, dominator->graph, false);
1278
1279 return inst->impl->IsDominate(dominator->impl);
1280 }
1281
IvisitUsersStatic(AbckitInst * inst,void * data,bool (* cb)(AbckitInst * user,void * data))1282 bool IvisitUsersStatic(AbckitInst *inst, void *data, bool (*cb)(AbckitInst *user, void *data))
1283 {
1284 LIBABCKIT_LOG_FUNC;
1285
1286 auto *user = inst->impl->GetFirstUser();
1287
1288 while (user != nullptr) {
1289 auto *userInst = inst->graph->implToInst.at(user->GetInst());
1290 if (!cb(userInst, data)) {
1291 return false;
1292 }
1293 user = user->GetNext();
1294 }
1295 return true;
1296 }
1297
IgetUserCountStatic(AbckitInst * inst)1298 uint32_t IgetUserCountStatic(AbckitInst *inst)
1299 {
1300 LIBABCKIT_LOG_FUNC;
1301 uint32_t count = 0;
1302
1303 auto *user = inst->impl->GetFirstUser();
1304
1305 while (user != nullptr) {
1306 count++;
1307 user = user->GetNext();
1308 }
1309 return count;
1310 }
1311
IvisitInputsStatic(AbckitInst * inst,void * data,bool (* cb)(AbckitInst * input,size_t inputIdx,void * data))1312 bool IvisitInputsStatic(AbckitInst *inst, void *data, bool (*cb)(AbckitInst *input, size_t inputIdx, void *data))
1313 {
1314 LIBABCKIT_LOG_FUNC;
1315 for (size_t i = 0; i < inst->impl->GetInputsCount(); i++) {
1316 auto *inputImpl = inst->impl->GetInput(i).GetInst();
1317 auto *input = inst->graph->implToInst.at(inputImpl);
1318 if (!cb(input, i, data)) {
1319 return false;
1320 }
1321 }
1322 return true;
1323 }
1324
IgetInputCountStatic(AbckitInst * inst)1325 uint64_t IgetInputCountStatic(AbckitInst *inst)
1326 {
1327 LIBABCKIT_LOG_FUNC;
1328
1329 return inst->impl->GetInputsCount();
1330 }
1331
IgetInputStatic(AbckitInst * inst,size_t index)1332 AbckitInst *IgetInputStatic(AbckitInst *inst, size_t index)
1333 {
1334 LIBABCKIT_LOG_FUNC;
1335 if (inst->impl->GetInputsCount() <= index) {
1336 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1337 return nullptr;
1338 }
1339
1340 auto *inputImpl = inst->impl->GetInput(index).GetInst();
1341 auto *input = inst->graph->implToInst.at(inputImpl);
1342 return input;
1343 }
1344
IsetInputStatic(AbckitInst * inst,AbckitInst * input,int32_t index)1345 void IsetInputStatic(AbckitInst *inst, AbckitInst *input, int32_t index)
1346 {
1347 LIBABCKIT_LOG_FUNC;
1348 LIBABCKIT_LOG(DEBUG) << index << '\n';
1349 LIBABCKIT_LOG(DEBUG) << inst->impl->GetInputs().size() << '\n';
1350 inst->impl->SetInput(index, input->impl);
1351 }
1352
IsetInputsStatic(AbckitInst * inst,size_t argCount,std::va_list args)1353 void IsetInputsStatic(AbckitInst *inst, size_t argCount, std::va_list args)
1354 {
1355 LIBABCKIT_LOG_FUNC;
1356 LIBABCKIT_LOG(DEBUG) << argCount << '\n';
1357 LIBABCKIT_LOG(DEBUG) << inst->impl->GetInputs().size() << '\n';
1358 for (size_t index = 0; index < argCount; ++index) {
1359 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
1360 AbckitInst *input = va_arg(args, AbckitInst *);
1361 inst->impl->SetInput(index, input->impl);
1362 }
1363 }
1364
IappendInputStatic(AbckitInst * inst,AbckitInst * input)1365 void IappendInputStatic(AbckitInst *inst, AbckitInst *input)
1366 {
1367 LIBABCKIT_LOG_FUNC;
1368 auto instImpl = inst->impl;
1369 static size_t rangeInputsCount = -1;
1370
1371 if (instImpl->IsOperandsDynamic()) {
1372 switch (instImpl->GetOpcode()) {
1373 case ark::compiler::Opcode::CallStatic: {
1374 instImpl->CastToCallStatic()->AppendInput(input->impl, input->impl->GetType());
1375 return;
1376 }
1377 case ark::compiler::Opcode::CallVirtual: {
1378 instImpl->CastToCallVirtual()->AppendInput(input->impl, input->impl->GetType());
1379 return;
1380 }
1381 case ark::compiler::Opcode::Intrinsic: {
1382 if (GetIntrinicMaxInputsCount(inst) == rangeInputsCount) {
1383 instImpl->CastToIntrinsic()->AppendInput(input->impl, input->impl->GetType());
1384 return;
1385 }
1386 if (instImpl->GetInputsCount() >= GetIntrinicMaxInputsCount(inst)) {
1387 LIBABCKIT_LOG(DEBUG) << "The maximum number of inputs has been reached for the instruction\n";
1388 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1389 return;
1390 }
1391 instImpl->CastToIntrinsic()->AppendInput(input->impl, input->impl->GetType());
1392 return;
1393 }
1394 case ark::compiler::Opcode::Phi: {
1395 instImpl->AppendInput(input->impl);
1396 return;
1397 }
1398 default:
1399 break;
1400 }
1401 }
1402
1403 LIBABCKIT_LOG(DEBUG) << "The instruction does not have the ability to add inputs\n";
1404 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1405 }
1406
1407 // Type helpers
1408
CreateGeneralType(AbckitFile * file,AbckitTypeId typeId,AbckitCoreClass * klass)1409 static AbckitType *CreateGeneralType(AbckitFile *file, AbckitTypeId typeId, AbckitCoreClass *klass)
1410 {
1411 return GetOrCreateType(file, typeId, 0, klass);
1412 }
1413
IgetTypeStatic(AbckitInst * inst)1414 AbckitType *IgetTypeStatic(AbckitInst *inst)
1415 {
1416 LIBABCKIT_LOG_FUNC;
1417 AbckitTypeId typeId = TypeToTypeId(inst->impl->GetType());
1418 AbckitCoreClass *klass = nullptr;
1419 if (typeId != ABCKIT_TYPE_ID_REFERENCE) {
1420 return CreateGeneralType(inst->graph->file, typeId, klass);
1421 }
1422 // Add get of ABCKIT_TYPE_ID_REFERENCE NOTE(ymolokanov)
1423 return CreateGeneralType(inst->graph->file, typeId, klass);
1424 }
1425
IgetTargetTypeStatic(AbckitInst * inst)1426 AbckitTypeId IgetTargetTypeStatic(AbckitInst *inst)
1427 {
1428 LIBABCKIT_LOG_FUNC;
1429 if (inst->impl->GetOpcode() != ark::compiler::Opcode::Cast) {
1430 LIBABCKIT_LOG(DEBUG) << "Instruction is not a cast\n";
1431 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1432 return AbckitTypeId::ABCKIT_TYPE_ID_INVALID;
1433 }
1434
1435 return TypeToTypeId(static_cast<ark::compiler::CastInst *>(inst->impl)->GetType());
1436 }
1437
IsetTargetTypeStatic(AbckitInst * inst,AbckitTypeId type)1438 void IsetTargetTypeStatic(AbckitInst *inst, AbckitTypeId type)
1439 {
1440 LIBABCKIT_LOG_FUNC;
1441 if (inst->impl->GetOpcode() != ark::compiler::Opcode::Cast) {
1442 LIBABCKIT_LOG(DEBUG) << "Instruction is not a cast\n";
1443 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1444 return;
1445 }
1446
1447 inst->impl->SetType(TypeIdToType(type));
1448 }
1449
IcheckIsCallStatic(AbckitInst * inst)1450 bool IcheckIsCallStatic(AbckitInst *inst)
1451 {
1452 LIBABCKIT_LOG_FUNC;
1453 return IsCallInst(inst);
1454 }
1455
IgetBasicBlockStatic(AbckitInst * inst)1456 AbckitBasicBlock *IgetBasicBlockStatic(AbckitInst *inst)
1457 {
1458 LIBABCKIT_LOG_FUNC;
1459 auto *graph = inst->graph;
1460 auto *implBB = inst->impl->GetBasicBlock();
1461 auto it = graph->implToBB.find(implBB);
1462 if (it != graph->implToBB.end()) {
1463 return it->second;
1464 }
1465 return nullptr;
1466 }
1467
IgetGraphStatic(AbckitInst * inst)1468 AbckitGraph *IgetGraphStatic(AbckitInst *inst)
1469 {
1470 LIBABCKIT_LOG_FUNC;
1471 return inst->graph;
1472 }
1473
IgetFunctionStatic(AbckitInst * inst)1474 AbckitCoreFunction *IgetFunctionStatic(AbckitInst *inst)
1475 {
1476 LIBABCKIT_LOG_FUNC;
1477 auto *graph = inst->graph;
1478
1479 ark::compiler::RuntimeInterface::MethodPtr methodPtr = nullptr;
1480 if (inst->impl->IsCall()) {
1481 auto *callInst = static_cast<ark::compiler::CallInst *>(inst->impl);
1482 methodPtr = callInst->GetCallMethod();
1483 } else if (inst->impl->IsIntrinsic()) {
1484 size_t idx = 0;
1485 if (IsDynamic(inst->graph->function->owningModule->target)) {
1486 auto instOpcode = GetDynamicOpcode(inst->impl);
1487 if (!HasMethodIdOperandDynamic(instOpcode)) {
1488 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1489 return nullptr;
1490 }
1491 idx = GetMethodIdOperandIndexDynamic(instOpcode);
1492 } else {
1493 auto instOpcode = GetStaticOpcode(inst->impl);
1494 if (!HasMethodIdOperandStatic(instOpcode)) {
1495 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1496 return nullptr;
1497 }
1498 idx = GetMethodIdOperandIndexStatic(instOpcode);
1499 }
1500
1501 auto *intrinsic = inst->impl->CastToIntrinsic();
1502 methodPtr = reinterpret_cast<ark::compiler::RuntimeInterface::MethodPtr>(intrinsic->GetImm(idx));
1503 } else {
1504 LIBABCKIT_LOG(DEBUG) << "Instruction is not a call or intrinsic\n";
1505 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1506 return nullptr;
1507 }
1508
1509 auto it = graph->irInterface->methods.find(reinterpret_cast<uintptr_t>(methodPtr));
1510 if (it == graph->irInterface->methods.end()) {
1511 LIBABCKIT_LOG(DEBUG) << "No requested call exists in current graph context\n";
1512 SetLastError(ABCKIT_STATUS_UNSUPPORTED);
1513 return nullptr;
1514 }
1515
1516 auto &nameToFunction = reinterpret_cast<CtxGInternal *>(graph->internal)->runtimeAdapter->IsMethodStatic(methodPtr)
1517 ? graph->file->nameToFunctionStatic
1518 : graph->file->nameToFunctionInstance;
1519 if (nameToFunction.count(it->second) == 0) {
1520 statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED);
1521 return nullptr;
1522 }
1523 return nameToFunction[it->second];
1524 }
1525
IsetFunctionStatic(AbckitInst * inst,AbckitCoreFunction * function)1526 void IsetFunctionStatic(AbckitInst *inst, AbckitCoreFunction *function)
1527 {
1528 LIBABCKIT_LOG_FUNC;
1529 auto *graph = inst->graph;
1530
1531 auto methodOffset = GetMethodOffset(graph, function);
1532
1533 if (inst->impl->IsCall()) {
1534 auto *callInst = static_cast<ark::compiler::CallInst *>(inst->impl);
1535 callInst->SetCallMethodId(methodOffset);
1536 } else if (inst->impl->IsIntrinsic()) {
1537 size_t idx = 0;
1538 if (IsDynamic(inst->graph->function->owningModule->target)) {
1539 auto instOpcode = GetDynamicOpcode(inst->impl);
1540 if (!HasMethodIdOperandDynamic(instOpcode)) {
1541 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1542 return;
1543 }
1544 idx = GetMethodIdOperandIndexDynamic(instOpcode);
1545 } else {
1546 auto instOpcode = GetStaticOpcode(inst->impl);
1547 if (!HasMethodIdOperandStatic(instOpcode)) {
1548 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1549 return;
1550 }
1551 idx = GetMethodIdOperandIndexStatic(instOpcode);
1552 }
1553
1554 auto *intrinsic = inst->impl->CastToIntrinsic();
1555 intrinsic->SetImm(idx, methodOffset);
1556 } else {
1557 LIBABCKIT_LOG(DEBUG) << "Instruction is not a call or intrinsic\n";
1558 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1559 return;
1560 }
1561 }
1562
IsetClassStatic(AbckitInst * inst,AbckitCoreClass * klass)1563 void IsetClassStatic(AbckitInst *inst, AbckitCoreClass *klass)
1564 {
1565 LIBABCKIT_LOG_FUNC;
1566 auto *graph = inst->graph;
1567 auto *intrinsic = inst->impl->CastToIntrinsic();
1568 auto instOpcode = GetStaticOpcode(inst->impl);
1569 if (!HasTypeIdOperandStatic(instOpcode)) {
1570 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1571 return;
1572 }
1573 size_t idx = GetTypeIdOperandIndexStatic(instOpcode);
1574 auto klassOffset = GetClassOffset(graph, klass);
1575 intrinsic->SetImm(idx, klassOffset);
1576 }
1577
IgetClassStatic(AbckitInst * inst)1578 AbckitCoreClass *IgetClassStatic(AbckitInst *inst)
1579 {
1580 LIBABCKIT_LOG_FUNC;
1581 auto *graph = inst->graph;
1582 auto *intrinsic = inst->impl->CastToIntrinsic();
1583 auto instOpcode = IgetOpcodeStaticStatic(inst);
1584 if (!HasTypeIdOperandStatic(instOpcode)) {
1585 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1586 return nullptr;
1587 }
1588 size_t idx = GetTypeIdOperandIndexStatic(instOpcode);
1589 auto classPtr = reinterpret_cast<ark::compiler::RuntimeInterface::ClassPtr>(intrinsic->GetImm(idx));
1590
1591 auto it = graph->ptrToClass.find(reinterpret_cast<uintptr_t>(classPtr));
1592 if (it == graph->ptrToClass.end()) {
1593 LIBABCKIT_LOG(DEBUG) << "No requested class exists in current graph context\n";
1594 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1595 return nullptr;
1596 }
1597 return it->second;
1598 }
1599
GcreateNullPtrStatic(AbckitGraph * graph)1600 AbckitInst *GcreateNullPtrStatic(AbckitGraph *graph)
1601 {
1602 auto instImpl = graph->impl->CreateInstNullPtr(ark::compiler::DataType::REFERENCE);
1603 auto *inst = CreateInstFromImpl(graph, instImpl);
1604 graph->impl->GetStartBlock()->AppendInst(instImpl);
1605 return inst;
1606 }
1607
IgetConstantValueI32Static(AbckitInst * inst)1608 int32_t IgetConstantValueI32Static(AbckitInst *inst)
1609 {
1610 if (!inst->impl->IsConst()) {
1611 LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction"
1612 << '\n';
1613 }
1614 if (inst->impl->GetType() != ark::compiler::DataType::INT32 &&
1615 inst->impl->GetType() != ark::compiler::DataType::UINT32) {
1616 LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n';
1617 }
1618 return static_cast<ark::compiler::ConstantInst *>(inst->impl)->GetInt32Value();
1619 }
1620
IgetConstantValueI64Static(AbckitInst * inst)1621 int64_t IgetConstantValueI64Static(AbckitInst *inst)
1622 {
1623 if (!inst->impl->IsConst()) {
1624 LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction"
1625 << '\n';
1626 }
1627 if (inst->impl->GetType() != ark::compiler::DataType::INT64 &&
1628 inst->impl->GetType() != ark::compiler::DataType::UINT64) {
1629 LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n';
1630 }
1631 return static_cast<ark::compiler::ConstantInst *>(inst->impl)->GetInt64Value();
1632 }
1633
IgetConstantValueU64Static(AbckitInst * inst)1634 uint64_t IgetConstantValueU64Static(AbckitInst *inst)
1635 {
1636 if (!inst->impl->IsConst()) {
1637 LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction"
1638 << '\n';
1639 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1640 }
1641 if (inst->impl->GetType() != ark::compiler::DataType::INT64 &&
1642 inst->impl->GetType() != ark::compiler::DataType::UINT64) {
1643 LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n';
1644 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1645 }
1646 return static_cast<ark::compiler::ConstantInst *>(inst->impl)->GetInt64Value();
1647 }
1648
IgetConstantValueF64Static(AbckitInst * inst)1649 double IgetConstantValueF64Static(AbckitInst *inst)
1650 {
1651 if (!inst->impl->IsConst()) {
1652 LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction"
1653 << '\n';
1654 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1655 }
1656 if (inst->impl->GetType() != ark::compiler::DataType::FLOAT64) {
1657 LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n';
1658 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1659 }
1660 return static_cast<ark::compiler::ConstantInst *>(inst->impl)->GetDoubleValue();
1661 }
1662
IgetImmediateStatic(AbckitInst * inst,size_t idx)1663 uint64_t IgetImmediateStatic(AbckitInst *inst, size_t idx)
1664 {
1665 LIBABCKIT_LOG_FUNC;
1666
1667 if (IgetImmediateCountStatic(inst) <= idx) {
1668 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1669 return 0;
1670 }
1671
1672 uint64_t ret = 0;
1673
1674 if (inst->impl->IsBinaryImmInst()) {
1675 ret = (static_cast<ark::compiler::BinaryImmOperation *>(inst->impl))->GetImm();
1676 } else if (inst->impl->GetOpcode() == ark::compiler::Opcode::Intrinsic) {
1677 ret = inst->impl->CastToIntrinsic()->GetImm(idx);
1678 } else {
1679 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1680 return 0;
1681 }
1682 return ret;
1683 }
1684
IsetImmediateStatic(AbckitInst * inst,size_t idx,uint64_t imm)1685 void IsetImmediateStatic(AbckitInst *inst, size_t idx, uint64_t imm)
1686 {
1687 LIBABCKIT_LOG_FUNC;
1688
1689 if (IgetImmediateCountStatic(inst) <= idx) {
1690 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1691 return;
1692 }
1693
1694 if (inst->impl->IsBinaryImmInst()) {
1695 if (GetBitLengthUnsigned(imm) <= GetBinaryImmOperationSize(inst->impl->GetOpcode())) {
1696 (static_cast<ark::compiler::BinaryImmOperation *>(inst->impl))->SetImm(imm);
1697 } else {
1698 LIBABCKIT_LOG(DEBUG) << "Immediate type overflow\n";
1699 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1700 }
1701 } else if (inst->impl->GetOpcode() == ark::compiler::Opcode::Intrinsic) {
1702 auto instr = inst->impl->CastToIntrinsic();
1703 if (GetBitLengthUnsigned(imm) <= GetIntrinsicBitImmSize(instr->GetIntrinsicId(), idx)) {
1704 instr->SetImm(idx, imm);
1705 } else {
1706 LIBABCKIT_LOG(DEBUG) << "Immediate type overflow\n";
1707 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1708 }
1709 } else {
1710 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1711 }
1712 }
1713
IgetImmediateSizeStatic(AbckitInst * inst,size_t idx)1714 AbckitBitImmSize IgetImmediateSizeStatic(AbckitInst *inst, size_t idx)
1715 {
1716 LIBABCKIT_LOG_FUNC;
1717
1718 if (IgetImmediateCountStatic(inst) <= idx) {
1719 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1720 return AbckitBitImmSize::BITSIZE_0;
1721 }
1722
1723 auto immBitSize = AbckitBitImmSize::BITSIZE_0;
1724 if (inst->impl->IsBinaryImmInst()) {
1725 immBitSize = GetBinaryImmOperationSize(inst->impl->GetOpcode());
1726 } else if (inst->impl->GetOpcode() == ark::compiler::Opcode::Intrinsic) {
1727 auto instr = inst->impl->CastToIntrinsic();
1728 immBitSize = GetIntrinsicBitImmSize(instr->GetIntrinsicId(), idx);
1729 } else {
1730 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1731 }
1732 return immBitSize;
1733 }
1734
IgetImmediateCountStatic(AbckitInst * inst)1735 uint64_t IgetImmediateCountStatic(AbckitInst *inst)
1736 {
1737 LIBABCKIT_LOG_FUNC;
1738
1739 uint64_t ret = 0;
1740
1741 if (inst->impl->IsBinaryImmInst()) {
1742 ret = 1;
1743 } else if (inst->impl->GetOpcode() == ark::compiler::Opcode::Intrinsic) {
1744 auto instr = inst->impl->CastToIntrinsic();
1745 return instr->HasImms() ? instr->GetImms().size() : 0;
1746 }
1747 return ret;
1748 }
1749
IgetModuleStatic(AbckitInst * inst)1750 AbckitCoreModule *IgetModuleStatic(AbckitInst *inst)
1751 {
1752 LIBABCKIT_LOG_FUNC;
1753
1754 if (!inst->impl->IsIntrinsic()) {
1755 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n";
1756 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1757 return nullptr;
1758 }
1759
1760 auto intrInst = inst->impl->CastToIntrinsic();
1761 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1762 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_GETMODULENAMESPACE &&
1763 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_GETMODULENAMESPACE) {
1764 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n";
1765 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1766 return nullptr;
1767 }
1768
1769 return inst->graph->function->owningModule->md[intrInst->GetImm(0)];
1770 }
1771
GetModuleIndex(AbckitGraph * graph,AbckitCoreModule * md)1772 uint64_t GetModuleIndex(AbckitGraph *graph, AbckitCoreModule *md)
1773 {
1774 uint64_t imm = 0;
1775 for (auto m : graph->function->owningModule->md) {
1776 if (m == md) {
1777 break;
1778 }
1779 imm++;
1780 }
1781 if (imm == graph->function->owningModule->md.size()) {
1782 LIBABCKIT_LOG(DEBUG) << "Can not find module descriptor for module with name '" << md->moduleName->impl
1783 << "'\n";
1784 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1785 return 0;
1786 }
1787 return imm;
1788 }
1789
IsetModuleStatic(AbckitInst * inst,AbckitCoreModule * md)1790 void IsetModuleStatic(AbckitInst *inst, AbckitCoreModule *md)
1791 {
1792 LIBABCKIT_LOG_FUNC;
1793
1794 if (!inst->impl->IsIntrinsic()) {
1795 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n";
1796 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1797 return;
1798 }
1799
1800 auto intrInst = inst->impl->CastToIntrinsic();
1801 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1802 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_GETMODULENAMESPACE &&
1803 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_GETMODULENAMESPACE) {
1804 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n";
1805 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1806 return;
1807 }
1808
1809 uint64_t imm = GetModuleIndex(inst->graph, md);
1810 if (statuses::GetLastError() != ABCKIT_STATUS_NO_ERROR) {
1811 return;
1812 }
1813 intrInst->SetImm(0, imm);
1814 }
1815
GetImportDescriptorDynamic(AbckitInst * inst,uint64_t idx)1816 AbckitCoreImportDescriptor *GetImportDescriptorDynamic(AbckitInst *inst, uint64_t idx)
1817 {
1818 auto *module = inst->graph->function->owningModule;
1819 for (auto &id : module->id) {
1820 auto idPayload = GetDynImportDescriptorPayload(id.get());
1821 if (!idPayload->isRegularImport) {
1822 continue;
1823 }
1824 if (idPayload->moduleRecordIndexOff == idx) {
1825 return id.get();
1826 }
1827 }
1828 UNREACHABLE();
1829 }
1830
IgetImportDescriptorStatic(AbckitInst * inst)1831 AbckitCoreImportDescriptor *IgetImportDescriptorStatic(AbckitInst *inst)
1832 {
1833 LIBABCKIT_LOG_FUNC;
1834 ASSERT(IsDynamic(inst->graph->function->owningModule->target));
1835
1836 if (!inst->impl->IsIntrinsic()) {
1837 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n";
1838 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1839 return nullptr;
1840 }
1841
1842 auto intrInst = inst->impl->CastToIntrinsic();
1843 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1844 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_LDEXTERNALMODULEVAR &&
1845 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_LDEXTERNALMODULEVAR) {
1846 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n";
1847 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1848 return nullptr;
1849 }
1850
1851 return GetImportDescriptorDynamic(inst, intrInst->GetImm(0));
1852 }
1853
GetImportDescriptorIdxDynamic(AbckitGraph * graph,AbckitCoreImportDescriptor * id)1854 uint32_t GetImportDescriptorIdxDynamic(AbckitGraph *graph, AbckitCoreImportDescriptor *id)
1855 {
1856 AbckitCoreModule *m = graph->function->owningModule;
1857 auto found = std::find_if(m->id.begin(), m->id.end(),
1858 [&](std::unique_ptr<AbckitCoreImportDescriptor> const &d) { return d.get() == id; });
1859 if (found == m->id.end()) {
1860 LIBABCKIT_LOG(DEBUG) << "Can not find the import in module imports\n";
1861 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1862 return 0;
1863 }
1864 return GetDynImportDescriptorPayload(found->get())->moduleRecordIndexOff;
1865 }
1866
IsetImportDescriptorStatic(AbckitInst * inst,AbckitCoreImportDescriptor * id)1867 void IsetImportDescriptorStatic(AbckitInst *inst, AbckitCoreImportDescriptor *id)
1868 {
1869 LIBABCKIT_LOG_FUNC;
1870 ASSERT(IsDynamic(inst->graph->function->owningModule->target));
1871
1872 if (!inst->impl->IsIntrinsic()) {
1873 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n";
1874 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1875 return;
1876 }
1877
1878 auto intrInst = inst->impl->CastToIntrinsic();
1879 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1880 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_LDEXTERNALMODULEVAR &&
1881 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_LDEXTERNALMODULEVAR) {
1882 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n";
1883 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1884 return;
1885 }
1886
1887 uint32_t imm = GetImportDescriptorIdxDynamic(inst->graph, id);
1888 if (statuses::GetLastError() != ABCKIT_STATUS_NO_ERROR) {
1889 return;
1890 }
1891 intrInst->SetImm(0, imm);
1892 }
1893
GetExportDescriptorDynamic(AbckitInst * inst,uint64_t idx)1894 AbckitCoreExportDescriptor *GetExportDescriptorDynamic(AbckitInst *inst, uint64_t idx)
1895 {
1896 auto *module = inst->graph->function->owningModule;
1897 for (auto &ed : module->ed) {
1898 auto edPayload = GetDynExportDescriptorPayload(ed.get());
1899 if (edPayload->kind != AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT) {
1900 continue;
1901 }
1902 if (edPayload->moduleRecordIndexOff == idx) {
1903 return ed.get();
1904 }
1905 }
1906 UNREACHABLE();
1907 }
1908
IgetExportDescriptorStatic(AbckitInst * inst)1909 AbckitCoreExportDescriptor *IgetExportDescriptorStatic(AbckitInst *inst)
1910 {
1911 LIBABCKIT_LOG_FUNC;
1912 ASSERT(IsDynamic(inst->graph->function->owningModule->target));
1913
1914 if (!inst->impl->IsIntrinsic()) {
1915 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n";
1916 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1917 return nullptr;
1918 }
1919
1920 auto intrInst = inst->impl->CastToIntrinsic();
1921 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1922 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_LDLOCALMODULEVAR &&
1923 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_LDLOCALMODULEVAR &&
1924 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_STMODULEVAR &&
1925 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_STMODULEVAR) {
1926 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n";
1927 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1928 return nullptr;
1929 }
1930
1931 return GetExportDescriptorDynamic(inst, intrInst->GetImm(0));
1932 }
1933
GetExportDescriptorIdxDynamic(AbckitGraph * graph,AbckitCoreExportDescriptor * ed)1934 uint32_t GetExportDescriptorIdxDynamic(AbckitGraph *graph, AbckitCoreExportDescriptor *ed)
1935 {
1936 AbckitCoreModule *m = graph->function->owningModule;
1937 auto found = std::find_if(m->ed.begin(), m->ed.end(),
1938 [&](std::unique_ptr<AbckitCoreExportDescriptor> const &d) { return d.get() == ed; });
1939 if (found == m->ed.end()) {
1940 LIBABCKIT_LOG(DEBUG) << "Can not find the import in module imports\n";
1941 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1942 return 0;
1943 }
1944 return GetDynExportDescriptorPayload(found->get())->moduleRecordIndexOff;
1945 }
1946
IsetExportDescriptorStatic(AbckitInst * inst,AbckitCoreExportDescriptor * ed)1947 void IsetExportDescriptorStatic(AbckitInst *inst, AbckitCoreExportDescriptor *ed)
1948 {
1949 LIBABCKIT_LOG_FUNC;
1950 ASSERT(IsDynamic(inst->graph->function->owningModule->target));
1951
1952 if (!inst->impl->IsIntrinsic()) {
1953 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n";
1954 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1955 return;
1956 }
1957
1958 auto intrInst = inst->impl->CastToIntrinsic();
1959 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1960 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_LDLOCALMODULEVAR &&
1961 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_LDLOCALMODULEVAR &&
1962 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_STMODULEVAR &&
1963 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_STMODULEVAR) {
1964 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n";
1965 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1966 return;
1967 }
1968
1969 uint32_t imm = GetExportDescriptorIdxDynamic(inst->graph, ed);
1970 if (statuses::GetLastError() != ABCKIT_STATUS_NO_ERROR) {
1971 return;
1972 }
1973 intrInst->SetImm(0, imm);
1974 }
1975
IgetConditionCodeStaticStatic(AbckitInst * inst)1976 AbckitIsaApiStaticConditionCode IgetConditionCodeStaticStatic(AbckitInst *inst)
1977 {
1978 return CcToStaticCc(inst->impl->CastToIf()->GetCc());
1979 }
1980
IgetConditionCodeDynamicStatic(AbckitInst * inst)1981 AbckitIsaApiDynamicConditionCode IgetConditionCodeDynamicStatic(AbckitInst *inst)
1982 {
1983 return CcToDynamicCc(inst->impl->CastToIf()->GetCc());
1984 }
1985
IsetConditionCodeStaticStatic(AbckitInst * inst,AbckitIsaApiStaticConditionCode cc)1986 void IsetConditionCodeStaticStatic(AbckitInst *inst, AbckitIsaApiStaticConditionCode cc)
1987 {
1988 inst->impl->CastToIf()->SetCc(CcToCc(cc));
1989 }
1990
IsetConditionCodeDynamicStatic(AbckitInst * inst,AbckitIsaApiDynamicConditionCode cc)1991 void IsetConditionCodeDynamicStatic(AbckitInst *inst, AbckitIsaApiDynamicConditionCode cc)
1992 {
1993 inst->impl->CastToIf()->SetCc(CcToCc(cc));
1994 }
1995
1996 } // namespace libabckit
1997