コード例 #1
0
ファイル: optimize.py プロジェクト: mbrukman/Cwerg
def main(argv):
    mode = "optimize"
    if argv:
        mode = argv.pop(0)

    unit = serialize.UnitParseFromAsm(sys.stdin)
    if mode == "optimize":
        UnitCfgInit(unit)
        unit_stats = UnitOpt(unit, True)
        UnitCfgExit(unit)
        print("\n".join(serialize.UnitRenderToASM(unit)))
    elif mode == "optlite":
        UnitCfgInit(unit)
        unit_stats = UnitOptBasic(unit, True)
        UnitCfgExit(unit)
        print("\n".join(serialize.UnitRenderToASM(unit)))
    elif mode == "optimize_stats":
        UnitCfgInit(unit)
        unit_stats = UnitOpt(unit, True)
        UnitCfgExit(unit)
        print("\n".join(serialize.UnitRenderToASM(unit)))
        print(f"# STATS:")
        for key, val in unit_stats.items():
            print(f"#  {key}: {val}")
    elif mode == "serialize":
        print("\n".join(serialize.UnitRenderToASM(unit)))
    elif mode == "cfg":
        UnitCfgInit(unit)
        print("\n".join(serialize.UnitRenderToASM(unit)))
    elif mode == "cfg2":
        UnitCfgInit(unit)
        UnitCfgExit(unit)
        print("\n".join(serialize.UnitRenderToASM(unit)))
    else:
        assert False, f"unknown mode: [{mode}]"
コード例 #2
0
    def testB(self):
        code = io.StringIO(r"""
.fun main NORMAL [S32] = [S32 A64]

.bbl %start
  poparg argc:S32
  poparg argv:A64
  mov b:S32 1
  add a:S32 b 1
  add x:S32 a 1
  blt argc 2 if_1_true
  bra if_1_end
  
.bbl if_1_true
   pusharg 1:S32
   ret
   
.bbl if_1_end
   pusharg 0:S32
   ret
""")
        unit = serialize.UnitParseFromAsm(code)
        fun = unit.fun_syms["main"]
        optimize.FunCfgInit(fun, unit)
        liveness.FunComputeLivenessInfo(fun)
        liveness.FunRemoveUselessInstructions(fun)
        # print ("@@@@\n", "\n".join(serialize.FunRenderToAsm(fun)))
        for bbl in fun.bbls:
            for ins in bbl.inss:
                self.assertTrue(ins.opcode in {o.POPARG, o.PUSHARG, o.RET, o.BLT}, f"bad ins {ins}")
コード例 #3
0
ファイル: codegen.py プロジェクト: robertmuth/Cwerg
 def main():
     parser = argparse.ArgumentParser(description='CodeGenC')
     parser.add_argument('--trace', action='store_const',
                         const=True, default=False,
                         help='show info after every step')
     parser.add_argument('--debug_parser', action='store_const',
                         const=True, default=False,
                         help='dump module before starting execution')
     parser.add_argument('filename', type=str,
                         help='file to execute')
     args = parser.parse_args()
     if args.filename == "-":
         fin = sys.stdin
     else:
         fin = open(args.filename)
     unit = serialize.UnitParseFromAsm(fin, args.debug_parser)
     assert "main" in unit.fun_syms
     print(PROLOG)
     for fun in unit.funs:
         if fun.kind is o.FUN_KIND.BUILTIN:
             continue
         sanity.FunCheck(fun, unit, check_push_pop=True, check_cfg=False)
         EmitFunctionProto(fun, True)
         print(";")
     for mem in unit.mems:
         EmitMemory(mem)
     for fun in unit.funs:
         if fun.kind is o.FUN_KIND.BUILTIN:
             continue
         EmitFunction(fun)
     print(EPILOG)
コード例 #4
0
def Translate(fin):
    scratch = regs.FLT_CALLEE_SAVE_REGS[0]
    ctx = regs.EmitContext(0xfc0, 0xfc0, 0xffff0000, 0xffff0000, 66, scratch)
    unit = serialize.UnitParseFromAsm(fin, cpu_regs=regs.CPU_REGS)
    for fun in unit.funs:
        for bbl in fun.bbls:
            for ins in bbl.inss:
                print()
                HandleIns(ins, ctx)
