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.mnemonic.include? "null" 96 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), graph_->GetOrCreateNullPtr()); 97 % elsif inst.acc_and_operands[1].imm? 98 % if inst.mnemonic == "movi" 99 if (graph_->IsBytecodeOptimizer()) { 100 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 101 } else { 102 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 103 } 104 % else 105 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 106 % end 107 % else 108 % raise "Unsupported instruction type" unless inst.acc_and_operands[1].reg? 109 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 1>())); 110 % end 111 fmovi: |- 112 % if inst.mnemonic == "fmovi" 113 auto imm = bit_cast<float>(instruction->GetImm<<%=inst.get_format%>, 0>()); 114 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateFloatConstant(imm)); 115 % else 116 auto imm = bit_cast<double>(instruction->GetImm<<%=inst.get_format%>, 0>()); 117 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateDoubleConstant(imm)); 118 % end 119 sta: |- 120 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), GetDefinitionAcc()); 121 % if inst.properties.include? "dynamic" 122 if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) { 123 TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress()))); 124 } 125 % end 126 lda: |- 127 % if inst.mnemonic.include? "null" 128 UpdateDefinitionAcc(graph_->GetOrCreateNullPtr()); 129 % elsif inst.acc_and_operands[1].imm? 130 % if inst.mnemonic == "ldai" 131 if (graph_->IsBytecodeOptimizer()) { 132 UpdateDefinitionAcc(FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 133 } else { 134 UpdateDefinitionAcc(FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 135 } 136 % else 137 UpdateDefinitionAcc(FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); 138 % if inst.properties.include? "dynamic" 139 if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) { 140 TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress()))); 141 } 142 BuildCastToAnyNumber(instruction); 143 % end 144 % end 145 % elsif inst.acc_and_operands[1].id? 146 BuildLoadFromPool<Opcode::<%= inst.opcode =~ /lda_type/ ? 'LoadType' : 'LoadString' %>>(instruction); 147 % if inst.opcode =~ /lda_str/ 148 if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) { 149 TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress()))); 150 } 151 % end 152 % else 153 % raise "Unsupported instruction type" unless inst.acc_and_operands[1].reg? 154 UpdateDefinitionAcc(GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); 155 % end 156 fldai: |- 157 auto imm = bit_cast<double>(instruction->GetImm<<%=inst.get_format%>, 0>()); 158 UpdateDefinitionAcc(FindOrCreateDoubleConstant(imm)); 159 % if inst.properties.include? "dynamic" 160 if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) { 161 TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast<int>(GetPc(instruction->GetAddress()))); 162 } 163 BuildCastToAnyNumber(instruction); 164 % end 165 operands: |- 166 % inst.inputs.each_with_index do |op, idx| 167 % if op.imm? 168 if (graph_->IsBytecodeOptimizer()) { 169 inst->SetInput(<%= idx %>, FindOrCreate32BitConstant(instruction->GetImm<<%= inst.get_format %>, 0>())); 170 } else { 171 inst->SetInput(<%= idx %>, <%= inst.get_input_string(idx) %>); 172 } 173 % else 174 inst->SetInput(<%= idx %>, <%= inst.get_input_string(idx) %>); 175 % end 176 % end 177 % if inst.has_dst? 178 % if inst.acc_and_operands.first.acc? 179 UpdateDefinitionAcc(inst); 180 % else 181 UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), inst); 182 % end 183 % end 184 return: |- 185 % opcode = inst.opcode.include?('void') ? 'ReturnVoid' : 'Return' 186 auto inst = graph_->CreateInst<%= opcode %>(GetCurrentMethodReturnType(), GetPc(instruction->GetAddress())); 187 <%=template('operands', inst, '')-%> 188 AddInstruction(inst); 189 ecma: |- 190 % name = inst.opcode.upcase.split('')[1] 191 % case name 192 % when "RETURNUNDEFINED" 193 auto cvat_input = FindOrCreateConstant(0); 194 cvat_input->SetType(DataType::Type::INT64); 195 auto cvat = graph->CreateInstCastValueToAnyType(0); 196 cvat->SetAnyType(panda::compiler::AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE); 197 cvat->SetInput(0, cvat_input); 198 auto inst = graph_->CreateInstReturn(DataType::ANY, GetPc(instruction->GetAddress())); 199 inst->SetInput(0, cvat); 200 AddInstruction(cvat); 201 AddInstruction(inst); 202 % when "RETURN" 203 auto inst = graph_->CreateInstReturn(DataType::ANY, GetPc(instruction->GetAddress())); 204 inst->SetInput(0, GetDefinitionAcc()); 205 AddInstruction(inst); 206 % when "JFALSE", "JTRUE" 207 % cmp_imm = name == "JFALSE" ? 0 : 1 208 auto cvat_input = FindOrCreateConstant(<%= cmp_imm %>); 209 cvat_input->SetType(DataType::INT64); 210 auto cvat = graph_->CreateInstCastValueToAnyType(0); 211 cvat->SetAnyType(panda::compiler::AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE); 212 cvat->SetInput(0, cvat_input); 213 auto cmp_inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), ConditionCode::CC_EQ); 214 cmp_inst->SetOperandsType(DataType::ANY); 215 cmp_inst->SetInput(0, GetDefinitionAcc()); 216 cmp_inst->SetInput(1, cvat); 217 auto jmp_inst = graph_->CreateInstIfImm(DataType::NO_TYPE, GetPc(instruction->GetAddress()), ConditionCode::CC_NE, 0); 218 jmp_inst->SetOperandsType(DataType::BOOL); 219 jmp_inst->SetInput(0, cmp_inst); 220 AddInstruction(cvat); 221 AddInstruction(cmp_inst); 222 AddInstruction(jmp_inst); 223 % else 224 BuildEcma(instruction); 225 auto pc = static_cast<int>(GetPc(instruction->GetAddress())); 226 if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod() && GetGraph()->GetRuntime()->IsPcBindType(pc)) { 227 TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), pc); 228 } 229 % end 230 nop: |- 231 unimplemented: |- 232 // TODO(msherstennikov): implement 233