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 "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)806 void BBdumpStatic(AbckitBasicBlock *basicBlock, int /*fd*/)
807 {
808 LIBABCKIT_LOG_FUNC;
809 LIBABCKIT_BAD_ARGUMENT_VOID(basicBlock)
810
811 std::stringstream ss;
812 LIBABCKIT_LOG_DUMP(basicBlock->impl->Dump(&ss), DEBUG);
813 }
814
BBcheckDominanceStatic(AbckitBasicBlock * basicBlock,AbckitBasicBlock * dominator)815 bool BBcheckDominanceStatic(AbckitBasicBlock *basicBlock, AbckitBasicBlock *dominator)
816 {
817 LIBABCKIT_LOG_FUNC;
818 LIBABCKIT_BAD_ARGUMENT(basicBlock, false);
819 LIBABCKIT_BAD_ARGUMENT(dominator, false);
820
821 LIBABCKIT_WRONG_CTX(basicBlock->graph, dominator->graph, false);
822
823 if (!GraphDominatorsTreeAnalysisIsValid(basicBlock->graph->impl)) {
824 LIBABCKIT_LOG(DEBUG) << "DominatorsTree analysis is not valid\n";
825 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
826 return false;
827 }
828
829 return dominator->impl->IsDominate(basicBlock->impl);
830 }
831
BBgetImmediateDominatorStatic(AbckitBasicBlock * basicBlock)832 AbckitBasicBlock *BBgetImmediateDominatorStatic(AbckitBasicBlock *basicBlock)
833 {
834 LIBABCKIT_LOG_FUNC;
835 LIBABCKIT_BAD_ARGUMENT(basicBlock, nullptr);
836
837 if (!GraphDominatorsTreeAnalysisIsValid(basicBlock->graph->impl)) {
838 LIBABCKIT_LOG(DEBUG) << "DominatorsTree analysis is not valid\n";
839 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
840 return nullptr;
841 }
842
843 auto *bb = basicBlock->impl->GetDominator();
844 return basicBlock->graph->implToBB.at(bb);
845 }
846
BBvisitDominatedBlocksStatic(AbckitBasicBlock * basicBlock,void * data,bool (* cb)(AbckitBasicBlock * dominatedBasicBlock,void * data))847 bool BBvisitDominatedBlocksStatic(AbckitBasicBlock *basicBlock, void *data,
848 bool (*cb)(AbckitBasicBlock *dominatedBasicBlock, void *data))
849 {
850 LIBABCKIT_LOG_FUNC;
851 LIBABCKIT_BAD_ARGUMENT(basicBlock, false)
852 LIBABCKIT_BAD_ARGUMENT(cb, false)
853
854 if (!GraphDominatorsTreeAnalysisIsValid(basicBlock->graph->impl)) {
855 LIBABCKIT_LOG(DEBUG) << "DominatorsTree analysis is not valid\n";
856 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
857 return false;
858 }
859
860 for (auto *bbImpl : basicBlock->impl->GetDominatedBlocks()) {
861 auto *bb = basicBlock->graph->implToBB.at(bbImpl);
862 if (!cb(bb, data)) {
863 return false;
864 }
865 }
866 return true;
867 }
868
BBinsertSuccBlockStatic(AbckitBasicBlock * basicBlock,AbckitBasicBlock * succBlock,uint32_t index)869 void BBinsertSuccBlockStatic(AbckitBasicBlock *basicBlock, AbckitBasicBlock *succBlock, uint32_t index)
870 {
871 LIBABCKIT_LOG_FUNC;
872 LIBABCKIT_BAD_ARGUMENT_VOID(basicBlock)
873 LIBABCKIT_BAD_ARGUMENT_VOID(succBlock)
874
875 LIBABCKIT_WRONG_CTX_VOID(basicBlock->graph, succBlock->graph);
876
877 auto &bbs = basicBlock->impl->GetSuccsBlocks();
878 if (index > bbs.size()) {
879 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
880 return;
881 }
882
883 if (index == bbs.size()) {
884 bbs.emplace_back(succBlock->impl);
885 } else {
886 bbs.resize(bbs.size() + 1);
887 for (size_t i = index + 1; i < bbs.size(); i++) {
888 bbs[i] = bbs[i - 1];
889 }
890 bbs[index] = succBlock->impl;
891 }
892
893 succBlock->impl->GetPredsBlocks().emplace_back(basicBlock->impl);
894 GraphInvalidateAnalyses(basicBlock->graph->impl);
895 }
896
BBappendSuccBlockStatic(AbckitBasicBlock * basicBlock,AbckitBasicBlock * succBlock)897 void BBappendSuccBlockStatic(AbckitBasicBlock *basicBlock, AbckitBasicBlock *succBlock)
898 {
899 LIBABCKIT_LOG_FUNC;
900 LIBABCKIT_BAD_ARGUMENT_VOID(basicBlock)
901 LIBABCKIT_BAD_ARGUMENT_VOID(succBlock)
902
903 LIBABCKIT_WRONG_CTX_VOID(basicBlock->graph, succBlock->graph);
904
905 basicBlock->impl->GetSuccsBlocks().emplace_back(succBlock->impl);
906 succBlock->impl->GetPredsBlocks().emplace_back(basicBlock->impl);
907 GraphInvalidateAnalyses(basicBlock->graph->impl);
908 }
909
BBgetTrueBranchStatic(AbckitBasicBlock * bb)910 AbckitBasicBlock *BBgetTrueBranchStatic(AbckitBasicBlock *bb)
911 {
912 LIBABCKIT_LOG_FUNC;
913 LIBABCKIT_BAD_ARGUMENT(bb, nullptr);
914
915 if (bb->impl->GetSuccsBlocks().empty()) {
916 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
917 return nullptr;
918 }
919 auto *tb = bb->impl->GetTrueSuccessor();
920 ASSERT(tb != nullptr);
921
922 return bb->graph->implToBB.at(tb);
923 }
924
BBgetFalseBranchStatic(AbckitBasicBlock * bb)925 AbckitBasicBlock *BBgetFalseBranchStatic(AbckitBasicBlock *bb)
926 {
927 LIBABCKIT_LOG_FUNC;
928 LIBABCKIT_BAD_ARGUMENT(bb, nullptr);
929
930 if (bb->impl->GetSuccsBlocks().size() < 2U) {
931 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
932 return nullptr;
933 }
934 auto *fb = bb->impl->GetFalseSuccessor();
935 ASSERT(fb != nullptr);
936
937 return bb->graph->implToBB.at(fb);
938 }
939
BBcreatePhiStatic(AbckitBasicBlock * bb,size_t argCount,std::va_list args)940 AbckitInst *BBcreatePhiStatic(AbckitBasicBlock *bb, size_t argCount, std::va_list args)
941 {
942 LIBABCKIT_LOG_FUNC;
943
944 LIBABCKIT_LOG(DEBUG) << argCount << '\n';
945 if (argCount < 1) {
946 LIBABCKIT_LOG(DEBUG) << "not enough inputs\n";
947 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
948 return nullptr;
949 }
950
951 std::vector<AbckitInst *> inputs;
952
953 for (size_t index = 0; index < argCount; ++index) {
954 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
955 AbckitInst *input = va_arg(args, AbckitInst *);
956 LIBABCKIT_BAD_ARGUMENT(input, nullptr);
957 inputs.emplace_back(input);
958 }
959
960 ark::compiler::DataType::Type type = inputs[0]->impl->GetType();
961 if (IsDynamic(bb->graph->function->owningModule->target)) {
962 type = ark::compiler::DataType::ANY;
963 }
964
965 for (auto *inst : inputs) {
966 if (IsDynamic(bb->graph->function->owningModule->target)) {
967 if (inst->impl->GetType() != ark::compiler::DataType::INT64 &&
968 inst->impl->GetType() != ark::compiler::DataType::ANY) {
969 LIBABCKIT_LOG(DEBUG) << "inconsistent input types\n";
970 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
971 return nullptr;
972 }
973 } else {
974 if (type != inst->impl->GetType()) {
975 LIBABCKIT_LOG(DEBUG) << "inconsistent input types\n";
976 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
977 return nullptr;
978 }
979 }
980 }
981
982 auto phiImpl = bb->graph->impl->CreateInstPhi(type, 0);
983 bb->impl->AppendPhi(phiImpl);
984 auto *phi = CreateInstFromImpl(bb->graph, phiImpl);
985 for (auto *inst : inputs) {
986 phiImpl->AppendInput(inst->impl);
987 }
988 return phi;
989 }
990
BBcreateCatchPhiStatic(AbckitBasicBlock * catchBegin,size_t argCount,std::va_list args)991 AbckitInst *BBcreateCatchPhiStatic(AbckitBasicBlock *catchBegin, size_t argCount, std::va_list args)
992 {
993 auto *instImpl = catchBegin->graph->impl->CreateInstCatchPhi();
994 auto *catchPhi = CreateInstFromImpl(catchBegin->graph, instImpl);
995
996 BBaddInstFrontStatic(catchBegin, catchPhi);
997
998 if (argCount == 0) {
999 auto type = IsDynamic(catchBegin->graph->function->owningModule->target) ? ark::compiler::DataType::ANY
1000 : ark::compiler::DataType::REFERENCE;
1001 instImpl->SetIsAcc();
1002 instImpl->SetType(type);
1003 return catchPhi;
1004 }
1005
1006 std::vector<ark::compiler::DataType::Type> types;
1007
1008 for (size_t index = 0; index < argCount; ++index) {
1009 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
1010 AbckitInst *inputOrThrowable = va_arg(args, AbckitInst *);
1011 if (index % 2U == 0) {
1012 types.push_back(inputOrThrowable->impl->GetType());
1013 catchPhi->impl->AppendInput(inputOrThrowable->impl);
1014 } else {
1015 catchPhi->impl->CastToCatchPhi()->AppendThrowableInst(inputOrThrowable->impl);
1016 }
1017 }
1018
1019 ASSERT(!types.empty());
1020
1021 if (IsDynamic(catchBegin->graph->function->owningModule->target)) {
1022 catchPhi->impl->SetType(ark::compiler::DataType::ANY);
1023 } else {
1024 for (int i = 1, j = types.size(); i < j; ++i) {
1025 if (types[0] != types[i]) {
1026 LIBABCKIT_LOG(DEBUG) << "All inputs of a catchPhi should be of the same type " << '\n';
1027 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1028 catchBegin->impl->EraseInst(instImpl, true);
1029 return nullptr;
1030 }
1031 }
1032 catchPhi->impl->SetType(types[0]);
1033 }
1034
1035 return catchPhi;
1036 }
1037
1038 // ========================================
1039 // Api for instruction manipulation
1040 // ========================================
1041
IremoveStatic(AbckitInst * inst)1042 void IremoveStatic(AbckitInst *inst)
1043 {
1044 LIBABCKIT_LOG_FUNC;
1045
1046 auto bbImpl = inst->impl->GetBasicBlock();
1047 LIBABCKIT_BAD_ARGUMENT_VOID(bbImpl)
1048
1049 bbImpl->RemoveInst(inst->impl);
1050 }
1051
IgetIdStatic(AbckitInst * inst)1052 uint32_t IgetIdStatic(AbckitInst *inst)
1053 {
1054 LIBABCKIT_LOG_FUNC;
1055 auto id = inst->impl->GetId();
1056 LIBABCKIT_LOG(DEBUG) << id << '\n';
1057 return id;
1058 }
1059
IgetLiteralArrayStatic(AbckitInst * inst)1060 AbckitLiteralArray *IgetLiteralArrayStatic(AbckitInst *inst)
1061 {
1062 LIBABCKIT_LOG_FUNC;
1063 size_t idx = 0;
1064 if (IsDynamic(inst->graph->function->owningModule->target)) {
1065 auto instOpcode = GetDynamicOpcode(inst->impl);
1066 if (!HasLiteralArrayIdOperandDynamic(instOpcode)) {
1067 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1068 return nullptr;
1069 }
1070 idx = GetLiteralArrayIdOperandIndexDynamic(instOpcode);
1071 } else {
1072 auto instOpcode = GetStaticOpcode(inst->impl);
1073 if (!HasLiteralArrayIdOperandStatic(instOpcode)) {
1074 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1075 return nullptr;
1076 }
1077 idx = GetLiteralArrayIdOperandIndexStatic(instOpcode);
1078 }
1079 auto &imms = inst->impl->CastToIntrinsic()->GetImms();
1080 ASSERT(!imms.empty());
1081 auto arrName = inst->graph->irInterface->literalarrays.at(imms[idx]);
1082 std::variant<ark::pandasm::LiteralArray *, panda::pandasm::LiteralArray *> arrImpl {
1083 (panda::pandasm::LiteralArray *)nullptr};
1084 if (IsDynamic(inst->graph->function->owningModule->target)) {
1085 arrImpl = reinterpret_cast<panda::pandasm::LiteralArray *>(
1086 PandasmWrapper::GetUnwrappedLiteralArrayTable(inst->graph->file->GetDynamicProgram()).at(arrName));
1087 } else {
1088 arrImpl = &inst->graph->file->GetStaticProgram()->literalarrayTable.at(arrName);
1089 }
1090
1091 // Search through already created litarrs
1092 auto &abckitLitArrs = inst->graph->file->litarrs;
1093 for (auto &item : abckitLitArrs) {
1094 if (item->impl == arrImpl) {
1095 return item.get();
1096 }
1097 }
1098
1099 // Create new litarr
1100 auto litarr = std::make_unique<AbckitLiteralArray>();
1101 litarr->file = inst->graph->file;
1102 litarr->impl = arrImpl;
1103 return abckitLitArrs.emplace_back(std::move(litarr)).get();
1104 }
1105
IsetLiteralArrayStatic(AbckitInst * inst,AbckitLiteralArray * la)1106 void IsetLiteralArrayStatic(AbckitInst *inst, AbckitLiteralArray *la)
1107 {
1108 LIBABCKIT_LOG_FUNC;
1109 size_t idx = 0;
1110 if (IsDynamic(inst->graph->function->owningModule->target)) {
1111 auto instOpcode = GetDynamicOpcode(inst->impl);
1112 if (!HasLiteralArrayIdOperandDynamic(instOpcode)) {
1113 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1114 return;
1115 }
1116 idx = GetLiteralArrayIdOperandIndexDynamic(instOpcode);
1117 } else {
1118 auto instOpcode = GetStaticOpcode(inst->impl);
1119 if (!HasLiteralArrayIdOperandStatic(instOpcode)) {
1120 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1121 return;
1122 }
1123 idx = GetLiteralArrayIdOperandIndexStatic(instOpcode);
1124 }
1125
1126 auto &imms = inst->impl->CastToIntrinsic()->GetImms();
1127 ASSERT(imms.size() == 2U);
1128 imms[idx] = GetLiteralArrayOffset(inst->graph, la);
1129 }
1130
IgetStringStatic(AbckitInst * inst)1131 AbckitString *IgetStringStatic(AbckitInst *inst)
1132 {
1133 LIBABCKIT_LOG_FUNC;
1134 size_t idx = 0;
1135 if (IsDynamic(inst->graph->function->owningModule->target)) {
1136 auto instOpcode = GetDynamicOpcode(inst->impl);
1137 if (!HasStringIdOperandDynamic(instOpcode)) {
1138 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1139 return nullptr;
1140 }
1141 idx = GetStringIdOperandIndexDynamic(instOpcode);
1142 } else {
1143 auto instOpcode = GetStaticOpcode(inst->impl);
1144 if (!HasStringIdOperandStatic(instOpcode)) {
1145 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1146 return nullptr;
1147 }
1148 idx = GetStringIdOperandIndexStatic(instOpcode);
1149 }
1150
1151 auto &imms = inst->impl->CastToIntrinsic()->GetImms();
1152 auto strName = inst->graph->irInterface->strings.at(imms[idx]);
1153 auto strImpl = inst->graph->file->strings.at(strName).get();
1154 return strImpl;
1155 }
1156
IsetStringStatic(AbckitInst * inst,AbckitString * str)1157 void IsetStringStatic(AbckitInst *inst, AbckitString *str)
1158 {
1159 LIBABCKIT_LOG_FUNC;
1160 size_t idx = 0;
1161 if (IsDynamic(inst->graph->function->owningModule->target)) {
1162 auto instOpcode = GetDynamicOpcode(inst->impl);
1163 if (!HasStringIdOperandDynamic(instOpcode)) {
1164 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1165 return;
1166 }
1167 idx = GetStringIdOperandIndexDynamic(instOpcode);
1168 } else {
1169 auto instOpcode = GetStaticOpcode(inst->impl);
1170 if (!HasStringIdOperandStatic(instOpcode)) {
1171 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1172 return;
1173 }
1174 idx = GetStringIdOperandIndexStatic(instOpcode);
1175 }
1176
1177 auto &imms = inst->impl->CastToIntrinsic()->GetImms();
1178 imms[idx] = GetStringOffset(inst->graph, str);
1179 }
1180
IgetOpcodeStaticStatic(AbckitInst * inst)1181 AbckitIsaApiStaticOpcode IgetOpcodeStaticStatic(AbckitInst *inst)
1182 {
1183 LIBABCKIT_LOG_FUNC;
1184 auto opc = inst->impl->GetOpcode();
1185 if (opc == ark::compiler::Opcode::Intrinsic) {
1186 return GetStaticIntrinsicOpcode(inst->impl->CastToIntrinsic());
1187 }
1188 return GetStaticOpcode(inst->impl);
1189 }
1190
IgetOpcodeDynamicStatic(AbckitInst * inst)1191 AbckitIsaApiDynamicOpcode IgetOpcodeDynamicStatic(AbckitInst *inst)
1192 {
1193 LIBABCKIT_LOG_FUNC;
1194 auto opc = inst->impl->GetOpcode();
1195 if (opc == ark::compiler::Opcode::Intrinsic) {
1196 switch (inst->impl->CastToIntrinsic()->GetIntrinsicId()) {
1197 case ark::compiler::RuntimeInterface::IntrinsicId::INTRINSIC_ABCKIT_LOAD_STRING:
1198 return ABCKIT_ISA_API_DYNAMIC_OPCODE_LOADSTRING;
1199 default:
1200 break;
1201 }
1202 return GetDynamicIntrinsicOpcode(inst->impl->CastToIntrinsic());
1203 }
1204 return GetDynamicOpcode(inst->impl);
1205 }
1206
IgetNextStatic(AbckitInst * inst)1207 AbckitInst *IgetNextStatic(AbckitInst *inst)
1208 {
1209 LIBABCKIT_LOG_FUNC;
1210
1211 auto *nextInstImpl = inst->impl->GetNext();
1212 if (nextInstImpl == nullptr) {
1213 return nullptr;
1214 }
1215 auto *nextInst = inst->graph->implToInst.at(nextInstImpl);
1216 return nextInst;
1217 }
1218
IgetPrevStatic(AbckitInst * inst)1219 AbckitInst *IgetPrevStatic(AbckitInst *inst)
1220 {
1221 LIBABCKIT_LOG_FUNC;
1222 auto *nextInstImpl = inst->impl->GetPrev();
1223 if (nextInstImpl == nullptr) {
1224 return nullptr;
1225 }
1226 auto *nextInst = inst->graph->implToInst.at(nextInstImpl);
1227 return nextInst;
1228 }
1229
IinsertAfterStatic(AbckitInst * inst,AbckitInst * next)1230 void IinsertAfterStatic(AbckitInst *inst, AbckitInst *next)
1231 {
1232 LIBABCKIT_LOG_FUNC;
1233 LIBABCKIT_BAD_ARGUMENT_VOID(inst)
1234 LIBABCKIT_BAD_ARGUMENT_VOID(next)
1235
1236 LIBABCKIT_WRONG_CTX_VOID(inst->graph, next->graph);
1237
1238 auto *bb = IgetBasicBlockStatic(next);
1239 LIBABCKIT_BAD_ARGUMENT_VOID(bb)
1240
1241 if (inst->impl->IsConst() || next->impl->IsConst()) {
1242 LIBABCKIT_LOG(DEBUG) << "can't use constant instruction as an argument";
1243 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1244 return;
1245 }
1246
1247 bb->impl->InsertAfter(inst->impl, next->impl);
1248 }
1249
IinsertBeforeStatic(AbckitInst * inst,AbckitInst * prev)1250 void IinsertBeforeStatic(AbckitInst *inst, AbckitInst *prev)
1251 {
1252 LIBABCKIT_LOG_FUNC;
1253 LIBABCKIT_BAD_ARGUMENT_VOID(inst)
1254 LIBABCKIT_BAD_ARGUMENT_VOID(prev)
1255
1256 LIBABCKIT_WRONG_CTX_VOID(inst->graph, prev->graph);
1257
1258 auto *bb = IgetBasicBlockStatic(prev);
1259 LIBABCKIT_BAD_ARGUMENT_VOID(bb)
1260
1261 if (inst->impl->IsConst() || prev->impl->IsConst()) {
1262 LIBABCKIT_LOG(DEBUG) << "can't use constant instruction as an argument";
1263 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1264 return;
1265 }
1266 bb->impl->InsertBefore(inst->impl, prev->impl);
1267 }
1268
IcheckDominanceStatic(AbckitInst * inst,AbckitInst * dominator)1269 bool IcheckDominanceStatic(AbckitInst *inst, AbckitInst *dominator)
1270 {
1271 LIBABCKIT_LOG_FUNC;
1272
1273 LIBABCKIT_WRONG_CTX(inst->graph, dominator->graph, false);
1274
1275 return inst->impl->IsDominate(dominator->impl);
1276 }
1277
IvisitUsersStatic(AbckitInst * inst,void * data,bool (* cb)(AbckitInst * user,void * data))1278 bool IvisitUsersStatic(AbckitInst *inst, void *data, bool (*cb)(AbckitInst *user, void *data))
1279 {
1280 LIBABCKIT_LOG_FUNC;
1281
1282 auto *user = inst->impl->GetFirstUser();
1283
1284 while (user != nullptr) {
1285 auto *userInst = inst->graph->implToInst.at(user->GetInst());
1286 if (!cb(userInst, data)) {
1287 return false;
1288 }
1289 user = user->GetNext();
1290 }
1291 return true;
1292 }
1293
IgetUserCountStatic(AbckitInst * inst)1294 uint32_t IgetUserCountStatic(AbckitInst *inst)
1295 {
1296 LIBABCKIT_LOG_FUNC;
1297 uint32_t count = 0;
1298
1299 auto *user = inst->impl->GetFirstUser();
1300
1301 while (user != nullptr) {
1302 count++;
1303 user = user->GetNext();
1304 }
1305 return count;
1306 }
1307
IvisitInputsStatic(AbckitInst * inst,void * data,bool (* cb)(AbckitInst * input,size_t inputIdx,void * data))1308 bool IvisitInputsStatic(AbckitInst *inst, void *data, bool (*cb)(AbckitInst *input, size_t inputIdx, void *data))
1309 {
1310 LIBABCKIT_LOG_FUNC;
1311 for (size_t i = 0; i < inst->impl->GetInputsCount(); i++) {
1312 auto *inputImpl = inst->impl->GetInput(i).GetInst();
1313 auto *input = inst->graph->implToInst.at(inputImpl);
1314 if (!cb(input, i, data)) {
1315 return false;
1316 }
1317 }
1318 return true;
1319 }
1320
IgetInputCountStatic(AbckitInst * inst)1321 uint64_t IgetInputCountStatic(AbckitInst *inst)
1322 {
1323 LIBABCKIT_LOG_FUNC;
1324
1325 return inst->impl->GetInputsCount();
1326 }
1327
IgetInputStatic(AbckitInst * inst,size_t index)1328 AbckitInst *IgetInputStatic(AbckitInst *inst, size_t index)
1329 {
1330 LIBABCKIT_LOG_FUNC;
1331 if (inst->impl->GetInputsCount() <= index) {
1332 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1333 return nullptr;
1334 }
1335
1336 auto *inputImpl = inst->impl->GetInput(index).GetInst();
1337 auto *input = inst->graph->implToInst.at(inputImpl);
1338 return input;
1339 }
1340
IsetInputStatic(AbckitInst * inst,AbckitInst * input,int32_t index)1341 void IsetInputStatic(AbckitInst *inst, AbckitInst *input, int32_t index)
1342 {
1343 LIBABCKIT_LOG_FUNC;
1344 LIBABCKIT_LOG(DEBUG) << index << '\n';
1345 LIBABCKIT_LOG(DEBUG) << inst->impl->GetInputs().size() << '\n';
1346 inst->impl->SetInput(index, input->impl);
1347 }
1348
IsetInputsStatic(AbckitInst * inst,size_t argCount,std::va_list args)1349 void IsetInputsStatic(AbckitInst *inst, size_t argCount, std::va_list args)
1350 {
1351 LIBABCKIT_LOG_FUNC;
1352 LIBABCKIT_LOG(DEBUG) << argCount << '\n';
1353 LIBABCKIT_LOG(DEBUG) << inst->impl->GetInputs().size() << '\n';
1354 for (size_t index = 0; index < argCount; ++index) {
1355 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
1356 AbckitInst *input = va_arg(args, AbckitInst *);
1357 inst->impl->SetInput(index, input->impl);
1358 }
1359 }
1360
IappendInputStatic(AbckitInst * inst,AbckitInst * input)1361 void IappendInputStatic(AbckitInst *inst, AbckitInst *input)
1362 {
1363 LIBABCKIT_LOG_FUNC;
1364 auto instImpl = inst->impl;
1365 static size_t rangeInputsCount = -1;
1366
1367 if (instImpl->IsOperandsDynamic()) {
1368 switch (instImpl->GetOpcode()) {
1369 case ark::compiler::Opcode::CallStatic: {
1370 instImpl->CastToCallStatic()->AppendInput(input->impl, input->impl->GetType());
1371 return;
1372 }
1373 case ark::compiler::Opcode::CallVirtual: {
1374 instImpl->CastToCallVirtual()->AppendInput(input->impl, input->impl->GetType());
1375 return;
1376 }
1377 case ark::compiler::Opcode::Intrinsic: {
1378 if (GetIntrinicMaxInputsCount(inst) == rangeInputsCount) {
1379 instImpl->CastToIntrinsic()->AppendInput(input->impl, input->impl->GetType());
1380 return;
1381 }
1382 if (instImpl->GetInputsCount() >= GetIntrinicMaxInputsCount(inst)) {
1383 LIBABCKIT_LOG(DEBUG) << "The maximum number of inputs has been reached for the instruction\n";
1384 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1385 return;
1386 }
1387 instImpl->CastToIntrinsic()->AppendInput(input->impl, input->impl->GetType());
1388 return;
1389 }
1390 case ark::compiler::Opcode::Phi: {
1391 instImpl->AppendInput(input->impl);
1392 return;
1393 }
1394 default:
1395 break;
1396 }
1397 }
1398
1399 LIBABCKIT_LOG(DEBUG) << "The instruction does not have the ability to add inputs\n";
1400 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1401 }
1402
1403 // Type helpers
1404
CreateGeneralType(AbckitFile * file,AbckitTypeId typeId,AbckitCoreClass * klass)1405 static AbckitType *CreateGeneralType(AbckitFile *file, AbckitTypeId typeId, AbckitCoreClass *klass)
1406 {
1407 return GetOrCreateType(file, typeId, 0, klass);
1408 }
1409
IgetTypeStatic(AbckitInst * inst)1410 AbckitType *IgetTypeStatic(AbckitInst *inst)
1411 {
1412 LIBABCKIT_LOG_FUNC;
1413 AbckitTypeId typeId = TypeToTypeId(inst->impl->GetType());
1414 AbckitCoreClass *klass = nullptr;
1415 if (typeId != ABCKIT_TYPE_ID_REFERENCE) {
1416 return CreateGeneralType(inst->graph->file, typeId, klass);
1417 }
1418 // Add get of ABCKIT_TYPE_ID_REFERENCE NOTE(ymolokanov)
1419 return CreateGeneralType(inst->graph->file, typeId, klass);
1420 }
1421
IgetTargetTypeStatic(AbckitInst * inst)1422 AbckitTypeId IgetTargetTypeStatic(AbckitInst *inst)
1423 {
1424 LIBABCKIT_LOG_FUNC;
1425 if (inst->impl->GetOpcode() != ark::compiler::Opcode::Cast) {
1426 LIBABCKIT_LOG(DEBUG) << "Instruction is not a cast\n";
1427 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1428 return AbckitTypeId::ABCKIT_TYPE_ID_INVALID;
1429 }
1430
1431 return TypeToTypeId(static_cast<ark::compiler::CastInst *>(inst->impl)->GetType());
1432 }
1433
IsetTargetTypeStatic(AbckitInst * inst,AbckitTypeId type)1434 void IsetTargetTypeStatic(AbckitInst *inst, AbckitTypeId type)
1435 {
1436 LIBABCKIT_LOG_FUNC;
1437 if (inst->impl->GetOpcode() != ark::compiler::Opcode::Cast) {
1438 LIBABCKIT_LOG(DEBUG) << "Instruction is not a cast\n";
1439 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1440 return;
1441 }
1442
1443 inst->impl->SetType(TypeIdToType(type));
1444 }
1445
IcheckIsCallStatic(AbckitInst * inst)1446 bool IcheckIsCallStatic(AbckitInst *inst)
1447 {
1448 LIBABCKIT_LOG_FUNC;
1449 return IsCallInst(inst);
1450 }
1451
IgetBasicBlockStatic(AbckitInst * inst)1452 AbckitBasicBlock *IgetBasicBlockStatic(AbckitInst *inst)
1453 {
1454 LIBABCKIT_LOG_FUNC;
1455 auto *graph = inst->graph;
1456 auto *implBB = inst->impl->GetBasicBlock();
1457 auto it = graph->implToBB.find(implBB);
1458 if (it != graph->implToBB.end()) {
1459 return it->second;
1460 }
1461 return nullptr;
1462 }
1463
IgetGraphStatic(AbckitInst * inst)1464 AbckitGraph *IgetGraphStatic(AbckitInst *inst)
1465 {
1466 LIBABCKIT_LOG_FUNC;
1467 return inst->graph;
1468 }
1469
IgetFunctionStatic(AbckitInst * inst)1470 AbckitCoreFunction *IgetFunctionStatic(AbckitInst *inst)
1471 {
1472 LIBABCKIT_LOG_FUNC;
1473 auto *graph = inst->graph;
1474
1475 ark::compiler::RuntimeInterface::MethodPtr methodPtr = nullptr;
1476 if (inst->impl->IsCall()) {
1477 auto *callInst = static_cast<ark::compiler::CallInst *>(inst->impl);
1478 methodPtr = callInst->GetCallMethod();
1479 } else if (inst->impl->IsIntrinsic()) {
1480 size_t idx = 0;
1481 if (IsDynamic(inst->graph->function->owningModule->target)) {
1482 auto instOpcode = GetDynamicOpcode(inst->impl);
1483 if (!HasMethodIdOperandDynamic(instOpcode)) {
1484 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1485 return nullptr;
1486 }
1487 idx = GetMethodIdOperandIndexDynamic(instOpcode);
1488 } else {
1489 auto instOpcode = GetStaticOpcode(inst->impl);
1490 if (!HasMethodIdOperandStatic(instOpcode)) {
1491 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1492 return nullptr;
1493 }
1494 idx = GetMethodIdOperandIndexStatic(instOpcode);
1495 }
1496
1497 auto *intrinsic = inst->impl->CastToIntrinsic();
1498 methodPtr = reinterpret_cast<ark::compiler::RuntimeInterface::MethodPtr>(intrinsic->GetImm(idx));
1499 } else {
1500 LIBABCKIT_LOG(DEBUG) << "Instruction is not a call or intrinsic\n";
1501 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1502 return nullptr;
1503 }
1504
1505 auto it = graph->irInterface->methods.find(reinterpret_cast<uintptr_t>(methodPtr));
1506 if (it == graph->irInterface->methods.end()) {
1507 LIBABCKIT_LOG(DEBUG) << "No requested call exists in current graph context\n";
1508 SetLastError(ABCKIT_STATUS_UNSUPPORTED);
1509 return nullptr;
1510 }
1511
1512 if (graph->file->nameToFunction.count(it->second) == 0) {
1513 statuses::SetLastError(ABCKIT_STATUS_UNSUPPORTED);
1514 return nullptr;
1515 }
1516 return graph->file->nameToFunction[it->second];
1517 }
1518
IsetFunctionStatic(AbckitInst * inst,AbckitCoreFunction * function)1519 void IsetFunctionStatic(AbckitInst *inst, AbckitCoreFunction *function)
1520 {
1521 LIBABCKIT_LOG_FUNC;
1522 auto *graph = inst->graph;
1523
1524 auto methodOffset = GetMethodOffset(graph, function);
1525
1526 if (inst->impl->IsCall()) {
1527 auto *callInst = static_cast<ark::compiler::CallInst *>(inst->impl);
1528 callInst->SetCallMethodId(methodOffset);
1529 } else if (inst->impl->IsIntrinsic()) {
1530 size_t idx = 0;
1531 if (IsDynamic(inst->graph->function->owningModule->target)) {
1532 auto instOpcode = GetDynamicOpcode(inst->impl);
1533 if (!HasMethodIdOperandDynamic(instOpcode)) {
1534 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1535 return;
1536 }
1537 idx = GetMethodIdOperandIndexDynamic(instOpcode);
1538 } else {
1539 auto instOpcode = GetStaticOpcode(inst->impl);
1540 if (!HasMethodIdOperandStatic(instOpcode)) {
1541 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1542 return;
1543 }
1544 idx = GetMethodIdOperandIndexStatic(instOpcode);
1545 }
1546
1547 auto *intrinsic = inst->impl->CastToIntrinsic();
1548 intrinsic->SetImm(idx, methodOffset);
1549 } else {
1550 LIBABCKIT_LOG(DEBUG) << "Instruction is not a call or intrinsic\n";
1551 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1552 return;
1553 }
1554 }
1555
IsetClassStatic(AbckitInst * inst,AbckitCoreClass * klass)1556 void IsetClassStatic(AbckitInst *inst, AbckitCoreClass *klass)
1557 {
1558 LIBABCKIT_LOG_FUNC;
1559 auto *graph = inst->graph;
1560 auto *intrinsic = inst->impl->CastToIntrinsic();
1561 auto instOpcode = GetStaticOpcode(inst->impl);
1562 if (!HasTypeIdOperandStatic(instOpcode)) {
1563 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1564 return;
1565 }
1566 size_t idx = GetTypeIdOperandIndexStatic(instOpcode);
1567 auto klassOffset = GetClassOffset(graph, klass);
1568 intrinsic->SetImm(idx, klassOffset);
1569 }
1570
IgetClassStatic(AbckitInst * inst)1571 AbckitCoreClass *IgetClassStatic(AbckitInst *inst)
1572 {
1573 LIBABCKIT_LOG_FUNC;
1574 auto *graph = inst->graph;
1575 auto *intrinsic = inst->impl->CastToIntrinsic();
1576 auto instOpcode = IgetOpcodeStaticStatic(inst);
1577 if (!HasTypeIdOperandStatic(instOpcode)) {
1578 statuses::SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1579 return nullptr;
1580 }
1581 size_t idx = GetTypeIdOperandIndexStatic(instOpcode);
1582 auto classPtr = reinterpret_cast<ark::compiler::RuntimeInterface::ClassPtr>(intrinsic->GetImm(idx));
1583
1584 auto it = graph->ptrToClass.find(reinterpret_cast<uintptr_t>(classPtr));
1585 if (it == graph->ptrToClass.end()) {
1586 LIBABCKIT_LOG(DEBUG) << "No requested class exists in current graph context\n";
1587 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1588 return nullptr;
1589 }
1590 return it->second;
1591 }
1592
GcreateNullPtrStatic(AbckitGraph * graph)1593 AbckitInst *GcreateNullPtrStatic(AbckitGraph *graph)
1594 {
1595 auto instImpl = graph->impl->CreateInstNullPtr(ark::compiler::DataType::REFERENCE);
1596 auto *inst = CreateInstFromImpl(graph, instImpl);
1597 graph->impl->GetStartBlock()->AppendInst(instImpl);
1598 return inst;
1599 }
1600
IgetConstantValueI32Static(AbckitInst * inst)1601 int32_t IgetConstantValueI32Static(AbckitInst *inst)
1602 {
1603 if (!inst->impl->IsConst()) {
1604 LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction"
1605 << '\n';
1606 }
1607 if (inst->impl->GetType() != ark::compiler::DataType::INT32 &&
1608 inst->impl->GetType() != ark::compiler::DataType::UINT32) {
1609 LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n';
1610 }
1611 return static_cast<ark::compiler::ConstantInst *>(inst->impl)->GetInt32Value();
1612 }
1613
IgetConstantValueI64Static(AbckitInst * inst)1614 int64_t IgetConstantValueI64Static(AbckitInst *inst)
1615 {
1616 if (!inst->impl->IsConst()) {
1617 LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction"
1618 << '\n';
1619 }
1620 if (inst->impl->GetType() != ark::compiler::DataType::INT64 &&
1621 inst->impl->GetType() != ark::compiler::DataType::UINT64) {
1622 LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n';
1623 }
1624 return static_cast<ark::compiler::ConstantInst *>(inst->impl)->GetInt64Value();
1625 }
1626
IgetConstantValueU64Static(AbckitInst * inst)1627 uint64_t IgetConstantValueU64Static(AbckitInst *inst)
1628 {
1629 if (!inst->impl->IsConst()) {
1630 LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction"
1631 << '\n';
1632 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1633 }
1634 if (inst->impl->GetType() != ark::compiler::DataType::INT64 &&
1635 inst->impl->GetType() != ark::compiler::DataType::UINT64) {
1636 LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n';
1637 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1638 }
1639 return static_cast<ark::compiler::ConstantInst *>(inst->impl)->GetInt64Value();
1640 }
1641
IgetConstantValueF64Static(AbckitInst * inst)1642 double IgetConstantValueF64Static(AbckitInst *inst)
1643 {
1644 if (!inst->impl->IsConst()) {
1645 LIBABCKIT_LOG(DEBUG) << "Input instruction of " << LIBABCKIT_FUNC_NAME << " must be constant instruction"
1646 << '\n';
1647 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1648 }
1649 if (inst->impl->GetType() != ark::compiler::DataType::FLOAT64) {
1650 LIBABCKIT_LOG(DEBUG) << "Type of input constant instruction in " << LIBABCKIT_FUNC_NAME << " is wrong" << '\n';
1651 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1652 }
1653 return static_cast<ark::compiler::ConstantInst *>(inst->impl)->GetDoubleValue();
1654 }
1655
IgetImmediateStatic(AbckitInst * inst,size_t idx)1656 uint64_t IgetImmediateStatic(AbckitInst *inst, size_t idx)
1657 {
1658 LIBABCKIT_LOG_FUNC;
1659
1660 if (IgetImmediateCountStatic(inst) <= idx) {
1661 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1662 return 0;
1663 }
1664
1665 uint64_t ret = 0;
1666
1667 if (inst->impl->IsBinaryImmInst()) {
1668 ret = (static_cast<ark::compiler::BinaryImmOperation *>(inst->impl))->GetImm();
1669 } else if (inst->impl->GetOpcode() == ark::compiler::Opcode::Intrinsic) {
1670 ret = inst->impl->CastToIntrinsic()->GetImm(idx);
1671 } else {
1672 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1673 return 0;
1674 }
1675 return ret;
1676 }
1677
IsetImmediateStatic(AbckitInst * inst,size_t idx,uint64_t imm)1678 void IsetImmediateStatic(AbckitInst *inst, size_t idx, uint64_t imm)
1679 {
1680 LIBABCKIT_LOG_FUNC;
1681
1682 if (IgetImmediateCountStatic(inst) <= idx) {
1683 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1684 return;
1685 }
1686
1687 if (inst->impl->IsBinaryImmInst()) {
1688 if (GetBitLengthUnsigned(imm) <= GetBinaryImmOperationSize(inst->impl->GetOpcode())) {
1689 (static_cast<ark::compiler::BinaryImmOperation *>(inst->impl))->SetImm(imm);
1690 } else {
1691 LIBABCKIT_LOG(DEBUG) << "Immediate type overflow\n";
1692 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1693 }
1694 } else if (inst->impl->GetOpcode() == ark::compiler::Opcode::Intrinsic) {
1695 auto instr = inst->impl->CastToIntrinsic();
1696 if (GetBitLengthUnsigned(imm) <= GetIntrinsicBitImmSize(instr->GetIntrinsicId(), idx)) {
1697 instr->SetImm(idx, imm);
1698 } else {
1699 LIBABCKIT_LOG(DEBUG) << "Immediate type overflow\n";
1700 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1701 }
1702 } else {
1703 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1704 }
1705 }
1706
IgetImmediateSizeStatic(AbckitInst * inst,size_t idx)1707 AbckitBitImmSize IgetImmediateSizeStatic(AbckitInst *inst, size_t idx)
1708 {
1709 LIBABCKIT_LOG_FUNC;
1710
1711 if (IgetImmediateCountStatic(inst) <= idx) {
1712 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1713 return AbckitBitImmSize::BITSIZE_0;
1714 }
1715
1716 auto immBitSize = AbckitBitImmSize::BITSIZE_0;
1717 if (inst->impl->IsBinaryImmInst()) {
1718 immBitSize = GetBinaryImmOperationSize(inst->impl->GetOpcode());
1719 } else if (inst->impl->GetOpcode() == ark::compiler::Opcode::Intrinsic) {
1720 auto instr = inst->impl->CastToIntrinsic();
1721 immBitSize = GetIntrinsicBitImmSize(instr->GetIntrinsicId(), idx);
1722 } else {
1723 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1724 }
1725 return immBitSize;
1726 }
1727
IgetImmediateCountStatic(AbckitInst * inst)1728 uint64_t IgetImmediateCountStatic(AbckitInst *inst)
1729 {
1730 LIBABCKIT_LOG_FUNC;
1731
1732 uint64_t ret = 0;
1733
1734 if (inst->impl->IsBinaryImmInst()) {
1735 ret = 1;
1736 } else if (inst->impl->GetOpcode() == ark::compiler::Opcode::Intrinsic) {
1737 auto instr = inst->impl->CastToIntrinsic();
1738 return instr->HasImms() ? instr->GetImms().size() : 0;
1739 }
1740 return ret;
1741 }
1742
IgetModuleStatic(AbckitInst * inst)1743 AbckitCoreModule *IgetModuleStatic(AbckitInst *inst)
1744 {
1745 LIBABCKIT_LOG_FUNC;
1746
1747 if (!inst->impl->IsIntrinsic()) {
1748 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n";
1749 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1750 return nullptr;
1751 }
1752
1753 auto intrInst = inst->impl->CastToIntrinsic();
1754 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1755 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_GETMODULENAMESPACE &&
1756 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_GETMODULENAMESPACE) {
1757 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n";
1758 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1759 return nullptr;
1760 }
1761
1762 return inst->graph->function->owningModule->md[intrInst->GetImm(0)];
1763 }
1764
GetModuleIndex(AbckitGraph * graph,AbckitCoreModule * md)1765 uint64_t GetModuleIndex(AbckitGraph *graph, AbckitCoreModule *md)
1766 {
1767 uint64_t imm = 0;
1768 for (auto m : graph->function->owningModule->md) {
1769 if (m == md) {
1770 break;
1771 }
1772 imm++;
1773 }
1774 if (imm == graph->function->owningModule->md.size()) {
1775 LIBABCKIT_LOG(DEBUG) << "Can not find module descriptor for module with name '" << md->moduleName->impl
1776 << "'\n";
1777 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1778 return 0;
1779 }
1780 return imm;
1781 }
1782
IsetModuleStatic(AbckitInst * inst,AbckitCoreModule * md)1783 void IsetModuleStatic(AbckitInst *inst, AbckitCoreModule *md)
1784 {
1785 LIBABCKIT_LOG_FUNC;
1786
1787 if (!inst->impl->IsIntrinsic()) {
1788 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n";
1789 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1790 return;
1791 }
1792
1793 auto intrInst = inst->impl->CastToIntrinsic();
1794 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1795 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_GETMODULENAMESPACE &&
1796 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_GETMODULENAMESPACE) {
1797 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have module id\n";
1798 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1799 return;
1800 }
1801
1802 uint64_t imm = GetModuleIndex(inst->graph, md);
1803 if (statuses::GetLastError() != ABCKIT_STATUS_NO_ERROR) {
1804 return;
1805 }
1806 intrInst->SetImm(0, imm);
1807 }
1808
GetImportDescriptorDynamic(AbckitInst * inst,uint64_t idx)1809 AbckitCoreImportDescriptor *GetImportDescriptorDynamic(AbckitInst *inst, uint64_t idx)
1810 {
1811 auto *module = inst->graph->function->owningModule;
1812 for (auto &id : module->id) {
1813 auto idPayload = GetDynImportDescriptorPayload(id.get());
1814 if (!idPayload->isRegularImport) {
1815 continue;
1816 }
1817 if (idPayload->moduleRecordIndexOff == idx) {
1818 return id.get();
1819 }
1820 }
1821 UNREACHABLE();
1822 }
1823
IgetImportDescriptorStatic(AbckitInst * inst)1824 AbckitCoreImportDescriptor *IgetImportDescriptorStatic(AbckitInst *inst)
1825 {
1826 LIBABCKIT_LOG_FUNC;
1827 ASSERT(IsDynamic(inst->graph->function->owningModule->target));
1828
1829 if (!inst->impl->IsIntrinsic()) {
1830 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n";
1831 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1832 return nullptr;
1833 }
1834
1835 auto intrInst = inst->impl->CastToIntrinsic();
1836 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1837 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_LDEXTERNALMODULEVAR &&
1838 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_LDEXTERNALMODULEVAR) {
1839 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n";
1840 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1841 return nullptr;
1842 }
1843
1844 return GetImportDescriptorDynamic(inst, intrInst->GetImm(0));
1845 }
1846
GetImportDescriptorIdxDynamic(AbckitGraph * graph,AbckitCoreImportDescriptor * id)1847 uint32_t GetImportDescriptorIdxDynamic(AbckitGraph *graph, AbckitCoreImportDescriptor *id)
1848 {
1849 AbckitCoreModule *m = graph->function->owningModule;
1850 auto found = std::find_if(m->id.begin(), m->id.end(),
1851 [&](std::unique_ptr<AbckitCoreImportDescriptor> const &d) { return d.get() == id; });
1852 if (found == m->id.end()) {
1853 LIBABCKIT_LOG(DEBUG) << "Can not find the import in module imports\n";
1854 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1855 return 0;
1856 }
1857 return GetDynImportDescriptorPayload(found->get())->moduleRecordIndexOff;
1858 }
1859
IsetImportDescriptorStatic(AbckitInst * inst,AbckitCoreImportDescriptor * id)1860 void IsetImportDescriptorStatic(AbckitInst *inst, AbckitCoreImportDescriptor *id)
1861 {
1862 LIBABCKIT_LOG_FUNC;
1863 ASSERT(IsDynamic(inst->graph->function->owningModule->target));
1864
1865 if (!inst->impl->IsIntrinsic()) {
1866 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n";
1867 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1868 return;
1869 }
1870
1871 auto intrInst = inst->impl->CastToIntrinsic();
1872 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1873 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_LDEXTERNALMODULEVAR &&
1874 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_LDEXTERNALMODULEVAR) {
1875 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have import descriptor\n";
1876 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1877 return;
1878 }
1879
1880 uint32_t imm = GetImportDescriptorIdxDynamic(inst->graph, id);
1881 if (statuses::GetLastError() != ABCKIT_STATUS_NO_ERROR) {
1882 return;
1883 }
1884 intrInst->SetImm(0, imm);
1885 }
1886
GetExportDescriptorDynamic(AbckitInst * inst,uint64_t idx)1887 AbckitCoreExportDescriptor *GetExportDescriptorDynamic(AbckitInst *inst, uint64_t idx)
1888 {
1889 auto *module = inst->graph->function->owningModule;
1890 for (auto &ed : module->ed) {
1891 auto edPayload = GetDynExportDescriptorPayload(ed.get());
1892 if (edPayload->kind != AbckitDynamicExportKind::ABCKIT_DYNAMIC_EXPORT_KIND_LOCAL_EXPORT) {
1893 continue;
1894 }
1895 if (edPayload->moduleRecordIndexOff == idx) {
1896 return ed.get();
1897 }
1898 }
1899 UNREACHABLE();
1900 }
1901
IgetExportDescriptorStatic(AbckitInst * inst)1902 AbckitCoreExportDescriptor *IgetExportDescriptorStatic(AbckitInst *inst)
1903 {
1904 LIBABCKIT_LOG_FUNC;
1905 ASSERT(IsDynamic(inst->graph->function->owningModule->target));
1906
1907 if (!inst->impl->IsIntrinsic()) {
1908 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n";
1909 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1910 return nullptr;
1911 }
1912
1913 auto intrInst = inst->impl->CastToIntrinsic();
1914 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1915 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_LDLOCALMODULEVAR &&
1916 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_LDLOCALMODULEVAR &&
1917 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_STMODULEVAR &&
1918 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_STMODULEVAR) {
1919 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n";
1920 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1921 return nullptr;
1922 }
1923
1924 return GetExportDescriptorDynamic(inst, intrInst->GetImm(0));
1925 }
1926
GetExportDescriptorIdxDynamic(AbckitGraph * graph,AbckitCoreExportDescriptor * ed)1927 uint32_t GetExportDescriptorIdxDynamic(AbckitGraph *graph, AbckitCoreExportDescriptor *ed)
1928 {
1929 AbckitCoreModule *m = graph->function->owningModule;
1930 auto found = std::find_if(m->ed.begin(), m->ed.end(),
1931 [&](std::unique_ptr<AbckitCoreExportDescriptor> const &d) { return d.get() == ed; });
1932 if (found == m->ed.end()) {
1933 LIBABCKIT_LOG(DEBUG) << "Can not find the import in module imports\n";
1934 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1935 return 0;
1936 }
1937 return GetDynExportDescriptorPayload(found->get())->moduleRecordIndexOff;
1938 }
1939
IsetExportDescriptorStatic(AbckitInst * inst,AbckitCoreExportDescriptor * ed)1940 void IsetExportDescriptorStatic(AbckitInst *inst, AbckitCoreExportDescriptor *ed)
1941 {
1942 LIBABCKIT_LOG_FUNC;
1943 ASSERT(IsDynamic(inst->graph->function->owningModule->target));
1944
1945 if (!inst->impl->IsIntrinsic()) {
1946 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n";
1947 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1948 return;
1949 }
1950
1951 auto intrInst = inst->impl->CastToIntrinsic();
1952 auto opcode = GetDynamicIntrinsicOpcode(intrInst);
1953 if (opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_LDLOCALMODULEVAR &&
1954 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_LDLOCALMODULEVAR &&
1955 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_STMODULEVAR &&
1956 opcode != ABCKIT_ISA_API_DYNAMIC_OPCODE_WIDE_STMODULEVAR) {
1957 LIBABCKIT_LOG(DEBUG) << "Instruction doesn't have export descriptor\n";
1958 SetLastError(ABCKIT_STATUS_BAD_ARGUMENT);
1959 return;
1960 }
1961
1962 uint32_t imm = GetExportDescriptorIdxDynamic(inst->graph, ed);
1963 if (statuses::GetLastError() != ABCKIT_STATUS_NO_ERROR) {
1964 return;
1965 }
1966 intrInst->SetImm(0, imm);
1967 }
1968
IgetConditionCodeStaticStatic(AbckitInst * inst)1969 AbckitIsaApiStaticConditionCode IgetConditionCodeStaticStatic(AbckitInst *inst)
1970 {
1971 return CcToStaticCc(inst->impl->CastToIf()->GetCc());
1972 }
1973
IgetConditionCodeDynamicStatic(AbckitInst * inst)1974 AbckitIsaApiDynamicConditionCode IgetConditionCodeDynamicStatic(AbckitInst *inst)
1975 {
1976 return CcToDynamicCc(inst->impl->CastToIf()->GetCc());
1977 }
1978
IsetConditionCodeStaticStatic(AbckitInst * inst,AbckitIsaApiStaticConditionCode cc)1979 void IsetConditionCodeStaticStatic(AbckitInst *inst, AbckitIsaApiStaticConditionCode cc)
1980 {
1981 inst->impl->CastToIf()->SetCc(CcToCc(cc));
1982 }
1983
IsetConditionCodeDynamicStatic(AbckitInst * inst,AbckitIsaApiDynamicConditionCode cc)1984 void IsetConditionCodeDynamicStatic(AbckitInst *inst, AbckitIsaApiDynamicConditionCode cc)
1985 {
1986 inst->impl->CastToIf()->SetCc(CcToCc(cc));
1987 }
1988
1989 } // namespace libabckit
1990