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