Example #1
0
    def test_inline2(self):
        harder = textwrap.dedent("""
        int callee(int i) {
            (void) print(i);
            while (i < 10) {
                i = i + 1;
                return i * 2;
            }
            return i;
        }

        int caller() {
            int x = 4;
            while (x < 10) {
                (void) print(x);
                x = call(callee, list(x));
            }
            return x;
        }
        """)
        mod = from_c(harder)
        func = mod.get_function("caller")
        verify(func)
        result = interp.run(func)

        [callsite] = findallops(func, 'call')
        inline.inline(func, callsite)
        cfa.run(func)
        verify(func)

        # TODO: update phi when splitting blocks
        result2 = interp.run(func)
        assert result == result2
Example #2
0
    def test_inline2(self):
        harder = """
        int callee(int i) {
            (void) print(i);
            while (i < 10) {
                i = i + 1;
                return i * 2;
            }
            return i;
        }

        int caller() {
            int x = 4;
            while (x < 10) {
                (void) print(x);
                x = call(callee, list(x));
            }
            return x;
        }
        """
        mod = from_c(harder)
        func = mod.get_function("caller")
        verify(func)
        result = interp.run(func)

        [callsite] = findallops(func, 'call')
        inline.inline(func, callsite)
        cfa.run(func)
        verify(func)
Example #3
0
    def test_inline2(self):
        harder = textwrap.dedent("""
        int callee(int i) {
            (void) print(i);
            while (i < 10) {
                i = i + 1;
                return i * 2;
            }
            return i;
        }

        int caller() {
            int x = 4;
            while (x < 10) {
                (void) print(x);
                x = call(callee, list(x));
            }
            return x;
        }
        """)
        mod = from_c(harder)
        func = mod.get_function("caller")
        verify(func)
        result = interp.run(func)

        [callsite] = findallops(func, 'call')
        inline.inline(func, callsite)
        cfa.run(func)
        verify(func)
Example #4
0
def rewrite_return(func):
    """Rewrite ret ops to assign to a variable instead, which is returned"""
    ret_normalization.run(func)
    [ret] = findallops(func, 'ret')
    [value] = ret.args
    ret.delete()
    return value
Example #5
0
def rewrite_return(func):
    """Rewrite ret ops to assign to a variable instead, which is returned"""
    ret_normalization.run(func)
    [ret] = findallops(func, 'ret')
    [value] = ret.args
    ret.delete()
    return value
Example #6
0
def find_handler(setup_handlers, exc_model, exc):
    for exc_setup in setup_handlers:
        [handler_blocks] = exc_setup.args
        for block in handler_blocks:
            for op in findallops(block.leaders, 'exc_catch'):
                [exc_types] = op.args
                if any(exc_model.exc_op_match(exc_type, exc)
                           for exc_type in exc_types):
                    return op.block
Example #7
0
def run(func, env, exc_model=interp.ExceptionModel()):
    b = OpBuilder()
    for op in func.ops:
        if op.opcode != 'exc_throw':
            continue
        [exc] = op.args
        if not isinstance(exc, Const):
            continue

        setup_handlers = findallops(op.block.leaders, 'exc_setup')
        handler = find_handler(setup_handlers, exc_model, exc.const)
        if handler:
            op.replace(b.jump(handler, result=op.result))
Example #8
0
def rewrite_exceptions(func, env, exc_model=interp.ExceptionModel()):
    """
    Rewrite exc_throw(exc) -> jump(handler_block) for statically determined
    exceptions.

    TODO: Can this be optimized instead after lowering to a zero-cost or
          costful model?
    """
    b = OpBuilder()
    for op in func.ops:
        if op.opcode != 'exc_throw':
            continue
        [exc] = op.args
        setup_handlers = findallops(op.block.leaders, 'exc_setup')
        handler = find_handler(setup_handlers, exc_model, exc)
        if handler:
            op.replace(b.jump(handler, result=op.result))
Example #9
0
def _verify_function(func):
    """Verify a pykit function"""
    # Verify arguments
    assert len(func.args) == len(func.type.argtypes)

    # Verify return presence and type
    restype = func.type.restype
    if not restype.is_void and not restype.is_opaque:
        rets = findallops(func, 'ret')
        for ret in rets:
            arg, = ret.args
            assert arg.type == restype, (arg.type, restype)

    verify_uniqueness(func)
    verify_block_order(func)
    verify_operations(func)
    verify_uses(func)
    verify_semantics(func)
Example #10
0
    def test_inline(self):
        simple = """
        #include <pykit_ir.h>

        int callee(int i) {
            return i * i;
        }

        int caller(int i) {
            int x = call(callee, list(i));
            return x;
        }
        """
        mod = from_c(simple)
        func = mod.get_function("caller")
        [callsite] = findallops(func, 'call')
        inline.inline(func, callsite)
        cfa.run(func)
        verify(func)
        assert interp.run(func, args=[10]) == 100
        assert len(list(func.blocks)) == 1
        assert opcodes(func) == ['mul', 'ret']
Example #11
0
    def test_inline(self):
        simple = textwrap.dedent("""
        #include <pykit_ir.h>

        int callee(int i) {
            return i * i;
        }

        int caller(int i) {
            int x = call(callee, list(i));
            return x;
        }
        """)
        mod = from_c(simple)
        func = mod.get_function("caller")
        [callsite] = findallops(func, 'call')
        inline.inline(func, callsite)
        cfa.run(func)
        verify(func)
        assert interp.run(func, args=[10]) == 100
        assert len(list(func.blocks)) == 1
        assert opcodes(func) == ['mul', 'ret']
Example #12
0
    def test_inline(self):
        simple = textwrap.dedent("""
        #include <pykit_ir.h>

        int callee(int i) {
            return i * i;
        }

        int caller(int i) {
            int x = call(callee, list(i));
            return x;
        }
        """)
        mod = from_c(simple)
        func = mod.get_function("caller")
        [callsite] = findallops(func, 'call')
        inline.inline(func, callsite)
        cfa.run(func)
        verify(func)
        assert interp.run(func, args=[10]) == 100
        assert len(list(func.blocks)) == 1
        self.assertEqual([o for o in opcodes(func) if o != 'convert'],
                         ['mul', 'ret'])
Example #13
0
def assert_inlinable(func, call, callee, uses):
    """
    Verify that a function call can be inlined.

    We can inline generators if they are consumed in a single loop:

        - iter(g) must be in a loop header
        - next(g) must be in the loop body

    :return: None if inlineable, or an exception with a message
    """
    if not isinstance(callee, Function):
        return CompileError("Cannot inline external function: %s" % (callee,))

    yields = findallops(callee, 'yield')
    if yields:
        for use in uses[call]:
            if use.opcode not in ('iter', 'next'):
                return CompileError(
                    "Cannot inline generator with use %s" % (use,))

        if len(uses[call]) != 2:
            return CompileError("Can only")
        loops = loop_detection.find_natural_loops(func)