Example #1
1
def ctypes_struct_to_lltype(S, name = None):
  if not name:
    name = S.__class__.__name__

  key = tuple(S._fields_)

  if key in _struct_cache:
    return _struct_cache[key]
  else:
    llvm_field_types = [ctypes_to_lltype(field_type)
                        for (_, field_type) in S._fields_]
    llvm_struct = lltype.struct(llvm_field_types, name)
    _struct_cache[key] = llvm_struct
    return llvm_struct
Example #2
0
def args_to_kernel_data_struct(kinds, argtypes):
    # Build up the kernel data structure. Currently, this means
    # adding a shape field for each array argument. First comes
    # the kernel data prefix with a spot for the 'owner' reference added.
    input_field_indices = []
    kernel_data_fields = [Type.struct([int8_p_type]*3)]
    kernel_data_ctypes_fields = [('base', JITCKernelData)]
    for i, (kind, a) in enumerate(izip(kinds, argtypes)):
        if isinstance(kind, tuple):
            if kind[0] != lla.C_CONTIGUOUS:
                raise ValueError('only support C contiguous array presently')
            input_field_indices.append(len(kernel_data_fields))
            kernel_data_fields.append(Type.array(
                            intp_type, len(bek.dshapes[i])-1))
            kernel_data_ctypes_fields.append(('operand_%d' % i,
                            c_ssize_t * (len(bek.dshapes[i])-1)))
        elif kind in [lla.SCALAR, lla.POINTER]:
            input_field_indices.append(None)
        else:
            raise TypeError(("unbound_single_ckernel codegen doesn't " +
                            "support the parameter kind %r yet") % (k,))
    # Make an LLVM and ctypes type for the extra data pointer.
    kernel_data_llvmtype = Type.struct(kernel_data_fields)
    class kernel_data_ctypestype(ctypes.Structure):
        _fields_ = kernel_data_ctypes_fields
    return (kernel_data_llvmtype, kernel_data_ctypestype)
Example #3
0
def create_instance(mod, spec, ctx):

    #  Spine
    #    |
    #
    # T ... = A .. | B .. | C ..
    #
    #                |
    #              Values

    lvals = []
    instances = []

    # Values
    # ======
    for value in spec.values:
        tys = [ctx[id] for id in value.params]
        lvals += [(value.name, Type.struct(tys, value.name))]

    # Spine
    # ======
    spine = Type.struct([a[1] for a in lvals], 'maybe')

    for i, (name, value) in enumerate(lvals):
        fn_spec = Type.function(void, value.elements)
        F = mod.add_function(fn_spec, value.name)
        instances += [F]

        build_constructor(F, value, spine, 1)

    return spine, instances
Example #4
0
def args_to_kernel_data_struct(kinds, argtypes):
    # Build up the kernel data structure. Currently, this means
    # adding a shape field for each array argument. First comes
    # the kernel data prefix with a spot for the 'owner' reference added.
    input_field_indices = []
    kernel_data_fields = [Type.struct([int8_p_type]*3)]
    kernel_data_ctypes_fields = [('base', JITCKernelData)]
    for i, (kind, a) in enumerate(izip(kinds, argtypes)):
        if isinstance(kind, tuple):
            if kind[0] != lla.C_CONTIGUOUS:
                raise ValueError('only support C contiguous array presently')
            input_field_indices.append(len(kernel_data_fields))
            kernel_data_fields.append(Type.array(
                            intp_type, len(bek.dshapes[i])-1))
            kernel_data_ctypes_fields.append(('operand_%d' % i,
                            c_ssize_t * (len(bek.dshapes[i])-1)))
        elif kind in [lla.SCALAR, lla.POINTER]:
            input_field_indices.append(None)
        else:
            raise TypeError(("unbound_single_ckernel codegen doesn't " +
                            "support the parameter kind %r yet") % (k,))
    # Make an LLVM and ctypes type for the extra data pointer.
    kernel_data_llvmtype = Type.struct(kernel_data_fields)
    class kernel_data_ctypestype(ctypes.Structure):
        _fields_ = kernel_data_ctypes_fields
    return (kernel_data_llvmtype, kernel_data_ctypestype)
Example #5
0
def create_instance(mod, spec, ctx):

    #  Spine
    #    |
    #
    # T ... = A .. | B .. | C ..
    #
    #                |
    #              Values

    lvals = []
    instances = []

    # Values
    # ======
    for value in spec.values:
        tys = [ctx[id] for id in value.params]
        lvals += [(value.name, Type.struct(tys, value.name))]

    # Spine
    # ======
    spine = Type.struct([a[1] for a in lvals], 'maybe')

    for i, (name, value) in enumerate(lvals):
        fn_spec = Type.function(void, value.elements)
        F = mod.add_function(fn_spec, value.name)
        instances += [F]

        build_constructor(F, value, spine, 1)

    return spine, instances
Example #6
0
    def get_data_type(self, ty):
        """
        Get a data representation of the type

        Returns None if it is an opaque pointer
        """
        if (isinstance(ty, types.Dummy) or
                isinstance(ty, types.Module) or
                isinstance(ty, types.Function) or
                isinstance(ty, types.Dispatcher) or
                isinstance(ty, types.Object) or
                isinstance(ty, types.Macro)):
            return Type.pointer(Type.int(8))

        elif isinstance(ty, types.CPointer):
            dty = self.get_data_type(ty.dtype)
            return Type.pointer(dty)

        elif isinstance(ty, types.Optional):
            return self.get_data_type(ty.type)

        elif isinstance(ty, types.Array):
            return self.get_struct_type(self.make_array(ty))

        elif isinstance(ty, types.UniTuple):
            dty = self.get_value_type(ty.dtype)
            return Type.array(dty, ty.count)

        elif isinstance(ty, types.Tuple):
            dtys = [self.get_value_type(t) for t in ty]
            return Type.struct(dtys)

        elif isinstance(ty, types.UniTupleIter):
            stty = self.get_struct_type(self.make_unituple_iter(ty))
            return stty

        elif isinstance(ty, types.Record):
            # Record are represented as byte array
            return Type.struct([Type.array(Type.int(8), ty.size)])

        elif isinstance(ty, types.UnicodeCharSeq):
            charty = Type.int(numpy_support.sizeof_unicode_char * 8)
            return Type.struct([Type.array(charty, ty.count)])

        elif isinstance(ty, types.CharSeq):
            charty = Type.int(8)
            return Type.struct([Type.array(charty, ty.count)])

        elif ty in STRUCT_TYPES:
            return self.get_struct_type(STRUCT_TYPES[ty])

        elif isinstance(ty, types.Pair):
            pairty = self.make_pair(ty.first_type, ty.second_type)
            return self.get_struct_type(pairty)

        else:
            return LTYPEMAP[ty]
