Ejemplo n.º 1
0
    def __call__(self, *args, **kwargs):
        from flypy.representation import byref, stack_allocate
        from flypy.conversion import (toctypes, fromctypes, toobject,
                                      fromobject, ctype)
        #from flypy.support.ctypes_support import CTypesStruct
        #from flypy.types import Function

        # Keep this alive for the duration of the call
        keepalive = list(args) + list(kwargs.values())

        # Order arguments
        args = flatargs(self.py_func, args, kwargs)

        # Translate
        cfunc, restype = self.translate([typeof(x) for x in args.flat])

        # Construct flypy values
        argtypes = [typeof(x) for x in args]
        arg_objs = list(starmap(fromobject, zip(args, argtypes)))

        # Map flypy values to a ctypes representation
        args = []
        for arg, argtype in zip(arg_objs, argtypes):
            c_arg = toctypes(arg, argtype, keepalive)
            if byref(argtype) and stack_allocate(argtype):
                c_arg = ctypes.pointer(c_arg)
            args.append(c_arg)

        # We need this cast since the ctypes function constructed from LLVM
        # IR has different structs (which are structurally equivalent)
        c_restype = ctype(restype)
        if byref(restype):
            c_result = c_restype()  # dummy result value
            args.append(ctypes.pointer(c_result))
            c_restype = None  # void

        c_signature = ctypes.PYFUNCTYPE(c_restype,
                                        *[type(arg) for arg in args])
        cfunc = ctypes.cast(cfunc, c_signature)

        # Handle calling convention
        if byref(restype):
            cfunc(*args)
        else:
            c_result = cfunc(*args)

        # Map ctypes result back to a python value
        result = fromctypes(c_result, restype)
        result_obj = toobject(result, restype)

        return result_obj
Ejemplo n.º 2
0
    def __call__(self, *args, **kwargs):
        from flypy.representation import byref, stack_allocate
        from flypy.conversion import (
            toctypes, fromctypes, toobject, fromobject, ctype)
        #from flypy.support.ctypes_support import CTypesStruct
        #from flypy.types import Function

        # Keep this alive for the duration of the call
        keepalive = list(args) + list(kwargs.values())

        # Order arguments
        args = flatargs(self.py_func, args, kwargs)

        # Translate
        cfunc, restype = self.translate([typeof(x) for x in args.flat])

        # Construct flypy values
        argtypes = [typeof(x) for x in args]
        arg_objs = list(starmap(fromobject, zip(args, argtypes)))

        # Map flypy values to a ctypes representation
        args = []
        for arg, argtype in zip(arg_objs, argtypes):
            c_arg = toctypes(arg, argtype, keepalive)
            if byref(argtype) and stack_allocate(argtype):
                c_arg = ctypes.pointer(c_arg)
            args.append(c_arg)

        # We need this cast since the ctypes function constructed from LLVM
        # IR has different structs (which are structurally equivalent)
        c_restype = ctype(restype)
        if byref(restype):
            c_result = c_restype() # dummy result value
            args.append(ctypes.pointer(c_result))
            c_restype = None # void

        c_signature = ctypes.PYFUNCTYPE(c_restype, *[type(arg) for arg in args])
        cfunc = ctypes.cast(cfunc, c_signature)

        # Handle calling convention
        if byref(restype):
            cfunc(*args)
        else:
            c_result = cfunc(*args)

        # Map ctypes result back to a python value
        result = fromctypes(c_result, restype)
        result_obj = toobject(result, restype)

        return result_obj
Ejemplo n.º 3
0
def rewrite_obj_return(func, env):
    """
    Handle returning stack-allocated objects.
    """
    if should_skip(env):
        return

    context = env['flypy.typing.context']
    restype = env['flypy.typing.restype']
    envs = env['flypy.state.envs']

    builder = Builder(func)

    stack_alloc = representation.byref(restype)

    if stack_alloc:
        out = func.add_arg(func.temp("out"), opaque_t)
        context[out] = Pointer[restype]
        func.type = types.Function(types.Void, func.type.argtypes, False)

    for arg in func.args:
        arg.type = opaque_t
    func.type = types.Function(func.type.restype,
                               (opaque_t, ) * len(func.args), False)

    is_generator = env['flypy.state.generator']
    for op in func.ops:
        if (op.opcode == 'ret' and op.args[0] is not None and stack_alloc
                and not is_generator):
            # ret val =>
            #     store (load val) out ; ret void
            [val] = op.args
            builder.position_before(op)
            newval = builder.load(val)
            builder.store(newval, out)
            op.set_args([None])

            # Update context
            context[newval] = StackVar[context[val]]

        elif op.opcode == 'call' and op.type != types.Void:
            # result = call(f, ...) =>
            #     alloca result ; call(f, ..., &result)
            ty = context[op]
            if conversion.byref(ty):
                f, args = op.args
                if not is_flypy_cc(f) or should_skip(envs[f]):
                    continue

                builder.position_before(op)
                retval = builder.alloca(opaque_t)
                builder.position_after(op)
                op.replace_uses(retval)

                newargs = args + [retval]
                op.set_args([f, newargs])

                # Update context
                context[retval] = context[op]
                context[op] = void
