예제 #1
0
파일: layout.py 프로젝트: pombreda/flypy
def representation_type(ty):
    """
    Get the low-level representation type for a high-level (user-defined) type.

    Returns
    =======
    The pykit type for the object layout.
    """

    from flypy.lib import vectorobject
    from flypy.lib import arrayobject
    from flypy.runtime.obj import pointerobject

    # NOTE: special cases should be kept to an absolute minimum here. They
    #       should probably be introduced only if ctypes cannot represent the
    #       type
    if ty.impl == vectorobject.Vector:
        base, count = ty.parameters
        return ptypes.Vector(representation_type(base), count)
    elif ty.impl == pointerobject.Pointer:
        # type pointed to may not be supported by ctypes
        (base, ) = ty.parameters
        if base.impl == vectorobject.Vector:
            return ptypes.Pointer(representation_type(base))

    cty = conversion.ctype(ty)
    result_type = ctypes_support.from_ctypes_type(cty)

    # struct uses pointer
    if result_type.is_struct:
        result_type = ptypes.Pointer(result_type)

    return result_type
예제 #2
0
def register_finalizer(caller, builder, env, context, type, gcmod, obj):
    """
    Register a finalizer for the object given as pointer `obj`.
    """
    from flypy.pipeline import phase
    curphase = env['flypy.state.phase']

    #(TODO: (indirect) allocation of a new object in __del__ will recurse
    # infinitely)

    if '__del__' in type.fields:
        # Compile __del__
        __del__ = type.fields['__del__']
        lfunc, env = phase.apply_phase(phase.codegen, __del__, (type, ),
                                       env['flypy.target'])

        # Retrieve function address of __del__
        cfunc = env["codegen.llvm.ctypes"]
        pointerval = ctypes.cast(cfunc, ctypes.c_void_p).value
        ptr = ir.Pointer(pointerval, ptypes.Pointer(ptypes.Void))
        context[ptr] = Pointer[void]

        # Cast object to void *
        obj_p = builder.convert(ptypes.Opaque, obj)
        context[obj_p] = Pointer[void]

        # Call gc_add_finalizer with (obj, ptr)
        result = caller.call(curphase, gcmod.gc_add_finalizer, [obj_p, ptr])
        context[result] = void

        return [obj_p, result]
예제 #3
0
def implement_from_array(builder, argtypes, parray):
    base, count = argtypes[0]
    vector_type = ptypes.Vector(base, count)
    ptr_type = ptypes.Pointer(vector_type)
    pv = builder.bitcast(parray, ptr_type)
    v = builder.ptrload(p)
    return builder.ret(v)
예제 #4
0
파일: ret.py 프로젝트: inaimathi/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.type.base, [return_var])
        else:
            result = None

        b.ret(result)
예제 #5
0
    def initialize(self):
        """Initialize pykit untypes structures"""

        # Setup Function
        sig = types.Function(types.Opaque, [types.Opaque] * len(self.argnames),
                             False)
        self.dst = Function(func_name(self.func), self.argnames, sig)

        # Setup Builder
        self.builder = Builder(self.dst)

        # Setup Blocks
        for offset in self.bytecode.labels:
            name = blockname(self.func, offset)
            block = self.dst.new_block(name)
            self.blocks[offset] = block
            self.stacks[block] = []

        # Setup Variables
        self.builder.position_at_beginning(self.dst.startblock)
        for varname in self.varnames:
            stackvar = self.builder.alloca(types.Pointer(types.Opaque),
                                           result=self.dst.temp(varname))
            self.allocas[varname] = stackvar

            # Initialize function arguments
            if varname in self.argnames:
                self.builder.store(self.dst.get_arg(varname), stackvar)
예제 #6
0
 def test_type(self):
     self.assertEqual(from_ctypes_type(ctypes.c_int32), types.Int32)
     self.assertEqual(from_ctypes_type(ctypes.POINTER(ctypes.c_int32)),
                      types.Pointer(types.Int32))
     self.assertEqual(
         from_ctypes_type(MyStruct),
         types.Struct(['x', 'y'], [types.Float32, types.Int64]))
예제 #7
0
    def test_value(self):
        self.assertEqual(from_ctypes_value(ctypes.c_int32(10)),
                         ir.Const(10, types.Int32))

        i = ctypes.c_int32(10)
        p = ctypes.pointer(i)
        addr = ctypes.cast(p, ctypes.c_void_p).value
        self.assertEqual(from_ctypes_value(p),
                         ir.Pointer(addr, types.Pointer(types.Int32)))