Example #7
0
 def test_struct_type(self):
     ta = Type.struct([Type.int(32), Type.float()])
     tb = Type.struct([Type.int(32), Type.float()])
     tc = Type.struct([Type.int(32), Type.int(32), Type.float()])
     ts = set([ta, tb, tc])
     self.assertTrue(len(ts) == 2)
     self.assertTrue(ta in ts)
     self.assertTrue(tb in ts)
     self.assertTrue(tc in ts)
Example #8
0
 def test_struct_type(self):
     ta = Type.struct([Type.int(32), Type.float()])
     tb = Type.struct([Type.int(32), Type.float()])
     tc = Type.struct([Type.int(32), Type.int(32), Type.float()])
     ts = set([ta, tb, tc])
     self.assertTrue(len(ts) == 2)
     self.assertTrue(ta in ts)
     self.assertTrue(tb in ts)
     self.assertTrue(tc in ts)
Example #9
0
 def test_struct_extract_value_2d(self):
     ta = Type.struct([Type.int(32), Type.float()])
     tb = Type.struct([ta, Type.float()])
     m = Module.new('')
     f = m.add_function(Type.function(Type.void(), []), "foo")
     b = Builder.new(f.append_basic_block(''))
     v = Constant.undef(tb)
     ins = b.insert_value(v, Constant.real(Type.float(), 1.234), [0, 1])
     ext = b.extract_value(ins, [0, 1])
     b.ret_void()
     m.verify()
     self.assertEqual(str(ext), 'float 0x3FF3BE76C0000000')
Example #10
0
    def get_data_type(self, ty):
        """
        Get a data representation of the type

        Returns None if it is an opaque pointer
        """
        if (isinstance(ty, types.Dummy) or
                isinstance(ty, types.Module) or
                isinstance(ty, types.Function) or
                isinstance(ty, types.Dispatcher) or
                isinstance(ty, types.Object) or
                isinstance(ty, types.Macro)):
            return Type.pointer(Type.int(8))

        elif isinstance(ty, types.CPointer):
            dty = self.get_data_type(ty.dtype)
            return Type.pointer(dty)

        elif isinstance(ty, types.Optional):
            return self.get_data_type(ty.type)

        elif isinstance(ty, types.Array):
            return self.get_struct_type(self.make_array(ty))

        elif isinstance(ty, types.UniTuple):
            dty = self.get_value_type(ty.dtype)
            return Type.array(dty, ty.count)

        elif isinstance(ty, types.Tuple):
            dtys = [self.get_value_type(t) for t in ty]
            return Type.struct(dtys)

        elif isinstance(ty, types.UniTupleIter):
            stty = self.get_struct_type(self.make_unituple_iter(ty))
            return stty

        elif isinstance(ty, types.Record):
            # Record are represented as byte array
            return Type.struct([Type.array(Type.int(8), ty.size)])

        elif isinstance(ty, types.UnicodeCharSeq):
            charty = Type.int(numpy_support.sizeof_unicode_char * 8)
            return Type.struct([Type.array(charty, ty.count)])

        elif isinstance(ty, types.CharSeq):
            charty = Type.int(8)
            return Type.struct([Type.array(charty, ty.count)])

        elif ty in STRUCT_TYPES:
            return self.get_struct_type(STRUCT_TYPES[ty])

        else:
            return LTYPEMAP[ty]
Example #11
0
 def test_struct_extract_value_2d(self):
     ta = Type.struct([Type.int(32), Type.float()])
     tb = Type.struct([ta, Type.float()])
     m = Module.new('')
     f = m.add_function(Type.function(Type.void(), []), "foo")
     b = Builder.new(f.append_basic_block(''))
     v = Constant.undef(tb)
     ins = b.insert_value(v, Constant.real(Type.float(), 1.234), [0, 1])
     ext = b.extract_value(ins, [0, 1])
     b.ret_void()
     m.verify()
     self.assertEqual(str(ext), 'float 0x3FF3BE76C0000000')
Example #12
0
def array_type(elt_type):
    return Type.struct(
        [
            pointer(elt_type),  # data
            int_type,  # dimensions
            pointer(int_type),  # shape
        ],
        name='ndarray_' + str(elt_type))
Example #13
0
def make_anonymous_struct(builder, values):
    """
    Create an anonymous struct constant containing the given LLVM *values*.
    """
    struct_type = Type.struct([v.type for v in values])
    struct_val = Constant.undef(struct_type)
    for i, v in enumerate(values):
        struct_val = builder.insert_value(struct_val, v, i)
    return struct_val
Example #14
0
def make_anonymous_struct(builder, values):
    """
    Create an anonymous struct constant containing the given LLVM *values*.
    """
    struct_type = Type.struct([v.type for v in values])
    struct_val = Constant.undef(struct_type)
    for i, v in enumerate(values):
        struct_val = builder.insert_value(struct_val, v, i)
    return struct_val
Example #15
0
    def get_value_type(self, ty):
        if ty == types.boolean:
            return Type.int(1)
        dataty = self.get_data_type(ty)

        if isinstance(ty, types.Record):
            # Record data are passed by refrence
            memory = dataty.elements[0]
            return Type.struct([Type.pointer(memory)])

        return dataty
