• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023-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 #include "codegen.h"
16 #include "runtime/include/coretypes/tagged_value.h"
17 
18 namespace ark::bytecodeopt {
19 
DoLdaObj(compiler::Register reg,std::vector<pandasm::Ins> & result)20 void DoLdaObj(compiler::Register reg, std::vector<pandasm::Ins> &result)
21 {
22     if (reg != compiler::GetAccReg()) {
23         result.emplace_back(pandasm::Create_LDA_OBJ(reg));
24     }
25 }
26 
DoLda(compiler::Register reg,std::vector<pandasm::Ins> & result)27 void DoLda(compiler::Register reg, std::vector<pandasm::Ins> &result)
28 {
29     if (reg != compiler::GetAccReg()) {
30         result.emplace_back(pandasm::Create_LDA(reg));
31     }
32 }
33 
DoLda64(compiler::Register reg,std::vector<pandasm::Ins> & result)34 void DoLda64(compiler::Register reg, std::vector<pandasm::Ins> &result)
35 {
36     if (reg != compiler::GetAccReg()) {
37         result.emplace_back(pandasm::Create_LDA_64(reg));
38     }
39 }
40 
DoStaObj(compiler::Register reg,std::vector<pandasm::Ins> & result)41 void DoStaObj(compiler::Register reg, std::vector<pandasm::Ins> &result)
42 {
43     if (reg != compiler::GetAccReg()) {
44         result.emplace_back(pandasm::Create_STA_OBJ(reg));
45     }
46 }
47 
DoSta(compiler::Register reg,std::vector<pandasm::Ins> & result)48 void DoSta(compiler::Register reg, std::vector<pandasm::Ins> &result)
49 {
50     if (reg != compiler::GetAccReg()) {
51         result.emplace_back(pandasm::Create_STA(reg));
52     }
53 }
54 
DoSta64(compiler::Register reg,std::vector<pandasm::Ins> & result)55 void DoSta64(compiler::Register reg, std::vector<pandasm::Ins> &result)
56 {
57     if (reg != compiler::GetAccReg()) {
58         result.emplace_back(pandasm::Create_STA_64(reg));
59     }
60 }
61 
DoSta(compiler::DataType::Type type,compiler::Register reg,std::vector<pandasm::Ins> & result)62 void DoSta(compiler::DataType::Type type, compiler::Register reg, std::vector<pandasm::Ins> &result)
63 {
64     if (compiler::DataType::Is64Bits(type, Arch::NONE)) {
65         DoSta64(reg, result);
66     } else {
67         DoSta(reg, result);
68     }
69 }
70 
DoLdaDyn(compiler::Register reg,std::vector<pandasm::Ins> & result)71 void DoLdaDyn(compiler::Register reg, std::vector<pandasm::Ins> &result)
72 {
73     if (reg != compiler::GetAccReg()) {
74         result.emplace_back(pandasm::Create_LDA_DYN(reg));
75     }
76 }
77 
DoStaDyn(compiler::Register reg,std::vector<pandasm::Ins> & result)78 void DoStaDyn(compiler::Register reg, std::vector<pandasm::Ins> &result)
79 {
80     if (reg != compiler::GetAccReg()) {
81         result.emplace_back(pandasm::Create_STA_DYN(reg));
82     }
83 }
84 
AppendCatchBlock(uint32_t typeId,const compiler::BasicBlock * tryBegin,const compiler::BasicBlock * tryEnd,const compiler::BasicBlock * catchBegin,const compiler::BasicBlock * catchEnd)85 void BytecodeGen::AppendCatchBlock(uint32_t typeId, const compiler::BasicBlock *tryBegin,
86                                    const compiler::BasicBlock *tryEnd, const compiler::BasicBlock *catchBegin,
87                                    const compiler::BasicBlock *catchEnd)
88 {
89     auto cb = pandasm::Function::CatchBlock();
90     if (typeId != 0U) {
91         cb.exceptionRecord = irInterface_->GetTypeIdByOffset(typeId);
92     }
93     cb.tryBeginLabel = BytecodeGen::LabelName(tryBegin->GetId());
94     cb.tryEndLabel = "end_" + BytecodeGen::LabelName(tryEnd->GetId());
95     cb.catchBeginLabel = BytecodeGen::LabelName(catchBegin->GetId());
96     cb.catchEndLabel = catchEnd == nullptr ? cb.catchBeginLabel : "end_" + BytecodeGen::LabelName(catchEnd->GetId());
97     catchBlocks_.emplace_back(cb);
98 }
99 
VisitTryBegin(const compiler::BasicBlock * bb)100 void BytecodeGen::VisitTryBegin(const compiler::BasicBlock *bb)
101 {
102     ASSERT(bb->IsTryBegin());
103     auto tryInst = GetTryBeginInst(bb);
104     auto tryEnd = tryInst->GetTryEndBlock();
105     ASSERT(tryEnd != nullptr && tryEnd->IsTryEnd());
106 
107     bb->EnumerateCatchHandlers([&, bb, tryEnd](BasicBlock *catchHandler, size_t typeId) {
108         AppendCatchBlock(typeId, bb, tryEnd, catchHandler);
109         return true;
110     });
111 }
112 
AddLineAndColumnNumber(const compiler::Inst * inst,size_t idx)113 void BytecodeGen::AddLineAndColumnNumber(const compiler::Inst *inst, size_t idx)
114 {
115     AddLineNumber(inst, idx);
116     if (GetGraph()->IsDynamicMethod()) {
117         AddColumnNumber(inst, idx);
118     }
119 }
120 
RunImpl()121 bool BytecodeGen::RunImpl()
122 {
123     Reserve(function_->ins.size());
124     for (auto *bb : GetGraph()->GetBlocksLinearOrder()) {
125         EmitLabel(BytecodeGen::LabelName(bb->GetId()));
126         if (bb->IsTryEnd()) {
127             auto label = "end_" + BytecodeGen::LabelName(bb->GetId());
128             EmitLabel(label);
129         }
130         for (const auto &inst : bb->AllInsts()) {
131             auto start = GetResult().size();
132             VisitInstruction(inst);
133             if (!GetStatus()) {
134                 return false;
135             }
136             auto end = GetResult().size();
137             ASSERT(end >= start);
138             for (auto i = start; i < end; ++i) {
139                 AddLineAndColumnNumber(inst, i);
140             }
141         }
142         if (bb->NeedsJump()) {
143             EmitJump(bb);
144         }
145     }
146     if (!GetStatus()) {
147         return false;
148     }
149     // Visit try-blocks in order they were declared
150     for (auto *bb : GetGraph()->GetTryBeginBlocks()) {
151         VisitTryBegin(bb);
152     }
153     function_->ins = std::move(GetResult());
154     function_->catchBlocks = catchBlocks_;
155     return true;
156 }
157 
EmitJump(const BasicBlock * bb)158 void BytecodeGen::EmitJump(const BasicBlock *bb)
159 {
160     BasicBlock *sucBb = nullptr;
161     ASSERT(bb != nullptr);
162 
163     if (bb->GetLastInst() == nullptr) {
164         ASSERT(bb->IsEmpty());
165         sucBb = bb->GetSuccsBlocks()[0U];
166         result_.push_back(pandasm::Create_JMP(BytecodeGen::LabelName(sucBb->GetId())));
167         return;
168     }
169 
170     ASSERT(bb->GetLastInst() != nullptr);
171     switch (bb->GetLastInst()->GetOpcode()) {
172         case Opcode::If:
173         case Opcode::IfImm:
174             ASSERT(bb->GetSuccsBlocks().size() == compiler::MAX_SUCCS_NUM);
175             sucBb = bb->GetFalseSuccessor();
176             break;
177         default:
178             sucBb = bb->GetSuccsBlocks()[0U];
179             break;
180     }
181     result_.push_back(pandasm::Create_JMP(BytecodeGen::LabelName(sucBb->GetId())));
182 }
183 
AddLineNumber(const Inst * inst,const size_t idx)184 void BytecodeGen::AddLineNumber(const Inst *inst, const size_t idx)
185 {
186     if (irInterface_ != nullptr && idx < result_.size()) {
187         auto ln = irInterface_->GetLineNumberByPc(inst->GetPc());
188         result_[idx].insDebug.SetLineNumber(ln);
189     }
190 }
191 
AddColumnNumber(const Inst * inst,const uint32_t idx)192 void BytecodeGen::AddColumnNumber(const Inst *inst, const uint32_t idx)
193 {
194     if (irInterface_ != nullptr && idx < result_.size()) {
195         auto cn = irInterface_->GetColumnNumberByPc(inst->GetPc());
196         result_[idx].insDebug.SetColumnNumber(cn);
197     }
198 }
199 
EncodeSpillFillData(const compiler::SpillFillData & sf)200 void BytecodeGen::EncodeSpillFillData(const compiler::SpillFillData &sf)
201 {
202     if (sf.SrcType() != compiler::LocationType::REGISTER || sf.DstType() != compiler::LocationType::REGISTER) {
203         LOG(ERROR, BYTECODE_OPTIMIZER) << "EncodeSpillFillData with unknown move type, src_type: "
204                                        << static_cast<int>(sf.SrcType())
205                                        << " dst_type: " << static_cast<int>(sf.DstType());
206         success_ = false;
207         UNREACHABLE();
208         return;
209     }
210     ASSERT(sf.GetType() != compiler::DataType::NO_TYPE);
211     ASSERT(sf.SrcValue() != compiler::GetInvalidReg() && sf.DstValue() != compiler::GetInvalidReg());
212 
213     if (sf.SrcValue() == sf.DstValue()) {
214         return;
215     }
216 
217     pandasm::Ins move;
218     if (GetGraph()->IsDynamicMethod()) {
219         result_.emplace_back(pandasm::Create_MOV_DYN(sf.DstValue(), sf.SrcValue()));
220         return;
221     }
222     switch (sf.GetType()) {
223         case compiler::DataType::INT64:
224         case compiler::DataType::UINT64:
225         case compiler::DataType::FLOAT64:
226             move = pandasm::Create_MOV_64(sf.DstValue(), sf.SrcValue());
227             break;
228         case compiler::DataType::REFERENCE:
229             move = pandasm::Create_MOV_OBJ(sf.DstValue(), sf.SrcValue());
230             break;
231         default:
232             move = pandasm::Create_MOV(sf.DstValue(), sf.SrcValue());
233     }
234     result_.emplace_back(move);
235 }
236 
VisitSpillFill(GraphVisitor * visitor,Inst * inst)237 void BytecodeGen::VisitSpillFill(GraphVisitor *visitor, Inst *inst)
238 {
239     auto *enc = static_cast<BytecodeGen *>(visitor);
240     for (auto sf : inst->CastToSpillFill()->GetSpillFills()) {
241         enc->EncodeSpillFillData(sf);
242     }
243 }
244 
245 template <typename UnaryPred>
HasUserPredicate(Inst * inst,UnaryPred p)246 bool HasUserPredicate(Inst *inst, UnaryPred p)
247 {
248     bool found = false;
249     for (auto const &u : inst->GetUsers()) {
250         if (p(u.GetInst())) {
251             found = true;
252             break;
253         }
254     }
255     return found;
256 }
257 
VisitConstant32(BytecodeGen * enc,compiler::Inst * inst,std::vector<pandasm::Ins> & res)258 static void VisitConstant32(BytecodeGen *enc, compiler::Inst *inst, std::vector<pandasm::Ins> &res)
259 {
260     auto type = inst->GetType();
261     ASSERT(compiler::DataType::Is32Bits(type, Arch::NONE));
262 
263     pandasm::Ins movi;
264     auto dstReg = inst->GetDstReg();
265     movi.regs.emplace_back(inst->GetDstReg());
266 
267     switch (type) {
268         case compiler::DataType::BOOL:
269         case compiler::DataType::INT8:
270         case compiler::DataType::UINT8:
271         case compiler::DataType::INT16:
272         case compiler::DataType::UINT16:
273         case compiler::DataType::INT32:
274         case compiler::DataType::UINT32:
275             if (enc->GetGraph()->IsDynamicMethod()) {
276                 res.emplace_back(pandasm::Create_LDAI_DYN(inst->CastToConstant()->GetInt32Value()));
277                 DoStaDyn(inst->GetDstReg(), res);
278             } else {
279                 if (dstReg == compiler::GetAccReg()) {
280                     pandasm::Ins ldai = pandasm::Create_LDAI(inst->CastToConstant()->GetInt32Value());
281                     res.emplace_back(ldai);
282                 } else {
283                     movi = pandasm::Create_MOVI(dstReg, inst->CastToConstant()->GetInt32Value());
284                     res.emplace_back(movi);
285                 }
286             }
287             break;
288         case compiler::DataType::FLOAT32:
289             if (enc->GetGraph()->IsDynamicMethod()) {
290                 res.emplace_back(pandasm::Create_FLDAI_DYN(inst->CastToConstant()->GetFloatValue()));
291                 DoStaDyn(inst->GetDstReg(), res);
292             } else {
293                 if (dstReg == compiler::GetAccReg()) {
294                     pandasm::Ins ldai = pandasm::Create_FLDAI(inst->CastToConstant()->GetFloatValue());
295                     res.emplace_back(ldai);
296                 } else {
297                     movi = pandasm::Create_FMOVI(dstReg, inst->CastToConstant()->GetFloatValue());
298                     res.emplace_back(movi);
299                 }
300             }
301             break;
302         default:
303             UNREACHABLE();
304     }
305 }
306 
VisitConstant64(BytecodeGen * enc,compiler::Inst * inst,std::vector<pandasm::Ins> & res)307 static void VisitConstant64(BytecodeGen *enc, compiler::Inst *inst, std::vector<pandasm::Ins> &res)
308 {
309     auto type = inst->GetType();
310     ASSERT(compiler::DataType::Is64Bits(type, Arch::NONE));
311 
312     pandasm::Ins movi;
313     auto dstReg = inst->GetDstReg();
314     movi.regs.emplace_back(inst->GetDstReg());
315 
316     switch (type) {
317         case compiler::DataType::INT64:
318         case compiler::DataType::UINT64:
319             if (enc->GetGraph()->IsDynamicMethod()) {
320                 res.emplace_back(pandasm::Create_LDAI_DYN(inst->CastToConstant()->GetInt64Value()));
321                 DoStaDyn(inst->GetDstReg(), res);
322             } else {
323                 if (dstReg == compiler::GetAccReg()) {
324                     pandasm::Ins ldai = pandasm::Create_LDAI_64(inst->CastToConstant()->GetInt64Value());
325                     res.emplace_back(ldai);
326                 } else {
327                     movi = pandasm::Create_MOVI_64(dstReg, inst->CastToConstant()->GetInt64Value());
328                     res.emplace_back(movi);
329                 }
330             }
331             break;
332         case compiler::DataType::FLOAT64:
333             if (enc->GetGraph()->IsDynamicMethod()) {
334                 res.emplace_back(pandasm::Create_FLDAI_DYN(inst->CastToConstant()->GetDoubleValue()));
335                 DoStaDyn(inst->GetDstReg(), res);
336             } else {
337                 if (dstReg == compiler::GetAccReg()) {
338                     pandasm::Ins ldai = pandasm::Create_FLDAI_64(inst->CastToConstant()->GetDoubleValue());
339                     res.emplace_back(ldai);
340                 } else {
341                     movi = pandasm::Create_FMOVI_64(dstReg, inst->CastToConstant()->GetDoubleValue());
342                     res.emplace_back(movi);
343                 }
344             }
345             break;
346         default:
347             UNREACHABLE();
348     }
349 }
350 
VisitConstant(GraphVisitor * visitor,Inst * inst)351 void BytecodeGen::VisitConstant(GraphVisitor *visitor, Inst *inst)
352 {
353     auto *enc = static_cast<BytecodeGen *>(visitor);
354     auto type = inst->GetType();
355 
356     /* Do not emit unused code for Const -> CastValueToAnyType chains */
357     if (enc->GetGraph()->IsDynamicMethod()) {
358         if (!HasUserPredicate(inst,
359                               [](Inst const *i) { return i->GetOpcode() != compiler::Opcode::CastValueToAnyType; })) {
360             return;
361         }
362     }
363 
364     switch (type) {
365         case compiler::DataType::BOOL:
366         case compiler::DataType::INT8:
367         case compiler::DataType::UINT8:
368         case compiler::DataType::INT16:
369         case compiler::DataType::UINT16:
370         case compiler::DataType::INT32:
371         case compiler::DataType::UINT32:
372         case compiler::DataType::FLOAT32:
373             VisitConstant32(enc, inst, enc->result_);
374             break;
375         case compiler::DataType::INT64:
376         case compiler::DataType::UINT64:
377         case compiler::DataType::FLOAT64:
378             VisitConstant64(enc, inst, enc->result_);
379             break;
380         case compiler::DataType::ANY: {
381             UNREACHABLE();
382         }
383         default:
384             UNREACHABLE();
385             LOG(ERROR, BYTECODE_OPTIMIZER) << "VisitConstant with unknown type" << type;
386             enc->success_ = false;
387     }
388 }
389 
EncodeSta(compiler::Register reg,compiler::DataType::Type type)390 void BytecodeGen::EncodeSta(compiler::Register reg, compiler::DataType::Type type)
391 {
392     pandasm::Opcode opc;
393     switch (type) {
394         case compiler::DataType::BOOL:
395         case compiler::DataType::UINT8:
396         case compiler::DataType::INT8:
397         case compiler::DataType::UINT16:
398         case compiler::DataType::INT16:
399         case compiler::DataType::UINT32:
400         case compiler::DataType::INT32:
401         case compiler::DataType::FLOAT32:
402             opc = pandasm::Opcode::STA;
403             break;
404         case compiler::DataType::UINT64:
405         case compiler::DataType::INT64:
406         case compiler::DataType::FLOAT64:
407             opc = pandasm::Opcode::STA_64;
408             break;
409         case compiler::DataType::ANY:
410             opc = pandasm::Opcode::STA_DYN;
411             break;
412         case compiler::DataType::REFERENCE:
413             opc = pandasm::Opcode::STA_OBJ;
414             break;
415         default:
416             UNREACHABLE();
417             LOG(ERROR, BYTECODE_OPTIMIZER) << "EncodeSta with unknown type" << type;
418             success_ = false;
419     }
420     pandasm::Ins sta;
421     sta.opcode = opc;
422     sta.regs.emplace_back(reg);
423 
424     result_.emplace_back(sta);
425 }
426 
ChooseCallOpcode(compiler::Opcode op,size_t nargs)427 static pandasm::Opcode ChooseCallOpcode(compiler::Opcode op, size_t nargs)
428 {
429     ASSERT(op == compiler::Opcode::CallStatic || op == compiler::Opcode::CallVirtual ||
430            op == compiler::Opcode::InitObject);
431     if (nargs > MAX_NUM_NON_RANGE_ARGS) {
432         switch (op) {
433             case compiler::Opcode::CallStatic:
434                 return pandasm::Opcode::CALL_RANGE;
435             case compiler::Opcode::CallVirtual:
436                 return pandasm::Opcode::CALL_VIRT_RANGE;
437             case compiler::Opcode::InitObject:
438                 return pandasm::Opcode::INITOBJ_RANGE;
439             default:
440                 UNREACHABLE();
441         }
442     } else if (nargs > MAX_NUM_SHORT_CALL_ARGS) {
443         switch (op) {
444             case compiler::Opcode::CallStatic:
445                 return pandasm::Opcode::CALL;
446             case compiler::Opcode::CallVirtual:
447                 return pandasm::Opcode::CALL_VIRT;
448             case compiler::Opcode::InitObject:
449                 return pandasm::Opcode::INITOBJ;
450             default:
451                 UNREACHABLE();
452         }
453     }
454     switch (op) {
455         case compiler::Opcode::CallStatic:
456             return pandasm::Opcode::CALL_SHORT;
457         case compiler::Opcode::CallVirtual:
458             return pandasm::Opcode::CALL_VIRT_SHORT;
459         case compiler::Opcode::InitObject:
460             return pandasm::Opcode::INITOBJ_SHORT;
461         default:
462             UNREACHABLE();
463     }
464 }
465 
ChooseCallAccOpcode(pandasm::Opcode op)466 static pandasm::Opcode ChooseCallAccOpcode(pandasm::Opcode op)
467 {
468     switch (op) {
469         case pandasm::Opcode::CALL_SHORT:
470             return pandasm::Opcode::CALL_ACC_SHORT;
471         case pandasm::Opcode::CALL:
472             return pandasm::Opcode::CALL_ACC;
473         case pandasm::Opcode::CALL_VIRT_SHORT:
474             return pandasm::Opcode::CALL_VIRT_ACC_SHORT;
475         case pandasm::Opcode::CALL_VIRT:
476             return pandasm::Opcode::CALL_VIRT_ACC;
477         default:
478             return pandasm::Opcode::INVALID;
479     }
480 }
481 
CastToCall(ark::compiler::Inst * inst)482 static ark::compiler::CallInst *CastToCall(ark::compiler::Inst *inst)
483 {
484     switch (inst->GetOpcode()) {
485         case compiler::Opcode::CallStatic:
486             return inst->CastToCallStatic();
487         case compiler::Opcode::CallVirtual:
488             return inst->CastToCallVirtual();
489         case compiler::Opcode::InitObject:
490             return inst->CastToInitObject();
491         default:
492             UNREACHABLE();
493     }
494 }
495 
CallHandler(GraphVisitor * visitor,Inst * inst,std::string methodId)496 void BytecodeGen::CallHandler(GraphVisitor *visitor, Inst *inst, std::string methodId)
497 {
498     auto op = inst->GetOpcode();
499     ASSERT(op == compiler::Opcode::CallStatic || op == compiler::Opcode::CallVirtual ||
500            op == compiler::Opcode::InitObject || op == compiler::Opcode::Intrinsic);
501     if (op == compiler::Opcode::Intrinsic) {
502         ASSERT(inst->IsCallOrIntrinsic());
503         op = compiler::Opcode::CallStatic;
504     }
505     auto *enc = static_cast<BytecodeGen *>(visitor);
506     auto sfCount = inst->GetInputsCount() - (inst->RequireState() ? 1U : 0U);
507     size_t start = op == compiler::Opcode::InitObject ? 1U : 0U;  // exclude LoadAndInitClass
508     auto nargs = sfCount - start;                                 // exclude LoadAndInitClass
509     pandasm::Ins ins;
510 
511     ins.opcode = ChooseCallOpcode(op, nargs);
512 
513     if (nargs > MAX_NUM_NON_RANGE_ARGS) {
514 #ifndef NDEBUG
515         auto startReg = inst->GetSrcReg(start);
516         ASSERT(startReg <= MAX_8_BIT_REG);
517         for (auto i = start; i < sfCount; ++i) {
518             auto reg = inst->GetSrcReg(i);
519             ASSERT(reg - startReg == static_cast<int>(i - start));  // check 'range-ness' of registers
520         }
521 #endif  // !NDEBUG
522         ins.regs.emplace_back(inst->GetSrcReg(start));
523     } else {
524         for (size_t i = start; i < sfCount; ++i) {
525             auto reg = inst->GetSrcReg(i);
526             ASSERT(reg < NUM_COMPACTLY_ENCODED_REGS || reg == compiler::GetAccReg());
527             if (reg == compiler::GetAccReg()) {
528                 ASSERT(inst->IsCallOrIntrinsic());
529                 ins.imms.emplace_back(static_cast<int64_t>(i));
530                 ins.opcode = ChooseCallAccOpcode(ins.opcode);
531             } else {
532                 ins.regs.emplace_back(reg);
533             }
534         }
535     }
536     ins.ids.emplace_back(std::move(methodId));
537     enc->result_.emplace_back(ins);
538     if (inst->GetDstReg() != compiler::GetInvalidReg() && inst->GetDstReg() != compiler::GetAccReg()) {
539         enc->EncodeSta(inst->GetDstReg(), inst->GetType());
540     }
541 }
542 
CallHandler(GraphVisitor * visitor,Inst * inst)543 void BytecodeGen::CallHandler(GraphVisitor *visitor, Inst *inst)
544 {
545     auto *enc = static_cast<BytecodeGen *>(visitor);
546     auto methodOffset = CastToCall(inst)->GetCallMethodId();
547     CallHandler(visitor, inst, enc->irInterface_->GetMethodIdByOffset(methodOffset));
548 }
549 
VisitCallStatic(GraphVisitor * visitor,Inst * inst)550 void BytecodeGen::VisitCallStatic(GraphVisitor *visitor, Inst *inst)
551 {
552     CallHandler(visitor, inst);
553 }
554 
VisitCallVirtual(GraphVisitor * visitor,Inst * inst)555 void BytecodeGen::VisitCallVirtual(GraphVisitor *visitor, Inst *inst)
556 {
557     CallHandler(visitor, inst);
558 }
559 
VisitInitObject(GraphVisitor * visitor,Inst * inst)560 void BytecodeGen::VisitInitObject(GraphVisitor *visitor, Inst *inst)
561 {
562     CallHandler(visitor, inst);
563 }
564 
VisitIf32(BytecodeGen * enc,compiler::IfInst * inst,std::vector<pandasm::Ins> & res,bool & success)565 static void VisitIf32(BytecodeGen *enc, compiler::IfInst *inst, std::vector<pandasm::Ins> &res, bool &success)
566 {
567     ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE));
568 
569     if (enc->GetGraph()->IsDynamicMethod()) {
570         DoLdaDyn(inst->GetSrcReg(0U), res);
571     } else {
572         DoLda(inst->GetSrcReg(0U), res);
573     }
574 
575     compiler::Register src = inst->GetSrcReg(1);
576     std::string label = BytecodeGen::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId());
577 
578     switch (inst->GetCc()) {
579         case compiler::CC_EQ: {
580             res.emplace_back(pandasm::Create_JEQ(src, label));
581             break;
582         }
583         case compiler::CC_NE: {
584             res.emplace_back(pandasm::Create_JNE(src, label));
585             break;
586         }
587         case compiler::CC_LT: {
588             res.emplace_back(pandasm::Create_JLT(src, label));
589             break;
590         }
591         case compiler::CC_LE: {
592             res.emplace_back(pandasm::Create_JLE(src, label));
593             break;
594         }
595         case compiler::CC_GT: {
596             res.emplace_back(pandasm::Create_JGT(src, label));
597             break;
598         }
599         case compiler::CC_GE: {
600             res.emplace_back(pandasm::Create_JGE(src, label));
601             break;
602         }
603         default:
604             LOG(ERROR, BYTECODE_OPTIMIZER)
605                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
606             success = false;
607     }
608 }
609 
VisitIf64Signed(BytecodeGen * enc,compiler::IfInst * inst,std::vector<pandasm::Ins> & res,bool & success)610 static void VisitIf64Signed(BytecodeGen *enc, compiler::IfInst *inst, std::vector<pandasm::Ins> &res, bool &success)
611 {
612     ASSERT(Is64Bits(inst->GetInputType(0U), Arch::NONE));
613     ASSERT(IsTypeSigned(inst->GetInputType(0U)));
614 
615     if (enc->GetGraph()->IsDynamicMethod()) {
616         DoLdaDyn(inst->GetSrcReg(0U), res);
617     } else {
618         DoLda64(inst->GetSrcReg(0U), res);
619     }
620 
621     res.emplace_back(pandasm::Create_CMP_64(inst->GetSrcReg(1U)));
622     std::string label = BytecodeGen::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId());
623 
624     switch (inst->GetCc()) {
625         case compiler::CC_EQ: {
626             res.emplace_back(pandasm::Create_JEQZ(label));
627             break;
628         }
629         case compiler::CC_NE: {
630             res.emplace_back(pandasm::Create_JNEZ(label));
631             break;
632         }
633         case compiler::CC_LT: {
634             res.emplace_back(pandasm::Create_JLTZ(label));
635             break;
636         }
637         case compiler::CC_LE: {
638             res.emplace_back(pandasm::Create_JLEZ(label));
639             break;
640         }
641         case compiler::CC_GT: {
642             res.emplace_back(pandasm::Create_JGTZ(label));
643             break;
644         }
645         case compiler::CC_GE: {
646             res.emplace_back(pandasm::Create_JGEZ(label));
647             break;
648         }
649         default:
650             LOG(ERROR, BYTECODE_OPTIMIZER)
651                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
652             success = false;
653     }
654 }
655 
VisitIf64Unsigned(BytecodeGen * enc,compiler::IfInst * inst,std::vector<pandasm::Ins> & res,bool & success)656 static void VisitIf64Unsigned(BytecodeGen *enc, compiler::IfInst *inst, std::vector<pandasm::Ins> &res, bool &success)
657 {
658     ASSERT(Is64Bits(inst->GetInputType(0U), Arch::NONE));
659     ASSERT(!IsTypeSigned(inst->GetInputType(0U)));
660 
661     if (enc->GetGraph()->IsDynamicMethod()) {
662         DoLdaDyn(inst->GetSrcReg(0U), res);
663     } else {
664         DoLda64(inst->GetSrcReg(0U), res);
665     }
666 
667     res.emplace_back(pandasm::Create_UCMP_64(inst->GetSrcReg(1U)));
668     std::string label = BytecodeGen::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId());
669 
670     switch (inst->GetCc()) {
671         case compiler::CC_EQ: {
672             res.emplace_back(pandasm::Create_JEQZ(label));
673             break;
674         }
675         case compiler::CC_NE: {
676             res.emplace_back(pandasm::Create_JNEZ(label));
677             break;
678         }
679         case compiler::CC_LT: {
680             res.emplace_back(pandasm::Create_JLTZ(label));
681             break;
682         }
683         case compiler::CC_LE: {
684             res.emplace_back(pandasm::Create_JLEZ(label));
685             break;
686         }
687         case compiler::CC_GT: {
688             res.emplace_back(pandasm::Create_JGTZ(label));
689             break;
690         }
691         case compiler::CC_GE: {
692             res.emplace_back(pandasm::Create_JGEZ(label));
693             break;
694         }
695         default:
696             LOG(ERROR, BYTECODE_OPTIMIZER)
697                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
698             success = false;
699     }
700 }
701 
VisitIfRef(BytecodeGen * enc,compiler::IfInst * inst,std::vector<pandasm::Ins> & res,bool & success)702 static void VisitIfRef([[maybe_unused]] BytecodeGen *enc, compiler::IfInst *inst, std::vector<pandasm::Ins> &res,
703                        bool &success)
704 {
705     ASSERT(IsReference(inst->GetInputType(0U)));
706 
707     DoLdaObj(inst->GetSrcReg(0U), res);
708 
709     compiler::Register src = inst->GetSrcReg(1);
710     std::string label = BytecodeGen::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId());
711 
712     switch (inst->GetCc()) {
713         case compiler::CC_EQ: {
714             res.emplace_back(pandasm::Create_JEQ_OBJ(src, label));
715             break;
716         }
717         case compiler::CC_NE: {
718             res.emplace_back(pandasm::Create_JNE_OBJ(src, label));
719             break;
720         }
721         default:
722             LOG(ERROR, BYTECODE_OPTIMIZER)
723                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
724             success = false;
725     }
726 }
727 
728 // NOLINTNEXTLINE(readability-function-size)
VisitIf(GraphVisitor * v,Inst * instBase)729 void BytecodeGen::VisitIf(GraphVisitor *v, Inst *instBase)
730 {
731     auto enc = static_cast<BytecodeGen *>(v);
732     auto inst = instBase->CastToIf();
733     switch (inst->GetInputType(0U)) {
734         case compiler::DataType::BOOL:
735         case compiler::DataType::UINT8:
736         case compiler::DataType::INT8:
737         case compiler::DataType::UINT16:
738         case compiler::DataType::INT16:
739         case compiler::DataType::UINT32:
740         case compiler::DataType::INT32: {
741             VisitIf32(enc, inst, enc->result_, enc->success_);
742             break;
743         }
744         case compiler::DataType::INT64: {
745             VisitIf64Signed(enc, inst, enc->result_, enc->success_);
746             break;
747         }
748         case compiler::DataType::UINT64: {
749             VisitIf64Unsigned(enc, inst, enc->result_, enc->success_);
750             break;
751         }
752         case compiler::DataType::REFERENCE: {
753             VisitIfRef(enc, inst, enc->result_, enc->success_);
754             break;
755         }
756         case compiler::DataType::ANY: {
757             if (enc->GetGraph()->IsDynamicMethod()) {
758 #if defined(ENABLE_BYTECODE_OPT) && defined(PANDA_WITH_ECMASCRIPT) && defined(ARK_INTRINSIC_SET)
759                 IfEcma(v, inst);
760                 break;
761 #endif
762             }
763             LOG(ERROR, BYTECODE_OPTIMIZER)
764                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
765             enc->success_ = false;
766             break;
767         }
768         default:
769             LOG(ERROR, BYTECODE_OPTIMIZER)
770                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
771             enc->success_ = false;
772     }
773 }
774 
775 #if defined(ENABLE_BYTECODE_OPT) && defined(PANDA_WITH_ECMASCRIPT)
IsEcmaConstTemplate(Inst const * inst)776 static std::optional<coretypes::TaggedValue> IsEcmaConstTemplate(Inst const *inst)
777 {
778     if (inst->GetOpcode() != compiler::Opcode::CastValueToAnyType) {
779         return {};
780     }
781     auto cvatInst = inst->CastToCastValueToAnyType();
782     if (!cvatInst->GetInput(0U).GetInst()->IsConst()) {
783         return {};
784     }
785     auto constInst = cvatInst->GetInput(0U).GetInst()->CastToConstant();
786 
787     switch (cvatInst->GetAnyType()) {
788         case compiler::AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE:
789             return coretypes::TaggedValue(coretypes::TaggedValue::VALUE_UNDEFINED);
790         case compiler::AnyBaseType::ECMASCRIPT_INT_TYPE:
791             return coretypes::TaggedValue(static_cast<int32_t>(constInst->GetIntValue()));
792         case compiler::AnyBaseType::ECMASCRIPT_DOUBLE_TYPE:
793             return coretypes::TaggedValue(constInst->GetDoubleValue());
794         case compiler::AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE:
795             return coretypes::TaggedValue(static_cast<bool>(constInst->GetInt64Value() != 0U));
796         case compiler::AnyBaseType::ECMASCRIPT_NULL_TYPE:
797             return coretypes::TaggedValue(coretypes::TaggedValue::VALUE_NULL);
798         default:
799             return {};
800     }
801 }
802 
803 #if defined(ARK_INTRINSIC_SET)
IfEcma(GraphVisitor * v,compiler::IfInst * inst)804 void BytecodeGen::IfEcma(GraphVisitor *v, compiler::IfInst *inst)
805 {
806     auto enc = static_cast<BytecodeGen *>(v);
807 
808     compiler::Register reg = compiler::INVALID_REG_ID;
809     coretypes::TaggedValue cmpVal;
810 
811     auto testLhs = IsEcmaConstTemplate(inst->GetInput(0U).GetInst());
812     auto testRhs = IsEcmaConstTemplate(inst->GetInput(1U).GetInst());
813 
814     if (testLhs.has_value() && testLhs->IsBoolean()) {
815         cmpVal = testLhs.value();
816         reg = inst->GetSrcReg(1U);
817     } else if (testRhs.has_value() && testRhs->IsBoolean()) {
818         cmpVal = testRhs.value();
819         reg = inst->GetSrcReg(0U);
820     } else {
821         LOG(ERROR, BYTECODE_OPTIMIZER) << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
822         enc->success_ = false;
823         return;
824     }
825 
826     DoLdaDyn(reg, enc->result_);
827     switch (inst->GetCc()) {
828         case compiler::CC_EQ: {
829             if (cmpVal.IsTrue()) {
830                 enc->result_.emplace_back(
831                     pandasm::Create_ECMA_JTRUE(LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId())));
832             } else {
833                 enc->result_.emplace_back(
834                     pandasm::Create_ECMA_JFALSE(LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId())));
835             }
836             break;
837         }
838         case compiler::CC_NE: {
839             if (cmpVal.IsTrue()) {
840                 enc->result_.emplace_back(pandasm::Create_ECMA_ISTRUE());
841             } else {
842                 enc->result_.emplace_back(pandasm::Create_ECMA_ISFALSE());
843             }
844             enc->result_.emplace_back(
845                 pandasm::Create_ECMA_JFALSE(LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId())));
846             break;
847         }
848         default:
849             LOG(ERROR, BYTECODE_OPTIMIZER)
850                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
851             enc->success_ = false;
852             return;
853     }
854 }
855 #endif
856 #endif
857 
VisitIfImm(GraphVisitor * v,Inst * instBase)858 void BytecodeGen::VisitIfImm(GraphVisitor *v, Inst *instBase)
859 {
860     auto inst = instBase->CastToIfImm();
861     auto imm = inst->GetImm();
862     if (imm == 0U) {
863         IfImmZero(v, instBase);
864         return;
865     }
866     IfImmNonZero(v, instBase);
867 }
868 
IfImmZero32(BytecodeGen * enc,compiler::IfImmInst * inst,std::vector<pandasm::Ins> & res,bool & success)869 static void IfImmZero32(BytecodeGen *enc, compiler::IfImmInst *inst, std::vector<pandasm::Ins> &res, bool &success)
870 {
871     ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE));
872 
873     if (enc->GetGraph()->IsDynamicMethod()) {
874         DoLdaDyn(inst->GetSrcReg(0U), res);
875     } else {
876         DoLda(inst->GetSrcReg(0U), res);
877     }
878 
879     std::string label = BytecodeGen::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId());
880 
881     switch (inst->GetCc()) {
882         case compiler::CC_EQ: {
883             res.emplace_back(pandasm::Create_JEQZ(label));
884             break;
885         }
886         case compiler::CC_NE: {
887             res.emplace_back(pandasm::Create_JNEZ(label));
888             break;
889         }
890         case compiler::CC_LT: {
891             res.emplace_back(pandasm::Create_JLTZ(label));
892             break;
893         }
894         case compiler::CC_LE: {
895             res.emplace_back(pandasm::Create_JLEZ(label));
896             break;
897         }
898         case compiler::CC_GT: {
899             res.emplace_back(pandasm::Create_JGTZ(label));
900             break;
901         }
902         case compiler::CC_GE: {
903             res.emplace_back(pandasm::Create_JGEZ(label));
904             break;
905         }
906         default:
907             LOG(ERROR, BYTECODE_OPTIMIZER)
908                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
909             success = false;
910     }
911 }
912 
IfImmZeroRef(BytecodeGen * enc,compiler::IfImmInst * inst,std::vector<pandasm::Ins> & res,bool & success)913 static void IfImmZeroRef(BytecodeGen *enc, compiler::IfImmInst *inst, std::vector<pandasm::Ins> &res, bool &success)
914 {
915     ASSERT(IsReference(inst->GetInputType(0U)));
916 
917     if (enc->GetGraph()->IsDynamicMethod()) {
918         DoLdaDyn(inst->GetSrcReg(0U), res);
919     } else {
920         DoLdaObj(inst->GetSrcReg(0U), res);
921     }
922 
923     std::string label = BytecodeGen::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId());
924 
925     switch (inst->GetCc()) {
926         case compiler::CC_EQ: {
927             res.emplace_back(pandasm::Create_JEQZ_OBJ(label));
928             break;
929         }
930         case compiler::CC_NE: {
931             res.emplace_back(pandasm::Create_JNEZ_OBJ(label));
932             break;
933         }
934         default:
935             LOG(ERROR, BYTECODE_OPTIMIZER)
936                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
937             success = false;
938     }
939 }
940 
941 // NOLINTNEXTLINE(readability-function-size)
IfImmZero(GraphVisitor * v,Inst * instBase)942 void BytecodeGen::IfImmZero(GraphVisitor *v, Inst *instBase)
943 {
944     auto enc = static_cast<BytecodeGen *>(v);
945     auto inst = instBase->CastToIfImm();
946     switch (inst->GetInputType(0U)) {
947         case compiler::DataType::BOOL:
948         case compiler::DataType::UINT8:
949         case compiler::DataType::INT8:
950         case compiler::DataType::UINT16:
951         case compiler::DataType::INT16:
952         case compiler::DataType::UINT32:
953         case compiler::DataType::INT32: {
954             IfImmZero32(enc, inst, enc->result_, enc->success_);
955             break;
956         }
957         case compiler::DataType::INT64:
958         case compiler::DataType::UINT64: {
959             IfImm64(v, instBase);
960             break;
961         }
962         case compiler::DataType::REFERENCE: {
963             IfImmZeroRef(enc, inst, enc->result_, enc->success_);
964             break;
965         }
966         default:
967             LOG(ERROR, BYTECODE_OPTIMIZER)
968                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
969             enc->success_ = false;
970     }
971 }
972 
IfImmNonZero32(BytecodeGen * enc,compiler::IfImmInst * inst,std::vector<pandasm::Ins> & res,bool & success)973 static void IfImmNonZero32(BytecodeGen *enc, compiler::IfImmInst *inst, std::vector<pandasm::Ins> &res, bool &success)
974 {
975     ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE));
976 
977     if (enc->GetGraph()->IsDynamicMethod()) {
978         res.emplace_back(pandasm::Create_LDAI_DYN(inst->GetImm()));
979     } else {
980         res.emplace_back(pandasm::Create_LDAI(inst->GetImm()));
981     }
982 
983     compiler::Register src = inst->GetSrcReg(0);
984     std::string label = BytecodeGen::LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId());
985 
986     switch (inst->GetCc()) {
987         case compiler::CC_EQ: {
988             res.emplace_back(pandasm::Create_JEQ(src, label));
989             break;
990         }
991         case compiler::CC_NE: {
992             res.emplace_back(pandasm::Create_JNE(src, label));
993             break;
994         }
995         case compiler::CC_LT: {
996             res.emplace_back(pandasm::Create_JLT(src, label));
997             break;
998         }
999         case compiler::CC_LE: {
1000             res.emplace_back(pandasm::Create_JLE(src, label));
1001             break;
1002         }
1003         case compiler::CC_GT: {
1004             res.emplace_back(pandasm::Create_JGT(src, label));
1005             break;
1006         }
1007         case compiler::CC_GE: {
1008             res.emplace_back(pandasm::Create_JGE(src, label));
1009             break;
1010         }
1011         default:
1012             LOG(ERROR, BYTECODE_OPTIMIZER)
1013                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1014             success = false;
1015     }
1016 }
1017 
1018 // NOLINTNEXTLINE(readability-function-size)
IfImmNonZero(GraphVisitor * v,Inst * instBase)1019 void BytecodeGen::IfImmNonZero(GraphVisitor *v, Inst *instBase)
1020 {
1021     auto enc = static_cast<BytecodeGen *>(v);
1022     auto inst = instBase->CastToIfImm();
1023     switch (inst->GetInputType(0U)) {
1024         case compiler::DataType::BOOL:
1025         case compiler::DataType::UINT8:
1026         case compiler::DataType::INT8:
1027         case compiler::DataType::UINT16:
1028         case compiler::DataType::INT16:
1029         case compiler::DataType::UINT32:
1030         case compiler::DataType::INT32: {
1031             IfImmNonZero32(enc, inst, enc->result_, enc->success_);
1032             break;
1033         }
1034         case compiler::DataType::INT64:
1035         case compiler::DataType::UINT64: {
1036             IfImm64(v, instBase);
1037             break;
1038         }
1039         case compiler::DataType::REFERENCE: {
1040             LOG(ERROR, BYTECODE_OPTIMIZER)
1041                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1042             LOG(ERROR, BYTECODE_OPTIMIZER)
1043                 << "VisitIfImm does not support non-zero imm of type reference, as no pandasm matches";
1044             enc->success_ = false;
1045             break;
1046         }
1047         default:
1048             LOG(ERROR, BYTECODE_OPTIMIZER)
1049                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1050             enc->success_ = false;
1051     }
1052 }
1053 
1054 // NOLINTNEXTLINE(readability-function-size)
IfImm64(GraphVisitor * v,Inst * instBase)1055 void BytecodeGen::IfImm64(GraphVisitor *v, Inst *instBase)
1056 {
1057     auto enc = static_cast<BytecodeGen *>(v);
1058     auto inst = instBase->CastToIfImm();
1059 
1060     if (enc->GetGraph()->IsDynamicMethod()) {
1061         enc->result_.emplace_back(pandasm::Create_LDAI_DYN(inst->GetImm()));
1062     } else {
1063         enc->result_.emplace_back(pandasm::Create_LDAI_64(inst->GetImm()));
1064     }
1065 
1066     std::string label = LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId());
1067 
1068     if (inst->GetInputType(0) == compiler::DataType::INT64) {
1069         enc->result_.emplace_back(pandasm::Create_CMP_64(inst->GetSrcReg(0U)));
1070     } else if (inst->GetInputType(0) == compiler::DataType::UINT64) {
1071         enc->result_.emplace_back(pandasm::Create_UCMP_64(inst->GetSrcReg(0U)));
1072     } else {
1073         LOG(ERROR, BYTECODE_OPTIMIZER) << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1074         enc->success_ = false;
1075         return;
1076     }
1077 
1078     switch (inst->GetCc()) {
1079         case compiler::CC_EQ: {
1080             enc->result_.emplace_back(pandasm::Create_JEQZ(label));
1081             break;
1082         }
1083         case compiler::CC_NE: {
1084             enc->result_.emplace_back(pandasm::Create_JNEZ(label));
1085             break;
1086         }
1087         case compiler::CC_LT: {
1088             enc->result_.emplace_back(pandasm::Create_JGTZ(label));
1089             break;
1090         }
1091         case compiler::CC_LE: {
1092             enc->result_.emplace_back(pandasm::Create_JGEZ(label));
1093             break;
1094         }
1095         case compiler::CC_GT: {
1096             enc->result_.emplace_back(pandasm::Create_JLTZ(label));
1097             break;
1098         }
1099         case compiler::CC_GE: {
1100             enc->result_.emplace_back(pandasm::Create_JLEZ(label));
1101             break;
1102         }
1103         default:
1104             LOG(ERROR, BYTECODE_OPTIMIZER)
1105                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1106             enc->success_ = false;
1107             return;
1108     }
1109 }
1110 
CastAccDownFromI32(compiler::DataType::Type type,std::vector<pandasm::Ins> & res)1111 static void CastAccDownFromI32(compiler::DataType::Type type, std::vector<pandasm::Ins> &res)
1112 {
1113     auto sizeBits = compiler::DataType::GetTypeSize(type, Arch::NONE);
1114     if (compiler::DataType::IsTypeSigned(type)) {
1115         auto shift = compiler::WORD_SIZE - sizeBits;
1116         res.emplace_back(pandasm::Create_SHLI(shift));
1117         res.emplace_back(pandasm::Create_ASHRI(shift));
1118     } else {
1119         auto andMask = (1U << sizeBits) - 1U;
1120         res.emplace_back(pandasm::Create_ANDI(andMask));
1121     }
1122 }
1123 
VisitCastFromI32(BytecodeGen * enc,compiler::CastInst * inst,std::vector<pandasm::Ins> & res,bool & success)1124 static void VisitCastFromI32([[maybe_unused]] BytecodeGen *enc, compiler::CastInst *inst,
1125                              std::vector<pandasm::Ins> &res, bool &success)
1126 {
1127     ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE));
1128 
1129     if (inst->GetType() == compiler::DataType::UINT32) {
1130         return;
1131     }
1132     DoLda(inst->GetSrcReg(0U), res);
1133 
1134     switch (inst->GetType()) {
1135         case compiler::DataType::FLOAT32: {
1136             res.emplace_back(pandasm::Create_I32TOF32());
1137             break;
1138         }
1139         case compiler::DataType::FLOAT64: {
1140             res.emplace_back(pandasm::Create_I32TOF64());
1141             break;
1142         }
1143         case compiler::DataType::INT64: {
1144             res.emplace_back(pandasm::Create_I32TOI64());
1145             break;
1146         }
1147         case compiler::DataType::INT16:
1148         case compiler::DataType::UINT16:
1149         case compiler::DataType::INT8:
1150         case compiler::DataType::UINT8: {
1151             CastAccDownFromI32(inst->GetType(), res);
1152             break;
1153         }
1154         case compiler::DataType::ANY: {
1155             UNREACHABLE();
1156         }
1157         default:
1158             LOG(ERROR, BYTECODE_OPTIMIZER)
1159                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1160             success = false;
1161             return;
1162     }
1163     DoSta(inst->GetType(), inst->GetDstReg(), res);
1164 }
1165 
VisitCastFromU32(BytecodeGen * enc,compiler::CastInst * inst,std::vector<pandasm::Ins> & res,bool & success)1166 static void VisitCastFromU32([[maybe_unused]] BytecodeGen *enc, compiler::CastInst *inst,
1167                              std::vector<pandasm::Ins> &res, bool &success)
1168 {
1169     ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE));
1170 
1171     if (inst->GetType() == compiler::DataType::INT32) {
1172         return;
1173     }
1174     DoLda(inst->GetSrcReg(0U), res);
1175 
1176     switch (inst->GetType()) {
1177         case compiler::DataType::FLOAT32: {
1178             res.emplace_back(pandasm::Create_U32TOF32());
1179             break;
1180         }
1181         case compiler::DataType::FLOAT64: {
1182             res.emplace_back(pandasm::Create_U32TOF64());
1183             break;
1184         }
1185         case compiler::DataType::INT64: {
1186             res.emplace_back(pandasm::Create_U32TOI64());
1187             break;
1188         }
1189         case compiler::DataType::INT16:
1190         case compiler::DataType::UINT16:
1191         case compiler::DataType::INT8:
1192         case compiler::DataType::UINT8: {
1193             CastAccDownFromI32(inst->GetType(), res);
1194             break;
1195         }
1196         case compiler::DataType::ANY: {
1197             UNREACHABLE();
1198         }
1199         default:
1200             LOG(ERROR, BYTECODE_OPTIMIZER)
1201                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1202             success = false;
1203             return;
1204     }
1205     DoSta(inst->GetType(), inst->GetDstReg(), res);
1206 }
1207 
VisitCastFromI64(BytecodeGen * enc,compiler::CastInst * inst,std::vector<pandasm::Ins> & res,bool & success)1208 static void VisitCastFromI64([[maybe_unused]] BytecodeGen *enc, compiler::CastInst *inst,
1209                              std::vector<pandasm::Ins> &res, bool &success)
1210 {
1211     ASSERT(Is64Bits(inst->GetInputType(0U), Arch::NONE));
1212     constexpr int64_t ANDI_32 = 0xffffffff;
1213 
1214     DoLda64(inst->GetSrcReg(0U), res);
1215 
1216     switch (inst->GetType()) {
1217         case compiler::DataType::INT32: {
1218             res.emplace_back(pandasm::Create_I64TOI32());
1219             break;
1220         }
1221         case compiler::DataType::UINT32: {
1222             res.emplace_back(pandasm::Create_ANDI(ANDI_32));
1223             break;
1224         }
1225         case compiler::DataType::FLOAT32: {
1226             res.emplace_back(pandasm::Create_I64TOF32());
1227             break;
1228         }
1229         case compiler::DataType::FLOAT64: {
1230             res.emplace_back(pandasm::Create_I64TOF64());
1231             break;
1232         }
1233         case compiler::DataType::INT16:
1234         case compiler::DataType::UINT16:
1235         case compiler::DataType::INT8:
1236         case compiler::DataType::UINT8: {
1237             res.emplace_back(pandasm::Create_I64TOI32());
1238             CastAccDownFromI32(inst->GetType(), res);
1239             break;
1240         }
1241         case compiler::DataType::ANY: {
1242             UNREACHABLE();
1243         }
1244         default:
1245             LOG(ERROR, BYTECODE_OPTIMIZER)
1246                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1247             success = false;
1248             return;
1249     }
1250     DoSta(inst->GetType(), inst->GetDstReg(), res);
1251 }
1252 
VisitCastFromF32(BytecodeGen * enc,compiler::CastInst * inst,std::vector<pandasm::Ins> & res,bool & success)1253 static void VisitCastFromF32([[maybe_unused]] BytecodeGen *enc, compiler::CastInst *inst,
1254                              std::vector<pandasm::Ins> &res, bool &success)
1255 {
1256     ASSERT(Is32Bits(inst->GetInputType(0U), Arch::NONE));
1257     ASSERT(IsFloatType(inst->GetInputType(0U)));
1258 
1259     constexpr int64_t ANDI_32 = 0xffffffff;
1260 
1261     DoLda(inst->GetSrcReg(0U), res);
1262 
1263     switch (inst->GetType()) {
1264         case compiler::DataType::FLOAT64: {
1265             res.emplace_back(pandasm::Create_F32TOF64());
1266             break;
1267         }
1268         case compiler::DataType::INT64: {
1269             res.emplace_back(pandasm::Create_F32TOI64());
1270             break;
1271         }
1272         case compiler::DataType::UINT64: {
1273             res.emplace_back(pandasm::Create_F32TOU64());
1274             break;
1275         }
1276         case compiler::DataType::INT32: {
1277             res.emplace_back(pandasm::Create_F32TOI32());
1278             break;
1279         }
1280         case compiler::DataType::UINT32: {
1281             res.emplace_back(pandasm::Create_F32TOU32());
1282             res.emplace_back(pandasm::Create_ANDI(ANDI_32));
1283             break;
1284         }
1285         case compiler::DataType::ANY: {
1286             UNREACHABLE();
1287         }
1288         default:
1289             LOG(ERROR, BYTECODE_OPTIMIZER)
1290                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1291             success = false;
1292             return;
1293     }
1294     DoSta(inst->GetType(), inst->GetDstReg(), res);
1295 }
1296 
VisitCastFromF64(BytecodeGen * enc,compiler::CastInst * inst,std::vector<pandasm::Ins> & res,bool & success)1297 static void VisitCastFromF64([[maybe_unused]] BytecodeGen *enc, compiler::CastInst *inst,
1298                              std::vector<pandasm::Ins> &res, bool &success)
1299 {
1300     ASSERT(Is64Bits(inst->GetInputType(0U), Arch::NONE));
1301     ASSERT(IsFloatType(inst->GetInputType(0U)));
1302 
1303     constexpr int64_t ANDI_32 = 0xffffffff;
1304 
1305     DoLda64(inst->GetSrcReg(0U), res);
1306 
1307     switch (inst->GetType()) {
1308         case compiler::DataType::FLOAT32: {
1309             res.emplace_back(pandasm::Create_F64TOF32());
1310             break;
1311         }
1312         case compiler::DataType::INT64: {
1313             res.emplace_back(pandasm::Create_F64TOI64());
1314             break;
1315         }
1316         case compiler::DataType::INT32: {
1317             res.emplace_back(pandasm::Create_F64TOI32());
1318             break;
1319         }
1320         case compiler::DataType::UINT32: {
1321             res.emplace_back(pandasm::Create_F64TOI64());
1322             res.emplace_back(pandasm::Create_ANDI(ANDI_32));
1323             break;
1324         }
1325         case compiler::DataType::ANY: {
1326             UNREACHABLE();
1327         }
1328         default:
1329             LOG(ERROR, BYTECODE_OPTIMIZER)
1330                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1331             success = false;
1332             return;
1333     }
1334     DoSta(inst->GetType(), inst->GetDstReg(), res);
1335 }
1336 
1337 // NOLINTNEXTLINE(readability-function-size)
VisitCast(GraphVisitor * v,Inst * instBase)1338 void BytecodeGen::VisitCast(GraphVisitor *v, Inst *instBase)
1339 {
1340     auto enc = static_cast<BytecodeGen *>(v);
1341     auto inst = instBase->CastToCast();
1342     switch (inst->GetInputType(0U)) {
1343         case compiler::DataType::INT32: {
1344             VisitCastFromI32(enc, inst, enc->result_, enc->success_);
1345             break;
1346         }
1347         case compiler::DataType::UINT32: {
1348             VisitCastFromU32(enc, inst, enc->result_, enc->success_);
1349             break;
1350         }
1351         case compiler::DataType::INT64: {
1352             VisitCastFromI64(enc, inst, enc->result_, enc->success_);
1353             break;
1354         }
1355         case compiler::DataType::FLOAT32: {
1356             VisitCastFromF32(enc, inst, enc->result_, enc->success_);
1357             break;
1358         }
1359         case compiler::DataType::FLOAT64: {
1360             VisitCastFromF64(enc, inst, enc->result_, enc->success_);
1361             break;
1362         }
1363         case compiler::DataType::REFERENCE: {
1364             switch (inst->GetType()) {
1365                 case compiler::DataType::ANY: {
1366                     UNREACHABLE();
1367                 }
1368                 default:
1369                     LOG(ERROR, BYTECODE_OPTIMIZER)
1370                         << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1371                     enc->success_ = false;
1372             }
1373             break;
1374         }
1375         default:
1376             LOG(ERROR, BYTECODE_OPTIMIZER)
1377                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1378             enc->success_ = false;
1379     }
1380 }
1381 
VisitLoadString(GraphVisitor * v,Inst * instBase)1382 void BytecodeGen::VisitLoadString(GraphVisitor *v, Inst *instBase)
1383 {
1384     pandasm::Ins ins;
1385     auto enc = static_cast<BytecodeGen *>(v);
1386     auto inst = instBase->CastToLoadString();
1387 
1388     /* Do not emit unused code for Str -> CastValueToAnyType chains */
1389     if (enc->GetGraph()->IsDynamicMethod()) {
1390         if (!HasUserPredicate(inst,
1391                               [](Inst const *i) { return i->GetOpcode() != compiler::Opcode::CastValueToAnyType; })) {
1392             return;
1393         }
1394     }
1395 
1396     enc->result_.emplace_back(pandasm::Create_LDA_STR(enc->irInterface_->GetStringIdByOffset(inst->GetTypeId())));
1397     if (inst->GetDstReg() != compiler::GetAccReg()) {
1398         if (enc->GetGraph()->IsDynamicMethod()) {
1399             enc->result_.emplace_back(pandasm::Create_STA_DYN(inst->GetDstReg()));
1400         } else {
1401             enc->result_.emplace_back(pandasm::Create_STA_OBJ(inst->GetDstReg()));
1402         }
1403     }
1404 }
1405 
VisitReturnAny(GraphVisitor * v,Inst * instBase)1406 void BytecodeGen::VisitReturnAny(GraphVisitor *v, [[maybe_unused]] Inst *instBase)
1407 {
1408     auto enc = static_cast<BytecodeGen *>(v);
1409     [[maybe_unused]] auto inst = instBase->CastToReturn();
1410 #if defined(ENABLE_BYTECODE_OPT) && defined(PANDA_WITH_ECMASCRIPT)
1411     auto testArg = IsEcmaConstTemplate(inst->GetInput(0U).GetInst());
1412     if (testArg.has_value() && testArg->IsUndefined()) {
1413         enc->result_.emplace_back(pandasm::Create_ECMA_RETURNUNDEFINED());
1414         return;
1415     }
1416 #endif
1417 #ifdef ARK_INTRINSIC_SET
1418     DoLdaDyn(inst->GetSrcReg(0U), enc->result_);
1419     enc->result_.emplace_back(pandasm::Create_ECMA_RETURN_DYN());
1420 #else
1421     // Do not support DataType::ANY in this case
1422     LOG(ERROR, BYTECODE_OPTIMIZER) << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1423     enc->success_ = false;
1424 #endif  // ARK_INTRINSIC_SET
1425 }
1426 
VisitReturn(GraphVisitor * v,Inst * instBase)1427 void BytecodeGen::VisitReturn(GraphVisitor *v, Inst *instBase)
1428 {
1429     pandasm::Ins ins;
1430     auto enc = static_cast<BytecodeGen *>(v);
1431     auto inst = instBase->CastToReturn();
1432     switch (inst->GetType()) {
1433         case compiler::DataType::BOOL:
1434         case compiler::DataType::UINT8:
1435         case compiler::DataType::INT8:
1436         case compiler::DataType::UINT16:
1437         case compiler::DataType::INT16:
1438         case compiler::DataType::UINT32:
1439         case compiler::DataType::INT32:
1440         case compiler::DataType::FLOAT32: {
1441             DoLda(inst->GetSrcReg(0U), enc->result_);
1442             enc->result_.emplace_back(pandasm::Create_RETURN());
1443             break;
1444         }
1445         case compiler::DataType::INT64:
1446         case compiler::DataType::UINT64:
1447         case compiler::DataType::FLOAT64: {
1448             DoLda64(inst->GetSrcReg(0U), enc->result_);
1449             enc->result_.emplace_back(pandasm::Create_RETURN_64());
1450             break;
1451         }
1452         case compiler::DataType::REFERENCE: {
1453             DoLdaObj(inst->GetSrcReg(0U), enc->result_);
1454             enc->result_.emplace_back(pandasm::Create_RETURN_OBJ());
1455             break;
1456         }
1457         case compiler::DataType::VOID: {
1458             enc->result_.emplace_back(pandasm::Create_RETURN_VOID());
1459             break;
1460         }
1461         case compiler::DataType::ANY: {
1462             BytecodeGen::VisitReturnAny(v, instBase);
1463             break;
1464         }
1465         default:
1466             LOG(ERROR, BYTECODE_OPTIMIZER)
1467                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1468             enc->success_ = false;
1469     }
1470 }
1471 
1472 #if defined(ENABLE_BYTECODE_OPT) && defined(PANDA_WITH_ECMASCRIPT)
IntToLdBool(int64_t v)1473 static auto IntToLdBool(int64_t v)
1474 {
1475     return v != 0 ? pandasm::Create_ECMA_LDTRUE() : pandasm::Create_ECMA_LDFALSE();
1476 }
1477 #endif
1478 
VisitCastValueToAnyType(GraphVisitor * v,Inst * instBase)1479 void BytecodeGen::VisitCastValueToAnyType(GraphVisitor *v, [[maybe_unused]] Inst *instBase)
1480 {
1481     auto enc = static_cast<BytecodeGen *>(v);
1482 
1483 #if defined(ENABLE_BYTECODE_OPT) && defined(PANDA_WITH_ECMASCRIPT)
1484     auto cvat = instBase->CastToCastValueToAnyType();
1485     switch (cvat->GetAnyType()) {
1486         case compiler::AnyBaseType::ECMASCRIPT_NULL_TYPE:
1487             enc->result_.emplace_back(pandasm::Create_ECMA_LDNULL());
1488             break;
1489         case compiler::AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE:
1490             if (!HasUserPredicate(cvat,
1491                                   [](Inst const *inst) { return inst->GetOpcode() != compiler::Opcode::Return; })) {
1492                 return;
1493             }
1494             enc->result_.emplace_back(pandasm::Create_ECMA_LDUNDEFINED());
1495             break;
1496         case compiler::AnyBaseType::ECMASCRIPT_INT_TYPE:
1497             ASSERT(cvat->GetInput(0U).GetInst()->IsConst());
1498             enc->result_.emplace_back(
1499                 pandasm::Create_LDAI_DYN(cvat->GetInput(0U).GetInst()->CastToConstant()->GetIntValue()));
1500             break;
1501         case compiler::AnyBaseType::ECMASCRIPT_DOUBLE_TYPE:
1502             ASSERT(cvat->GetInput(0U).GetInst()->IsConst());
1503             enc->result_.emplace_back(
1504                 pandasm::Create_FLDAI_DYN(cvat->GetInput(0U).GetInst()->CastToConstant()->GetDoubleValue()));
1505             break;
1506         case compiler::AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE:
1507             ASSERT(cvat->GetInput(0U).GetInst()->IsBoolConst());
1508             if (!HasUserPredicate(cvat, [](Inst const *inst) { return inst->GetOpcode() != compiler::Opcode::If; })) {
1509                 return;
1510             }
1511             enc->result_.emplace_back(IntToLdBool((cvat->GetInput(0U).GetInst()->CastToConstant()->GetInt64Value())));
1512             break;
1513         case compiler::AnyBaseType::ECMASCRIPT_STRING_TYPE:
1514             enc->result_.emplace_back(pandasm::Create_LDA_STR(
1515                 enc->irInterface_->GetStringIdByOffset(cvat->GetInput(0U).GetInst()->CastToLoadString()->GetTypeId())));
1516             break;
1517         case compiler::AnyBaseType::ECMASCRIPT_BIGINT_TYPE:
1518             enc->result_.emplace_back(pandasm::Create_ECMA_LDBIGINT(
1519                 enc->irInterface_->GetStringIdByOffset(cvat->GetInput(0U).GetInst()->CastToLoadString()->GetTypeId())));
1520             break;
1521         default:
1522             UNREACHABLE();
1523     }
1524     DoStaDyn(cvat->GetDstReg(), enc->result_);
1525 #else
1526     LOG(ERROR, BYTECODE_OPTIMIZER) << "Codegen for " << compiler::GetOpcodeString(instBase->GetOpcode()) << " failed";
1527     enc->success_ = false;
1528 #endif
1529 }
1530 
1531 // NOLINTNEXTLINE(readability-function-size)
VisitStoreObject(GraphVisitor * v,Inst * instBase)1532 void BytecodeGen::VisitStoreObject(GraphVisitor *v, Inst *instBase)
1533 {
1534     if (TryPluginStoreObjectVisitor(v, instBase)) {
1535         return;
1536     }
1537 
1538     auto enc = static_cast<BytecodeGen *>(v);
1539     const compiler::StoreObjectInst *inst = instBase->CastToStoreObject();
1540 
1541     compiler::Register vd = inst->GetSrcReg(0U);
1542     compiler::Register vs = inst->GetSrcReg(1U);
1543     std::string id = enc->irInterface_->GetFieldIdByOffset(inst->GetTypeId());
1544 
1545     bool isAccType = (vs == compiler::GetAccReg());
1546 
1547     switch (inst->GetType()) {
1548         case compiler::DataType::BOOL:
1549         case compiler::DataType::UINT8:
1550         case compiler::DataType::INT8:
1551         case compiler::DataType::UINT16:
1552         case compiler::DataType::INT16:
1553         case compiler::DataType::UINT32:
1554         case compiler::DataType::INT32:
1555         case compiler::DataType::FLOAT32:
1556             if (isAccType) {
1557                 enc->result_.emplace_back(pandasm::Create_STOBJ(vd, id));
1558             } else {
1559                 enc->result_.emplace_back(pandasm::Create_STOBJ_V(vs, vd, id));
1560             }
1561             break;
1562         case compiler::DataType::INT64:
1563         case compiler::DataType::UINT64:
1564         case compiler::DataType::FLOAT64:
1565             if (isAccType) {
1566                 enc->result_.emplace_back(pandasm::Create_STOBJ_64(vd, id));
1567             } else {
1568                 enc->result_.emplace_back(pandasm::Create_STOBJ_V_64(vs, vd, id));
1569             }
1570             break;
1571         case compiler::DataType::REFERENCE:
1572             if (isAccType) {
1573                 enc->result_.emplace_back(pandasm::Create_STOBJ_OBJ(vd, id));
1574             } else {
1575                 enc->result_.emplace_back(pandasm::Create_STOBJ_V_OBJ(vs, vd, id));
1576             }
1577             break;
1578         default:
1579             LOG(ERROR, BYTECODE_OPTIMIZER)
1580                 << "Wrong DataType for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1581             enc->success_ = false;
1582     }
1583 }
1584 
VisitStoreStatic(GraphVisitor * v,Inst * instBase)1585 void BytecodeGen::VisitStoreStatic(GraphVisitor *v, Inst *instBase)
1586 {
1587     if (TryPluginStoreStaticVisitor(v, instBase)) {
1588         return;
1589     }
1590 
1591     auto enc = static_cast<BytecodeGen *>(v);
1592     auto inst = instBase->CastToStoreStatic();
1593 
1594     compiler::Register vs = inst->GetSrcReg(1U);
1595     std::string id = enc->irInterface_->GetFieldIdByOffset(inst->GetTypeId());
1596 
1597     switch (inst->GetType()) {
1598         case compiler::DataType::BOOL:
1599         case compiler::DataType::UINT8:
1600         case compiler::DataType::INT8:
1601         case compiler::DataType::UINT16:
1602         case compiler::DataType::INT16:
1603         case compiler::DataType::UINT32:
1604         case compiler::DataType::INT32:
1605         case compiler::DataType::FLOAT32:
1606             DoLda(vs, enc->result_);
1607             enc->result_.emplace_back(pandasm::Create_STSTATIC(id));
1608             break;
1609         case compiler::DataType::INT64:
1610         case compiler::DataType::UINT64:
1611         case compiler::DataType::FLOAT64:
1612             DoLda64(vs, enc->result_);
1613             enc->result_.emplace_back(pandasm::Create_STSTATIC_64(id));
1614             break;
1615         case compiler::DataType::REFERENCE:
1616             DoLdaObj(vs, enc->result_);
1617             enc->result_.emplace_back(pandasm::Create_STSTATIC_OBJ(id));
1618             break;
1619         default:
1620             LOG(ERROR, BYTECODE_OPTIMIZER)
1621                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1622             enc->success_ = false;
1623     }
1624 }
1625 
IsAccLoadObject(const compiler::LoadObjectInst * inst)1626 static bool IsAccLoadObject(const compiler::LoadObjectInst *inst)
1627 {
1628     return inst->GetDstReg() == compiler::GetAccReg();
1629 }
1630 
VisitLoadObject(GraphVisitor * v,Inst * instBase)1631 void BytecodeGen::VisitLoadObject(GraphVisitor *v, Inst *instBase)
1632 {
1633     if (TryPluginLoadObjectVisitor(v, instBase)) {
1634         return;
1635     }
1636 
1637     auto enc = static_cast<BytecodeGen *>(v);
1638     auto inst = instBase->CastToLoadObject();
1639 
1640     compiler::Register vs = inst->GetSrcReg(0U);
1641     compiler::Register vd = inst->GetDstReg();
1642     std::string id = enc->irInterface_->GetFieldIdByOffset(inst->GetTypeId());
1643 
1644     bool isAccType = IsAccLoadObject(inst);
1645 
1646     switch (inst->GetType()) {
1647         case compiler::DataType::BOOL:
1648         case compiler::DataType::UINT8:
1649         case compiler::DataType::INT8:
1650         case compiler::DataType::UINT16:
1651         case compiler::DataType::INT16:
1652         case compiler::DataType::UINT32:
1653         case compiler::DataType::INT32:
1654         case compiler::DataType::FLOAT32:
1655             if (isAccType) {
1656                 enc->result_.emplace_back(pandasm::Create_LDOBJ(vs, id));
1657             } else {
1658                 enc->result_.emplace_back(pandasm::Create_LDOBJ_V(vd, vs, id));
1659             }
1660             break;
1661         case compiler::DataType::INT64:
1662         case compiler::DataType::UINT64:
1663         case compiler::DataType::FLOAT64:
1664             if (isAccType) {
1665                 enc->result_.emplace_back(pandasm::Create_LDOBJ_64(vs, id));
1666             } else {
1667                 enc->result_.emplace_back(pandasm::Create_LDOBJ_V_64(vd, vs, id));
1668             }
1669             break;
1670         case compiler::DataType::REFERENCE:
1671             if (isAccType) {
1672                 enc->result_.emplace_back(pandasm::Create_LDOBJ_OBJ(vs, id));
1673             } else {
1674                 enc->result_.emplace_back(pandasm::Create_LDOBJ_V_OBJ(vd, vs, id));
1675             }
1676             break;
1677         default:
1678             LOG(ERROR, BYTECODE_OPTIMIZER)
1679                 << "Wrong DataType for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1680             enc->success_ = false;
1681     }
1682 }
1683 
VisitLoadStatic(GraphVisitor * v,Inst * instBase)1684 void BytecodeGen::VisitLoadStatic(GraphVisitor *v, Inst *instBase)
1685 {
1686     if (TryPluginLoadStaticVisitor(v, instBase)) {
1687         return;
1688     }
1689 
1690     auto enc = static_cast<BytecodeGen *>(v);
1691     auto inst = instBase->CastToLoadStatic();
1692 
1693     compiler::Register vd = inst->GetDstReg();
1694     std::string id = enc->irInterface_->GetFieldIdByOffset(inst->GetTypeId());
1695 
1696     switch (inst->GetType()) {
1697         case compiler::DataType::BOOL:
1698         case compiler::DataType::UINT8:
1699         case compiler::DataType::INT8:
1700         case compiler::DataType::UINT16:
1701         case compiler::DataType::INT16:
1702         case compiler::DataType::UINT32:
1703         case compiler::DataType::INT32:
1704         case compiler::DataType::FLOAT32:
1705             enc->result_.emplace_back(pandasm::Create_LDSTATIC(id));
1706             DoSta(vd, enc->result_);
1707             break;
1708         case compiler::DataType::INT64:
1709         case compiler::DataType::UINT64:
1710         case compiler::DataType::FLOAT64:
1711             enc->result_.emplace_back(pandasm::Create_LDSTATIC_64(id));
1712             DoSta64(vd, enc->result_);
1713             break;
1714         case compiler::DataType::REFERENCE:
1715             enc->result_.emplace_back(pandasm::Create_LDSTATIC_OBJ(id));
1716             DoStaObj(vd, enc->result_);
1717             break;
1718         default:
1719             LOG(ERROR, BYTECODE_OPTIMIZER)
1720                 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
1721             enc->success_ = false;
1722     }
1723 }
1724 
VisitCatchPhi(GraphVisitor * v,Inst * inst)1725 void BytecodeGen::VisitCatchPhi(GraphVisitor *v, Inst *inst)
1726 {
1727     if (inst->CastToCatchPhi()->IsAcc()) {
1728         bool hasRealUsers = false;
1729         for (auto &user : inst->GetUsers()) {
1730             if (!user.GetInst()->IsSaveState()) {
1731                 hasRealUsers = true;
1732                 break;
1733             }
1734         }
1735         if (hasRealUsers) {
1736             auto enc = static_cast<BytecodeGen *>(v);
1737             enc->result_.emplace_back(pandasm::Create_STA_OBJ(inst->GetDstReg()));
1738         }
1739     }
1740 }
1741 
1742 #include "generated/codegen_intrinsics.cpp"
1743 #include "generated/insn_selection.cpp"
1744 }  // namespace ark::bytecodeopt
1745