コード例 #5
0
    def main():
        parser = argparse.ArgumentParser(description='CodeGenA64')
        parser.add_argument('-mode', type=str, help='mode')
        parser.add_argument(
            '-add_startup_code',
            action='store_true',
            help=
            'Add startup code (symbol _startup) which calls main and provides access to argc/argv'
        )

        parser.add_argument('input', type=str, help='input file')
        parser.add_argument('output', type=str, help='output file')
        args = parser.parse_args()

        assert args.mode in _ALLOWED_MODES
        fin = sys.stdin if args.input == "-" else open(args.input)

        unit = serialize.UnitParseFromAsm(fin)
        opt_stats: Dict[str, int] = collections.defaultdict(int)

        if args.mode == "binary":
            # we need to legalize all functions first as this may change the signature
            # and fills in cpu reg usage which is used by subsequent interprocedural opts.
            LegalizeAll(unit, opt_stats, None)
            RegAllocGlobal(unit, opt_stats, None)
            RegAllocLocal(unit, opt_stats, None)
            x64unit = EmitUnitAsBinary(unit, args.add_startup_code)
            exe = assembler.Assemble(x64unit, True)
            exe.save(open(args.output, "wb"))
            os.chmod(args.output, stat.S_IREAD | stat.S_IEXEC | stat.S_IWRITE)
            return

        fout = sys.stdout if args.output == "-" else open(args.output, "w")

        # we need to legalize all functions first as this may change the signature
        # and fills in cpu reg usage which is used by subsequent interprocedural opts.
        LegalizeAll(unit, opt_stats, fout)
        if args.mode == "legalize":
            print("\n".join(serialize.UnitRenderToASM(unit)), file=fout)
            return

        RegAllocGlobal(unit, opt_stats, fout)
        if args.mode == "reg_alloc_global":
            print("\n".join(serialize.UnitRenderToASM(unit)), file=fout)
            return

        RegAllocLocal(unit, opt_stats, fout)
        if args.mode == "reg_alloc_local":
            print("\n".join(serialize.UnitRenderToASM(unit)), file=fout)
            return

        assert args.mode == "normal"
        EmitUnitAsText(unit, fout)
        if False:
            print(f"# STATS:")
            for key, val in sorted(opt_stats.items()):
                print(f"#  {key}: {val}", file=fout)
コード例 #6
0
ファイル: reaching_defs_test.py プロジェクト: mbrukman/Cwerg
    def testBaseRegPropagation2(self):
        code = io.StringIO(r"""
.fun foo NORMAL [] = []
    .reg S32 [x]
    .reg U32 [y]
    .reg A32 [a counter] 

.bbl start
    poparg counter
    poparg y

    lea a counter 666
    ld x = a 0
    mul x = x 777
    st a 334 = x

    lea a counter y
    ld x = a 0
    mul x = x 777
    st a 0 = x

    lea a counter y
    ld x = a 0
    mul x = x 777
    st a 0 = x

    mov a counter
    ld x = a 0
    mul x = x 777
    st a 334 = x

    ret
         """)

        unit = serialize.UnitParseFromAsm(code, False)
        fun = unit.fun_syms["foo"]
        bbl = fun.bbls[0]

        cfg.FunInitCFG(fun)
        liveness.FunComputeLivenessInfo(fun)
        reaching_defs.FunComputeReachingDefs(fun)
        reaching_defs.FunPropagateConsts(fun)
        reaching_defs.FunLoadStoreSimplify(fun)
        liveness.FunRemoveUselessInstructions(fun)
        print("\n".join(serialize.FunRenderToAsm(fun)))
        # all ld/st were re-written
        for ins in bbl.inss:
            self.assertIn(ins.opcode.name, {
                "ret",
                "mul",
                "poparg",
                "ld",
                "ld",
                "st",
                "st",
            })
