def test_bug2(self): """ Check that if blocks are in function in strange order, the dag builder works """ module = ir.Module('dut') function = ir.Procedure('tst', ir.Binding.GLOBAL) module.add_function(function) block1 = ir.Block('b1') block2 = ir.Block('b2') function.add_block(block1) function.add_block(block2) function.entry = block2 con = ir.Const(2, 'con', ir.i32) block2.add_instruction(con) block2.add_instruction(ir.Jump(block1)) block1.add_instruction(ir.Cast(con, 'con_cast', ir.i8)) block1.add_instruction(ir.Exit()) # Target generation target = get_arch('arm') frame = target.new_frame('a', function) function_info = FunctionInfo(frame) debug_db = DebugDb() prepare_function_info(target, function_info, function) dag_builder = SelectionGraphBuilder(target) sgraph = dag_builder.build(function, function_info, debug_db) dag_splitter = DagSplitter(target)
def test_normal_use(self): alloc = self.builder.emit(ir.Alloc('A', 4, 4)) addr = self.builder.emit(ir.AddressOf(alloc, 'addr')) cnst = self.builder.emit(ir.Const(1, 'cnst', ir.i32)) self.builder.emit(ir.Store(cnst, addr)) self.builder.emit(ir.Load(addr, 'Ld', ir.i32)) self.builder.emit(ir.Exit()) self.mem2reg.run(self.module) self.assertNotIn(alloc, self.function.entry.instructions)
def test_store_uses_alloc_as_value(self): """ When only stores and loads use the alloc, the store can use the alloc as a value. In this case, the store must remain """ alloc = self.builder.emit(ir.Alloc('A', 4, 4)) addr = self.builder.emit(ir.AddressOf(alloc, 'addr')) self.builder.emit(ir.Store(addr, addr)) self.builder.emit(ir.Exit()) self.mem2reg.run(self.module) self.assertIn(alloc, self.function.entry.instructions)
def test_byte_lift(self): """ Test byte data type to work """ alloc = self.builder.emit(ir.Alloc('A', 1, 1)) addr = self.builder.emit(ir.AddressOf(alloc, 'addr')) cnst = self.builder.emit(ir.Const(1, 'cnst', ir.i8)) self.builder.emit(ir.Store(cnst, addr)) self.builder.emit(ir.Load(addr, 'Ld', ir.i8)) self.builder.emit(ir.Exit()) self.mem2reg.run(self.module) self.assertNotIn(alloc, self.function.entry.instructions)
def test_different_type_not_lifted(self): """ different types must persist """ alloc = self.builder.emit(ir.Alloc('A', 1, 1)) addr = self.builder.emit(ir.AddressOf(alloc, 'addr')) cnst = self.builder.emit(ir.Const(1, 'cnst', ir.i32)) self.builder.emit(ir.Store(cnst, addr)) self.builder.emit(ir.Load(addr, 'Ld', ir.i8)) self.builder.emit(ir.Exit()) self.mem2reg.run(self.module) self.assertIn(alloc, self.function.entry.instructions)
def gen_function(self, name): function = self.builder.new_procedure(name) self.builder.set_function(function) first_block = self.builder.new_block() function.entry = first_block self.builder.set_block(first_block) for i in range(random.randrange(10, 80)): self.gen_ins(i) self.builder.emit(ir.Exit())
def test_builder(self): f = self.b.new_procedure("add", ir.Binding.GLOBAL) self.b.set_function(f) entry = self.b.new_block() f.entry = entry self.b.set_block(entry) bb = self.b.new_block() self.b.emit(ir.Jump(bb)) self.b.set_block(bb) self.b.emit(ir.Const(0, "const", ir.i32)) self.b.emit(ir.Exit())
def test_builder(self): f = self.b.new_procedure("test", ir.Binding.GLOBAL) self.b.set_function(f) entry = self.b.new_block() f.entry = entry self.b.set_block(entry) bb = self.b.new_block() self.b.emit(ir.Jump(bb)) self.b.set_block(bb) v1 = self.b.emit(ir.Const(5, "const", ir.i32)) v2 = self.b.emit(ir.Const(7, "const", ir.i32)) self.b.emit(ir.add(v1, v2, "add", ir.i32)) self.b.emit(ir.Exit()) self.cf.run(self.m)
def test_write(self): module = ir.Module("mod1") function = ir.Procedure("func1", ir.Binding.GLOBAL) module.add_function(function) entry = ir.Block("entry") function.add_block(entry) function.entry = entry entry.add_instruction(ir.Exit()) f = io.StringIO() writer = irutils.Writer(file=f) writer.write(module) # print(f.getvalue()) f2 = io.StringIO(f.getvalue()) reader = irutils.Reader() module2 = reader.read(f2) f3 = io.StringIO() writer = irutils.Writer(file=f3) writer.write(module2) self.assertEqual(f3.getvalue(), f.getvalue())
def parse(): woot = metamodel_from_file('say.tx') model = woot.model_from_file('test.say') module = ir.Module('main') func = ir.Procedure('main') module.add_function(func) block = ir.Block('entry') func.add_block(block) func.entry = block for statement in model.statements: text = statement.text data = struct.pack('<i', len(text)) + text.encode('ascii') text_val = ir.LiteralData(data, 'text') block.add_instruction(text_val) block.add_instruction(ir.ProcedureCall('crt_print', [text_val])) block.add_instruction(ir.Exit()) return module
def compile(self, filename): self.variables = {} # Prepare the module ir_module = ir.Module('toy') self.io_print2 = ir.ExternalProcedure('io_print2', [ir.ptr, self.int_type]) ir_module.add_external(self.io_print2) ir_function = ir.Procedure('toy_toy', ir.Binding.GLOBAL) ir_module.add_function(ir_function) self.ir_block = ir.Block('entry') ir_function.entry = self.ir_block ir_function.add_block(self.ir_block) # Load the program: self.toy_mm.model_from_file(filename) # close the procedure self.emit(ir.Exit()) verify_module(ir_module) return ir_module
def test_bug1(self): """ This is the bug: function XXX sleep(i32 ms) entry: JUMP block12 block12: i32 loaded = load global_tick i32 binop = loaded + ms JUMP block14 block14: i32 loaded_2 = load global_tick IF binop > loaded_2 THEN block14 ELSE epilog epilog: exit Selection graph for function XXX sleep(i32 ms) entry: MOVI32[vreg0ms](REGI32[R1]) JMP[bsp_sleep_block12:] block12: MOVI32[vreg1loaded](LDRI32(LABEL[bsp_global_tick])) JMP[bsp_sleep_block14:] block14: MOVI32[vreg4loaded_2](LDRI32(LABEL[bsp_global_tick])) CJMP[('>', bsp_sleep_block14:, bsp_sleep_epilog:)] (REGI32[vreg5binop], REGI32[vreg4loaded_2]) epilog: """ builder = Builder() module = ir.Module('fuzz') global_tick = ir.Variable('global_tick', ir.Binding.GLOBAL, 4, 4) module.add_variable(global_tick) builder.module = module function = builder.new_procedure('sleep', ir.Binding.GLOBAL) ms = ir.Parameter('ms', ir.i32) function.add_parameter(ms) builder.set_function(function) entry = builder.new_block() function.entry = entry builder.set_block(entry) block12 = builder.new_block() builder.emit(ir.Jump(block12)) builder.set_block(block12) loaded = builder.emit(ir.Load(global_tick, 'loaded', ir.i32)) binop = builder.emit(ir.Binop(loaded, '+', ms, 'binop', ir.i32)) block14 = builder.new_block() builder.emit(ir.Jump(block14)) builder.set_block(block14) loaded2 = builder.emit(ir.Load(global_tick, 'loaded2', ir.i32)) epilog = builder.new_block() builder.emit(ir.CJump(binop, '>', loaded2, block14, epilog)) builder.set_block(epilog) builder.emit(ir.Exit()) # print('module:') # print_module(module) # Target generation target = ExampleArch() frame = target.new_frame('a', function) function_info = FunctionInfo(frame) debug_db = DebugDb() prepare_function_info(target, function_info, function) dag_builder = SelectionGraphBuilder(target) sgraph = dag_builder.build(function, function_info, debug_db) dag_splitter = DagSplitter(target) # print(function_info.value_map) for b in function: # root = function_info.block_roots[b] #print('root=', root) #for tree in dag_splitter.split_into_trees(root, frame): # print('tree=', tree) pass
def test_glue_blocks(self): epilog = self.builder.new_block() self.builder.emit(ir.Jump(epilog)) self.builder.set_block(epilog) self.builder.emit(ir.Exit())