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