Example #16
0
 def test_arg_attr(self):
     m = Module.new('oifjda')
     vptr = Type.pointer(Type.float())
     sptr = Type.pointer(Type.struct([]))
     fnty = Type.function(Type.void(), [vptr] * 5)
     func = m.add_function(fnty, 'foo')
     attrs = [lc.ATTR_STRUCT_RET, lc.ATTR_BY_VAL, lc.ATTR_NEST,
              lc.ATTR_NO_ALIAS, lc.ATTR_NO_CAPTURE]
     for i, attr in enumerate(attrs):
         arg = func.args[i]
         self.assertEqual(i, arg.arg_no)
         arg.add_attribute(attr)
         self.assertTrue(attr in func.args[i])
Example #17
0
def ctypes_struct_to_lltype(S, name=None):
    if not name:
        name = S.__class__.__name__

    key = tuple(S._fields_)

    if key in _struct_cache:
        return _struct_cache[key]
    else:
        llvm_field_types = [
            ctypes_to_lltype(field_type) for (_, field_type) in S._fields_
        ]
        llvm_struct = lltype.struct(llvm_field_types, name)
        _struct_cache[key] = llvm_struct
        return llvm_struct
Example #18
0
def test_dtype_from_type_complex():
    """
    Test to-numpy translation of a complex LLVM type.
    """

    from llvm.core  import Type
    from qy         import (
        type_from_dtype,
        dtype_from_type,
        )

    dtype = numpy.dtype([("f0", [("f0", numpy.int32), ("f1", numpy.int32)], (4,))])
    type_ = Type.struct([Type.array(Type.packed_struct([Type.int(32)] * 2), 4)])
    dtype2 = dtype_from_type(type_)

    assert_equal(dtype2.itemsize, dtype.itemsize)
    assert_equal(str(dtype2), str(dtype))
Example #19
0
def array_type(nd, kind, el_type=char_type, module=None):
    base = kind & (~(HAS_ND | HAS_DIMKIND))
    if base == C_CONTIGUOUS:
        dimstr = 'Array_C'
    elif base == F_CONTIGUOUS:
        dimstr = 'Array_F'
    elif base == STRIDED:
        dimstr = 'Array_S'
    elif base == NEW_STRIDED:
        dimstr = 'Array_N'
    else:
        raise TypeError("Do not understand Array kind of %d" % kind)

    if (kind & HAS_ND):
        dimstr += '_ND'
    elif (kind & HAS_DIMKIND):
        dimstr += '_DK'

    key = "%s_%s_%d" % (dimstr, str(el_type), nd)
    if module is not None:
        modcache = _cache.setdefault(module.id, {})
        if key in modcache:
            return modcache[key]

    terms = [Type.pointer(el_type)]  # data

    if (kind & HAS_ND):
        terms.append(int32_type)  # nd
    elif (kind & HAS_DIMKIND):
        terms.extend([int16_type, int16_type])  # nd, dimkind

    if base in [C_CONTIGUOUS, F_CONTIGUOUS]:
        terms.append(Type.array(intp_type, nd))  # shape
    elif base == NEW_STRIDED:
        terms.append(Type.array(diminfo_type, nd))  # diminfo
    elif base == STRIDED:
        terms.extend([
            Type.array(intp_type, nd),  # shape
            Type.array(intp_type, nd)
        ])  # strides

    terms.append(void_p_type)
    ret = Type.struct(terms, name=key)
    if module is not None:
        modcache[key] = ret
    return ret
Example #20
0
def array_type(nd, kind, el_type=char_type, module=None):
    base = kind & (~(HAS_ND | HAS_DIMKIND))
    if base == C_CONTIGUOUS:
        dimstr = 'Array_C'
    elif base == F_CONTIGUOUS:
        dimstr = 'Array_F'
    elif base == STRIDED:
        dimstr = 'Array_S'
    elif base == NEW_STRIDED:
        dimstr = 'Array_N'
    else:
        raise TypeError("Do not understand Array kind of %d" % kind)

    if (kind & HAS_ND):
        dimstr += '_ND'
    elif (kind & HAS_DIMKIND):
        dimstr += '_DK'

    key = "%s_%s_%d" % (dimstr, str(el_type), nd)
    if module is not None:
        modcache = _cache.setdefault(module.id,{})
        if key in modcache:
            return modcache[key]

    terms = [Type.pointer(el_type)]        # data

    if (kind & HAS_ND):
        terms.append(int32_type)           # nd
    elif (kind & HAS_DIMKIND):
        terms.extend([int16_type, int16_type]) # nd, dimkind

    if base in [C_CONTIGUOUS, F_CONTIGUOUS]:
        terms.append(Type.array(intp_type, nd))     # shape
    elif base == NEW_STRIDED:
        terms.append(Type.array(diminfo_type, nd))       # diminfo
    elif base == STRIDED:
        terms.extend([Type.array(intp_type, nd),    # shape
                      Type.array(intp_type, nd)])   # strides

    terms.append(void_p_type)
    ret = Type.struct(terms, name=key)
    if module is not None:
        modcache[key] = ret
    return ret
Example #21
0
    def get_data_type(self, ty):
        """
        Get a data representation of the type

        Returns None if it is an opaque pointer
        """
        if (isinstance(ty, types.Dummy) or
                isinstance(ty, types.Module) or
                isinstance(ty, types.Function) or
                isinstance(ty, types.Dispatcher) or
                isinstance(ty, types.Object) or
                isinstance(ty, types.Macro)):
            return Type.pointer(Type.int(8))

        elif isinstance(ty, types.CPointer):
            dty = self.get_data_type(ty.dtype)
            return Type.pointer(dty)

        elif isinstance(ty, types.Optional):
            return self.get_data_type(ty.type)

        elif isinstance(ty, types.Array):
            return self.get_struct_type(self.make_array(ty))

        elif isinstance(ty, types.UniTuple):
            dty = self.get_value_type(ty.dtype)
            return Type.array(dty, ty.count)

        elif isinstance(ty, types.Tuple):
            dtys = [self.get_value_type(t) for t in ty]
            return Type.struct(dtys)

        elif isinstance(ty, types.UniTupleIter):
            stty = self.get_struct_type(self.make_unituple_iter(ty))
            return stty

        elif ty in STRUCT_TYPES:
            return self.get_struct_type(STRUCT_TYPES[ty])

        else:
            return LTYPEMAP[ty]
