1# Copyright (c) 2021-2022 Huawei Device Co., Ltd. 2# Licensed under the Apache License, Version 2.0 (the "License"); 3# you may not use this file except in compliance with the License. 4# You may obtain a copy of the License at 5# 6# http://www.apache.org/licenses/LICENSE-2.0 7# 8# Unless required by applicable law or agreed to in writing, software 9# distributed under the License is distributed on an "AS IS" BASIS, 10# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11# See the License for the specific language governing permissions and 12# limitations under the License. 13 14templates: 15 binop: |- 16 % regex_arithm = /(fdiv|fmod|add|sub|mul|and|or|xor|ashr|shr|shl|neg|not)[2i]?/ 17 % opc = inst.stripped_mnemonic.match regex_arithm 18 % raise "Wrong binop instruction" unless opc 19 % opc = opc[1].capitalize.gsub('Ashr', 'AShr').gsub('Fdiv', 'Div').gsub('Fmod', 'Mod') 20 auto inst = graph_->CreateInst<%= opc %>(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); 21 <%=template('operands', inst, '')-%> 22 AddInstruction(inst); 23 binop_z: |- 24 % opc = inst.stripped_mnemonic =~ /div/ ? 'Div' : 'Mod' 25 auto inst_save_state = CreateSaveState(Opcode::SaveState, GetPc(instruction->GetAddress())); 26 auto inst_check = graph_->CreateInstZeroCheck(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); 27 % if inst.acc_and_operands.last.imm? 28 if (graph_->IsBytecodeOptimizer()) { 29 inst_check->SetInput(0, FindOrCreate32BitConstant(instruction->GetImm<<%= inst.get_format %>, 0>())); 30 } else { 31 inst_check->SetInput(0, <%= inst.get_input_string(1) %>); 32 } 33 % else 34 inst_check->SetInput(0, <%= inst.get_input_string(1) %>); 35 % end 36 inst_check->SetInput(1, inst_save_state); 37 auto inst = graph_->CreateInst<%= opc %>(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); 38 inst->SetInput(0, <%= inst.get_input_string(0) %>); 39 inst->SetInput(1, inst_check); 40 UpdateDefinitionAcc(inst); 41 AddInstruction(inst_save_state); 42 AddInstruction(inst_check); 43 AddInstruction(inst); 44 inci: |- 45 auto inst = graph_->CreateInstAdd(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); 46 inst->SetInput(0, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); 47 if (graph_->IsBytecodeOptimizer()) { 48 inst->SetInput(1, FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 49 } else { 50 inst->SetInput(1, FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 51 } 52 AddInstruction(inst); 53 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), inst); 54 cast: |- 55 auto inst = graph_->CreateInstCast(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); 56 auto input = GetDefinitionAcc(); 57 inst->SetInput(0, input); 58 inst->SetOperandsType(<%= get_type(inst.type(0)) %>); 59 if (!input->HasType()) { 60 input->SetType(<%= get_type(inst.type(0)) %>); 61 } 62 UpdateDefinitionAcc(inst); 63 AddInstruction(inst); 64 cmp: |- 65 % if inst.mnemonic.include? "obj" 66 auto inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), ConditionCode::CC_NE); 67 % else 68 auto inst = graph_->CreateInstCmp(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); 69 % end 70 inst->SetInput(0, GetDefinitionAcc()); 71 inst->SetInput(1, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); 72 inst->SetOperandsType(<%= get_type(inst.type(0)) %>); 73 % if inst.stripped_mnemonic.start_with? 'fcmp' 74 inst->Set<%= inst.opcode =~ /^fcmpg/ ? 'Fcmpg' : 'Fcmpl' %>(); 75 % end 76 AddInstruction(inst); 77 UpdateDefinitionAcc(inst); 78 if: |- 79 auto inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), <%= get_cc(inst) %>); 80 inst->SetOperandsType(<%= get_type(inst.type(0)) %>); 81 % if inst.acc_and_operands.size > 2 82 inst->SetInput(1, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); 83 % else 84 inst->SetInput(1, FindOrCreateConstant(0)); 85 % end 86 inst->SetInput(0, GetDefinitionAcc()); 87 auto inst_jump = graph_->CreateInstIfImm(DataType::NO_TYPE, GetPc(instruction->GetAddress()), ConditionCode::CC_NE, 0); 88 inst_jump->SetOperandsType(DataType::BOOL); 89 inst_jump->SetInput(0, inst); 90 inst_jump->SetMethod(graph_->GetMethod()); 91 AddInstruction(inst); 92 AddInstruction(inst_jump); 93 jump: |- 94 mov: |- 95 % if inst.acc_and_operands[1].imm? 96 % if inst.mnemonic == "movi" 97 if (graph_->IsBytecodeOptimizer()) { 98 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 99 } else { 100 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 101 } 102 % else 103 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 104 % end 105 % else 106 % raise "Unsupported instruction type" unless inst.acc_and_operands[1].reg? 107 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 1>())); 108 % end 109 fmovi: |- 110 % if inst.mnemonic == "fmovi" 111 auto imm = bit_cast<float>(instruction->GetImm<<%=inst.get_format%>, 0>()); 112 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateFloatConstant(imm)); 113 % else 114 auto imm = bit_cast<double>(instruction->GetImm<<%=inst.get_format%>, 0>()); 115 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateDoubleConstant(imm)); 116 % end 117 sta: |- 118 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), GetDefinitionAcc()); 119 lda: |- 120 % if inst.acc_and_operands[1].imm? 121 % if inst.mnemonic == "ldai" 122 if (graph_->IsBytecodeOptimizer()) { 123 UpdateDefinitionAcc(FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 124 } else { 125 UpdateDefinitionAcc(FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 126 } 127 % else 128 UpdateDefinitionAcc(FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 129 % if inst.properties.include? "dynamic" 130 BuildCastToAnyNumber(instruction); 131 % end 132 % end 133 % elsif inst.acc_and_operands[1].id? 134 BuildLoadFromPool<Opcode::<%= inst.opcode =~ /lda_type/ ? 'LoadType' : 'LoadString' %>>(instruction); 135 % else 136 % raise "Unsupported instruction type" unless inst.acc_and_operands[1].reg? 137 UpdateDefinitionAcc(GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); 138 % end 139 fldai: |- 140 auto imm = bit_cast<double>(instruction->GetImm<<%=inst.get_format%>, 0>()); 141 UpdateDefinitionAcc(FindOrCreateDoubleConstant(imm)); 142 % if inst.properties.include? "dynamic" 143 BuildCastToAnyNumber(instruction); 144 % end 145 operands: |- 146 % inst.inputs.each_with_index do |op, idx| 147 % if op.imm? 148 if (graph_->IsBytecodeOptimizer()) { 149 inst->SetInput(<%= idx %>, FindOrCreate32BitConstant(instruction->GetImm<<%= inst.get_format %>, 0>())); 150 } else { 151 inst->SetInput(<%= idx %>, <%= inst.get_input_string(idx) %>); 152 } 153 % else 154 inst->SetInput(<%= idx %>, <%= inst.get_input_string(idx) %>); 155 % end 156 % end 157 % if inst.has_dst? 158 % if inst.acc_and_operands.first.acc? 159 UpdateDefinitionAcc(inst); 160 % else 161 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), inst); 162 % end 163 % end 164 return: |- 165 % opcode = inst.opcode.include?('void') ? 'ReturnVoid' : 'Return' 166 auto inst = graph_->CreateInst<%= opcode %>(GetCurrentMethodReturnType(), GetPc(instruction->GetAddress())); 167 <%=template('operands', inst, '')-%> 168 AddInstruction(inst); 169 ecma: |- 170 % name = inst.opcode.upcase.split('')[1] 171 % case name 172 % when "RETURNUNDEFINED" 173 auto cvat_input = FindOrCreateConstant(0); 174 cvat_input->SetType(DataType::Type::INT64); 175 auto cvat = graph->CreateInstCastValueToAnyType(0); 176 cvat->SetAnyType(panda::compiler::AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE); 177 cvat->SetInput(0, cvat_input); 178 auto inst = graph_->CreateInstReturn(DataType::ANY, GetPc(instruction->GetAddress())); 179 inst->SetInput(0, cvat); 180 AddInstruction(cvat); 181 AddInstruction(inst); 182 % when "RETURN" 183 auto inst = graph_->CreateInstReturn(DataType::ANY, GetPc(instruction->GetAddress())); 184 inst->SetInput(0, GetDefinitionAcc()); 185 AddInstruction(inst); 186 % when "JFALSE", "JTRUE" 187 % cmp_imm = name == "JFALSE" ? 0 : 1 188 auto cvat_input = FindOrCreateConstant(<%= cmp_imm %>); 189 cvat_input->SetType(DataType::INT64); 190 auto cvat = graph_->CreateInstCastValueToAnyType(0); 191 cvat->SetAnyType(panda::compiler::AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE); 192 cvat->SetInput(0, cvat_input); 193 auto cmp_inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), ConditionCode::CC_EQ); 194 cmp_inst->SetOperandsType(DataType::ANY); 195 cmp_inst->SetInput(0, GetDefinitionAcc()); 196 cmp_inst->SetInput(1, cvat); 197 auto jmp_inst = graph_->CreateInstIfImm(DataType::NO_TYPE, GetPc(instruction->GetAddress()), ConditionCode::CC_NE, 0); 198 jmp_inst->SetOperandsType(DataType::BOOL); 199 jmp_inst->SetInput(0, cmp_inst); 200 AddInstruction(cvat); 201 AddInstruction(cmp_inst); 202 AddInstruction(jmp_inst); 203 % else 204 BuildEcma(instruction); 205 % end 206 nop: |- 207 unimplemented: |- 208 // TODO(msherstennikov): implement 209