コード例 #7
0
    def testD(self):
        code = io.StringIO(r"""
.fun arm_syscall_write SIGNATURE [S32] = [S32 A32 U32]

.fun putchar NORMAL [] = [U32]

.fun writeln NORMAL [] = [A32 U32]
# live_out: ['r0', 'r1']
.reg S32 [$r0_S32 dummy]
.reg U32 [$r0_U32 $r1_U32 $r2_U32 len]
.reg A32 [$r0_A32 $r1_A32 buf]
.bbl start
    mov buf $r0_A32@r0                     # 0
    mov len $r1_U32@r1                     # 1
    mov $r2_U32@r2 len                     # 2
    mov $r1_A32@r1 buf                     # 3
    mov $r0_S32@r0 1                       # 4
    syscall arm_syscall_write 4:U32        # 5
    mov dummy $r0_S32@r0                   # 6
    mov $r0_U32@r0 10                      # 7
    bsr putchar                            # 8
    ret                                    # 9
""")
        cpu_regs = {"r0": ir.CpuReg("r0", 0), "r1": ir.CpuReg("r1", 1), "r2": ir.CpuReg("r2", 2)}
        unit = serialize.UnitParseFromAsm(code, cpu_regs=cpu_regs)

        fun = unit.fun_syms["arm_syscall_write"]
        fun.cpu_live_out = {cpu_regs["r0"]}
        fun.cpu_live_in = {cpu_regs["r0"], cpu_regs["r1"], cpu_regs["r2"]}

        fun = unit.fun_syms["putchar"]
        fun.cpu_live_in = {cpu_regs["r0"]}

        fun = unit.fun_syms["writeln"]
        cfg.FunSplitBbls(fun)
        cfg.FunInitCFG(fun)
        cfg.FunRemoveUnconditionalBranches(fun)
        cfg.FunRemoveEmptyBbls(fun)
        liveness.FunComputeLivenessInfo(fun)
        ranges = liveness.BblGetLiveRanges(fun.bbls[0], fun, fun.bbls[0].live_out, False)
        ranges.sort()
        print("TestD")
        for lr in ranges:
            print(lr)
        self.assertEqual(ranges, [
            liveness.LiveRange(liveness.BEFORE_BBL, 0, fun.reg_syms["$r0_A32"], 1),
            liveness.LiveRange(liveness.BEFORE_BBL, 1, fun.reg_syms["$r1_U32"], 1),
            liveness.LiveRange(0, 3, fun.reg_syms["buf"], 1),
            liveness.LiveRange(1, 2, fun.reg_syms["len"], 1),
            liveness.LiveRange(2, 5, fun.reg_syms["$r2_U32"], 0),
            liveness.LiveRange(3, 5, fun.reg_syms["$r1_A32"], 0),
            liveness.LiveRange(4, 5, fun.reg_syms["$r0_S32"], 0),
            liveness.LiveRange(5, 6, fun.reg_syms["$r0_S32"], 1),
            liveness.LiveRange(6, liveness.NO_USE, fun.reg_syms["dummy"], 0),
            liveness.LiveRange(7, 8, fun.reg_syms["$r0_U32"], 0),
        ])
コード例 #8
0
def Translate(fin):
    unit = serialize.UnitParseFromAsm(fin, cpu_regs=regs.CPU_REGS_MAP)
    for fun in unit.funs:
        ctx = regs.EmitContext(0xfc0, 0xfc0, 0xffff0000, 0xffff0000, 66)
        if "gpr_scratch" in fun.name:
            ctx.scratch_cpu_reg = regs.GPR_REGS[6]
        fun.FinalizeStackSlots()
        for bbl in fun.bbls:
            for ins in bbl.inss:
                print()
                HandleIns(ins, ctx)
コード例 #9
0
ファイル: reg_alloc_test.py プロジェクト: robertmuth/Cwerg
    def testBacktrack(self):
        # this is a good example for linear scan producing pretty bad assignments
        code = io.StringIO(r"""
.fun main NORMAL [U32 U32 U32 U32] = [U32 U32 U32 U32]

.bbl start
    poparg w:U32 
    poparg x:U32 
    poparg y:U32 
    poparg z:U32 
    
    mov a:U32 1
    mov b:U32 2
    mov c:U32 3
    mov d:U32 4
    
    cmpeq e:U32 a b c d
    
    pusharg z
    pusharg y
    pusharg x
    pusharg w
    ret
        """)

        unit = serialize.UnitParseFromAsm(code, False)
        fun = unit.fun_syms["main"]
        bbl = fun.bbls[0]

        _DumpBblWithLineNumbers(bbl)

        live_ranges = liveness.BblGetLiveRanges(bbl, fun, set(), True)
        live_ranges.sort()

        pool = TestRegPool(MakeGenericCpuRegs(4))
        reg_alloc.RegisterAssignerLinearScan(live_ranges, pool)
        for n, lr in enumerate(live_ranges):
            # print (lr)
            if not lr.uses:
                if n <= 3:
                    assert lr.cpu_reg.no == n
                else:
                    assert lr.cpu_reg is ir.CPU_REG_SPILL, f"unexpected reg {lr}"

        live_ranges = liveness.BblGetLiveRanges(bbl, fun, set(), True)
        live_ranges.sort()
        pool = TestRegPool(MakeGenericCpuRegs(8))
        reg_alloc.RegisterAssignerLinearScanFancy(live_ranges, pool, False)
        for n, lr in enumerate(live_ranges):
            # print (lr)
            assert lr.cpu_reg != ir.CPU_REG_SPILL, f"unexpected reg {lr}"
