Пример #1
0
class TestBuilder(unittest.TestCase):

    def setUp(self):
        self.f = Function("testfunc", ['a'],
                          types.Function(types.Float32, [types.Int32]))
        self.b = Builder(self.f)
        self.b.position_at_end(self.f.add_block('entry'))
        self.a = self.f.get_arg('a')

    def test_basic_builder(self):
        v = self.b.alloca(types.Pointer(types.Float32), [])
        result = self.b.mul(types.Int32, [self.a, self.a], result='r')
        c = self.b.convert(types.Float32, [result])
        self.b.store(c, v)
        val = self.b.load(types.Float32, [v])
        self.b.ret(val)
        # print(string(self.f))
        self.assertEqual(str(self.f).strip(), basic_expected)

    def test_splitblock(self):
        old, new = self.b.splitblock('newblock')
        with self.b.at_front(old):
            self.b.add(types.Int32, [self.a, self.a])
        with self.b.at_end(new):
            self.b.div(types.Int32, [self.a, self.a])
        # print(string(self.f))
        self.assertEqual(split_expected, string(self.f))

    def test_loop_builder(self):
        square = self.b.mul(types.Int32, [self.a, self.a])
        c = self.b.convert(types.Float32, [square])
        self.b.position_after(square)
        _, block = self.b.splitblock('start', terminate=True)
        self.b.position_at_end(block)

        const = partial(Const, type=types.Int32)
        cond, body, exit = self.b.gen_loop(const(5), const(10), const(2))
        with self.b.at_front(body):
            self.b.print_(c)
        with self.b.at_end(exit):
            self.b.ret(c)

        # print(string(self.f))
        # verify.verify(self.f)
        # self.assertEqual(loop_expected, string(self.f))

# TestBuilder('test_basic_builder').debug()
# TestBuilder('test_splitblock').debug()
# TestBuilder('test_loop_builder').debug()
# unittest.main()
Пример #2
0
class TestBuilder(unittest.TestCase):
    def setUp(self):
        self.f = Function("testfunc", ['a'],
                          types.Function(types.Float32, [types.Int32]))
        self.b = Builder(self.f)
        self.b.position_at_end(self.f.add_block('entry'))
        self.a = self.f.get_arg('a')

    def test_basic_builder(self):
        v = self.b.alloca(types.Pointer(types.Float32), [])
        result = self.b.mul(types.Int32, [self.a, self.a], result='r')
        c = self.b.convert(types.Float32, [result])
        self.b.store(c, v)
        val = self.b.load(types.Float32, [v])
        self.b.ret(val)
        # print(string(self.f))
        self.assertEqual(str(self.f).strip(), basic_expected)

    def test_splitblock(self):
        old, new = self.b.splitblock('newblock')
        with self.b.at_front(old):
            self.b.add(types.Int32, [self.a, self.a])
        with self.b.at_end(new):
            self.b.div(types.Int32, [self.a, self.a])
        # print(string(self.f))
        self.assertEqual(split_expected, string(self.f))

    def test_loop_builder(self):
        square = self.b.mul(types.Int32, [self.a, self.a])
        c = self.b.convert(types.Float32, [square])
        self.b.position_after(square)
        _, block = self.b.splitblock('start', terminate=True)
        self.b.position_at_end(block)

        const = partial(Const, type=types.Int32)
        cond, body, exit = self.b.gen_loop(const(5), const(10), const(2))
        with self.b.at_front(body):
            self.b.print_(c)
        with self.b.at_end(exit):
            self.b.ret(c)

        # print(string(self.f))
        # verify.verify(self.f)
        # self.assertEqual(loop_expected, string(self.f))


# TestBuilder('test_basic_builder').debug()
# TestBuilder('test_splitblock').debug()
# TestBuilder('test_loop_builder').debug()
# unittest.main()
Пример #3
0
def run(func, env=None, return_block=None):
    """
    Rewrite 'ret' operations into jumps to a return block and assignments
    to a return variable.
    """
    b = Builder(func)
    return_block = return_block or func.new_block("pykit.return")

    # Allocate return variable
    if not func.type.restype.is_void:
        with b.at_front(func.startblock):
            return_var = b.alloca(types.Pointer(func.type.restype), [])
            b.store(Undef(func.type.restype), return_var)
    else:
        return_var = None

    # Repace 'ret' instructions with jumps and assignments
    for op in func.ops:
        if op.opcode == "ret":
            b.position_after(op)
            if return_var:
                b.store(op.args[0], return_var)
            b.jump(return_block)
            op.delete()

    with b.at_end(return_block):
        if return_var:
            result = b.load(return_var.type.base, [return_var])
        else:
            result = None

        b.ret(result)