Example #22
0
def llvm_type(type):
    ty = type.__class__
    if ty == Boolean:
        return Type.int(1)
    elif ty == Integral:
        return Type.int(type.bits)
    elif type == Float32:
        return Type.float()
    elif type == Float64:
        return Type.double()
    elif ty == Struct:
        return Type.struct([llvm_type(ftype) for ftype in type.types])
    elif ty == Pointer:
        return Type.pointer(llvm_type(type.base))
    elif ty == Function:
        return Type.function(llvm_type(type.restype),
                             [llvm_type(argtype) for argtype in type.argtypes])
    elif ty == Void:
        return Type.void()
    else:
        raise TypeError("Cannot convert type %s" % (type,))
Example #23
0
    def get_data_type(self, ty):
        """
        Get a data representation of the type

        Returns None if it is an opaque pointer
        """
        if (isinstance(ty, types.Dummy) or isinstance(ty, types.Module)
                or isinstance(ty, types.Function)
                or isinstance(ty, types.Dispatcher)
                or isinstance(ty, types.Object)
                or isinstance(ty, types.Macro)):
            return Type.pointer(Type.int(8))

        elif isinstance(ty, types.CPointer):
            dty = self.get_data_type(ty.dtype)
            return Type.pointer(dty)

        elif isinstance(ty, types.Optional):
            return self.get_data_type(ty.type)

        elif isinstance(ty, types.Array):
            return self.get_struct_type(self.make_array(ty))

        elif isinstance(ty, types.UniTuple):
            dty = self.get_value_type(ty.dtype)
            return Type.array(dty, ty.count)

        elif isinstance(ty, types.Tuple):
            dtys = [self.get_value_type(t) for t in ty]
            return Type.struct(dtys)

        elif isinstance(ty, types.UniTupleIter):
            stty = self.get_struct_type(self.make_unituple_iter(ty))
            return stty

        elif ty in STRUCT_TYPES:
            return self.get_struct_type(STRUCT_TYPES[ty])

        else:
            return LTYPEMAP[ty]
Example #24
0
def array_type(nd, kind, el_type=char_type):
    key = (kind, nd, el_type)
    if _cache.has_key(key):
        return _cache[key]

    base = kind & (~(HAS_ND | HAS_DIMKIND))
    if base == C_CONTIGUOUS:
        dimstr = 'Array_C'
    elif base == F_CONTIGUOUS:
        dimstr = 'Array_F'
    elif base == STRIDED:
        dimstr = 'Array_S'
    elif base == STRIDED_SOA:
        dimstr = 'Array_A'
    else:
        raise TypeError("Do not understand Array kind of %d" % kind)

    terms = [Type.pointer(el_type)]  # data

    if (kind & HAS_ND):
        terms.append(int32_type)  # nd
        dimstr += '_ND'
    elif (kind & HAS_DIMKIND):
        terms.extend([int16_type, int16_type])  # nd, dimkind
        dimstr += '_DK'

    if base in [C_CONTIGUOUS, F_CONTIGUOUS]:
        terms.append(Type.array(intp_type, nd))  # shape
    elif base == STRIDED:
        terms.append(Type.array(diminfo_type, nd))  # diminfo
    elif base == STRIDED_SOA:
        terms.extend([
            Type.array(intp_type, nd),  # shape
            Type.array(intp_type, nd)
        ])  # strides

    ret = Type.struct(terms, name=dimstr)
    _cache[key] = ret
    return ret
Example #25
0
def handle_struct(type, memo):
    # Check the cache with a hashable struct type
    key = type

    if key in memo:
        return memo[key]
    if key in opaque_memo:
        return opaque_memo[key]

    # Allocate and pre-order cache dummy struct
    struct_type = Type.opaque('dummy_struct_type')
    memo[key] = struct_type
    opaque_memo[key] = struct_type

    # Process fields and re-cache
    fields = [llvm_type(ftype, memo) for ftype in type.types]
    result = Type.struct(fields)
    struct_type.set_body([result])

    memo[key] = result
    opaque_memo[key] = result

    return result
Example #26
0
def array_type(nd, kind, el_type=char_type):
    key = (kind, nd, el_type)
    if _cache.has_key(key):
        return _cache[key]

    base = kind & (~(HAS_ND | HAS_DIMKIND))
    if base == C_CONTIGUOUS:
        dimstr = 'Array_C'
    elif base == F_CONTIGUOUS:
        dimstr = 'Array_F'
    elif base == STRIDED:
        dimstr = 'Array_S'
    elif base == STRIDED_SOA:
        dimstr = 'Array_A'
    else:
        raise TypeError("Do not understand Array kind of %d" % kind)

    terms = [Type.pointer(el_type)]        # data

    if (kind & HAS_ND):
        terms.append(int32_type)           # nd
        dimstr += '_ND'
    elif (kind & HAS_DIMKIND):
        terms.extend([int16_type, int16_type]) # nd, dimkind
        dimstr += '_DK'

    if base in [C_CONTIGUOUS, F_CONTIGUOUS]:
        terms.append(Type.array(intp_type, nd))     # shape
    elif base == STRIDED:
        terms.append(Type.array(diminfo_type, nd))       # diminfo
    elif base == STRIDED_SOA:
        terms.extend([Type.array(intp_type, nd),    # shape
                      Type.array(intp_type, nd)])   # strides

    ret = Type.struct(terms, name=dimstr)
    _cache[key] = ret
    return ret
Example #27
0
int_type = Type.int()
float_type = Type.double()
bool_type = Type.int(1)
void_type = Type.void()
char_type = Type.int(8)