コード例 #10
0
def Translate(fin):
    unit = serialize.UnitParseFromAsm(fin, cpu_regs=regs.CPU_REGS_MAP)
    for fun in unit.funs:
        ctx = regs.EmitContext(0, 0, 0)
        ctx.scratch_cpu_reg = ir.CPU_REG_INVALID

        ctx.scratch_cpu_reg = ir.CPU_REG_INVALID
        fun.FinalizeStackSlots()
        for bbl in fun.bbls:
            for ins in bbl.inss:
                if "gpr_scratch" in fun.name:
                    ctx.scratch_cpu_reg = regs.CPU_REGS_MAP["rax"]
                print()
                HandleIns(ins, ctx)
コード例 #11
0
def main():
    parser = argparse.ArgumentParser(description='inspector')
    parser.add_argument('-debug', help='enable webserver debugging',
                        action='store_true')
    parser.add_argument('-port', type=int, help='web server port', default=5000)
    parser.add_argument('input', type=str, help='input file')
    args = parser.parse_args()

    opt_stats: Dict[str, int] = collections.defaultdict(int)
    unit = serialize.UnitParseFromAsm(open(args.input))
    MODS.append(RenderCwerg("orig", unit))

    if MODE == "opt":
        optimize.UnitCfgInit(unit)
        MODS.append(RenderCwerg("prepped", unit))
        optimize.UnitOpt(unit, False)
        CleanUnit(unit)
        MODS.append(RenderCwerg("optimized", unit))
        optimize.UnitCfgExit(unit)
        CleanUnit(unit)
        MODS.append(RenderCwerg("final", unit))
    else:
        stats: Dict[str, int] = collections.defaultdict(int)
        codegen.LegalizeAll(unit, stats, None)
        CleanUnit(unit)
        MODS.append(RenderCwerg("legalized", unit))

        codegen.RegAllocGlobal(unit, stats, None)
        CleanUnit(unit)
        MODS.append(RenderCwerg("global_allocated", unit))

        codegen.RegAllocLocal(unit, stats, None)
        CleanUnit(unit)
        MODS.append(RenderCwerg("locals_allocated", unit))

        cpu_unit = codegen.codegen(unit)
        MODS.append(RenderCpu("assembler", cpu_unit))

    http_server = http.server.HTTPServer(('', args.port), MyRequestHandler)
    print(f'Starting HTTP server at http://localhost:{args.port}')
    try:
        http_server.serve_forever()
    except KeyboardInterrupt:
        pass
    print('Stopping HTTP server')
    http_server.server_close()
コード例 #12
0
ファイル: inspector.py プロジェクト: mbrukman/Cwerg
def main():
    parser = argparse.ArgumentParser(description='inspector')
    parser.add_argument('-debug',
                        help='enable webserver debugging',
                        action='store_true')
    parser.add_argument('-port',
                        type=int,
                        help='web server port',
                        default=5000)
    parser.add_argument('input', type=str, help='input file')
    args = parser.parse_args()

    opt_stats: Dict[str, int] = collections.defaultdict(int)
    unit = serialize.UnitParseFromAsm(open(args.input))
    # Note, deepcopy has all kinds of issues and we do not expect
    # to use a copy in further computations
    MODS.append(("orig", copy.deepcopy(unit)))
    if True:
        optimize.UnitCfgInit(unit)
        MODS.append(("prepped", copy.deepcopy(unit)))
        optimize.UnitOpt(unit, False)
        # MODS.append(("optimized", copy.deepcopy(unit)))
        # optimize.UnitCfgExit(unit)
        # MODS.append(("final", copy.deepcopy(unit)))
    else:
        stats: Dict[str, int] = collections.defaultdict(int)
        codegen.optimize_all(unit, stats)
        MODS.append(("optimized", copy.deepcopy(unit)))

        codegen.legalize_all(unit, stats)
        MODS.append(("legalized", copy.deepcopy(unit)))

        codegen.reg_alloc_all(unit, stats)
        MODS.append(("reg_allocated", copy.deepcopy(unit)))

        arm_mod = codegen.codegen(unit)
        MODS.append(("assembler", arm_mod))

    http_server = http.server.HTTPServer(('', args.port), MyRequestHandler)
    print(f'Starting HTTP server at http://localhost:{args.port}')
    try:
        http_server.serve_forever()
    except KeyboardInterrupt:
        pass
    print('Stopping HTTP server')
    http_server.server_close()
