Beispiel #1
0
def _InsRewriteDivRemShifts(ins: ir.Ins,
                            fun: ir.Fun) -> Optional[List[ir.Ins]]:
    opc = ins.opcode
    ops = ins.operands
    if opc is o.DIV and ops[0].kind.flavor() != o.DK_FLAVOR_F:
        # note: we could leave it to the register allocator to pick a CpuReg for ops[2]
        # but then we would somehow have to  ensure that the reg is NOT rdx.
        # By forcing rcx for ops[2] we sidestep the issue
        rax = fun.FindOrAddCpuReg(regs.CPU_REGS_MAP["rax"], ops[0].kind)
        rcx = fun.FindOrAddCpuReg(regs.CPU_REGS_MAP["rcx"], ops[0].kind)
        rdx = fun.FindOrAddCpuReg(regs.CPU_REGS_MAP["rdx"], ops[0].kind)
        return [
            ir.Ins(o.MOV, [rax, ops[1]]),
            ir.Ins(o.MOV, [rcx, ops[2]]),
            ir.Ins(o.DIV, [rdx, rax, rcx
                           ]),  # note the notion of src/dst regs is murky here
            ir.Ins(o.MOV, [ops[0], rax])
        ]
    elif opc is o.REM and ops[0].kind.flavor() != o.DK_FLAVOR_F:
        rax = fun.FindOrAddCpuReg(regs.CPU_REGS_MAP["rax"], ops[0].kind)
        rcx = fun.FindOrAddCpuReg(regs.CPU_REGS_MAP["rcx"], ops[0].kind)
        rdx = fun.FindOrAddCpuReg(regs.CPU_REGS_MAP["rdx"], ops[0].kind)
        return [
            ir.Ins(o.MOV, [rax, ops[1]]),
            ir.Ins(o.MOV, [rcx, ops[2]]),
            ir.Ins(o.DIV, [rdx, rax, rcx
                           ]),  # note the notion of src/dst regs is murky here
            ir.Ins(o.MOV, [ops[0], rdx])
        ]
    elif opc in {o.SHR, o.SHL} and isinstance(ops[2], ir.Reg):
        rcx = fun.FindOrAddCpuReg(regs.CPU_REGS_MAP["rcx"], ops[0].kind)
        mov = ir.Ins(o.MOV, [rcx, ops[2]])
        ops[2] = rcx
        mask = _SHIFT_MASK.get(ops[0].kind)
        if mask:
            return [mov, ir.Ins(o.AND, [rcx, rcx, mask]), ins]
        else:
            return [mov, ins]
    else:
        return None
Beispiel #2
0
def _InsPushargConversionReverse(ins: ir.Ins, fun: ir.Fun,
                                 params: List[ir.CpuReg]) -> Optional[
    List[ir.Ins]]:
    """
    This pass converts pusharg reg -> mov arg_reg = reg

    Note:
         * params is passed around between calls to this function
         * pusharg's always precede calls or returns
    """
    if ins.opcode is o.PUSHARG:
        cpu_reg = params.pop(0)
        src = ins.operands[0]
        reg = fun.FindOrAddCpuReg(cpu_reg, src.kind)
        return [ir.Ins(o.MOV, [reg, src])]
    assert not params, f"params {params} should be empty at ins {ins} {ins.operands}"
    if ins.opcode.is_call():
        callee: ir.Fun = cfg.InsCallee(ins)
        assert isinstance(callee, ir.Fun)
        params += GetCpuRegsForSignature(callee.input_types)
    elif ins.opcode is o.RET:
        params += GetCpuRegsForSignature(fun.output_types)
    return None
Beispiel #3
0
def _InsPopargConversion(ins: ir.Ins, fun: ir.Fun,
                         params: List[ir.CpuReg]) -> Optional[List[ir.Ins]]:
    """
    This pass converts `poparg reg` -> `mov reg = arg_reg`

    it must used in a forward pass over the Bbl and will update `param`
    for use with the next Ins in the BBl. The initial value of `param`
    reflects the Fun's arguments.

    """
    if ins.opcode is o.POPARG:
        cpu_reg = params.pop(0)
        dst = ins.operands[0]
        # assert dst.kind == cpu_reg.kind
        reg = fun.FindOrAddCpuReg(cpu_reg, dst.kind)
        return [ir.Ins(o.MOV, [dst, reg])]

    assert not params, f"params {params} should be empty at ins {ins}"

    if ins.opcode.is_call():
        callee: ir.Fun = cfg.InsCallee(ins)
        assert isinstance(callee, ir.Fun)
        params += GetCpuRegsForSignature(callee.output_types)
    return None