def test_stringliteral_to_unicode(self): # See issue #6907, explicit signature on bar() takes a unicode_type but # the call to bar() in foo() is with a StringLiteral @jit(types.void(types.unicode_type), nopython=True) def bar(string): pass @jit(types.void(), nopython=True) def foo2(): bar("literal string")
def omnisci_column_set_null_(typingctx, col_var, row_idx): # Float values are serialized as integers by OmniSciDB # For reference, here is the conversion table for float and double # FLOAT: 1.1754944e-38 -> 8388608 # DOUBLE: 2.2250738585072014e-308 -> 4503599627370496 # ^ ^ # fp value serialized T = col_var.eltype sig = types.void(col_var, row_idx) target_info = TargetInfo() null_value = target_info.null_values[str(T)] def codegen(context, builder, signature, args): zero = int32_t(0) data, index = args assert data.opname == 'load' buf = data.operands[0] ptr = builder.load(builder.gep(buf, [zero, zero])) ty = ptr.type.pointee nv = ir.Constant(ir.IntType(T.bitwidth), null_value) if isinstance(T, types.Float): nv = builder.bitcast(nv, ty) builder.store(nv, builder.gep(ptr, [index])) return sig, codegen
def barrier_no_arg_impl(context, builder, sig, args): assert not args sig = types.void(types.uint32) barrier = _declare_function(context, builder, "barrier", sig, ["unsigned int"]) flags = context.get_constant(types.uint32, enums.CLK_GLOBAL_MEM_FENCE) builder.call(barrier, [flags]) return _void_value
def free_omnisci_buffer(typingctx, ret): sig = types.void(ret) def codegen(context, builder, signature, args): buffers = builder_buffers[builder] # TODO: using stdlib `free` that works only for CPU. For CUDA # devices, we need to use omniscidb provided deallocator. free_fnty = llvm_ir.FunctionType(void_t, [int8_t.as_pointer()]) free_fn = builder.module.get_or_insert_function(free_fnty, name="free") # We skip the ret pointer iff we're returning a Buffer # otherwise, we free everything if isinstance(ret, BufferPointer): [arg] = args ptr = builder.load(builder.gep(arg, [int32_t(0), int32_t(0)])) ptr = builder.bitcast(ptr, int8_t.as_pointer()) for ptr8 in buffers: with builder.if_then(builder.icmp_signed('!=', ptr, ptr8)): builder.call(free_fn, [ptr8]) else: for ptr8 in buffers: builder.call(free_fn, [ptr8]) del builder_buffers[builder] return sig, codegen
def gdb_internal(tyctx): function_sig = types.void() def codegen(cgctx, builder, signature, args): init_gdb_codegen(cgctx, builder, signature, args, const_args, do_break=do_break) return cgctx.get_constant(types.none, None) return function_sig, codegen
def void_func(typingctx, a): sig = types.void(types.int32) def codegen(context, builder, signature, args): pass # do nothing, return None, should be turned into # dummy value return sig, codegen
def printf(typingctx, format_type, *args): """printf that can be called from Numba jit-decorated functions. """ if isinstance(format_type, nb_types.StringLiteral): sig = nb_types.void(format_type, nb_types.BaseTuple.from_types(args)) def codegen(context, builder, signature, args): cgutils.printf(builder, format_type.literal_value, *args[1:]) return sig, codegen
def bp_internal(tyctx): function_sig = types.void() def codegen(cgctx, builder, signature, args): mod = builder.module fnty = ir.FunctionType(ir.VoidType(), tuple()) breakpoint = mod.get_or_insert_function(fnty, "numba_gdb_breakpoint") builder.call(breakpoint, tuple()) return cgctx.get_constant(types.none, None) return function_sig, codegen
def specialize(self, *args): ''' Create a new instance of this dispatcher specialized for the given *args*. ''' argtypes = tuple( [self.typingctx.resolve_argument_type(a) for a in args]) targetoptions = self.targetoptions targetoptions['link'] = self.link return Dispatcher(self.py_func, [types.void(*argtypes)], self._bind, targetoptions)
def fflush(typingctx): """fflush that can be called from Numba jit-decorated functions. Note: fflush is available only for CPU target. """ sig = nb_types.void(nb_types.void) def codegen(context, builder, signature, args): target_info = TargetInfo() if target_info.is_cpu: cg_fflush(builder) return sig, codegen
def memcpy_region(typingctx, dst, dst_offset, src, src_offset, nbytes, align): """Copy nbytes from *(src + src_offset) to *(dst + dst_offset)""" def codegen(context, builder, signature, args): [ dst_val, dst_offset_val, src_val, src_offset_val, nbytes_val, align_val ] = args src_ptr = builder.gep(src_val, [src_offset_val]) dst_ptr = builder.gep(dst_val, [dst_offset_val]) cgutils.raw_memcpy(builder, dst_ptr, src_ptr, nbytes_val, align_val) return context.get_dummy_value() sig = types.void(types.voidptr, types.intp, types.voidptr, types.intp, types.intp, types.intp) return sig, codegen
def free_all_other_buffers(typingctx, value_to_keep_alive): """ Black magic function which automatically frees all the buffers which were allocated in the function apart the given one. value_to_keep_alive can be of any type: - if it's of a Buffer type, it will be kept alive and not freed - if it's of any other type, all buffers will be freed unconditionally The end user should never call this function explicitly: it is automatically inserted by omnisci_pipeline.AutoFreeBuffers. """ sig = types.void(value_to_keep_alive) def codegen(context, builder, signature, args): buffers = builder_buffers[builder] # TODO: using stdlib `free` that works only for CPU. For CUDA # devices, we need to use omniscidb provided deallocator. target_info = TargetInfo() try: free_buffer_fn_name = target_info.info['fn_free_buffer'] except KeyError as msg: raise UnsupportedError(f'{target_info} does not provide {msg}') free_buffer_fnty = llvm_ir.FunctionType(void_t, [int8_t.as_pointer()]) free_buffer_fn = irutils.get_or_insert_function( builder.module, free_buffer_fnty, free_buffer_fn_name) if isinstance(value_to_keep_alive, BufferPointer): # free all the buffers apart value_to_keep_alive [keep_alive] = args keep_alive_ptr = builder.load( builder.gep(keep_alive, [int32_t(0), int32_t(0)])) keep_alive_ptr = builder.bitcast(keep_alive_ptr, int8_t.as_pointer()) for ptr8 in buffers: with builder.if_then( builder.icmp_signed('!=', keep_alive_ptr, ptr8)): builder.call(free_buffer_fn, [ptr8]) else: # free all the buffers unconditionally for ptr8 in buffers: builder.call(free_buffer_fn, [ptr8]) del builder_buffers[builder] return sig, codegen
def omnisci_udtfmanager_set_output_row_size_(typingctx, mgr, num_rows): sig = types.void(mgr, num_rows) target_info = TargetInfo() if target_info.software[1][:3] < (5, 9, 0): raise UnsupportedError(error_msg % (".".join(map(str, target_info.software[1])))) def codegen(context, builder, sig, args): mgr_ptr, num_rows_arg = args mgr_i8ptr = builder.bitcast(mgr_ptr, i8p) fnty = ir.FunctionType(ir.VoidType(), [i8p, i64]) fn = irutils.get_or_insert_function( builder.module, fnty, "TableFunctionManager_set_output_row_size") builder.call(fn, [mgr_i8ptr, num_rows_arg]) return sig, codegen
def printf(typingctx, format_type, *args): """printf that can be called from Numba jit-decorated functions. Note: printf is available only for CPU target. """ if isinstance(format_type, nb_types.StringLiteral): sig = nb_types.void(format_type, nb_types.BaseTuple.from_types(args)) def codegen(context, builder, signature, args): target_info = TargetInfo() if target_info.is_cpu: cgutils.printf(builder, format_type.literal_value, *args[1:]) cg_fflush(builder) return sig, codegen else: raise TypeError( f'expected StringLiteral but got {type(format_type).__name__}')
def ctor_impl(context, builder, sig, args): """ Generic constructor (__new__) for jitclasses. """ # Allocate the instance inst_typ = sig.return_type alloc_type = context.get_data_type(inst_typ.get_data_type()) alloc_size = context.get_abi_sizeof(alloc_type) meminfo = context.nrt.meminfo_alloc_dtor( builder, context.get_constant(types.uintp, alloc_size), imp_dtor(context, builder.module, inst_typ), ) data_pointer = context.nrt.meminfo_data(builder, meminfo) data_pointer = builder.bitcast(data_pointer, alloc_type.as_pointer()) # Nullify all data builder.store(cgutils.get_null_value(alloc_type), data_pointer) inst_struct = context.make_helper(builder, inst_typ) inst_struct.meminfo = meminfo inst_struct.data = data_pointer # Call the jitted __init__ # TODO: extract the following into a common util init_sig = (sig.return_type,) + sig.args init = inst_typ.jit_methods['__init__'] disp_type = types.Dispatcher(init) call = context.get_function(disp_type, types.void(*init_sig)) _add_linking_libs(context, call) realargs = [inst_struct._getvalue()] + list(args) call(builder, realargs) # Prepare return value ret = inst_struct._getvalue() return imputils.impl_ret_new_ref(context, builder, inst_typ, ret)
def specialize(self, *args): ''' Create a new instance of this dispatcher specialized for the given *args*. ''' cc = get_current_device().compute_capability argtypes = tuple( [self.typingctx.resolve_argument_type(a) for a in args]) if self.specialized: raise RuntimeError('Dispatcher already specialized') specialization = self.specializations.get((cc, argtypes)) if specialization: return specialization targetoptions = self.targetoptions targetoptions['link'] = self.link specialization = Dispatcher(self.py_func, [types.void(*argtypes)], self._bind, targetoptions) self.specializations[cc, argtypes] = specialization return specialization
def free_buffer(typingctx, buf): """ Free a buffer """ sig = types.void(buf) assert isinstance(buf, BufferPointer) def codegen(context, builder, signature, args): # TODO: using stdlib `free` that works only for CPU. For CUDA # devices, we need to use omniscidb provided deallocator. target_info = TargetInfo() free_buffer_fn_name = target_info.info['fn_free_buffer'] free_buffer_fnty = llvm_ir.FunctionType(void_t, [int8_t.as_pointer()]) free_buffer_fn = irutils.get_or_insert_function( builder.module, free_buffer_fnty, free_buffer_fn_name) [buf] = args buf_ptr = builder.load(builder.gep( buf, [int32_t(0), int32_t(0)])) # buf.ptr buf_ptr = builder.bitcast(buf_ptr, int8_t.as_pointer()) builder.call(free_buffer_fn, [buf_ptr]) return sig, codegen
def set_output_row_size(typingctx, set_output_row_size): """``set_output_row_size`` sets the row size of output Columns and allocates the corresponding column buffers .. note:: ``set_output_row_size`` is available only for CPU target and OmniSciDB v5.7 or newer """ # void is declared as 'none' in Numba and 'none' is converted to a void* (int8*). See: # https://github.com/numba/numba/blob/6881dfe3883d1344014ea16185ed87de4b75b9a1/numba/core/types/__init__.py#L95 sig = nb_types.void(nb_types.int64) def codegen(context, builder, sig, args): target_info = TargetInfo() if target_info.software[1][:3] < (5, 7, 0): msg = 'set_output_row_size is only available in OmniSciDB 5.7 or newer' raise UnsupportedError(msg) fnty = ir.FunctionType(ir.VoidType(), [ir.IntType(64)]) fn = irutils.get_or_insert_function(builder.module, fnty, name="set_output_row_size") assert fn.is_declaration builder.call(fn, args) # don't return anything return sig, codegen
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. """
@box(CharType) def box_char(typ, val, c): """ """ fnty = lir.FunctionType(lir.IntType(8).as_pointer(), [lir.IntType(8)]) fn = c.builder.module.get_or_insert_function(fnty, name="get_char_ptr") c_str = c.builder.call(fn, [val]) pystr = c.pyapi.string_from_string_and_size( c_str, c.context.get_constant(types.intp, 1)) # TODO: delete ptr return pystr del_str = types.ExternalFunction("del_str", types.void(std_str_type)) _hash_str = types.ExternalFunction("_hash_str", types.int64(std_str_type)) get_c_str = types.ExternalFunction("get_c_str", types.voidptr(std_str_type)) @overload_method(StringType, 'c_str') def str_c_str(str_typ): return lambda s: get_c_str(s) @overload_method(StringType, 'join') def str_join(str_typ, iterable_typ): # TODO: more efficient implementation (e.g. C++ string buffer) def str_join_impl(sep_str, str_container): res = "" counter = 0