コード例 #13
0
ファイル: reg_alloc_test.py プロジェクト: LOpSSH/Cwerg
    def testSimple(self):

        code = io.StringIO(r"""
.fun main NORMAL [U32 U32 U32 U32] = [U32 U32 U32 U32]

.bbl start
    poparg w:U32 
    poparg x:U32 
    poparg y:U32 
    poparg z:U32 
    
    pusharg z
    pusharg y
    pusharg x
    pusharg w
    ret
        """)

        unit = serialize.UnitParseFromAsm(code, False)
        fun = unit.fun_syms["main"]
        bbl = fun.bbls[0]

        DumpBbl(bbl)

        live_ranges = BblGetLiveRanges(bbl, fun, {}, True)
        live_ranges.sort()

        pool = TestRegPool(MakeGenericCpuRegs(4))
        reg_alloc.RegisterAssignerLinearScan(live_ranges, pool)
        for n, lr in enumerate(live_ranges):
            # print (lr)
            if not lr.uses:
                assert lr.cpu_reg.no == n, f"unexpected reg {lr}"

        live_ranges = BblGetLiveRanges(bbl, fun, {}, True)
        live_ranges.sort()
        pool = TestRegPool(MakeGenericCpuRegs(3))
        reg_alloc.RegisterAssignerLinearScan(live_ranges, pool)
        for n, lr in enumerate(live_ranges):
            # print (lr)
            if not lr.uses:
                if n <= 2:
                    assert lr.cpu_reg.no == n
                else:
                    assert lr.cpu_reg == ir.CPU_REG_SPILL, f"unexpected reg {lr}"
コード例 #14
0
    def testC(self):
        code = io.StringIO(r"""
.fun main NORMAL [S32] = []
.bbl %start
    mov %out:S32 3
    bra next
.bbl next
    pusharg %out
    ret
""")
        unit = serialize.UnitParseFromAsm(code)
        fun = unit.fun_syms["main"]
        optimize.FunCfgInit(fun, unit)
        liveness.FunComputeLivenessInfo(fun)
        # print ("@@@@\n", "\n".join(serialize.FunRenderToAsm(fun)))
        liveness.FunRemoveUselessInstructions(fun)
        # print ("@@@@\n", "\n".join(serialize.FunRenderToAsm(fun)))
        self.assertEqual(1, len(fun.bbls[0].inss))
        self.assertEqual(2, len(fun.bbls[1].inss))
コード例 #15
0
    def testE(self):
        code = io.StringIO(r"""


.fun test NORMAL [F32 F32 F32 F32] = [F32 F32]
.reg F32 [a b add sub mul div  $s0_F32  $s1_F32  $s2_F32  $s3_F32]
.bbl start
    mov a $s0_F32@s0
    mov b $s1_F32@s1
    add add a b
    sub sub a b
    mul mul a b
    div div a b
    mov $s3_F32@s3 div
    mov $s2_F32@s2 mul
    mov $s1_F32@s1 sub
    mov $s0_F32@s0 add
    ret
""")
        cpu_regs = {
            "s0": ir.CpuReg("s0", 0),
            "s1": ir.CpuReg("s1", 1),
            "s2": ir.CpuReg("s2", 2),
            "s3": ir.CpuReg("s3", 2)
        }
        unit = serialize.UnitParseFromAsm(code, cpu_regs=cpu_regs)
        fun = unit.fun_syms["test"]
        fun.cpu_live_out = {
            cpu_regs["s0"], cpu_regs["s1"], cpu_regs["s2"], cpu_regs["s3"]
        }
        fun.cpu_live_in = {cpu_regs["s0"], cpu_regs["s1"]}
        cfg.FunSplitBblsAtTerminators(fun)
        cfg.FunInitCFG(fun)
        cfg.FunRemoveUnconditionalBranches(fun)
        cfg.FunRemoveEmptyBbls(fun)
        liveness.FunComputeLivenessInfo(fun)
        ranges = liveness.BblGetLiveRanges(fun.bbls[0], fun,
                                           fun.bbls[0].live_out)
        ranges.sort()
        print("TestE")
        for lr in ranges:
            print(lr)
