def test_equality(self): self.assertEqual(types.int32, types.int32) self.assertEqual(types.uint32, types.uint32) self.assertEqual(types.complex64, types.complex64) self.assertEqual(types.float32, types.float32) # Different signedness self.assertNotEqual(types.int32, types.uint32) # Different width self.assertNotEqual(types.int64, types.int32) self.assertNotEqual(types.float64, types.float32) self.assertNotEqual(types.complex64, types.complex128) # Different domain self.assertNotEqual(types.int64, types.float64) self.assertNotEqual(types.uint64, types.float64) self.assertNotEqual(types.complex64, types.float64) # Same arguments but different return types get_pointer = None sig_a = typing.signature(types.intp, types.intp) sig_b = typing.signature(types.voidptr, types.intp) a = types.ExternalFunctionPointer(sig=sig_a, get_pointer=get_pointer) b = types.ExternalFunctionPointer(sig=sig_b, get_pointer=get_pointer) self.assertNotEqual(a, b) # Different call convention a = types.ExternalFunctionPointer(sig=sig_a, get_pointer=get_pointer) b = types.ExternalFunctionPointer(sig=sig_a, get_pointer=get_pointer, cconv='stdcall') self.assertNotEqual(a, b) # Different get_pointer a = types.ExternalFunctionPointer(sig=sig_a, get_pointer=get_pointer) b = types.ExternalFunctionPointer(sig=sig_a, get_pointer=object()) self.assertNotEqual(a, b) # Different template classes bearing the same name class DummyTemplate(object): key = "foo" a = types.BoundFunction(DummyTemplate, types.int32) class DummyTemplate(object): key = "bar" b = types.BoundFunction(DummyTemplate, types.int32) self.assertNotEqual(a, b) # Different dtypes self.assertNotEqual(types.DType(types.int32), types.DType(types.int64)) # CPointer with same addrspace self.assertEqual(types.CPointer(types.float32), types.CPointer(types.float32)) # CPointer with different addrspace self.assertNotEqual(types.CPointer(types.float32, 0), types.CPointer(types.float32, 1))
def _conversion_tests(self, check): check(c_double, types.float64) check(c_int, types.intc) check(c_uint16, types.uint16) check(c_size_t, types.uintp) check(c_ssize_t, types.intp) check(c_void_p, types.voidptr) check(POINTER(c_float), types.CPointer(types.float32)) check(POINTER(POINTER(c_float)), types.CPointer(types.CPointer(types.float32))) check(None, types.void)
def __init__(self, dmm, fe_type): # ndim = fe_type.ndim members = [ ("data", types.CPointer(fe_type.dtype)), ("meminfo", types.MemInfoPointer(fe_type.dtype)), ] super(ArrayCTypesModel, self).__init__(dmm, fe_type, members)
def test_mangling_arg_type_2(dtypes, addrspaces): dtype, expected_dtype_str = dtypes addrspace, expected_addrspace_str = addrspaces got = itanium_mangler.mangle_type( types.CPointer(dtype, addrspace=addrspace)) expected = "PU" + expected_addrspace_str + expected_dtype_str assert got == expected
def _convert_internal(ctypeobj): # Recursive helper if issubclass(ctypeobj, ctypes._Pointer): valuety = _convert_internal(ctypeobj._type_) if valuety is not None: return types.CPointer(valuety) else: return _FROM_CTYPES.get(ctypeobj)
def array_impl_unsafe_get_ctypes_pointer(arrtype): if isinstance(arrtype, types.Array): unsafe_cast = unsafe_caster(types.CPointer(arrtype.dtype)) def array_impl(arr): return unsafe_cast(src=arr.ctypes.data) return array_impl
def __init__(self, dmm, fe_type): array_type = fe_type.array_type dtype = array_type.dtype ndim = array_type.ndim members = [('array', array_type), ('pointers', types.EphemeralArray(types.CPointer(dtype), ndim)), ('indices', types.EphemeralArray(types.intp, ndim)), ('exhausted', types.EphemeralPointer(types.boolean)), ] super(FlatIter, self).__init__(dmm, fe_type, members)
def __init__(self, dmm, fe_typ): cls_data_ty = types.ClassDataType(fe_typ) # MemInfoPointer uses the `dtype` attribute to traverse for nested # NRT MemInfo. Since we handle nested NRT MemInfo ourselves, # we will replace provide MemInfoPointer with an opaque type # so that it does not raise exception for nested meminfo. dtype = types.Opaque('Opaque.' + str(cls_data_ty)) members = [ ('meminfo', types.MemInfoPointer(dtype)), ('data', types.CPointer(cls_data_ty)), ] super(InstanceModel, self).__init__(dmm, fe_typ, members)
def __init__(self, dmm, fe_type): ndim = fe_type.ndim members = [ ( "meminfo", types.CPointer(fe_type.dtype, addrspace=fe_type.addrspace), ), ( "parent", types.CPointer(fe_type.dtype, addrspace=fe_type.addrspace), ), ("nitems", types.intp), ("itemsize", types.intp), ( "data", types.CPointer(fe_type.dtype, addrspace=fe_type.addrspace), ), ("shape", types.UniTuple(types.intp, ndim)), ("strides", types.UniTuple(types.intp, ndim)), ] super(DPPYArrayModel, self).__init__(dmm, fe_type, members)
def omnisci_buffer_get_ptr_(typingctx, data): eltype = data.eltype ptrtype = types.CPointer(eltype) sig = ptrtype(data) def codegen(context, builder, signature, args): data, = args assert data.opname == 'load' struct = data.operands[0] return builder.load(builder.gep(struct, [int32_t(0), int32_t(0)])) return sig, codegen
def omnisci_buffer_ptr_get_ptr_(typingctx, data): eltype = data.eltype ptrtype = types.CPointer(eltype) sig = ptrtype(data) def codegen(context, builder, signature, args): data, = args rawptr = cgutils.alloca_once_value(builder, value=data) struct = builder.load(builder.gep(rawptr, [int32_t(0)])) return builder.load(builder.gep(struct, [int32_t(0), int32_t(0)])) return sig, codegen
def __init__(self, dmm, fe_type): ndim = fe_type.ndim members = [ ("meminfo", types.MemInfoPointer(fe_type.dtype)), ("parent", types.pyobject), ("nitems", types.intp), ("itemsize", types.intp), ("data", types.CPointer(fe_type.dtype)), ("shape", types.UniTuple(types.intp, ndim)), ("strides", types.UniTuple(types.intp, ndim)), ] super(ArrayModel, self).__init__(dmm, fe_type, members)
def __init__(self, dmm, fe_type): ndim = fe_type.ndim members = [ ('meminfo', types.MemInfoPointer(fe_type.dtype)), ('parent', types.pyobject), ('nitems', types.intp), ('itemsize', types.intp), ('data', types.CPointer(fe_type.dtype)), ('shape', types.UniTuple(types.intp, ndim)), ('strides', types.UniTuple(types.intp, ndim)), ] super(ArrayModel, self).__init__(dmm, fe_type, members)
def generic(self, args, kws): if kws or len(args) != 1: return [ary] = args if not isinstance(ary, types.Buffer): raise TypingError( "from_buffer() expected a buffer object, got %s" % (ary, )) if ary.layout not in ('C', 'F'): raise TypingError( "from_buffer() unsupported on non-contiguous buffers (got %s)" % (ary, )) if ary.layout != 'C' and ary.ndim > 1: raise TypingError( "from_buffer() only supports multidimensional arrays with C layout (got %s)" % (ary, )) ptr = types.CPointer(ary.dtype) return templates.signature(ptr, ary)
def map_type(cffi_type, use_record_dtype=False): """ Map CFFI type to numba type. Parameters ---------- cffi_type: The CFFI type to be converted. use_record_dtype: bool (default: False) When True, struct types are mapped to a NumPy Record dtype. """ primed_map_type = partial(map_type, use_record_dtype=use_record_dtype) kind = getattr(cffi_type, 'kind', '') if kind == 'union': raise TypeError("No support for CFFI union") elif kind == 'function': if cffi_type.ellipsis: raise TypeError("vararg function is not supported") restype = primed_map_type(cffi_type.result) argtypes = [primed_map_type(arg) for arg in cffi_type.args] return templates.signature(restype, *argtypes) elif kind == 'pointer': pointee = cffi_type.item if pointee.kind == 'void': return types.voidptr else: return types.CPointer(primed_map_type(pointee)) elif kind == 'array': dtype = primed_map_type(cffi_type.item) nelem = cffi_type.length return types.NestedArray(dtype=dtype, shape=(nelem, )) elif kind == 'struct' and use_record_dtype: return map_struct_to_record_dtype(cffi_type) else: result = _type_map().get(cffi_type) if result is None: raise TypeError(cffi_type) return result
def test_type_parsing(self): ffi = self.get_ffi() # Check struct typedef big_struct = ffi.typeof('big_struct') nbtype = cffi_support.map_type(big_struct, use_record_dtype=True) self.assertIsInstance(nbtype, types.Record) self.assertEqual(len(nbtype), 4) self.assertEqual(nbtype.typeof('i1'), types.int32) self.assertEqual(nbtype.typeof('f2'), types.float32) self.assertEqual(nbtype.typeof('d3'), types.float64) self.assertEqual( nbtype.typeof('af4'), types.NestedArray(dtype=types.float32, shape=(9, )), ) # Check function typedef myfunc = ffi.typeof('myfunc') sig = cffi_support.map_type(myfunc, use_record_dtype=True) self.assertIsInstance(sig, typing.Signature) self.assertEqual(sig.args[0], types.CPointer(nbtype)) self.assertEqual(sig.args[1], types.uintp) self.assertEqual(sig.return_type, types.float64)
@lowering_registry.lower_cast(nb_types.CPointer, nb_types.intp) @lowering_registry.lower_cast(nb_types.RawPointer, nb_types.intp) def impl_T_star_to_intp(context, builder, fromty, toty, value): return builder.ptrtoint(value, ir.IntType(toty.bitwidth)) @lowering_registry.lower_cast(nb_types.CPointer, nb_types.RawPointer) @lowering_registry.lower_cast(nb_types.RawPointer, nb_types.CPointer) def impl_T_star_to_T_star(context, builder, fromty, toty, value): return builder.bitcast(value, Type.fromnumba(toty).tollvmir()) scalar_types = [getattr(nb_types, typename) for typename in ['int64', 'int32', 'int16', 'int8', 'uint64', 'uint32', 'uint16', 'uint8', 'float32', 'float64', 'boolean']] pointer_value_types = [nb_types.intp, nb_types.voidptr] pointer_types = [nb_types.CPointer(s) for s in scalar_types] + [nb_types.voidptr] for p1 in pointer_value_types: for p2 in pointer_types: # ANSI C requires 12 as a maximum supported pointer level. for i in range(12): if p1 != p2: typeconv.rules.default_type_manager.set_compatible( p1, p2, typeconv.Conversion.safe) typeconv.rules.default_type_manager.set_compatible( p2, p1, typeconv.Conversion.safe) p2 = nb_types.CPointer(p2)
scalar_types = [ getattr(nb_types, typename) for typename in [ "int64", "int32", "int16", "int8", "uint64", "uint32", "uint16", "uint8", "float32", "float64", "boolean", ] ] pointer_value_types = [nb_types.intp, nb_types.voidptr] pointer_types = [nb_types.CPointer(s) for s in scalar_types] + [nb_types.voidptr] for p1 in pointer_value_types: for p2 in pointer_types: # ANSI C requires 12 as a maximum supported pointer level. for i in range(12): if p1 != p2: typeconv.rules.default_type_manager.set_compatible( p1, p2, typeconv.Conversion.safe) typeconv.rules.default_type_manager.set_compatible( p2, p1, typeconv.Conversion.safe) p2 = nb_types.CPointer(p2)
out[1:3] = in_.shape out[3:5] = in_.strides out[5] = in_.flags.c_contiguous out[6] = in_.flags.f_contiguous s = 0 for i, j in np.ndindex(m, n): s += in_[i, j] * (i - j) out[7] = s return cfarray_usecase carray_dtype_usecase = make_cfarray_dtype_usecase(carray) farray_dtype_usecase = make_cfarray_dtype_usecase(farray) carray_float32_usecase_sig = types.void(types.CPointer(types.float32), types.CPointer(types.float32), types.intp, types.intp) carray_float64_usecase_sig = types.void(types.CPointer(types.float64), types.CPointer(types.float64), types.intp, types.intp) carray_voidptr_usecase_sig = types.void(types.voidptr, types.voidptr, types.intp, types.intp) class TestCFunc(TestCase): def test_basic(self): """ Basic usage and properties of a cfunc.
class TestPointerOfInt32(test_factory()): fe_type = types.CPointer(types.int32)
# then prepare the arg for a concrete instance if isinstance(tyinp, types.ArrayCompatible): ary = ctxt.make_array(tyinp)(ctxt, bld, inp) shape = cgutils.unpack_tuple(bld, ary.shape, tyinp.ndim) strides = cgutils.unpack_tuple(bld, ary.strides, tyinp.ndim) return _ArrayHelper(ctxt, bld, shape, strides, ary.data, tyinp.layout, tyinp.dtype, tyinp.ndim, inp) elif (types.unliteral(tyinp) in types.number_domain | {types.boolean} or isinstance(tyinp, types.scalars._NPDatetimeBase)): return _ScalarHelper(ctxt, bld, inp, tyinp) else: raise NotImplementedError('unsupported type for {0}: {1}'.format( where, str(tyinp))) _broadcast_onto_sig = types.intp(types.intp, types.CPointer(types.intp), types.intp, types.CPointer(types.intp)) def _broadcast_onto(src_ndim, src_shape, dest_ndim, dest_shape): '''Low-level utility function used in calculating a shape for an implicit output array. This function assumes that the destination shape is an LLVM pointer to a C-style array that was already initialized to a size of one along all axes. Returns an integer value: >= 1 : Succeeded. Return value should equal the number of dimensions in the destination shape. 0 : Failed to broadcast because source shape is larger than the destination shape (this case should be weeded out at type checking).
def native_atomic_add(context, builder, sig, args): aryty, indty, valty = sig.args ary, inds, val = args dtype = aryty.dtype if indty == types.intp: indices = [inds] # just a single integer indty = [indty] else: indices = cgutils.unpack_tuple(builder, inds, count=len(indty)) indices = [ context.cast(builder, i, t, types.intp) for t, i in zip(indty, indices) ] if dtype != valty: raise TypeError("expecting %s but got %s" % (dtype, valty)) if aryty.ndim != len(indty): raise TypeError("indexing %d-D array with %d-D index" % (aryty.ndim, len(indty))) lary = context.make_array(aryty)(context, builder, ary) ptr = cgutils.get_item_pointer(context, builder, aryty, lary, indices) if dtype == types.float32 or dtype == types.float64: context.extra_compile_options[target.LLVM_SPIRV_ARGS] = [ "--spirv-ext=+SPV_EXT_shader_atomic_float_add" ] name = "__spirv_AtomicFAddEXT" elif dtype == types.int32 or dtype == types.int64: name = "__spirv_AtomicIAdd" else: raise TypeError("Unsupported type") assert name != "" ptr_type = context.get_value_type(dtype).as_pointer() ptr_type.addrspace = aryty.addrspace retty = context.get_value_type(sig.return_type) spirv_fn_arg_types = [ ptr_type, ir.IntType(32), ir.IntType(32), context.get_value_type(sig.args[2]), ] from numba_dppy import extended_numba_itanium_mangler as ext_itanium_mangler numba_ptr_ty = types.CPointer(dtype, addrspace=ptr_type.addrspace) mangled_fn_name = ext_itanium_mangler.mangle( name, [ numba_ptr_ty, "__spv.Scope.Flag", "__spv.MemorySemanticsMask.Flag", valty, ], ) fnty = ir.FunctionType(retty, spirv_fn_arg_types) fn = cgutils.get_or_insert_function(builder.module, fnty, mangled_fn_name) fn.calling_convention = target.CC_SPIR_FUNC sycl_memory_order = atomic_helper.sycl_memory_order.relaxed sycl_memory_scope = atomic_helper.sycl_memory_scope.device spirv_scope = atomic_helper.get_scope(sycl_memory_scope) spirv_memory_semantics_mask = atomic_helper.get_memory_semantics_mask( sycl_memory_order) fn_args = [ ptr, context.get_constant(types.int32, spirv_scope), context.get_constant(types.int32, spirv_memory_semantics_mask), val, ] return builder.call(fn, fn_args)
def test_mangling_arg_type(dtypes): dtype, expected_str = dtypes got = itanium_mangler.mangle_type(types.CPointer(dtype)) expected = "P" + expected_str assert got == expected