1 /*
2 * Copyright (c) 2021-2022 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 "common.h"
17 #include "generate_ecma.inl"
18 #include "tagged_value.h"
19
20 namespace panda::bytecodeopt {
21
22 using panda_file::LiteralTag;
23
DoLda(compiler::Register reg,std::vector<pandasm::Ins> & result)24 void DoLda(compiler::Register reg, std::vector<pandasm::Ins> &result)
25 {
26 if (reg != compiler::ACC_REG_ID) {
27 result.emplace_back(pandasm::Create_LDA(reg));
28 }
29 }
30
DoSta(compiler::Register reg,std::vector<pandasm::Ins> & result)31 void DoSta(compiler::Register reg, std::vector<pandasm::Ins> &result)
32 {
33 if (reg != compiler::ACC_REG_ID) {
34 result.emplace_back(pandasm::Create_STA(reg));
35 }
36 }
37
AppendCatchBlock(uint32_t type_id,const compiler::BasicBlock * try_begin,const compiler::BasicBlock * try_end,const compiler::BasicBlock * catch_begin,const compiler::BasicBlock * catch_end)38 void BytecodeGen::AppendCatchBlock(uint32_t type_id, const compiler::BasicBlock *try_begin,
39 const compiler::BasicBlock *try_end, const compiler::BasicBlock *catch_begin,
40 const compiler::BasicBlock *catch_end)
41 {
42 auto cb = pandasm::Function::CatchBlock();
43 if (type_id != 0) {
44 cb.exception_record = ir_interface_->GetTypeIdByOffset(type_id);
45 }
46 cb.try_begin_label = BytecodeGen::LabelName(try_begin->GetId());
47 cb.try_end_label = "end_" + BytecodeGen::LabelName(try_end->GetId());
48 cb.catch_begin_label = BytecodeGen::LabelName(catch_begin->GetId());
49 cb.catch_end_label =
50 catch_end == nullptr ? cb.catch_begin_label : "end_" + BytecodeGen::LabelName(catch_end->GetId());
51 catch_blocks_.emplace_back(cb);
52 }
53
VisitTryBegin(const compiler::BasicBlock * bb)54 void BytecodeGen::VisitTryBegin(const compiler::BasicBlock *bb)
55 {
56 ASSERT(bb->IsTryBegin());
57 auto try_inst = GetTryBeginInst(bb);
58 auto try_end = try_inst->GetTryEndBlock();
59 ASSERT(try_end != nullptr && try_end->IsTryEnd());
60
61 bb->EnumerateCatchHandlers([&, bb, try_end](BasicBlock *catch_handler, size_t type_id) {
62 AppendCatchBlock(type_id, bb, try_end, catch_handler);
63 return true;
64 });
65 }
66
RunImpl()67 bool BytecodeGen::RunImpl()
68 {
69 Reserve(function_->ins.size());
70 TypeInfoComponents elements;
71 AddTypeInfoIndexForArguments(&elements);
72 bool need_handle_ins_type = GetGraph()->GetRuntime()->HasInsTypeinfo();
73 int32_t insn_order = 0;
74 for (auto *bb : GetGraph()->GetBlocksLinearOrder()) {
75 EmitLabel(BytecodeGen::LabelName(bb->GetId()));
76 if (bb->IsTryEnd() || bb->IsCatchEnd()) {
77 auto label = "end_" + BytecodeGen::LabelName(bb->GetId());
78 EmitLabel(label);
79 }
80 for (const auto &inst : bb->AllInsts()) {
81 auto start = GetResult().size();
82 VisitInstruction(inst);
83 if (!GetStatus()) {
84 return false;
85 }
86 auto end = GetResult().size();
87 ASSERT(end >= start);
88 for (auto i = start; i < end; ++i) {
89 AddLineNumber(inst, i);
90 AddColumnNumber(inst, i);
91 }
92 if (need_handle_ins_type && end > start) {
93 // fill ins types. Need to exclude invalid ins as they do not emit
94 insn_order += std::count_if(GetResult().begin() + start, GetResult().end(),
95 [](const auto &ins) { return ins.opcode != pandasm::Opcode::INVALID; });
96 AddTypeInfoIndexForIns(insn_order - 1, inst->GetId(), &elements);
97 }
98 }
99 if (bb->NeedsJump()) {
100 EmitJump(bb);
101 insn_order++;
102 }
103 }
104 if (!GetStatus()) {
105 return false;
106 }
107 // Visit try-blocks in order they were declared
108 for (auto *bb : GetGraph()->GetTryBeginBlocks()) {
109 VisitTryBegin(bb);
110 }
111 function_->ins = std::move(GetResult());
112 function_->catch_blocks = catch_blocks_;
113 if (need_handle_ins_type) {
114 UpdateTypeInfoIndexAnnotation(&elements);
115 }
116 return true;
117 }
118
AddTypeInfoIndexForArguments(TypeInfoComponents * elements) const119 void BytecodeGen::AddTypeInfoIndexForArguments(TypeInfoComponents *elements) const
120 {
121 std::unordered_map<int32_t, TypeInfoIndex> args_types_map;
122 if (GetGraph()->GetRuntime()->FillArgTypePairs(&args_types_map)) {
123 for (const auto &[arg, type] : args_types_map) {
124 ASSERT(arg < 0);
125 AddOrderAndTypeInfoIndex(arg, type, elements);
126 }
127 }
128 }
129
AddOrderAndTypeInfoIndex(int32_t order,TypeInfoIndex type,TypeInfoComponents * elements) const130 void BytecodeGen::AddOrderAndTypeInfoIndex(int32_t order, TypeInfoIndex type, TypeInfoComponents *elements) const
131 {
132 pandasm::LiteralArray::Literal order_tag;
133 order_tag.tag_ = LiteralTag::TAGVALUE;
134 order_tag.value_ = static_cast<uint8_t>(LiteralTag::INTEGER);
135 elements->emplace_back(order_tag);
136
137 pandasm::LiteralArray::Literal order_lit;
138 order_lit.tag_ = LiteralTag::INTEGER;
139 order_lit.value_ = bit_cast<uint32_t>(order);
140 elements->emplace_back(order_lit);
141
142 pandasm::LiteralArray::Literal type_tag;
143 type_tag.tag_ = LiteralTag::TAGVALUE;
144 pandasm::LiteralArray::Literal type_lit;
145 if (std::holds_alternative<std::string>(type)) {
146 type_tag.value_ = static_cast<uint8_t>(LiteralTag::LITERALARRAY);
147 type_lit.tag_ = LiteralTag::LITERALARRAY;
148 type_lit.value_ = std::get<std::string>(type);
149 } else {
150 type_tag.value_ = static_cast<uint8_t>(LiteralTag::BUILTINTYPEINDEX);
151 type_lit.tag_ = LiteralTag::BUILTINTYPEINDEX;
152 type_lit.value_ = std::get<BuiltinIndexType>(type);
153 }
154
155 elements->emplace_back(type_tag);
156 elements->emplace_back(type_lit);
157 }
158
AddTypeInfoIndexForIns(int32_t order,size_t id,TypeInfoComponents * elements) const159 void BytecodeGen::AddTypeInfoIndexForIns(int32_t order, size_t id, TypeInfoComponents *elements) const
160 {
161 auto type = GetGraph()->GetRuntime()->GetTypeInfoIndexByInstId(id);
162 if (type != NO_EXPLICIT_TYPE) {
163 AddOrderAndTypeInfoIndex(order, type, elements);
164 }
165 }
166
UpdateTypeInfoIndexAnnotation(const TypeInfoComponents * elements)167 void BytecodeGen::UpdateTypeInfoIndexAnnotation(const TypeInfoComponents *elements)
168 {
169 #ifndef NDEBUG
170 LOG(DEBUG, BYTECODE_OPTIMIZER) << "Typeinfo after optimization for function : " << function_->name;
171 const size_t PAIR_GAP = 4; // 4: tag, order, tag, value, ...
172 ASSERT(elements->size() % PAIR_GAP == 0);
173 for (size_t i = 1; i < elements->size(); i += PAIR_GAP) {
174 auto order = bit_cast<int32_t>(std::get<uint32_t>((*elements)[i].value_));
175 const auto &element = (*elements)[i + 2]; // 2: gap between order and value
176 if (element.tag_ == LiteralTag::LITERALARRAY) {
177 auto type = std::get<std::string>(element.value_);
178 LOG(DEBUG, BYTECODE_OPTIMIZER) << "[" << order << ", " << type << "], ";
179 } else {
180 ASSERT(element.tag_ == LiteralTag::BUILTINTYPEINDEX);
181 auto type = std::get<BuiltinIndexType>(element.value_);
182 LOG(DEBUG, BYTECODE_OPTIMIZER) << "[" << order << ", " << type << "], ";
183 }
184 }
185 #endif
186
187 const auto &key = *(GetGraph()->GetRuntime()->GetTypeLiteralArrayKey());
188 auto &litarr_table = GetProgram()->literalarray_table;
189 ASSERT(litarr_table.find(key) != litarr_table.end());
190 pandasm::LiteralArray array(*elements);
191 litarr_table[key] = array;
192 }
193
EmitJump(const BasicBlock * bb)194 void BytecodeGen::EmitJump(const BasicBlock *bb)
195 {
196 BasicBlock *suc_bb = nullptr;
197 ASSERT(bb != nullptr);
198
199 if (bb->GetLastInst() == nullptr) {
200 ASSERT(bb->IsEmpty());
201 suc_bb = bb->GetSuccsBlocks()[0];
202 result_.push_back(pandasm::Create_JMP(BytecodeGen::LabelName(suc_bb->GetId())));
203 return;
204 }
205
206 ASSERT(bb->GetLastInst() != nullptr);
207 switch (bb->GetLastInst()->GetOpcode()) {
208 case Opcode::If:
209 case Opcode::IfImm:
210 ASSERT(bb->GetSuccsBlocks().size() == compiler::MAX_SUCCS_NUM);
211 suc_bb = bb->GetFalseSuccessor();
212 break;
213 default:
214 suc_bb = bb->GetSuccsBlocks()[0];
215 break;
216 }
217 result_.push_back(pandasm::Create_JMP(BytecodeGen::LabelName(suc_bb->GetId())));
218 }
219
AddLineNumber(const Inst * inst,const size_t idx)220 void BytecodeGen::AddLineNumber(const Inst *inst, const size_t idx)
221 {
222 if (ir_interface_ != nullptr && idx < result_.size()) {
223 auto ln = ir_interface_->GetLineNumberByPc(inst->GetPc());
224 result_[idx].ins_debug.SetLineNumber(ln);
225 }
226 }
227
AddColumnNumber(const Inst * inst,const uint32_t idx)228 void BytecodeGen::AddColumnNumber(const Inst *inst, const uint32_t idx)
229 {
230 if (ir_interface_ != nullptr && idx < result_.size()) {
231 auto cn = ir_interface_->GetLineNumberByPc(inst->GetPc());
232 result_[idx].ins_debug.SetColumnNumber(cn);
233 }
234 }
235
EncodeSpillFillData(const compiler::SpillFillData & sf)236 void BytecodeGen::EncodeSpillFillData(const compiler::SpillFillData &sf)
237 {
238 if (sf.SrcType() != compiler::LocationType::REGISTER || sf.DstType() != compiler::LocationType::REGISTER) {
239 LOG(ERROR, BYTECODE_OPTIMIZER) << "EncodeSpillFillData with unknown move type, src_type: "
240 << static_cast<int>(sf.SrcType())
241 << " dst_type: " << static_cast<int>(sf.DstType());
242 success_ = false;
243 UNREACHABLE();
244 return;
245 }
246 ASSERT(sf.GetType() != compiler::DataType::NO_TYPE);
247 ASSERT(sf.SrcValue() != compiler::INVALID_REG && sf.DstValue() != compiler::INVALID_REG);
248
249 if (sf.SrcValue() == sf.DstValue()) {
250 return;
251 }
252
253 pandasm::Ins move;
254 result_.emplace_back(pandasm::Create_MOV(sf.DstValue(), sf.SrcValue()));
255 return;
256 }
257
VisitSpillFill(GraphVisitor * visitor,Inst * inst)258 void BytecodeGen::VisitSpillFill(GraphVisitor *visitor, Inst *inst)
259 {
260 auto *enc = static_cast<BytecodeGen *>(visitor);
261 for (auto sf : inst->CastToSpillFill()->GetSpillFills()) {
262 enc->EncodeSpillFillData(sf);
263 }
264 }
265
266 template <typename UnaryPred>
HasUserPredicate(Inst * inst,UnaryPred p)267 bool HasUserPredicate(Inst *inst, UnaryPred p)
268 {
269 bool found = false;
270 for (auto const &u : inst->GetUsers()) {
271 if (p(u.GetInst())) {
272 found = true;
273 break;
274 }
275 }
276 return found;
277 }
278
VisitConstant(GraphVisitor * visitor,Inst * inst)279 void BytecodeGen::VisitConstant(GraphVisitor *visitor, Inst *inst)
280 {
281 auto *enc = static_cast<BytecodeGen *>(visitor);
282 auto type = inst->GetType();
283
284 /* Do not emit unused code for Const -> CastValueToAnyType chains */
285 if (!HasUserPredicate(inst,
286 [](Inst const *i) { return i->GetOpcode() != compiler::Opcode::CastValueToAnyType; })) {
287 return;
288 }
289
290 pandasm::Ins movi;
291 movi.regs.emplace_back(inst->GetDstReg());
292 switch (type) {
293 case compiler::DataType::INT64:
294 case compiler::DataType::UINT64:
295 enc->result_.emplace_back(pandasm::Create_LDAI(inst->CastToConstant()->GetInt64Value()));
296 DoSta(inst->GetDstReg(), enc->result_);
297 break;
298 case compiler::DataType::FLOAT64:
299 enc->result_.emplace_back(pandasm::Create_FLDAI(inst->CastToConstant()->GetDoubleValue()));
300 DoSta(inst->GetDstReg(), enc->result_);
301 break;
302 case compiler::DataType::INT32:
303 case compiler::DataType::UINT32:
304 enc->result_.emplace_back(pandasm::Create_LDAI(inst->CastToConstant()->GetInt32Value()));
305 DoSta(inst->GetDstReg(), enc->result_);
306 break;
307 default:
308 UNREACHABLE();
309 LOG(ERROR, BYTECODE_OPTIMIZER) << "VisitConstant with unknown type" << type;
310 enc->success_ = false;
311 }
312 }
313
EncodeSta(compiler::Register reg,compiler::DataType::Type type)314 void BytecodeGen::EncodeSta(compiler::Register reg, compiler::DataType::Type type)
315 {
316 pandasm::Opcode opc;
317 switch (type) {
318 case compiler::DataType::ANY:
319 opc = pandasm::Opcode::STA;
320 break;
321 default:
322 UNREACHABLE();
323 LOG(ERROR, BYTECODE_OPTIMIZER) << "EncodeSta with unknown type" << type;
324 success_ = false;
325 }
326 pandasm::Ins sta;
327 sta.opcode = opc;
328 sta.regs.emplace_back(reg);
329
330 result_.emplace_back(sta);
331 }
332
333 // NOLINTNEXTLINE(readability-function-size)
VisitIf(GraphVisitor * v,Inst * inst_base)334 void BytecodeGen::VisitIf(GraphVisitor *v, Inst *inst_base)
335 {
336 auto enc = static_cast<BytecodeGen *>(v);
337 auto inst = inst_base->CastToIf();
338 switch (inst->GetInputType(0)) {
339 case compiler::DataType::ANY: {
340 #if defined(ENABLE_BYTECODE_OPT) && defined(PANDA_WITH_ECMASCRIPT) && defined(ARK_INTRINSIC_SET)
341 IfEcma(v, inst);
342 break;
343 #else
344 [[fallthrough]];
345 #endif
346 }
347 default:
348 LOG(ERROR, BYTECODE_OPTIMIZER)
349 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
350 enc->success_ = false;
351 break;
352 }
353 }
354
355 #if defined(ENABLE_BYTECODE_OPT) && defined(PANDA_WITH_ECMASCRIPT)
IsEcmaConstTemplate(Inst const * inst)356 static std::optional<coretypes::TaggedValue> IsEcmaConstTemplate(Inst const *inst)
357 {
358 if (inst->GetOpcode() != compiler::Opcode::CastValueToAnyType) {
359 return {};
360 }
361 auto cvat_inst = inst->CastToCastValueToAnyType();
362 if (!cvat_inst->GetInput(0).GetInst()->IsConst()) {
363 return {};
364 }
365 auto const_inst = cvat_inst->GetInput(0).GetInst()->CastToConstant();
366
367 switch (cvat_inst->GetAnyType()) {
368 case compiler::AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE:
369 return coretypes::TaggedValue(coretypes::TaggedValue::VALUE_UNDEFINED);
370 case compiler::AnyBaseType::ECMASCRIPT_INT_TYPE:
371 return coretypes::TaggedValue(static_cast<int32_t>(const_inst->GetIntValue()));
372 case compiler::AnyBaseType::ECMASCRIPT_DOUBLE_TYPE:
373 return coretypes::TaggedValue(const_inst->GetDoubleValue());
374 case compiler::AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE:
375 return coretypes::TaggedValue(static_cast<bool>(const_inst->GetInt64Value() != 0));
376 case compiler::AnyBaseType::ECMASCRIPT_NULL_TYPE:
377 return coretypes::TaggedValue(coretypes::TaggedValue::VALUE_NULL);
378 default:
379 return {};
380 }
381 }
382
383 #if defined(ARK_INTRINSIC_SET)
IfEcma(GraphVisitor * v,compiler::IfInst * inst)384 void BytecodeGen::IfEcma(GraphVisitor *v, compiler::IfInst *inst)
385 {
386 auto enc = static_cast<BytecodeGen *>(v);
387
388 compiler::Register reg = compiler::INVALID_REG_ID;
389 coretypes::TaggedValue cmp_val;
390
391 auto test_lhs = IsEcmaConstTemplate(inst->GetInput(0).GetInst());
392 auto test_rhs = IsEcmaConstTemplate(inst->GetInput(1).GetInst());
393
394 if (test_lhs.has_value() && test_lhs->IsBoolean()) {
395 cmp_val = test_lhs.value();
396 reg = inst->GetSrcReg(1);
397 } else if (test_rhs.has_value() && test_rhs->IsBoolean()) {
398 cmp_val = test_rhs.value();
399 reg = inst->GetSrcReg(0);
400 } else {
401 LOG(ERROR, BYTECODE_OPTIMIZER) << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
402 enc->success_ = false;
403 return;
404 }
405
406 DoLda(reg, enc->result_);
407 switch (inst->GetCc()) {
408 case compiler::CC_EQ: {
409 if (cmp_val.IsTrue()) {
410 enc->result_.emplace_back(
411 pandasm::Create_ECMA_JTRUE(LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId())));
412 } else {
413 enc->result_.emplace_back(
414 pandasm::Create_ECMA_JFALSE(LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId())));
415 }
416 break;
417 }
418 case compiler::CC_NE: {
419 if (cmp_val.IsTrue()) {
420 enc->result_.emplace_back(pandasm::Create_ECMA_ISTRUE());
421 } else {
422 enc->result_.emplace_back(pandasm::Create_ECMA_ISFALSE());
423 }
424 enc->result_.emplace_back(
425 pandasm::Create_ECMA_JFALSE(LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId())));
426 break;
427 }
428 default:
429 LOG(ERROR, BYTECODE_OPTIMIZER)
430 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
431 enc->success_ = false;
432 return;
433 }
434 }
435 #endif
436 #endif
437
VisitIfImm(GraphVisitor * v,Inst * inst_base)438 void BytecodeGen::VisitIfImm(GraphVisitor *v, Inst *inst_base)
439 {
440 auto inst = inst_base->CastToIfImm();
441 auto imm = inst->GetImm();
442 if (imm == 0) {
443 IfImmZero(v, inst_base);
444 return;
445 }
446 }
447
IfImmZero(GraphVisitor * v,Inst * inst_base)448 void BytecodeGen::IfImmZero(GraphVisitor *v, Inst *inst_base)
449 {
450 auto enc = static_cast<BytecodeGen *>(v);
451 auto inst = inst_base->CastToIfImm();
452 DoLda(inst->GetSrcReg(0), enc->result_);
453 auto label = LabelName(inst->GetBasicBlock()->GetTrueSuccessor()->GetId());
454 switch (inst->GetCc()) {
455 case compiler::CC_EQ:
456 enc->result_.emplace_back(pandasm::Create_JEQZ(label));
457 return;
458 case compiler::CC_NE:
459 enc->result_.emplace_back(pandasm::Create_JNEZ(label));
460 return;
461 default:
462 UNREACHABLE();
463 }
464 }
465
VisitLoadString(GraphVisitor * v,Inst * inst_base)466 void BytecodeGen::VisitLoadString(GraphVisitor *v, Inst *inst_base)
467 {
468 pandasm::Ins ins;
469 auto enc = static_cast<BytecodeGen *>(v);
470 auto inst = inst_base->CastToLoadString();
471 /* Do not emit unused code for Str -> CastValueToAnyType chains */
472 if (!HasUserPredicate(inst,
473 [](Inst const *i) { return i->GetOpcode() != compiler::Opcode::CastValueToAnyType; })) {
474 return;
475 }
476
477 enc->result_.emplace_back(pandasm::Create_LDA_STR(enc->ir_interface_->GetStringIdByOffset(inst->GetTypeId())));
478 if (inst->GetDstReg() != compiler::ACC_REG_ID) {
479 enc->result_.emplace_back(pandasm::Create_STA(inst->GetDstReg()));
480 }
481 }
482
VisitReturn(GraphVisitor * v,Inst * inst_base)483 void BytecodeGen::VisitReturn(GraphVisitor *v, Inst *inst_base)
484 {
485 pandasm::Ins ins;
486 auto enc = static_cast<BytecodeGen *>(v);
487 auto inst = inst_base->CastToReturn();
488 switch (inst->GetType()) {
489 case compiler::DataType::ANY: {
490 #if defined(ENABLE_BYTECODE_OPT) && defined(PANDA_WITH_ECMASCRIPT)
491 auto test_arg = IsEcmaConstTemplate(inst->GetInput(0).GetInst());
492 if (test_arg.has_value() && test_arg->IsUndefined()) {
493 enc->result_.emplace_back(pandasm::Create_RETURNUNDEFINED());
494 break;
495 }
496 #endif
497 DoLda(inst->GetSrcReg(0), enc->result_);
498 enc->result_.emplace_back(pandasm::Create_RETURN());
499 break;
500 }
501 default:
502 LOG(ERROR, BYTECODE_OPTIMIZER)
503 << "Codegen for " << compiler::GetOpcodeString(inst->GetOpcode()) << " failed";
504 enc->success_ = false;
505 }
506 }
507
VisitCastValueToAnyType(GraphVisitor * v,Inst * inst_base)508 void BytecodeGen::VisitCastValueToAnyType([[maybe_unused]] GraphVisitor *v, [[maybe_unused]] Inst *inst_base)
509 {
510 auto enc = static_cast<BytecodeGen *>(v);
511
512 #if defined(ENABLE_BYTECODE_OPT) && defined(PANDA_WITH_ECMASCRIPT)
513 auto cvat = inst_base->CastToCastValueToAnyType();
514 switch (cvat->GetAnyType()) {
515 case compiler::AnyBaseType::ECMASCRIPT_NULL_TYPE:
516 enc->result_.emplace_back(pandasm::Create_LDNULL());
517 break;
518 case compiler::AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE:
519 if (!HasUserPredicate(cvat,
520 [](Inst const *inst) { return inst->GetOpcode() != compiler::Opcode::Return; })) {
521 return;
522 }
523 enc->result_.emplace_back(pandasm::Create_LDUNDEFINED());
524 break;
525 case compiler::AnyBaseType::ECMASCRIPT_INT_TYPE: {
526 ASSERT(cvat->GetInput(0).GetInst()->IsConst());
527 auto input = cvat->GetInput(0).GetInst()->CastToConstant();
528 enc->result_.emplace_back(pandasm::Create_LDAI(input->GetIntValue()));
529 break;
530 }
531 case compiler::AnyBaseType::ECMASCRIPT_DOUBLE_TYPE: {
532 ASSERT(cvat->GetInput(0).GetInst()->IsConst());
533 auto input = cvat->GetInput(0).GetInst()->CastToConstant();
534 enc->result_.emplace_back(pandasm::Create_FLDAI(input->GetDoubleValue()));
535 break;
536 }
537 case compiler::AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE: {
538 ASSERT(cvat->GetInput(0).GetInst()->IsBoolConst());
539 auto input = cvat->GetInput(0).GetInst()->CastToConstant();
540 if (!HasUserPredicate(cvat, [](Inst const *inst) { return inst->GetOpcode() != compiler::Opcode::If; })) {
541 return;
542 }
543 uint64_t val = input->GetInt64Value();
544 if (val != 0) {
545 enc->result_.emplace_back(pandasm::Create_LDTRUE());
546 } else {
547 enc->result_.emplace_back(pandasm::Create_LDFALSE());
548 }
549 break;
550 }
551 case compiler::AnyBaseType::ECMASCRIPT_STRING_TYPE: {
552 auto input = cvat->GetInput(0).GetInst()->CastToLoadString();
553 enc->result_.emplace_back(
554 pandasm::Create_LDA_STR(enc->ir_interface_->GetStringIdByOffset(input->GetTypeId())));
555 break;
556 }
557 default:
558 return;
559 }
560 DoSta(cvat->GetDstReg(), enc->result_);
561 #else
562 LOG(ERROR, BYTECODE_OPTIMIZER) << "Codegen for " << compiler::GetOpcodeString(inst_base->GetOpcode()) << " failed";
563 enc->success_ = false;
564 #endif
565 }
566
567 // NOLINTNEXTLINE(readability-function-size)
VisitIntrinsic(GraphVisitor * visitor,Inst * inst_base)568 void BytecodeGen::VisitIntrinsic(GraphVisitor *visitor, Inst *inst_base)
569 {
570 ASSERT(inst_base->IsIntrinsic());
571 VisitEcma(visitor, inst_base);
572 }
573
VisitCatchPhi(GraphVisitor * visitor,Inst * inst)574 void BytecodeGen::VisitCatchPhi(GraphVisitor *visitor, Inst *inst)
575 {
576 if (inst->CastToCatchPhi()->IsAcc()) {
577 for (auto &user : inst->GetUsers()) {
578 if (!user.GetInst()->IsSaveState()) {
579 UNREACHABLE();
580 }
581 }
582 }
583 }
584
585 #include "generated/codegen_intrinsics.cpp"
586 #include "generated/insn_selection.cpp"
587 } // namespace panda::bytecodeopt
588