コード例 #16
0
    def testD(self):
        code = io.StringIO(r"""
.fun arm_syscall_write SIGNATURE [S32] = [S32 A32 U32]

.fun putchar NORMAL [] = [U32]

.fun writeln NORMAL [] = [A32 U32]
# live_out: ['r0', 'r1']
.reg S32 [$r0_S32 dummy]
.reg U32 [$r0_U32 $r1_U32 $r2_U32 len]
.reg A32 [$r0_A32 $r1_A32 buf]
.bbl start
    mov buf $r0_A32@r0                     # 0
    mov len $r1_U32@r1                     # 1
    mov $r2_U32@r2 len                     # 2
    mov $r1_A32@r1 buf                     # 3
    mov $r0_S32@r0 1                       # 4
    syscall arm_syscall_write 4:U32        # 5
    mov dummy $r0_S32@r0                   # 6
    mov $r0_U32@r0 10                      # 7
    bsr putchar                            # 8
    ret                                    # 9
""")
        cpu_regs = {
            "r0": ir.CpuReg("r0", 0),
            "r1": ir.CpuReg("r1", 1),
            "r2": ir.CpuReg("r2", 2)
        }
        unit = serialize.UnitParseFromAsm(code, cpu_regs=cpu_regs)

        fun = unit.fun_syms["arm_syscall_write"]
        fun.cpu_live_out = {cpu_regs["r0"]}
        fun.cpu_live_in = {cpu_regs["r0"], cpu_regs["r1"], cpu_regs["r2"]}

        fun = unit.fun_syms["putchar"]
        fun.cpu_live_in = {cpu_regs["r0"]}

        fun = unit.fun_syms["writeln"]
        cfg.FunSplitBblsAtTerminators(fun)
        cfg.FunInitCFG(fun)
        cfg.FunRemoveUnconditionalBranches(fun)
        cfg.FunRemoveEmptyBbls(fun)
        liveness.FunComputeLivenessInfo(fun)
        ranges = liveness.BblGetLiveRanges(fun.bbls[0], fun,
                                           fun.bbls[0].live_out)
        ranges.sort()
        print("TestD")
        for lr in ranges:
            print(lr)

        lr_r0 = liveness.LiveRange(liveness.BEFORE_BBL, 0,
                                   fun.reg_syms["$r0_A32"], 1)
        lr_r1 = liveness.LiveRange(liveness.BEFORE_BBL, 1,
                                   fun.reg_syms["$r1_U32"], 1)
        lr_buf = liveness.LiveRange(0, 3, fun.reg_syms["buf"], 1)
        lr_len = liveness.LiveRange(1, 2, fun.reg_syms["len"], 1)
        lr_r0_2 = liveness.LiveRange(5, 6, fun.reg_syms["$r0_S32"], 1)

        expected = [
            lr_r0,
            lr_r1,
            liveness.LiveRange(0,
                               0,
                               reg=ir.REG_INVALID,
                               num_uses=1,
                               uses=[lr_r0]),
            lr_buf,
            liveness.LiveRange(1,
                               1,
                               reg=ir.REG_INVALID,
                               num_uses=1,
                               uses=[lr_r1]),
            lr_len,
            liveness.LiveRange(2,
                               2,
                               reg=ir.REG_INVALID,
                               num_uses=1,
                               uses=[lr_len]),
            liveness.LiveRange(2, 5, fun.reg_syms["$r2_U32"], 0),
            liveness.LiveRange(3,
                               3,
                               reg=ir.REG_INVALID,
                               num_uses=1,
                               uses=[lr_buf]),
            liveness.LiveRange(3, 5, fun.reg_syms["$r1_A32"], 0),
            liveness.LiveRange(4, 5, fun.reg_syms["$r0_S32"], 0),
            lr_r0_2,
            liveness.LiveRange(6,
                               6,
                               reg=ir.REG_INVALID,
                               num_uses=1,
                               uses=[lr_r0_2]),
            liveness.LiveRange(6, liveness.NO_USE, fun.reg_syms["dummy"], 0),
            liveness.LiveRange(7, 8, fun.reg_syms["$r0_U32"], 0),
        ]
        # self.assertSequenceEqual(ranges, expected) # this does not work because of the uses field
        self.assertEqual(len(ranges), len(expected))
        for a, b in zip():
            self.assertEqual(a, b)