pointer = Type.pointer

any_type = pointer(Type.int(ptrsize))
string_type = pointer(char_type)

# { i32*, i32, i32* }
array_type = lambda elt_type: Type.struct(
    [
        pointer(elt_type),  # data         | (<type>)*
        int_type,  # dimensions   | int
        pointer(int_type),  # strides      | int*
    ],
    name='ndarray_' + str(elt_type))

# opaque for now
blaze_type = lambda datashape: Type.opaque(name="blaze")

#------------------------------------------------------------------------
# Constants
#------------------------------------------------------------------------

false = Constant.int(bool_type, 0)
true = Constant.int(bool_type, 1)
zero = Constant.int(int_type, 0)
Example #28
0
    def unbound_single_ckernel(self):
        """Creates an UnboundCKernelFunction with the ExprSingleOperation prototype.
        """
        import ctypes
        if self._unbound_single_ckernel is None:
            i8_p_type = Type.pointer(Type.int(8))
            func_type = Type.function(void_type,
                            [i8_p_type, Type.pointer(i8_p_type), i8_p_type])
            module = self.module.clone()
            single_ck_func_name = self.func.name +"_single_ckernel"
            single_ck_func = Function.new(module, func_type,
                                              name=single_ck_func_name)
            block = single_ck_func.append_basic_block('entry')
            builder = lc.Builder.new(block)
            dst_ptr_arg, src_ptr_arr_arg, extra_ptr_arg = single_ck_func.args
            dst_ptr_arg.name = 'dst_ptr'
            src_ptr_arr_arg.name = 'src_ptrs'
            extra_ptr_arg.name = 'extra_ptr'
            # Build up the kernel data structure. Currently, this means
            # adding a shape field for each array argument. First comes
            # the kernel data prefix with a spot for the 'owner' reference added.
            input_field_indices = []
            kernel_data_fields = [Type.struct([i8_p_type]*3)]
            kernel_data_ctypes_fields = [('base', JITKernelData)]
            for i, (kind, a) in enumerate(izip(self.kinds, self.argtypes)):
                if isinstance(kind, tuple):
                    if kind[0] != lla.C_CONTIGUOUS:
                        raise ValueError('only support C contiguous array presently')
                    input_field_indices.append(len(kernel_data_fields))
                    kernel_data_fields.append(Type.array(
                                    intp_type, len(self.dshapes[i])-1))
                    kernel_data_ctypes_fields.append(('operand_%d' % i,
                                    c_ssize_t * (len(self.dshapes[i])-1)))
                elif kind in [SCALAR, POINTER]:
                    input_field_indices.append(None)
                else:
                    raise TypeError(("unbound_single_ckernel codegen doesn't " +
                                    "support the parameter kind %r yet") % (k,))
            # Make an LLVM and ctypes type for the extra data pointer.
            kernel_data_llvmtype = Type.struct(kernel_data_fields)
            class kernel_data_ctypestype(ctypes.Structure):
                _fields_ = kernel_data_ctypes_fields
            # Cast the extra pointer to the right llvm type
            extra_struct = builder.bitcast(extra_ptr_arg,
                            Type.pointer(kernel_data_llvmtype))
            # Convert the src pointer args to the
            # appropriate kinds for the llvm call
            args = []
            for i, (kind, atype) in enumerate(izip(self.kinds[:-1], self.argtypes)):
                if kind == SCALAR:
                    src_ptr = builder.bitcast(builder.load(
                                    builder.gep(src_ptr_arr_arg,
                                            (lc.Constant.int(intp_type, i),))),
                                        Type.pointer(atype))
                    src_val = builder.load(src_ptr)
                    args.append(src_val)
                elif kind == POINTER:
                    src_ptr = builder.bitcast(builder.load(
                                    builder.gep(src_ptr_arr_arg,
                                            (lc.Constant.int(intp_type, i),))),
                                        Type.pointer(atype))                    
                    args.append(src_ptr)
                elif isinstance(kind, tuple):
                    src_ptr = builder.bitcast(builder.load(
                                    builder.gep(src_ptr_arr_arg,
                                            (lc.Constant.int(intp_type, i),))),
                                        Type.pointer(kind[2]))
                    # First get the shape of this parameter. This will
                    # be a combination of Fixed and TypeVar (Var unsupported
                    # here for now)
                    shape = self.dshapes[i][:-1]
                    # Get the llvm array
                    arr_var = builder.alloca(atype.pointee)
                    builder.store(src_ptr,
                                    builder.gep(arr_var,
                                    (lc.Constant.int(int32_type, 0),
                                     lc.Constant.int(int32_type, 0))))
                    for j, sz in enumerate(shape):
                        if isinstance(sz, Fixed):
                            # If the shape is already known at JIT compile time,
                            # insert the constant
                            shape_el_ptr = builder.gep(arr_var,
                                            (lc.Constant.int(int32_type, 0),
                                             lc.Constant.int(int32_type, 1),
                                             lc.Constant.int(intp_type, j)))
                            builder.store(lc.Constant.int(intp_type,
                                                    operator.index(sz)),
                                            shape_el_ptr)
                        elif isinstance(sz, TypeVar):
                            # TypeVar types are only known when the kernel is bound,
                            # so copy it from the extra data pointer
                            sz_from_extra_ptr = builder.gep(extra_struct,
                                            (lc.Constant.int(int32_type, 0),
                                             lc.Constant.int(int32_type,
                                                    input_field_indices[i]),
                                             lc.Constant.int(intp_type, j)))
                            sz_from_extra = builder.load(sz_from_extra_ptr)
                            shape_el_ptr = builder.gep(arr_var,
                                            (lc.Constant.int(int32_type, 0),
                                             lc.Constant.int(int32_type, 1),
                                             lc.Constant.int(intp_type, j)))
                            builder.store(sz_from_extra, shape_el_ptr)
                        else:
                            raise TypeError(("unbound_single_ckernel codegen doesn't " +
                                            "support dimension type %r") % type(sz))
                    args.append(arr_var)
            # Call the function and store in the dst
            kind = self.kinds[-1]
            func = module.get_function_named(self.func.name)
            if kind == SCALAR:
                dst_ptr = builder.bitcast(dst_ptr_arg,
                                Type.pointer(self.return_type))
                dst_val = builder.call(func, args)
                builder.store(dst_val, dst_ptr)
            elif kind == POINTER:
                dst_ptr = builder.bitcast(dst_ptr_arg,
                                Type.pointer(self.return_type))                
                builder.call(func, args + [dst_ptr])
            elif isinstance(kind, tuple):
                dst_ptr = builder.bitcast(dst_ptr_arg,
                                Type.pointer(kind[2]))
                # First get the shape of the output. This will
                # be a combination of Fixed and TypeVar (Var unsupported
                # here for now)
                shape = self.dshapes[-1][:-1]
                # Get the llvm array
                arr_var = builder.alloca(self.argtypes[-1].pointee)
                builder.store(dst_ptr,
                                builder.gep(arr_var,
                                    (lc.Constant.int(int32_type, 0),
                                    lc.Constant.int(int32_type, 0))))
                for j, sz in enumerate(shape):
                    if isinstance(sz, Fixed):
                        # If the shape is already known at JIT compile time,
                        # insert the constant
                        shape_el_ptr = builder.gep(arr_var,
                                        (lc.Constant.int(int32_type, 0),
                                         lc.Constant.int(int32_type, 1),
                                         lc.Constant.int(intp_type, j)))
                        builder.store(lc.Constant.int(intp_type,
                                                operator.index(sz)),
                                        shape_el_ptr)
                    elif isinstance(sz, TypeVar):
                        # TypeVar types are only known when the kernel is bound,
                        # so copy it from the extra data pointer
                        sz_from_extra_ptr = builder.gep(extra_struct,
                                        (lc.Constant.int(int32_type, 0),
                                         lc.Constant.int(int32_type,
                                                input_field_indices[-1]),
                                         lc.Constant.int(intp_type, j)))
                        sz_from_extra = builder.load(sz_from_extra_ptr)
                        shape_el_ptr = builder.gep(arr_var,
                                        (lc.Constant.int(int32_type, 0),
                                         lc.Constant.int(int32_type, 1),
                                         lc.Constant.int(intp_type, j)))
                        builder.store(sz_from_extra, shape_el_ptr)
                    else:
                        raise TypeError(("unbound_single_ckernel codegen doesn't " +
                                        "support dimension type %r") % type(sz))
                builder.call(func, args + [arr_var])
            else:
                raise TypeError(("single_ckernel codegen doesn't " +
                                "support kind %r") % kind)
            builder.ret_void()

            #print("Function before optimization passes:")
            #print(single_ck_func)
            #module.verify()

            import llvm.ee as le
            from llvm.passes import build_pass_managers
            tm = le.TargetMachine.new(opt=3, cm=le.CM_JITDEFAULT, features='')
            pms = build_pass_managers(tm, opt=3, fpm=False,
                            vectorize=True, loop_vectorize=True)
            pms.pm.run(module)

            #print("Function after optimization passes:")
            #print(single_ck_func)

            # DEBUGGING: Verify the module.
            #module.verify()
            # TODO: Cache the EE - the interplay with the func_ptr
            #       was broken, so just avoiding caching for now
            # FIXME: Temporarily disabling AVX, because of misdetection
            #        in linux VMs. Some code is in llvmpy's workarounds
            #        submodule related to this.
            ee = le.EngineBuilder.new(module).mattrs("-avx").create()
            func_ptr = ee.get_pointer_to_function(single_ck_func)
            # Create a function which copies the shape from data
            # descriptors to the extra data struct.
            if len(kernel_data_ctypes_fields) == 1:
                def bind_func(estruct, dst_dd, src_dd_list):
                    pass
            else:
                def bind_func(estruct, dst_dd, src_dd_list):
                    for i, (ds, dd) in enumerate(
                                    izip(self.dshapes, src_dd_list + [dst_dd])):
                        shape = [operator.index(dim)
                                        for dim in dd.dshape[-len(ds):-1]]
                        cshape = getattr(estruct, 'operand_%d' % i)
                        for j, dim_size in enumerate(shape):
                            cshape[j] = dim_size

            self._unbound_single_ckernel = UnboundCKernelFunction(
                            ExprSingleOperation(func_ptr),
                            kernel_data_ctypestype,
                            bind_func,
                            (ee, func_ptr))

        return self._unbound_single_ckernel
