1/** 2 * Copyright (c) 2021-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 16static ark::compiler::CallInst *CastToCallLaunch(ark::compiler::Inst *inst) 17{ 18 switch (inst->GetOpcode()) { 19 case compiler::Opcode::CallLaunchStatic: 20 return inst->CastToCallLaunchStatic(); 21 case compiler::Opcode::CallLaunchVirtual: 22 return inst->CastToCallLaunchVirtual(); 23 default: 24 UNREACHABLE(); 25 } 26} 27 28static ark::pandasm::Opcode ChooseCallLaunchOpcode(ark::compiler::Opcode op, size_t nargs) 29{ 30 ASSERT(op == compiler::Opcode::CallLaunchStatic || op == compiler::Opcode::CallLaunchVirtual); 31 if (nargs > MAX_NUM_NON_RANGE_ARGS) { 32 switch (op) { 33 case compiler::Opcode::CallLaunchStatic: 34 return pandasm::Opcode::ETS_LAUNCH_RANGE; 35 case compiler::Opcode::CallLaunchVirtual: 36 return pandasm::Opcode::ETS_LAUNCH_VIRT_RANGE; 37 default: 38 UNREACHABLE(); 39 } 40 } else if (nargs > MAX_NUM_SHORT_CALL_ARGS) { 41 switch (op) { 42 case compiler::Opcode::CallLaunchStatic: 43 return pandasm::Opcode::ETS_LAUNCH; 44 case compiler::Opcode::CallLaunchVirtual: 45 return pandasm::Opcode::ETS_LAUNCH_VIRT; 46 default: 47 UNREACHABLE(); 48 } 49 } 50 switch (op) { 51 case compiler::Opcode::CallLaunchStatic: 52 return pandasm::Opcode::ETS_LAUNCH_SHORT; 53 case compiler::Opcode::CallLaunchVirtual: 54 return pandasm::Opcode::ETS_LAUNCH_VIRT_SHORT; 55 default: 56 UNREACHABLE(); 57 } 58} 59 60static void CallLaunchHandler(ark::compiler::GraphVisitor *visitor, ark::compiler::Inst *inst) 61{ 62 auto op = inst->GetOpcode(); 63 ASSERT(op == ark::compiler::Opcode::CallLaunchStatic || op == ark::compiler::Opcode::CallLaunchVirtual); 64 auto *enc = static_cast<BytecodeGen *>(visitor); 65 auto callInst = CastToCallLaunch(inst); 66 auto sfCount = inst->GetInputsCount() - (inst->RequireState() ? 1 : 0); 67 size_t start = 1; 68 auto nargs = sfCount - start; 69 pandasm::Ins ins; 70 ins.opcode = ChooseCallLaunchOpcode(op, nargs); 71 72 auto zeroArg = inst->GetInput(0).GetInst(); 73 ASSERT(zeroArg->GetOpcode() == Opcode::NewObject); 74 auto newobjInst = zeroArg->CastToNewObject(); 75 76 if (nargs > MAX_NUM_NON_RANGE_ARGS) { 77#ifndef NDEBUG 78 auto startReg = inst->GetSrcReg(start); 79 ASSERT(startReg <= MAX_8_BIT_REG); 80 for (size_t i = start; i < sfCount; ++i) { 81 auto reg = inst->GetSrcReg(i); 82 ASSERT(reg - startReg == static_cast<int>(i - start)); // check 'range-ness' of registers 83 } 84#endif // !NDEBUG 85 ins.regs.emplace_back(inst->GetSrcReg(start)); 86 } else { 87 for (size_t i = start; i < sfCount; ++i) { 88 auto reg = inst->GetSrcReg(i); 89 ASSERT(reg < NUM_COMPACTLY_ENCODED_REGS); 90 ins.regs.emplace_back(reg); 91 } 92 } 93 ins.ids.emplace_back(enc->irInterface_->GetMethodIdByOffset(callInst->GetCallMethodId())); 94 enc->result_.emplace_back(ins); 95 if (newobjInst->GetDstReg() != compiler::GetAccReg()) { 96 enc->result_.emplace_back(pandasm::Create_STA_OBJ(newobjInst->GetDstReg())); 97 } 98} 99 100static void VisitCallLaunchStatic(ark::compiler::GraphVisitor *visitor, ark::compiler::Inst *inst) 101{ 102 CallLaunchHandler(visitor, inst); 103} 104 105static void VisitCallLaunchVirtual(GraphVisitor *visitor, Inst *inst) 106{ 107 CallLaunchHandler(visitor, inst); 108} 109 110static void VisitEtsLdObjByName(BytecodeGen *enc, compiler::IntrinsicInst *inst) 111{ 112 auto v0 = inst->GetSrcReg(0); 113 auto bcId0 = enc->irInterface_->GetFieldIdByOffset(static_cast<uint32_t>(inst->GetImms()[0])); 114 switch (inst->GetIntrinsicId()) { 115 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_LD_OBJ_BY_NAME_I32: 116 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_LD_OBJ_BY_NAME_F32: 117 enc->result_.emplace_back(pandasm::Create_ETS_LDOBJ_NAME(v0, bcId0)); 118 DoSta(inst->GetDstReg(), enc->result_); 119 break; 120 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_LD_OBJ_BY_NAME_I64: 121 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_LD_OBJ_BY_NAME_F64: 122 enc->result_.emplace_back(pandasm::Create_ETS_LDOBJ_NAME_64(v0, bcId0)); 123 DoSta64(inst->GetDstReg(), enc->result_); 124 break; 125 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_LD_OBJ_BY_NAME_OBJ: 126 enc->result_.emplace_back(pandasm::Create_ETS_LDOBJ_NAME_OBJ(v0, bcId0)); 127 DoStaObj(inst->GetDstReg(), enc->result_); 128 break; 129 default: 130 UNREACHABLE(); 131 } 132} 133 134static void VisitEtsStObjByName(BytecodeGen *enc, compiler::IntrinsicInst *inst) 135{ 136 auto v0 = inst->GetSrcReg(0); 137 auto bcId0 = enc->irInterface_->GetFieldIdByOffset(static_cast<uint32_t>(inst->GetImms()[0])); 138 switch (inst->GetIntrinsicId()) { 139 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_I32: 140 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_I16: 141 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_I8: 142 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_F32: 143 DoLda(inst->GetSrcReg(1U), enc->result_); 144 enc->result_.emplace_back(pandasm::Create_ETS_STOBJ_NAME(v0, bcId0)); 145 break; 146 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_I64: 147 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_F64: 148 DoLda64(inst->GetSrcReg(1U), enc->result_); 149 enc->result_.emplace_back(pandasm::Create_ETS_STOBJ_NAME_64(v0, bcId0)); 150 break; 151 case compiler::RuntimeInterface::IntrinsicId::INTRINSIC_COMPILER_ETS_ST_OBJ_BY_NAME_OBJ: 152 DoLdaObj(inst->GetSrcReg(1U), enc->result_); 153 enc->result_.emplace_back(pandasm::Create_ETS_STOBJ_NAME_OBJ(v0, bcId0)); 154 break; 155 default: 156 UNREACHABLE(); 157 } 158} 159 160static void VisitLoadUndefined(GraphVisitor *visitor, Inst *inst) 161{ 162 auto *enc = static_cast<BytecodeGen *>(visitor); 163 if (inst->GetDstReg() == compiler::GetAccReg()) { 164 enc->result_.emplace_back(pandasm::Create_ETS_LDUNDEFINED()); 165 } else { 166 enc->result_.emplace_back(pandasm::Create_ETS_MOVUNDEFINED(inst->GetDstReg())); 167 } 168} 169 170static void VisitEtsEquals(GraphVisitor *visitor, Inst *inst) 171{ 172 auto *enc = static_cast<BytecodeGen *>(visitor); 173 auto v0 = inst->GetSrcReg(0); 174 auto v1 = inst->GetSrcReg(1); 175 enc->result_.emplace_back(pandasm::Create_ETS_EQUALS(v0, v1)); 176 DoSta(inst->GetDstReg(), enc->result_); 177} 178