예제 #8
0
 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
예제 #9
0
파일: test_builder.py 프로젝트: nouiz/pykit
 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)
예제 #10
0
    def alloca(self, varname):
        if varname not in self.allocas:
            # Allocate variable with alloca
            with self.builder.at_front(self.func.startblock):
                type = types.Pointer(self.local_vars[varname])
                result = self.func.temp(varname)
                self.allocas[varname] = self.builder.alloca(type, [], result)

        return self.allocas[varname]
예제 #11
0
    def test_unit(self):
        self.assertEqual(types.Void, types.Void)
        self.assertEqual(types.Bool, types.Bool)
        self.assertEqual(types.Int32, types.Int32)
        self.assertEqual(types.Float32, types.Float32)
        self.assertEqual(types.Pointer(types.Int32),
                         types.Pointer(types.Int32))
        self.assertEqual(types.Vector(types.Int32, 4),
                         types.Vector(types.Int32, 4))


        self.assertNotEqual(types.Void, types.Bool)
        self.assertNotEqual(types.Pointer(types.Void),
                            types.Pointer(types.Bool))
        self.assertNotEqual(types.Vector(types.Int32, 4),
                            types.Vector(types.Int32, 5))
        self.assertNotEqual(types.Vector(types.Int32, 4),
                            types.Vector(types.Int64, 4))
예제 #12
0
def from_ctypes_type(ctypes_type, memo=None):
    """
    Convert a ctypes type to a pykit type.

    Supported are structs, unit types (int/float)
    """
    if memo is None:
        memo = {}
    if hashable(ctypes_type) and ctypes_type in memo:
        return memo[ctypes_type]

    if hashable(ctypes_type) and ctypes_type in ctypes_map:
        result = ctypes_map[ctypes_type]
    elif ctypes_type is ctypes.c_void_p:
        result = types.Pointer(types.Void)
    elif is_ctypes_array_type(ctypes_type):
        result = types.Array(from_ctypes_type(ctypes_type._type_, memo),
                             ctypes_type._length_)
    elif is_ctypes_pointer_type(ctypes_type):
        result = types.Pointer(from_ctypes_type(ctypes_type._type_, memo))
    elif is_ctypes_struct_type(ctypes_type):
        # pre-order caching for recursive data structures
        f_names = []
        f_types = []
        result = types.Struct(f_names, f_types)
        memo[ctypes_type] = result

        fields = [(name, from_ctypes_type(field_type, memo))
                  for name, field_type in ctypes_type._fields_]
        fieldnames, fieldtypes = zip(*fields) or (('dummy', ), (types.Int8, ))

        f_names.extend(fieldnames)
        f_types.extend(fieldtypes)
    elif is_ctypes_function_type(ctypes_type):
        c_restype = from_ctypes_type(ctypes_type._restype_, memo)
        c_argtypes = [
            from_ctypes_type(argty, memo) for argty in ctypes_type._argtypes_
        ]
        result = types.Function(c_restype, c_argtypes, False)
    else:
        raise NotImplementedError(ctypes_type)

    memo[ctypes_type] = result
    return result
예제 #13
0
def allocate_object(caller, builder, type, env):
    """
    Allocate object of type `type`.
    """
    if stack_allocate(type):
        obj = builder.alloca(ptypes.Pointer(ptypes.Opaque))
        return [obj], obj
    else:
        if env['flypy.target'] != 'cpu':
            raise errors.CompileError(
                "Cannot heap allocate object of type %s with target %r" %
                (type, env['flypy.target']))
        return heap_allocate(caller, builder, type, env)
예제 #14
0
def rewrite_constructors(func, env):
    """
    Rewrite constructor application to object allocation followed by
    cls.__init__:

    Rewrite C(x, y) to:

        obj = allocate()
        C.__init__(obj, x, y)
        register_finalizer(obj.__del__)

    """
    phase = env['flypy.state.phase']
    context = env['flypy.typing.context']

    b = OpBuilder()
    caller = Caller(b, context, env)

    for op in func.ops:
        if op.opcode == 'call':
            cls, args = op.args
            if isinstance(cls, Const) and is_flypy_type(cls.const):
                cls = cls.const
                f = cls.__init__
                type = context[op]

                # Allocate object
                obj = ir.Op('allocate_obj',
                            ptypes.Pointer(ptypes.Void),
                            args=[])
                register_finalizer = ir.Op('register_finalizer',
                                           ptypes.Void,
                                           args=[obj])
                context[register_finalizer] = void
                context[obj] = type

                # Initialize object (call __init__)
                # TODO: implement this on Type.__call__ when we support *args
                initialize = caller.call(phase, f, [obj] + op.args[1])

                op.replace_uses(obj)
                op.replace([obj, initialize, register_finalizer])