Ejemplo n.º 4
0
def rewrite_obj_return(func, env):
    """
    Handle returning stack-allocated objects.
    """
    if should_skip(env):
        return

    context = env['flypy.typing.context']
    restype = env['flypy.typing.restype']
    envs =  env['flypy.state.envs']

    builder = Builder(func)

    stack_alloc = representation.byref(restype)

    if stack_alloc:
        out = func.add_arg(func.temp("out"), opaque_t)
        context[out] = Pointer[restype]
        func.type = types.Function(types.Void, func.type.argtypes, False)

    for arg in func.args:
        arg.type = opaque_t
    func.type = types.Function(func.type.restype, (opaque_t,) * len(func.args),
                               False)

    is_generator = env['flypy.state.generator']
    for op in func.ops:
        if (op.opcode == 'ret' and op.args[0] is not None and
                stack_alloc and not is_generator):
            # ret val =>
            #     store (load val) out ; ret void
            [val] = op.args
            builder.position_before(op)
            newval = builder.load(val)
            builder.store(newval, out)
            op.set_args([None])

            # Update context
            context[newval] = StackVar[context[val]]

        elif op.opcode == 'call' and op.type != types.Void:
            # result = call(f, ...) =>
            #     alloca result ; call(f, ..., &result)
            ty = context[op]
            if conversion.byref(ty):
                f, args = op.args
                if not is_flypy_cc(f) or should_skip(envs[f]):
                    continue

                builder.position_before(op)
                retval = builder.alloca(opaque_t)
                builder.position_after(op)
                op.replace_uses(retval)

                newargs = args + [retval]
                op.set_args([f, newargs])

                # Update context
                context[retval] = context[op]
                context[op] = void
Ejemplo n.º 5
0
    def ctype(cls, ty):
        restype = ctype(ty.restype)
        argtypes = [ctype(argtype) for argtype in ty.argtypes]

        if byref(ty.restype):
            argtypes.append(ctypes.POINTER(restype))
            restype = None # void

        return ctypes.POINTER(ctypes.PYFUNCTYPE(restype, *argtypes))
Ejemplo n.º 6
0
    def ctype(cls, ty):
        restype = ctype(ty.restype)
        argtypes = [ctype(argtype) for argtype in ty.argtypes]

        if byref(ty.restype):
            argtypes.append(ctypes.POINTER(restype))
            restype = None  # void

        return ctypes.POINTER(ctypes.PYFUNCTYPE(restype, *argtypes))
Ejemplo n.º 7
0
def rewrite_constants(func, env):
    """
    Rewrite constants with user-defined types to IR constants. Also rewrite
    constants of builtins to instances of flypy classes.

        e.g. constant(None)  -> constant(NoneValue)
             constant("foo") -> constant(Bytes("foo"))
    """
    if env['flypy.state.opaque']:
        return

    context = env['flypy.typing.context']

    for op in func.ops:
        if op.opcode == 'exc_catch':
            continue
        constants = collect_constants(op)
        new_constants = []
        for c in constants:
            ty = context[c]

            # Python -> flypy (if not already)
            flypy_obj = fromobject(c.const, ty)
            # flypy -> ctypes
            ctype_obj = toctypes(flypy_obj, ty, _keep_alive)
            if byref(ty):
                ctype_obj = ctypes.pointer(ctype_obj)
            # ctypes -> pykit
            new_const = from_ctypes_value(ctype_obj)

            context[new_const] = ty
            new_constants.append(new_const)

            _keep_alive.extend([ctype_obj, c.const])

        substitute_args(op, constants, new_constants)
Ejemplo n.º 8
0
def rewrite_constants(func, env):
    """
    Rewrite constants with user-defined types to IR constants. Also rewrite
    constants of builtins to instances of flypy classes.

        e.g. constant(None)  -> constant(NoneValue)
             constant("foo") -> constant(Bytes("foo"))
    """
    if env['flypy.state.opaque']:
        return

    context = env['flypy.typing.context']

    for op in func.ops:
        if op.opcode == 'exc_catch':
            continue
        constants = collect_constants(op)
        new_constants = []
        for c in constants:
            ty = context[c]

            # Python -> flypy (if not already)
            flypy_obj = fromobject(c.const, ty, _keep_alive)
            # flypy -> ctypes
            ctype_obj = toctypes(flypy_obj, ty, _keep_alive)
            if byref(ty):
                ctype_obj = ctypes.pointer(ctype_obj)
            # ctypes -> pykit
            new_const = from_ctypes_value(ctype_obj)

            context[new_const] = ty
            new_constants.append(new_const)

            _keep_alive.extend([ctype_obj, c.const])

        substitute_args(op, constants, new_constants)