Пример #4
0
Файл: ret.py Проект: flypy/pykit
def run(func, env=None, return_block=None):
    """
    Rewrite 'ret' operations into jumps to a return block and assignments
    to a return variable.
    """
    b = Builder(func)
    return_block = return_block or func.new_block("pykit.return")

    # Allocate return variable
    if not func.type.restype.is_void:
        with b.at_front(func.startblock):
            return_var = b.alloca(types.Pointer(func.type.restype))
            b.store(Undef(func.type.restype), return_var)
    else:
        return_var = None

    # Repace 'ret' instructions with jumps and assignments
    for op in func.ops:
        if op.opcode == "ret":
            b.position_after(op)
            if return_var:
                b.store(op.args[0], return_var)
            b.jump(return_block)
            op.delete()

    with b.at_end(return_block):
        if return_var:
            result = b.load(return_var)
        else:
            result = None

        b.ret(result)
Пример #5
0
class TestBuilder(unittest.TestCase):

    def setUp(self):
        self.f = Function("testfunc", ['a'],
                          types.Function(types.Float32, [types.Int32]))
        self.b = Builder(self.f)
        self.b.position_at_end(self.f.new_block('entry'))
        self.a = self.f.get_arg('a')

    def test_basic_builder(self):
        v = self.b.alloca(types.Pointer(types.Float32), [])
        result = self.b.mul(types.Int32, [self.a, self.a], result='r')
        c = self.b.convert(types.Float32, [result])
        self.b.store(c, v)
        val = self.b.load(types.Float32, [v])
        self.b.ret(val)
        # print(string(self.f))
        assert interp.run(self.f, args=[10]) == 100

    def test_splitblock(self):
        old, new = self.b.splitblock('newblock')
        with self.b.at_front(old):
            self.b.add(types.Int32, [self.a, self.a])
        with self.b.at_end(new):
            self.b.div(types.Int32, [self.a, self.a])
        self.assertEqual(opcodes(self.f), ['add', 'div'])

    def test_loop_builder(self):
        square = self.b.mul(types.Int32, [self.a, self.a])
        c = self.b.convert(types.Float32, [square])
        self.b.position_after(square)
        _, block = self.b.splitblock('start', terminate=True)
        self.b.position_at_end(block)

        const = partial(Const, type=types.Int32)
        cond, body, exit = self.b.gen_loop(const(5), const(10), const(2))
        with self.b.at_front(body):
            self.b.print(c)
        with self.b.at_end(exit):
            self.b.ret(c)

        self.assertEqual(interp.run(self.f, args=[10]), 100.0)
Пример #6
0
def move_generator(func, consumer, empty_body):
    gen = consumer.generator
    gen.unlink()

    b = Builder(func)
    b.position_at_end(empty_body)
    b.emit(gen)

    with b.at_end(empty_body):
        loop_exit = determine_loop_exit(consumer.loop)
        b.jump(loop_exit)
Пример #7
0
def move_generator(func, consumer, empty_body):
    gen = consumer.generator
    gen.unlink()

    b = Builder(func)
    b.position_at_end(empty_body)
    b.emit(gen)

    with b.at_end(empty_body):
        loop_exit = determine_loop_exit(consumer.loop)
        b.jump(loop_exit)
Пример #8
0
def inline(func, call):
    """
    Inline the call instruction into func.

    :return: { old_op : new_op }
    """
    callee = call.args[0]
    callblock = call.block
    # assert_inlinable(func, call, callee, uses)

    builder = Builder(func)
    builder.position_before(call)
    inline_header, inline_exit = builder.splitblock()
    new_callee, valuemap = copy_function(callee, temper=func.temp)
    result = rewrite_return(new_callee)

    # Fix up arguments
    for funcarg, arg in zip(new_callee.args, call.args[1]):
        funcarg.replace_uses(arg)

    # Copy blocks
    new_blocks = list(new_callee.blocks)
    after = inline_header
    for block in new_blocks:
        block.parent = None
        func.add_block(block, after=after)
        after = block

    # Fix up wiring
    builder.jump(new_callee.startblock)
    with builder.at_end(new_callee.exitblock):
        builder.jump(inline_exit)

    stretch_exception_block(builder, callblock, new_blocks)

    # Fix up final result of call
    if result is not None:
        # non-void return
        result.unlink()
        result.result = call.result
        call.replace(result)
    else:
        call.delete()

    func.reset_uses()
    #verify(func)

    return valuemap
Пример #9
0
def inline(func, call, uses=None):
    """
    Inline the call instruction into func.

    :param uses: defuse information
    """
    callee = call.args[0]
    # assert_inlinable(func, call, callee, uses)

    builder = Builder(func)
    builder.position_before(call)
    inline_header, inline_exit = builder.splitblock()
    new_callee = copy_function(callee, temper=func.temp)
    result = rewrite_return(new_callee)

    # Fix up arguments
    for funcarg, arg in zip(new_callee.args, call.args[1]):
        funcarg.replace_uses(arg)

    # Copy blocks
    after = inline_header
    for block in new_callee.blocks:
        block.parent = None
        func.add_block(block, after=after)
        after = block

    # Fix up wiring
    builder.jump(new_callee.startblock)
    with builder.at_end(new_callee.exitblock):
        builder.jump(inline_exit)

    # Fix up final result of call
    if result is not None:
        # non-void return
        result.unlink()
        result.result = call.result
        call.replace(result)
    else:
        call.delete()

    func.reset_uses()
    verify(func)