Example #29
0
def str_to_kind(str):
    trial = eval(str)
    if trial not in array_kinds:
        raise ValueError("Invalid Array Kind")
    return trial


void_type = C.void
int32_type = C.int32
char_type = C.char
int16_type = C.int16
intp_type = C.intp

diminfo_type = Type.struct(
    [
        intp_type,  # shape
        intp_type  # stride
    ],
    name='diminfo')

_cache = {}


# This is the way we define LLVM arrays.
#  CONTIGUOUS and STRIDED are strongly encouraged...
def array_type(nd, kind, el_type=char_type):
    key = (kind, nd, el_type)
    if _cache.has_key(key):
        return _cache[key]

    base = kind & (~(HAS_ND | HAS_DIMKIND))
    if base == C_CONTIGUOUS:
Example #30
0
 def get_struct_type(self, struct):
     """
     Get the LLVM struct type for the given Structure class *struct*.
     """
     fields = [self.get_struct_member_type(v) for _, v in struct._fields]
     return Type.struct(fields)
Example #31
0
    def get_data_type(self, ty):
        """
        Get a data representation of the type that is safe for storage.
        Record data are stored as byte array.

        Returns None if it is an opaque pointer
        """
        try:
            fac = type_registry.match(ty)
        except KeyError:
            pass
        else:
            return fac(self, ty)

        if (isinstance(ty, types.Dummy) or
                isinstance(ty, types.Module) or
                isinstance(ty, types.Function) or
                isinstance(ty, types.Dispatcher) or
                isinstance(ty, types.Object) or
                isinstance(ty, types.Macro)):
            return PYOBJECT

        elif isinstance(ty, types.CPointer):
            dty = self.get_data_type(ty.dtype)
            return Type.pointer(dty)

        elif isinstance(ty, types.Optional):
            return self.get_data_type(ty.type)

        elif isinstance(ty, types.Array):
            return self.get_struct_type(self.make_array(ty))

        elif isinstance(ty, types.UniTuple):
            dty = self.get_value_type(ty.dtype)
            return Type.array(dty, ty.count)

        elif isinstance(ty, types.Tuple):
            dtys = [self.get_value_type(t) for t in ty]
            return Type.struct(dtys)

        elif isinstance(ty, types.Record):
            # Record are represented as byte array
            return Type.struct([Type.array(Type.int(8), ty.size)])

        elif isinstance(ty, types.UnicodeCharSeq):
            charty = Type.int(numpy_support.sizeof_unicode_char * 8)
            return Type.struct([Type.array(charty, ty.count)])

        elif isinstance(ty, types.CharSeq):
            charty = Type.int(8)
            return Type.struct([Type.array(charty, ty.count)])

        elif ty in STRUCT_TYPES:
            return self.get_struct_type(STRUCT_TYPES[ty])

        else:
            try:
                impl = struct_registry.match(ty)
            except KeyError:
                pass
            else:
                return self.get_struct_type(impl(ty))

        if isinstance(ty, types.Pair):
            pairty = self.make_pair(ty.first_type, ty.second_type)
            return self.get_struct_type(pairty)

        else:
            return LTYPEMAP[ty]