コード例 #17
0
ファイル: reaching_defs_test.py プロジェクト: mbrukman/Cwerg
    def testBaseRegPropagation1(self):
        code = io.StringIO(r"""
 .mem COUNTER 4 RW
 .data 4 [0]

.fun foo NORMAL [] = []
    .stk array 4 4000
    .reg S32 [x]
    .reg U32 [y] 
    .reg A32 [counter] 

.bbl start
    lea.mem counter = COUNTER 0
    ld x = counter 0
    add x = x 1
    st counter 0 = x

    lea.mem counter = COUNTER 100
    ld x = counter 100
    add x = x 1
    st counter 300 = x

    mov y 666
    lea.mem counter = COUNTER 0
    ld x = counter y
    add x = x 1
    st counter y = x

    lea.stk counter = array 0
    ld x = counter 0
    add x = x 1
    st counter 0 = x

    lea.stk counter = array 100
    ld x = counter 100
    add x = x 1
    st counter 300 = x

    mov y 666
    lea.stk counter = array 0
    ld x = counter y
    add x = x 1
    st counter y = x

    ret
         """)

        unit = serialize.UnitParseFromAsm(code, False)
        fun = unit.fun_syms["foo"]
        bbl = fun.bbls[0]

        cfg.FunInitCFG(fun)
        liveness.FunComputeLivenessInfo(fun)
        reaching_defs.FunComputeReachingDefs(fun)
        reaching_defs.FunPropagateConsts(fun)
        # reaching_defs.FunConstantFold(fun, True)
        reaching_defs.FunLoadStoreSimplify(fun)

        liveness.FunRemoveUselessInstructions(fun)
        print("\n".join(serialize.FunRenderToAsm(fun)))
        # all ld/st were re-written
        for ins in bbl.inss:
            self.assertIn(
                ins.opcode.name,
                {"ret", "add", "ld.mem", "st.mem", "ld.stk", "st.stk"})
コード例 #18
0
    def testA(self):

        code = io.StringIO(r"""
.fun printf_u BUILTIN [] = [A32 U32]

.fun multi BUILTIN [U32 U32 U32 U32 U32] = [U32 U32]

.mem fmt 4 RO
.data 1 "%d\n\0"

.fun main NORMAL [S32] = []
.reg U32 [a s m d M x y out]
.reg A64 [f] 

.bbl start
    mov x = 70
    mov y = 6

    pusharg y
    pusharg x
    bsr multi
    poparg a
    poparg s
    poparg m
    poparg d
    poparg M

    lea.mem f = fmt 0
    pusharg a
    pusharg f
    bsr printf_u

    pusharg s
    pusharg f
    bsr printf_u

    pusharg m
    pusharg f
    bsr printf_u

    pusharg d
    pusharg f
    bsr printf_u

    pusharg M
    pusharg f
    bsr printf_u

    mov out = 0
    pusharg out
    ret
        """)

        unit = serialize.UnitParseFromAsm(code, False)
        fun = unit.fun_syms["main"]
        bbl = fun.bbls[0]

        x = fun.reg_syms["x"]
        y = fun.reg_syms["y"]
        a = fun.reg_syms["a"]
        s = fun.reg_syms["s"]
        m = fun.reg_syms["m"]
        d = fun.reg_syms["d"]
        M = fun.reg_syms["M"]
        out = fun.reg_syms["out"]
        f = fun.reg_syms["f"]

        DumpBbl(bbl)
        live_ranges = liveness.BblGetLiveRanges(bbl, fun, bbl.live_out, False)
        live_ranges.sort()
        lr_cross_bbl = [lr for lr in live_ranges if lr.is_cross_bbl()]
        lr_lac = [lr for lr in live_ranges if liveness.LiveRangeFlag.LAC in lr.flags]

        assert len(live_ranges) == 9, f"{live_ranges}"
        assert len(lr_cross_bbl) == 0, f"{lr_cross_bbl}"
        assert len(lr_lac) == 5, f"{lr_lac}"
        for lr in live_ranges:
            print("checking LR lac:", lr)
            # assert lr.lac == lr.reg in {M, d, f, m, s}, f"LR {lr}"
            self.assertNotEqual(lr.def_pos, lr.last_use_pos)
            self.assertEqual(liveness.LiveRangeFlag.LAC in lr.flags, lr.reg in {M, d, f, m, s})