Пример #10
0
class TestBuilder(unittest.TestCase):

    def setUp(self):
        self.f = Function("testfunc", ['a'],
                          types.Function(types.Float32, [types.Int32], False))
        self.b = Builder(self.f)
        self.b.position_at_end(self.f.new_block('entry'))
        self.a = self.f.get_arg('a')

    def test_basic_builder(self):
        v = self.b.alloca(types.Pointer(types.Float32))
        result = self.b.mul(self.a, self.a, result='r')
        c = self.b.convert(types.Float32, result)
        self.b.store(c, v)
        val = self.b.load(v)
        self.b.ret(val)
        # print(string(self.f))
        assert interp.run(self.f, args=[10]) == 100

    def test_splitblock(self):
        old, new = self.b.splitblock('newblock')
        with self.b.at_front(old):
            self.b.add(self.a, self.a)
        with self.b.at_end(new):
            self.b.div(self.a, self.a)
        self.assertEqual(opcodes(self.f), ['add', 'div'])

    def test_loop_builder(self):
        square = self.b.mul(self.a, self.a)
        c = self.b.convert(types.Float32, square)
        self.b.position_after(square)
        _, block = self.b.splitblock('start', terminate=True)
        self.b.position_at_end(block)

        const = partial(Const, type=types.Int32)
        cond, body, exit = self.b.gen_loop(const(5), const(10), const(2))
        with self.b.at_front(body):
            self.b.print(c)
        with self.b.at_end(exit):
            self.b.ret(c)

        self.assertEqual(interp.run(self.f, args=[10]), 100.0)

    def test_splitblock_preserve_phis(self):
        """
        block1:
            %0 = mul a a
            jump(newblock)

        newblock:
            %1 = phi([block1], [%0])
            ret %1
        """
        square = self.b.mul(self.a, self.a)
        old, new = self.b.splitblock('newblock', terminate=True)
        with self.b.at_front(new):
            phi = self.b.phi(types.Int32, [self.f.startblock], [square])
            self.b.ret(phi)

        # Now split block1
        self.b.position_after(square)
        block1, split = self.b.splitblock(terminate=True)

        phi, ret = new.ops
        blocks, values = phi.args
        self.assertEqual(blocks, [split])
Пример #11
0
class TestBuilder(unittest.TestCase):
    def setUp(self):
        self.f = Function("testfunc", ['a'],
                          types.Function(types.Float32, [types.Int32], False))
        self.b = Builder(self.f)
        self.b.position_at_end(self.f.new_block('entry'))
        self.a = self.f.get_arg('a')

    def test_basic_builder(self):
        v = self.b.alloca(types.Pointer(types.Float32))
        result = self.b.mul(self.a, self.a, result='r')
        c = self.b.convert(types.Float32, result)
        self.b.store(c, v)
        val = self.b.load(v)
        self.b.ret(val)
        # print(string(self.f))
        assert interp.run(self.f, args=[10]) == 100

    def test_splitblock(self):
        old, new = self.b.splitblock('newblock')
        with self.b.at_front(old):
            self.b.add(self.a, self.a)
        with self.b.at_end(new):
            self.b.div(self.a, self.a)
        self.assertEqual(opcodes(self.f), ['add', 'div'])

    def test_loop_builder(self):
        square = self.b.mul(self.a, self.a)
        c = self.b.convert(types.Float32, square)
        self.b.position_after(square)
        _, block = self.b.splitblock('start', terminate=True)
        self.b.position_at_end(block)

        const = partial(Const, type=types.Int32)
        cond, body, exit = self.b.gen_loop(const(5), const(10), const(2))
        with self.b.at_front(body):
            self.b.print(c)
        with self.b.at_end(exit):
            self.b.ret(c)

        self.assertEqual(interp.run(self.f, args=[10]), 100.0)

    def test_splitblock_preserve_phis(self):
        """
        block1:
            %0 = mul a a
            jump(newblock)

        newblock:
            %1 = phi([block1], [%0])
            ret %1
        """
        square = self.b.mul(self.a, self.a)
        old, new = self.b.splitblock('newblock', terminate=True)
        with self.b.at_front(new):
            phi = self.b.phi(types.Int32, [self.f.startblock], [square])
            self.b.ret(phi)

        # Now split block1
        self.b.position_after(square)
        block1, split = self.b.splitblock(terminate=True)

        phi, ret = new.ops
        blocks, values = phi.args
        self.assertEqual(blocks, [split])