Example #32
0
    trial = eval(str)
    if trial not in array_kinds:
        raise ValueError("Invalid Array Kind")
    return trial

void_type = C.void
int32_type = C.int32
char_type = C.char
int16_type = C.int16
intp_type = C.intp
int_type = C.int
char_p_type = lc.Type.pointer(C.char)
void_p_type = C.void_p

diminfo_type = Type.struct([intp_type,    # shape
                            intp_type     # stride
                            ], name='diminfo')

zero_p = lc.Constant.int(intp_type, 0)
one_p = lc.Constant.int(intp_type, 1)

# We use a per-module cache because the LLVM linker wants a new struct
#   with the same name in different modules.
# The linker does *not* like the *same* struct with the *same* name in
#   two different modules.
_cache = {}
# This is the way we define LLVM arrays.
#  C_CONTIGUOUS, F_CONTIGUOUS, and STRIDED are strongly encouraged...
def array_type(nd, kind, el_type=char_type, module=None):
    base = kind & (~(HAS_ND | HAS_DIMKIND))
    if base == C_CONTIGUOUS:
Example #33
0
    def get_data_type(self, ty):
        """
        Get a data representation of the type that is safe for storage.
        Record data are stored as byte array.

        Returns None if it is an opaque pointer
        """
        try:
            fac = type_registry.match(ty)
        except KeyError:
            pass
        else:
            return fac(self, ty)

        if (isinstance(ty, types.Dummy) or
                isinstance(ty, types.Module) or
                isinstance(ty, types.Function) or
                isinstance(ty, types.Dispatcher) or
                isinstance(ty, types.Object) or
                isinstance(ty, types.Macro)):
            return PYOBJECT

        elif isinstance(ty, types.CPointer):
            dty = self.get_data_type(ty.dtype)
            return Type.pointer(dty)

        elif isinstance(ty, types.Optional):
            return self.get_struct_type(self.make_optional(ty))

        elif isinstance(ty, types.Array):
            return self.get_struct_type(self.make_array(ty))

        elif isinstance(ty, types.UniTuple):
            dty = self.get_value_type(ty.dtype)
            return Type.array(dty, ty.count)

        elif isinstance(ty, types.Tuple):
            dtys = [self.get_value_type(t) for t in ty]
            return Type.struct(dtys)

        elif isinstance(ty, types.Record):
            # Record are represented as byte array
            return Type.struct([Type.array(Type.int(8), ty.size)])

        elif isinstance(ty, types.UnicodeCharSeq):
            charty = Type.int(numpy_support.sizeof_unicode_char * 8)
            return Type.struct([Type.array(charty, ty.count)])

        elif isinstance(ty, types.CharSeq):
            charty = Type.int(8)
            return Type.struct([Type.array(charty, ty.count)])

        elif ty in STRUCT_TYPES:
            return self.get_struct_type(STRUCT_TYPES[ty])

        else:
            try:
                impl = struct_registry.match(ty)
            except KeyError:
                pass
            else:
                return self.get_struct_type(impl(ty))

        if isinstance(ty, types.Pair):
            pairty = self.make_pair(ty.first_type, ty.second_type)
            return self.get_struct_type(pairty)

        else:
            return LTYPEMAP[ty]
Example #34
0
 def test_struct_identical(self):
     ta = Type.struct([Type.int(32), Type.float()], name='ta')
     tb = Type.struct([Type.int(32), Type.float()])
     self.assertTrue(ta.is_layout_identical(tb))
Example #35
0
 def test_struct_identical(self):
     ta = Type.struct([Type.int(32), Type.float()], name='ta')
     tb = Type.struct([Type.int(32), Type.float()])
     self.assertTrue(ta.is_layout_identical(tb))
Example #36
0
 def get_struct_type(self, struct):
     fields = [self.get_data_type(v) for _, v in struct._fields]
     return Type.struct(fields)
Example #37
0
 def test_struct_identical(self):
     m = Module.new("test_struct_identical")
     ta = Type.struct([Type.int(32), Type.float()], name="ta")
     tb = Type.struct([Type.int(32), Type.float()])
     self.assertTrue(ta.is_layout_identical(tb))
Example #38
0
float_type = lc.Type.double()
bool_type  = lc.Type.int(1)
void_type  = lc.Type.void()
char_type  = lc.Type.int(8)

