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