def match_addrmode5(node, values, idx, dag: Dag): from codegen.dag import VirtualDagOps, DagValue from codegen.types import ValueType value = values[idx] if value.node.opcode == VirtualDagOps.FRAME_INDEX: index = value.node.index base = DagValue( dag.add_frame_index_node(value.ty, index, True), 0) offset = DagValue(dag.add_target_constant_node( value.ty, 0), 0) return idx + 1, [base, offset] if value.node.opcode == VirtualDagOps.ADD: value1 = value.node.operands[0] value2 = value.node.operands[1] if value1.node.opcode == VirtualDagOps.CONSTANT: base = value2 assert(value1.node.value.value % 4 == 0) offset = DagValue(dag.add_target_constant_node( value1.ty, ConstantInt(value1.node.value.value >> 2, value1.node.value.ty)), 0) return idx + 1, [base, offset] elif value2.node.opcode == VirtualDagOps.CONSTANT: base = value1 assert(value2.node.value.value % 4 == 0) offset = DagValue(dag.add_target_constant_node( value2.ty, ConstantInt(value2.node.value.value >> 2, value2.node.value.ty)), 0) return idx + 1, [base, offset] if value.node.opcode == VirtualDagOps.SUB: if value2.node.opcode == VirtualDagOps.CONSTANT: raise NotImplementedError() # if value.node.opcode == ARMDagOps.WRAPPER: # base = value.node.operands[0] # offset = DagValue(dag.add_target_constant_node( # value.ty, 0), 0) # return idx + 1, MatcherResult([base, offset]) # only base. base = value assert(base.node.opcode != VirtualDagOps.TARGET_CONSTANT) offset = DagValue(dag.add_target_constant_node( value.ty, 0), 0) return idx + 1, [base, offset]
def get_legalized_op(operand, legalized): from codegen.dag import DagValue if operand.node not in legalized: return operand legalized_node = legalized[operand.node] if isinstance(legalized_node, (list, tuple)): return [DagValue(n, operand.index) for n in legalized_node] return DagValue(legalized_node, operand.index)
def apply_value(self, value, dag): from codegen.dag import VirtualDagOps, DagValue if value.node.opcode == VirtualDagOps.CONSTANT: value = DagValue( dag.add_target_constant_node(value.ty, value.node.value), 0) if value.node.opcode == VirtualDagOps.FRAME_INDEX: value = DagValue( dag.add_frame_index_node(value.ty, value.node.index, True), 0) return value
def construct(self, node, dag, result): from codegen.dag import DagValue return [ DagValue( dag.add_target_constant_node(node.value_types[0], self.value), 0) ]
def match(self, node, dag): from codegen.types import ValueType from codegen.spec import MachineRegisterDef from codegen.mir import MachineRegister from codegen.dag import VirtualDagOps, DagValue value = DagValue(node, 0) return self.pattern.match(None, [value], 0, dag)
def construct(self, node, dag, result): from codegen.dag import DagValue from codegen.mir import MachineRegister return [ DagValue( dag.add_register_node(node.value_types[0], MachineRegister(self.reg)), 0) ]
def match_addrmode6(node, values, idx, dag: Dag): from codegen.dag import VirtualDagOps, DagValue from codegen.types import ValueType value = values[idx] addr = value align = DagValue(dag.add_target_constant_node( value.ty, 1), 0) # TODO: Need alignment information return idx + 1, [addr, align]
def match_fi_addr(node, values, idx, dag): from codegen.dag import VirtualDagOps, DagValue from codegen.types import ValueType value = values[idx] if value.node.opcode == VirtualDagOps.FRAME_INDEX: index = value.node.index fi = DagValue(dag.add_frame_index_node(value.ty, index, True), 0) return idx + 1, fi return idx, None
def match_imm0_65535(node, values, idx, dag): from codegen.dag import VirtualDagOps from codegen.types import ValueType value = values[idx] if value.node.opcode not in [VirtualDagOps.CONSTANT, VirtualDagOps.TARGET_CONSTANT]: return idx, None if not in_bits_unsigned(value.node.value.value, 16): return idx, None target_value = DagValue(dag.add_target_constant_node( value.ty, value.node.value), 0) return idx + 1, target_value
def match_mod_imm(node, values, idx, dag): from codegen.dag import VirtualDagOps from codegen.types import ValueType value = values[idx] if value.node.opcode not in [VirtualDagOps.CONSTANT, VirtualDagOps.TARGET_CONSTANT]: return idx, None constant = value.node.value.value if get_mod_imm(constant) != -1: target_value = DagValue(dag.add_target_constant_node( value.ty, constant), 0) return idx + 1, target_value return idx, None
def construct(self, node, dag: Dag, result: MatcherResult): operands = [] for operand in self.operands: value = operand.construct(node, dag, result) operands.extend(value) assert (len(operands) == 1) base_node = operands[0].node from codegen.dag import DagNode, DagValue if isinstance(base_node, DagNode): return [DagValue(base_node, 0)] # return [DagValue(dag.add_node(base_node.opcode, [self.value_type], *base_node.operands), 0)] else: raise NotImplementedError()
def match_imm_shifter_operand(node, values, idx, dag): from codegen.dag import VirtualDagOps from codegen.types import ValueType value = values[idx] opc = get_shift_opcode(value.node.opcode) if opc == 0: return idx, None rhs = value.node.operands[1] if rhs.node.opcode not in [VirtualDagOps.CONSTANT, VirtualDagOps.TARGET_CONSTANT]: return idx, None rhs_val = rhs.node.value.value base = value.node.operands[0] opc = DagValue(dag.add_target_constant_node( value.ty, opc | (rhs_val << 3)), 0) return idx + 1, [base, opc]
FMV_D_X = def_inst_node_(RISCVMachineOps.FMV_D_X) FMV_X_D = def_inst_node_(RISCVMachineOps.FMV_X_D) MUL = def_inst_node_(RISCVMachineOps.MUL) DIV = def_inst_node_(RISCVMachineOps.DIV) DIVU = def_inst_node_(RISCVMachineOps.DIVU) REM = def_inst_node_(RISCVMachineOps.REM) REMU = def_inst_node_(RISCVMachineOps.REMU) from codegen.dag import DagValue HI20 = def_node_xform_( I32Imm, lambda value, dag: DagValue( dag.add_target_constant_node( value.node.value_types[0], ConstantInt((value.node.value.value & 0xFFFFFFFF) >> 12, value.node .value.ty)), 0)) def get_bits_sext(value, bits): minus = value < 0 value = abs(value) value = value & ((1 << bits) - 1) if minus: value = -value return value
def construct(self, node, dag, result): from codegen.dag import DagValue ops = [] for operand, operand_name in zip(self.operands, self.opcode.ins): ops.extend(operand.construct(node, dag, result)) inst = self.opcode # Capture chain chain = None operand_idx = 0 if operand_idx < len(node.operands) and node.operands[ operand_idx].ty.value_type == ValueType.OTHER: chain = node.operands[operand_idx] operand_idx += 1 stack = [] if chain is None: stack.append(node) while len(stack) > 0: parent_node = stack.pop() if len(parent_node.operands) == 0: break if parent_node.operands[0].ty.value_type == ValueType.OTHER: chain = parent_node.operands[0] break for operand in parent_node.operands: stack.append(operand.node) if not chain: chain = dag.entry glue = None for reg in inst.uses: assert (isinstance(reg, MachineRegisterDef)) operand = dic[reg].value if not operand: continue reg_node = DagValue( dag.add_target_register_node(operand.ty, reg), 0) chain = DagValue( dag.add_node(VirtualDagOps.COPY_TO_REG, [ MachineValueType(ValueType.OTHER), MachineValueType(ValueType.GLUE) ], chain, reg_node, operand), 0) glue = chain.get_value(1) if len(node.operands ) > 0 and node.operands[-1].ty.value_type == ValueType.GLUE: glue = node.operands[-1] if chain: ops.append(chain) if glue: ops.append(glue) return [ DagValue( dag.add_machine_dag_node(inst, node.value_types, *ops), 0) ]
def match(self, node, values, idx, dag): from codegen.dag import DagValue return self.matcher.match(None, [DagValue(node, 0)], 0, dag)
def construct(inst, node, dag: Dag, result: MatcherResult): from codegen.types import ValueType, MachineValueType from codegen.spec import MachineRegisterDef from codegen.dag import DagValue dic = result.values_as_dict ops = [] for name, opnd in inst.ins.items(): ops.extend(opnd.apply(dic[name].value, dag)) operands = list(node.operands) # Capture chain chain = None operand_idx = 0 if operand_idx < len(operands) and operands[ operand_idx].ty.value_type == ValueType.OTHER: chain = operands[operand_idx] operand_idx += 1 stack = [] if chain is None: stack.append(node) while len(stack) > 0: parent_node = stack.pop() if len(parent_node.operands) == 0: break if parent_node.operands[0].ty.value_type == ValueType.OTHER: chain = parent_node.operands[0] break for operand in parent_node.operands: stack.append(operand.node) if not chain: chain = dag.entry glue = None if len(operands) > 0 and operands[-1].ty.value_type == ValueType.GLUE: glue = node.operands[-1] operands.pop() for reg in inst.uses: assert (isinstance(reg, MachineRegisterDef)) if not reg in dic: continue operand = dic[reg].value if not operand: continue reg_node = DagValue(dag.add_target_register_node(operand.ty, reg), 0) copy_to_reg_ops = [chain, reg_node, operand] if glue: copy_to_reg_ops.append(glue) chain = DagValue( dag.add_node(VirtualDagOps.COPY_TO_REG, [ MachineValueType(ValueType.OTHER), MachineValueType(ValueType.GLUE) ], *copy_to_reg_ops), 0) glue = chain.get_value(1) operand_idx += len(ops) while operand_idx < len(operands): operand = operands[operand_idx] operand_idx += 1 if operand == glue: continue ops.append(operand) if chain: ops.append(chain) if glue: ops.append(glue) return dag.add_machine_dag_node(inst, node.value_types, *ops)
def match(self, node, values, idx, dag): from codegen.types import ValueType, MachineValueType from codegen.spec import MachineRegisterDef from codegen.mir import MachineRegister from codegen.dag import VirtualDagOps, DagValue, StoreDagNode, LoadDagNode if idx >= len(values): return idx, None value = values[idx] node = value.node # Check opcode _, res = self.opcode.match(None, [value], 0, dag) if not res: return idx, None mem_vt = self.props["mem_vt"] if "mem_vt" in self.props else None if mem_vt: assert (isinstance(node, (StoreDagNode, LoadDagNode))) if node.mem_operand.size != MachineValueType( mem_vt).get_size_in_byte(): return idx, None # Check operands operand_idx = 0 # Capture chain chain = None if operand_idx < len(node.operands) and node.operands[ operand_idx].ty.value_type == ValueType.OTHER: chain = node.operands[operand_idx] operand_idx += 1 match_results = [] for matcher in self.operands: operand_idx, res = matcher.match(node, node.operands, operand_idx, dag) if not res: return idx, None match_results.append(res) for sub_value in res.sub_values: match_results.append(sub_value) # while operand_idx < len(node.operands) and node.operands[operand_idx].node.opcode == VirtualDagOps.UNDEF: # operand_idx += 1 # if operand_idx != len(node.operands): # return None # Check values value_idx = 0 node_values = [DagValue(node, i) for i in range(len(node.value_types))] for matcher in self.values: _, res = matcher.match(node, node_values, value_idx, dag) if not res: return idx, None match_results.append(res) for sub_value in res.sub_values: match_results.append(sub_value) return idx + 1, MatcherResult(None, None, match_results)