vec_type = lambda width, elt_type: Type.vector(elt_type, width)

pointer = Type.pointer

any_type = pointer(Type.int(ptrsize))
string_type = pointer(char_type)

# naive array
array_type = lambda elt_type: Type.struct([
    pointer(elt_type), # data      | (<type>)*
    int_type,          # nd        | int
    pointer(int_type), # strides   | int*
], name='ndarray_' + str(elt_type))

intp_type = Type.pointer(int_type)

#------------------------------------------------------------------------
# Array Types
#------------------------------------------------------------------------

# Contiguous or Fortran
# ---------------------
#
# struct {
#    eltype *data;
#    intp shape[nd];
Example #39
0
def array_type(elt_type):
    return Type.struct([
        pointer(elt_type),  # data
        int_type,           # dimensions
        pointer(int_type),  # shape
    ], name='ndarray_' + str(elt_type))
Example #40
0
def ArrayF_Type(eltype):
    return Type.struct([
        pointer(eltype),    # data   | (<type>)*
        intp_type,          # shape  | intp
    ], name='Array_F<' + str(eltype) + '>')
Example #41
0
#!/usr/bin/env python3
from llvm.core import Module, Constant, Type, Function, Builder, FCMP_ULT

PTR = lambda t: Type.pointer(t)
Int8  = Type.int(8)
Int32 = Type.int(32)
Int64 = Type.int(64)
Void  = Type.void()
STR   = PTR(Int8)
STRArray = PTR(STR)
STRList = Type.struct([Int64, STRArray], "STRList")

# class STRList:
#   type = None
#   def __init__(self, size):
#     # assert all(type(v) == type(values[0]) for v in values), \
#       # "all elements of list should be of the same type"
#     self.size = size

#   def codegen(self):
#     self.type = STRList



def argv(func):
  global module
  blk = func.append_basic_block("args")
  builder = Builder.new(blk)
  # fn = module.get_function_named("mainargs")
  fn = LLVMFunction("mainargs", args=[Int32, STRArray], ret=PTR(STRList), m=module)
  # print(fn.type.pointee.args)
Example #42
0
 def get_struct_type(self, struct):
     """
     Get the LLVM struct type for the given Structure class *struct*.
     """
     fields = [self.get_struct_member_type(v) for _, v in struct._fields]
     return Type.struct(fields)
Example #43
0
def ArrayS_Type(eltype):
    return Type.struct([
        pointer(eltype),             # data   | (<type>)*
        Type.array(diminfo_type, 2), # shape  | diminfo
    ], name='Array_S<' + str(eltype) + '>')
Example #44
0
_trace_refs_ = hasattr(sys, 'getobjects')
_plat_bits = struct_.calcsize('@P') * 8

_int8 = Type.int(8)
_int32 = Type.int(32)

_void_star = Type.pointer(_int8)

_int8_star = _void_star

_sizeof_py_ssize_t = ctypes.sizeof(getattr(ctypes, 'c_size_t'))
_llvm_py_ssize_t = Type.int(_sizeof_py_ssize_t * 8)

if _trace_refs_:
    _pyobject_head = Type.struct([_void_star, _void_star,
                                  _llvm_py_ssize_t, _void_star])
    _pyobject_head_init = Constant.struct([
        Constant.null(_void_star),            # _ob_next
        Constant.null(_void_star),            # _ob_prev
        Constant.int(_llvm_py_ssize_t, 1),    # ob_refcnt
        Constant.null(_void_star),            # ob_type
        ])

else:
    _pyobject_head = Type.struct([_llvm_py_ssize_t, _void_star])
    _pyobject_head_init = Constant.struct([
        Constant.int(_llvm_py_ssize_t, 1),    # ob_refcnt
        Constant.null(_void_star),            # ob_type
        ])

_pyobject_head_p = Type.pointer(_pyobject_head)
Example #45
0
_trace_refs_ = hasattr(sys, 'getobjects')
_plat_bits = struct_.calcsize('@P') * 8

_int8 = Type.int(8)
_int32 = Type.int(32)

_void_star = Type.pointer(_int8)

_int8_star = _void_star

_sizeof_py_ssize_t = ctypes.sizeof(getattr(ctypes, 'c_size_t'))
_llvm_py_ssize_t = Type.int(_sizeof_py_ssize_t * 8)

if _trace_refs_:
    _pyobject_head = Type.struct(
        [_void_star, _void_star, _llvm_py_ssize_t, _void_star])
    _pyobject_head_init = Constant.struct([
        Constant.null(_void_star),  # _ob_next
        Constant.null(_void_star),  # _ob_prev
        Constant.int(_llvm_py_ssize_t, 1),  # ob_refcnt
        Constant.null(_void_star),  # ob_type
    ])

else:
    _pyobject_head = Type.struct([_llvm_py_ssize_t, _void_star])
    _pyobject_head_init = Constant.struct([
        Constant.int(_llvm_py_ssize_t, 1),  # ob_refcnt
        Constant.null(_void_star),  # ob_type
    ])

_pyobject_head_p = Type.pointer(_pyobject_head)
Example #46
0
int_type   = Type.int()
float_type = Type.double()
bool_type  = Type.int(1)
void_type  = Type.void()
char_type  = Type.int(8)

pointer = Type.pointer

any_type   = pointer(Type.int(ptrsize))
string_type = pointer(char_type)

# { i32*, i32, i32* }
array_type = lambda elt_type: Type.struct([
    pointer(elt_type), # data         | (<type>)*
    int_type,          # dimensions   | int
    pointer(int_type), # strides      | int*
], name='ndarray_' + str(elt_type))

# opaque for now
blaze_type = lambda datashape: Type.opaque(name="blaze")

#------------------------------------------------------------------------
# Constants
#------------------------------------------------------------------------

false = Constant.int(bool_type, 0)
true  = Constant.int(bool_type, 1)
zero  = Constant.int(int_type, 0)

#------------------------------------------------------------------------