# Copyright (c) 2021-2022 Huawei Device Co., Ltd. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. templates: binop: |- % regex_arithm = /(fdiv|fmod|add|sub|mul|and|or|xor|ashr|shr|shl|neg|not)[2i]?/ % opc = inst.stripped_mnemonic.match regex_arithm % raise "Wrong binop instruction" unless opc % opc = opc[1].capitalize.gsub('Ashr', 'AShr').gsub('Fdiv', 'Div').gsub('Fmod', 'Mod') auto inst = graph_->CreateInst<%= opc %>(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); <%=template('operands', inst, '')-%> AddInstruction(inst); binop_z: |- % opc = inst.stripped_mnemonic =~ /div/ ? 'Div' : 'Mod' auto inst_save_state = CreateSaveState(Opcode::SaveState, GetPc(instruction->GetAddress())); auto inst_check = graph_->CreateInstZeroCheck(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); % if inst.acc_and_operands.last.imm? if (graph_->IsBytecodeOptimizer()) { inst_check->SetInput(0, FindOrCreate32BitConstant(instruction->GetImm<<%= inst.get_format %>, 0>())); } else { inst_check->SetInput(0, <%= inst.get_input_string(1) %>); } % else inst_check->SetInput(0, <%= inst.get_input_string(1) %>); % end inst_check->SetInput(1, inst_save_state); auto inst = graph_->CreateInst<%= opc %>(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); inst->SetInput(0, <%= inst.get_input_string(0) %>); inst->SetInput(1, inst_check); UpdateDefinitionAcc(inst); AddInstruction(inst_save_state); AddInstruction(inst_check); AddInstruction(inst); inci: |- auto inst = graph_->CreateInstAdd(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); inst->SetInput(0, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); if (graph_->IsBytecodeOptimizer()) { inst->SetInput(1, FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); } else { inst->SetInput(1, FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); } AddInstruction(inst); UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), inst); cast: |- auto inst = graph_->CreateInstCast(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); auto input = GetDefinitionAcc(); inst->SetInput(0, input); inst->SetOperandsType(<%= get_type(inst.type(0)) %>); if (!input->HasType()) { input->SetType(<%= get_type(inst.type(0)) %>); } UpdateDefinitionAcc(inst); AddInstruction(inst); cmp: |- % if inst.mnemonic.include? "obj" auto inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), ConditionCode::CC_NE); % else auto inst = graph_->CreateInstCmp(<%= get_type(inst.dtype) %>, GetPc(instruction->GetAddress())); % end inst->SetInput(0, GetDefinitionAcc()); inst->SetInput(1, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); inst->SetOperandsType(<%= get_type(inst.type(0)) %>); % if inst.stripped_mnemonic.start_with? 'fcmp' inst->Set<%= inst.opcode =~ /^fcmpg/ ? 'Fcmpg' : 'Fcmpl' %>(); % end AddInstruction(inst); UpdateDefinitionAcc(inst); if: |- auto inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), <%= get_cc(inst) %>); inst->SetOperandsType(<%= get_type(inst.type(0)) %>); % if inst.acc_and_operands.size > 2 inst->SetInput(1, GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); % else inst->SetInput(1, FindOrCreateConstant(0)); % end inst->SetInput(0, GetDefinitionAcc()); auto inst_jump = graph_->CreateInstIfImm(DataType::NO_TYPE, GetPc(instruction->GetAddress()), ConditionCode::CC_NE, 0); inst_jump->SetOperandsType(DataType::BOOL); inst_jump->SetInput(0, inst); inst_jump->SetMethod(graph_->GetMethod()); AddInstruction(inst); AddInstruction(inst_jump); jump: |- mov: |- % if inst.acc_and_operands[1].imm? % if inst.mnemonic == "movi" if (graph_->IsBytecodeOptimizer()) { UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); } else { UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); } % else UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); % end % else % raise "Unsupported instruction type" unless inst.acc_and_operands[1].reg? UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 1>())); % end fmovi: |- % if inst.mnemonic == "fmovi" auto imm = bit_cast(instruction->GetImm<<%=inst.get_format%>, 0>()); UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateFloatConstant(imm)); % else auto imm = bit_cast(instruction->GetImm<<%=inst.get_format%>, 0>()); UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), FindOrCreateDoubleConstant(imm)); % end sta: |- UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), GetDefinitionAcc()); % if inst.properties.include? "dynamic" if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) { TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast(GetPc(instruction->GetAddress()))); } % end lda: |- % if inst.acc_and_operands[1].imm? % if inst.mnemonic == "ldai" if (graph_->IsBytecodeOptimizer()) { UpdateDefinitionAcc(FindOrCreate32BitConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); } else { UpdateDefinitionAcc(FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); } % else UpdateDefinitionAcc(FindOrCreateConstant(instruction->GetImm<<%=inst.get_format%>, 0>())); % if inst.properties.include? "dynamic" if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) { TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast(GetPc(instruction->GetAddress()))); } BuildCastToAnyNumber(instruction); % end % end % elsif inst.acc_and_operands[1].id? BuildLoadFromPool>(instruction); % if inst.opcode =~ /lda_str/ if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) { TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast(GetPc(instruction->GetAddress()))); } % end % else % raise "Unsupported instruction type" unless inst.acc_and_operands[1].reg? UpdateDefinitionAcc(GetDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>())); % end fldai: |- auto imm = bit_cast(instruction->GetImm<<%=inst.get_format%>, 0>()); UpdateDefinitionAcc(FindOrCreateDoubleConstant(imm)); % if inst.properties.include? "dynamic" if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod()) { TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), static_cast(GetPc(instruction->GetAddress()))); } BuildCastToAnyNumber(instruction); % end operands: |- % inst.inputs.each_with_index do |op, idx| % if op.imm? if (graph_->IsBytecodeOptimizer()) { inst->SetInput(<%= idx %>, FindOrCreate32BitConstant(instruction->GetImm<<%= inst.get_format %>, 0>())); } else { inst->SetInput(<%= idx %>, <%= inst.get_input_string(idx) %>); } % else inst->SetInput(<%= idx %>, <%= inst.get_input_string(idx) %>); % end % end % if inst.has_dst? % if inst.acc_and_operands.first.acc? UpdateDefinitionAcc(inst); % else UpdateDefinition(instruction->GetVReg<<%=inst.get_format%>, 0>(), inst); % end % end return: |- % opcode = inst.opcode.include?('void') ? 'ReturnVoid' : 'Return' auto inst = graph_->CreateInst<%= opcode %>(GetCurrentMethodReturnType(), GetPc(instruction->GetAddress())); <%=template('operands', inst, '')-%> AddInstruction(inst); ecma: |- % name = inst.opcode.upcase.split('')[1] % case name % when "RETURNUNDEFINED" auto cvat_input = FindOrCreateConstant(0); cvat_input->SetType(DataType::Type::INT64); auto cvat = graph->CreateInstCastValueToAnyType(0); cvat->SetAnyType(panda::compiler::AnyBaseType::ECMASCRIPT_UNDEFINED_TYPE); cvat->SetInput(0, cvat_input); auto inst = graph_->CreateInstReturn(DataType::ANY, GetPc(instruction->GetAddress())); inst->SetInput(0, cvat); AddInstruction(cvat); AddInstruction(inst); % when "RETURN" auto inst = graph_->CreateInstReturn(DataType::ANY, GetPc(instruction->GetAddress())); inst->SetInput(0, GetDefinitionAcc()); AddInstruction(inst); % when "JFALSE", "JTRUE" % cmp_imm = name == "JFALSE" ? 0 : 1 auto cvat_input = FindOrCreateConstant(<%= cmp_imm %>); cvat_input->SetType(DataType::INT64); auto cvat = graph_->CreateInstCastValueToAnyType(0); cvat->SetAnyType(panda::compiler::AnyBaseType::ECMASCRIPT_BOOLEAN_TYPE); cvat->SetInput(0, cvat_input); auto cmp_inst = graph_->CreateInstCompare(DataType::BOOL, GetPc(instruction->GetAddress()), ConditionCode::CC_EQ); cmp_inst->SetOperandsType(DataType::ANY); cmp_inst->SetInput(0, GetDefinitionAcc()); cmp_inst->SetInput(1, cvat); auto jmp_inst = graph_->CreateInstIfImm(DataType::NO_TYPE, GetPc(instruction->GetAddress()), ConditionCode::CC_NE, 0); jmp_inst->SetOperandsType(DataType::BOOL); jmp_inst->SetInput(0, cmp_inst); AddInstruction(cvat); AddInstruction(cmp_inst); AddInstruction(jmp_inst); % else BuildEcma(instruction); auto pc = static_cast(GetPc(instruction->GetAddress())); if (GetGraph()->IsBytecodeOptimizer() && GetGraph()->IsDynamicMethod() && GetGraph()->GetRuntime()->IsPcBindType(pc)) { TryFillInstIdTypePair(GetDefinitionAcc()->GetId(), pc); } % end nop: |- unimplemented: |- // TODO(msherstennikov): implement