예제 #15
0
파일: reg2mem.py 프로젝트: YusufCakan/pykit
def generate_copies(func, phis):
    """
    Emit stores to stack variables in predecessor blocks.
    """
    builder = Builder(func)
    vars = {}
    loads = {}

    # Allocate a stack variable for each phi
    builder.position_at_beginning(func.startblock)
    for block in phis:
        for phi in phis[block]:
            vars[phi] = builder.alloca(types.Pointer(phi.type))

    # Generate loads in blocks containing the phis
    for block in phis:
        leaders = list(block.leaders)
        last_leader = leaders[-1] if leaders else block.head
        builder.position_after(last_leader)
        for phi in phis[block]:
            loads[phi] = builder.load(vars[phi])

    # Generate copies (store to stack variables)
    for block in phis:
        for phi in phis[block]:
            preds, args = phi.args
            var = vars[phi]
            phi_args = [loads.get(arg, arg) for arg in args]
            for pred, arg in zip(preds, phi_args):
                builder.position_before(pred.terminator)
                builder.store(arg, var)

    # Replace phis
    for block in phis:
        for phi in phis[block]:
            phi.replace_uses(loads[phi])
            phi.delete()

    return vars, loads
예제 #16
0
    def gen_loop(self, start=None, stop=None, step=None):
        """
        Generate a loop given start, stop, step and the index variable type.
        The builder's position is set to the end of the body block.

        Returns (condition_block, body_block, exit_block).
        """
        self._assert_position()
        assert isinstance(stop,
                          Value), "Stop should be a Constant or Operation"

        ty = stop.type
        start = start or Const(0, ty)
        step = step or Const(1, ty)
        assert start.type == ty == step.type

        with self.at_front(self.func.blocks[0]):
            var = self.alloca(types.Pointer(ty), [])

        prev, exit = self.splitblock('loop.exit')
        cond = self.func.add_block('loop.cond', after=prev)
        body = self.func.add_block('loop.body', after=cond)

        with self.at_end(prev):
            self.store(start, var)
            self.jump(cond)

        # Condition
        with self.at_front(cond):
            index = self.load(ty, [var])
            self.store(self.add(ty, [index, step]), var)
            self.cbranch(self.lt(types.Bool, [index, stop]), body, exit)

        with self.at_end(body):
            self.jump(cond)

        self.position_at_beginning(body)
        return cond, body, exit
예제 #17
0
 def visit_PtrDecl(self, decl):
     return types.Pointer(self.visit(decl.type.type))
예제 #18
0
def create():
    t = types.Struct([], [])
    t.names.extend(['spam', 'ham', 'eggs'])
    t.types.extend([types.Pointer(t), types.Int64, t])
    return t
예제 #19
0
from __future__ import print_function, division, absolute_import

import ctypes

from flypy import jit, representation, conversion
from flypy.types import Pointer, void
from flypy.compiler import is_flypy_cc

from pykit import types
from pykit.ir import OpBuilder, Builder

#===------------------------------------------------------------------===
# Return Objects
#===------------------------------------------------------------------===

opaque_t = types.Pointer(types.Opaque)


@jit('StackVar[a]')
class StackVar(object):
    """
    Represent the loaded stack layout of a value.
    """

    layout = []

    @classmethod
    def ctype(cls, ty):
        cty = conversion.ctype(ty.parameters[0])
        # Get the base type if a pointer
        if hasattr(cty, '_type_'):
예제 #20
0
 def op_addressof(self, op, func):
     assert func.address
     addr = const_int(i64, func.address)
     return self.builder.inttoptr(
         addr, self.llvm_type(types.Pointer(types.Void)))
예제 #21
0
def implement_to_array(builder, argtypes, vector, parray):
    pvector_t = ptypes.Pointer(argtypes[0])
    pvector = builder.bitcast(pvector_t, parray)
    builder.ptrstore(vector, pvector)
예제 #22
0
파일: parser.py 프로젝트: nouiz/pykit
def _build_type(type, args):
    ty, tail = to_type(args[0]), args[1:]
    for i in range(len(tail)):
        ty = types.Pointer(ty)
    return ty