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]
def get_array_type(typo, length): if typo == 'int': return Type.array(Type.int(32), length) elif typo == 'double': return Type.array(Type.double(), length) elif typo == 'String': ch = Type.int(8) return Type.array(Type.pointer(ch), length) elif typo == 'char': return Type.array(Type.int(8), length)
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]
def testCreateArrayType(self): ty = Type.int8() a = Type.array(ty, 2) self.assertEqual(2, a.array_length()) t = a.element_type() self.assertEqual(ty.name, t.name)
def pack_array(builder, values): n = len(values) ty = values[0].type ary = Constant.undef(Type.array(ty, n)) for i, v in enumerate(values): ary = builder.insert_value(ary, v, i) return ary
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)
def _generic_array(context, builder, shape, dtype, symbol_name, addrspace, can_dynsized=False): elemcount = reduce(operator.mul, shape) lldtype = context.get_data_type(dtype) laryty = Type.array(lldtype, elemcount) if addrspace == nvvm.ADDRSPACE_LOCAL: # Special case local addrespace allocation to use alloca # NVVM is smart enough to only use local memory if no register is # available dataptr = builder.alloca(laryty, name=symbol_name) else: lmod = cgutils.get_module(builder) # Create global variable in the requested address-space gvmem = lmod.add_global_variable(laryty, symbol_name, addrspace) if elemcount <= 0: if can_dynsized: # dynamic shared memory gvmem.linkage = lc.LINKAGE_EXTERNAL else: raise ValueError("array length <= 0") else: gvmem.linkage = lc.LINKAGE_INTERNAL gvmem.initializer = lc.Constant.undef(laryty) if dtype not in types.number_domain: raise TypeError("unsupported type: %s" % dtype) # Convert to generic address-space conv = nvvmutils.insert_addrspace_conv(lmod, Type.int(8), addrspace) addrspaceptr = gvmem.bitcast(Type.pointer(Type.int(8), addrspace)) dataptr = builder.call(conv, [addrspaceptr]) return _make_array(context, builder, dataptr, dtype, shape)
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
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
def testAlloca(self): ty = Type.int8() bldr = Builder.create() a = bldr.alloca(ty, 'a') self.assertEqual(' %a = alloca i8', str(a)) arr = Type.array(ty, 2) b = bldr.alloca(arr, 'b') self.assertEqual(' %b = alloca [2 x i8]', str(b))
def testGEP(self): ty = Type.int64() ptr_ty = Type.int64() bldr = Builder.create() arr_ty = Type.array(ty, 2) a = bldr.alloca(arr_ty, 'a') offset = Value.const_int(ptr_ty, 0, True) b = bldr.gep(a, [offset, offset], 'gep') self.assertEqual(' %gep = getelementptr [2 x i64]* %a, i64 0, i64 0', str(b))
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
def testInsertValue(self): ty = Type.int8() v = Value.const_int(ty, 1, True) n = Value.const_int(ty, 2, True) arr_ty = Type.array(ty, 2) bldr = Builder.create() a = bldr.alloca(arr_ty, 'a') a_content = bldr.load(a, 'content') b = bldr.insert_value(a_content, v, 0, 'b') self.assertEqual(' %b = insertvalue [2 x i8] %content, i8 1, 0', str(b)) c = bldr.extract_value(a_content, 0, 'c') self.assertEqual(' %c = extractvalue [2 x i8] %content, 0', str(c))
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
def code_gen(self): if self.constant_token.lexme_type == LexmeType.Integer: return Constant.int(Helper.get_type(self.constant_token.lexme_type), self.constant_token.word) elif self.constant_token.lexme_type == LexmeType.Double: return Constant.real(Helper.get_type(self.constant_token.lexme_type), self.constant_token.word) elif self.constant_token.lexme_type == LexmeType.String: s = self.constant_token.word.strip('"') global constant_string_num global_string = GlobalVariable.new(g_llvm_module, Type.array(Type.int(8), len(s) + 1), ".str%d" % constant_string_num) constant_string_num += 1 global_string.initializer = Constant.stringz(s) return global_string elif self.constant_token.lexme_type == LexmeType.Char: ascii = ord(self.constant_token.word.strip("'")) return Constant.int(Helper.get_type(self.constant_token.lexme_type), ascii)
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))
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]
def create_global_load_save_array_module(): mod = Module.CreateWithName('module') ty = Type.int8(mod.context) array_ty = Type.array(ty, 2) x = Global.add(mod, array_ty, 'x') v = Value.const_int(ty, 0, True) ptr_ty = Type.int64(mod.context) v0 = Value.const_int(ptr_ty, 0, True) x.initializer = Value.const_array(ty, [v, v]) def create_store(): ft = Type.function(Type.void(), [ty, ptr_ty], False) f = mod.add_function('store', ft) bb = f.append_basic_block('body') bldr = Builder.create(mod.context) bldr.position_at_end(bb) xt = f.get_param(0) offset = f.get_param(1) elem_ptr = bldr.gep(x, [v0, offset], 'elem') bldr.store(xt, elem_ptr) bldr.ret_void() def create_load(): ft = Type.function(ty, [ptr_ty], False) f = mod.add_function('load', ft) bb = f.append_basic_block('body') bldr = Builder.create(mod.context) bldr.position_at_end(bb) offset = f.get_param(0) elem_ptr = bldr.gep(x, [v0, offset], 'elem') y = bldr.load(elem_ptr, 'y') bldr.ret(y) create_store() create_load() return mod
def code_gen(self): if self.constant_token.lexme_type == LexmeType.Integer: return Constant.int( Helper.get_type(self.constant_token.lexme_type), self.constant_token.word) elif self.constant_token.lexme_type == LexmeType.Double: return Constant.real( Helper.get_type(self.constant_token.lexme_type), self.constant_token.word) elif self.constant_token.lexme_type == LexmeType.String: s = self.constant_token.word.strip('"') global constant_string_num global_string = GlobalVariable.new( g_llvm_module, Type.array(Type.int(8), len(s) + 1), ".str%d" % constant_string_num) constant_string_num += 1 global_string.initializer = Constant.stringz(s) return global_string elif self.constant_token.lexme_type == LexmeType.Char: ascii = ord(self.constant_token.word.strip("'")) return Constant.int( Helper.get_type(self.constant_token.lexme_type), ascii)
def llvm_type(type, memo=None): if memo is None: memo = {} if hashable(type) and type in memo: return memo[type] ty = type.__class__ if ty == Boolean: result = Type.int(1) elif ty == Integral: result = Type.int(type.bits) elif type == Float32: result = Type.float() elif type == Float64: result = Type.double() elif ty == Array: result = Type.array(llvm_type(type.base, memo), type.count) elif ty == Vector: result = Type.vector(llvm_type(type.base, memo), type.count) elif ty == Struct: result = handle_struct(type, memo) elif ty == Pointer: if type.base.is_void: return Type.pointer(Type.int(8)) result = Type.pointer(llvm_type(type.base, memo)) elif ty == Function: result = Type.function( llvm_type(type.restype, memo), [llvm_type(argtype, memo) for argtype in type.argtypes], var_arg=type.varargs) elif ty == VoidT: result = Type.void() else: raise TypeError("Cannot convert type %s" % (type,)) memo[type] = result return result
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]
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
def buildMemory(module, maxmem): '''Build memory array''' memoryType = Type.array(Type.int(), maxmem) memory = GlobalVariable.new(module, memoryType, 'memory') memory.initializer = array([num(0)] * maxmem) return memory
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]
def ArrayS_Type(eltype): return Type.struct([ pointer(eltype), # data | (<type>)* Type.array(diminfo_type, 2), # shape | diminfo ], name='Array_S<' + str(eltype) + '>')