def cprint_lower(context, builder, sig, args): from sdc.str_ext import string_type, char_type for i, val in enumerate(args): typ = sig.args[i] if typ == string_type: fnty = lir.FunctionType(lir.VoidType(), [lir.IntType(8).as_pointer()]) fn = cgutils.get_or_insert_function(builder.module, fnty, name="print_str") builder.call(fn, [val]) cgutils.printf(builder, " ") continue if typ == char_type: fnty = lir.FunctionType(lir.VoidType(), [lir.IntType(8)]) fn = cgutils.get_or_insert_function(builder.module, fnty, name="print_char") builder.call(fn, [val]) cgutils.printf(builder, " ") continue if isinstance(typ, types.ArrayCTypes): cgutils.printf(builder, "%p ", val) continue format_str = typ_to_format[typ] cgutils.printf(builder, "%{} ".format(format_str), val) cgutils.printf(builder, "\n") return context.get_dummy_value()
def impl(context, builder, sig, args): context.nrt._require_nrt() size, align = args mod = builder.module u32 = ir.IntType(32) voidptr = cgutils.voidptr_t get_alloc_fnty = ir.FunctionType(voidptr, ()) get_alloc_fn = cgutils.get_or_insert_function( mod, get_alloc_fnty, name="_nrt_get_sample_external_allocator" ) ext_alloc = builder.call(get_alloc_fn, ()) fnty = ir.FunctionType(voidptr, [cgutils.intp_t, u32, voidptr]) fn = cgutils.get_or_insert_function( mod, fnty, name="NRT_MemInfo_alloc_safe_aligned_external" ) fn.return_value.add_attribute("noalias") if isinstance(align, builtins.int): align = context.get_constant(types.uint32, align) else: assert align.type == u32, "align must be a uint32" call = builder.call(fn, [size, align, ext_alloc]) call.name = "allocate_MyArray" return call
def impl(context, builder, sig, args): context.nrt._require_nrt() size, align = args mod = builder.module u32 = ir.IntType(32) # Get the Numba external allocator for USM memory. ext_allocator_fnty = ir.FunctionType(cgutils.voidptr_t, []) ext_allocator_fn = cgutils.get_or_insert_function( mod, ext_allocator_fnty, name="usmarray_get_ext_allocator" ) ext_allocator = builder.call(ext_allocator_fn, []) # Get the Numba function to allocate an aligned array with an external allocator. fnty = ir.FunctionType( cgutils.voidptr_t, [cgutils.intp_t, u32, cgutils.voidptr_t] ) fn = cgutils.get_or_insert_function( mod, fnty, name="NRT_MemInfo_alloc_safe_aligned_external" ) fn.return_value.add_attribute("noalias") if isinstance(align, builtins.int): align = context.get_constant(types.uint32, align) else: assert align.type == u32, "align must be a uint32" call = builder.call(fn, [size, align, ext_allocator]) call.name = "allocate_UsmArray" return call
def _get_equal(context, module, datamodel, container_element_type): assert datamodel.contains_nrt_meminfo() fe_type = datamodel.fe_type data_ptr_ty = datamodel.get_data_type().as_pointer() wrapfnty = context.call_conv.get_function_type(types.int32, [fe_type, fe_type]) argtypes = [fe_type, fe_type] def build_wrapper(fn): builder = Builder(fn.append_basic_block()) args = context.call_conv.decode_arguments(builder, argtypes, fn) sig = typing.signature(types.boolean, fe_type, fe_type) op = operator.eq fnop = context.typing_context.resolve_value_type(op) fnop.get_call_type(context.typing_context, sig.args, {}) eqfn = context.get_function(fnop, sig) res = eqfn(builder, args) intres = context.cast(builder, res, types.boolean, types.int32) context.call_conv.return_value(builder, intres) wrapfn = cgutils.get_or_insert_function( module, wrapfnty, name='.numba_{}.{}_equal.wrap'.format(context.fndesc.mangled_name, container_element_type)) build_wrapper(wrapfn) equal_fnty = ir.FunctionType(ir.IntType(32), [data_ptr_ty, data_ptr_ty]) equal_fn = cgutils.get_or_insert_function( module, equal_fnty, name='.numba_{}.{}_equal'.format(context.fndesc.mangled_name, container_element_type), ) builder = Builder(equal_fn.append_basic_block()) lhs = datamodel.load_from_data_pointer(builder, equal_fn.args[0]) rhs = datamodel.load_from_data_pointer(builder, equal_fn.args[1]) status, retval = context.call_conv.call_function( builder, wrapfn, types.boolean, argtypes, [lhs, rhs], ) with builder.if_then(status.is_ok, likely=True): with builder.if_then(status.is_none): builder.ret(context.get_constant(types.int32, 0)) retval = context.cast(builder, retval, types.boolean, types.int32) builder.ret(retval) # Error out builder.ret(context.get_constant(types.int32, -1)) return equal_fn
def codegen(cgctx, builder, sig, llargs): name = overloadable_function.__name__ struct_ptr = cgutils.create_struct_proxy(inst)(cgctx, builder, value=llargs[0]) # Get the 'state' and 'fnptr_next_(type)' members of the struct state = struct_ptr.state next_double_addr = getattr(struct_ptr, f'fnptr_{name}') # LLVM IR types needed ll_void_ptr_t = cgctx.get_value_type(types.voidptr) ll_return_t = cgctx.get_value_type(return_type) ll_uintp_t = cgctx.get_value_type(types.uintp) # Convert the stored Generator function address to a pointer next_fn_fnptr = builder.inttoptr(next_double_addr, ll_void_ptr_t) # Add the function to the module fnty = ir.FunctionType(ll_return_t, (ll_uintp_t, )) next_fn = cgutils.get_or_insert_function(builder.module, fnty, name) # Bit cast the function pointer to the function type fnptr_as_fntype = builder.bitcast(next_fn_fnptr, next_fn.type) # call it with the "state" address as the arg ret = builder.call(fnptr_as_fntype, (state, )) return ret
def define_dtor(self): "Define the destructor if not already defined" context = self._context builder = self._builder mod = builder.module # Declare dtor fnty = ir.FunctionType(ir.VoidType(), [cgutils.voidptr_t]) fn = cgutils.get_or_insert_function(mod, fnty, '.dtor.list.{}'.format(self.dtype)) if not fn.is_declaration: # End early if the dtor is already defined return fn fn.linkage = 'linkonce_odr' # Populate the dtor builder = ir.IRBuilder(fn.append_basic_block()) base_ptr = fn.args[0] # void* # get payload payload = ListPayloadAccessor(context, builder, self._ty, base_ptr) # Loop over all data to decref intp = payload.size.type with cgutils.for_range_slice(builder, start=intp(0), stop=payload.size, step=intp(1), intp=intp) as (idx, _): val = payload.getitem(idx) context.nrt.decref(builder, self.dtype, val) builder.ret_void() return fn
def codegen(context, builder, sig, args): fnty = ir.FunctionType( ll_status, [ll_list_type, ll_bytes], ) [l, item] = args [tl, titem] = sig.args fn = cgutils.get_or_insert_function(builder.module, fnty, 'numba_list_append') dm_item = context.data_model_manager[titem] data_item = dm_item.as_data(builder, item) ptr_item = cgutils.alloca_once_value(builder, data_item) lp = _container_get_data(context, builder, tl, l) status = builder.call( fn, [ lp, _as_bytes(builder, ptr_item), ], ) return status
def _list_codegen_set_method_table(context, builder, lp, itemty): vtablety = ir.LiteralStructType([ ll_voidptr_type, # item incref ll_voidptr_type, # item decref ]) setmethod_fnty = ir.FunctionType( ir.VoidType(), [ll_list_type, vtablety.as_pointer()]) setmethod_fn = cgutils.get_or_insert_function( builder.module, setmethod_fnty, 'numba_list_set_method_table') vtable = cgutils.alloca_once(builder, vtablety, zfill=True) # install item incref/decref item_incref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 0) item_decref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 1) dm_item = context.data_model_manager[itemty] if dm_item.contains_nrt_meminfo(): item_incref, item_decref = _get_incref_decref(context, builder.module, dm_item, "list") builder.store( builder.bitcast(item_incref, item_incref_ptr.type.pointee), item_incref_ptr, ) builder.store( builder.bitcast(item_decref, item_decref_ptr.type.pointee), item_decref_ptr, ) builder.call(setmethod_fn, [lp, vtable])
def mark_variable(self, builder, allocavalue, name, lltype, size, line, datamodel=None, argidx=None): arg_index = 0 if argidx is None else argidx m = self.module fnty = ir.FunctionType(ir.VoidType(), [ir.MetaDataType()] * 3) decl = cgutils.get_or_insert_function(m, fnty, 'llvm.dbg.declare') mdtype = self._var_type(lltype, size, datamodel=datamodel) name = name.replace('.', '$') # for gdb to work correctly mdlocalvar = m.add_debug_info( 'DILocalVariable', { 'name': name, 'arg': arg_index, 'scope': self.subprograms[-1], 'file': self.difile, 'line': line, 'type': mdtype, }) mdexpr = m.add_debug_info('DIExpression', {}) return builder.call(decl, [allocavalue, mdlocalvar, mdexpr])
def lower_dist_comm_req_dealloc(context, builder, sig, args): fnty = lir.FunctionType(lir.VoidType(), [lir.IntType(8).as_pointer()]) fn = cgutils.get_or_insert_function(builder.module, fnty, name="comm_req_dealloc") builder.call(fn, args) return context.get_dummy_value()
def lower_dist_wait(context, builder, sig, args): fnty = lir.FunctionType( lir.IntType(32), [mpi_req_llvm_type, lir.IntType(1)]) fn = cgutils.get_or_insert_function(builder.module, fnty, name="hpat_dist_wait") return builder.call(fn, args)
def lower_dist_isend(context, builder, sig, args): # store an int to specify data type typ_enum = _numba_to_c_type_map[sig.args[0].dtype] typ_arg = context.get_constant(types.int32, typ_enum) out = make_array(sig.args[0])(context, builder, args[0]) if len(args) == 4: cond_arg = context.get_constant(types.boolean, True) else: cond_arg = args[4] call_args = [ builder.bitcast(out.data, lir.IntType(8).as_pointer()), args[1], typ_arg, args[2], args[3], cond_arg ] # array, size, extra arg type for type enum # pe, tag, cond arg_typs = [ lir.IntType(8).as_pointer(), lir.IntType(32), lir.IntType(32), lir.IntType(32), lir.IntType(32), lir.IntType(1) ] fnty = lir.FunctionType(mpi_req_llvm_type, arg_typs) fn = cgutils.get_or_insert_function(builder.module, fnty, name="hpat_dist_isend") return builder.call(fn, call_args)
def getpointer_from_string(context, builder, sig, args): val = args[0] fnty = lir.FunctionType(lir.IntType(8).as_pointer(), [lir.IntType(8).as_pointer()]) fn = cgutils.get_or_insert_function(builder.module, fnty, name="get_c_str") c_str = builder.call(fn, [val]) return c_str
def core(context, builder, sig, args): lmod = builder.module fretty = context.get_value_type(retty) fargtys = [context.get_value_type(arg.ty) for arg in nbargs] fnty = ir.FunctionType(fretty, fargtys) fn = cgutils.get_or_insert_function(lmod, fnty, func) return builder.call(fn, args)
def call_native_getiter(context, builder, dict_type, dict_val, it): """ This function should produce LLVM code for calling native hashmap_getiter and fill iterator data accordingly """ ty_key, ty_val = dict_type.key_type, dict_type.value_type key_type_postfix, value_type_postfix = _get_types_postfixes(ty_key, ty_val) nrt_table = context.nrt.get_nrt_api(builder) llvoidptr = context.get_value_type(types.voidptr) fnty = lir.FunctionType( llvoidptr, [it.meminfo.type.as_pointer(), llvoidptr, llvoidptr]) func_name = f"hashmap_getiter_{key_type_postfix}_to_{value_type_postfix}" fn_hashmap_getiter = cgutils.get_or_insert_function(builder.module, fnty, name=func_name) cdict = cgutils.create_struct_proxy(dict_type)(context, builder, value=dict_val) it.state = builder.call( fn_hashmap_getiter, [it._get_ptr_by_name('meminfo'), nrt_table, cdict.data_ptr]) # store the reference to parent and incref it.parent = dict_val if context.enable_nrt: context.nrt.incref(builder, dict_type, dict_val)
def declare_vprint(lmod): voidptrty = ir.PointerType(ir.IntType(8)) # NOTE: the second argument to vprintf() points to the variable-length # array of arguments (after the format) vprintfty = ir.FunctionType(ir.IntType(32), [voidptrty, voidptrty]) vprintf = cgutils.get_or_insert_function(lmod, vprintfty, "vprintf") return vprintf
def ptx_syncwarp_mask(context, builder, sig, args): fname = 'llvm.nvvm.bar.warp.sync' lmod = builder.module fnty = ir.FunctionType(ir.VoidType(), (ir.IntType(32), )) sync = cgutils.get_or_insert_function(lmod, fnty, fname) builder.call(sync, args) return context.get_dummy_value()
def lower_dist_allgather(context, builder, sig, args): arr_typ = sig.args[0] val_typ = sig.args[1] assert val_typ == arr_typ.dtype # type enum arg assert val_typ in _numba_to_c_type_map, "invalid allgather type" typ_enum = _numba_to_c_type_map[val_typ] typ_arg = context.get_constant(types.int32, typ_enum) # size arg is 1 for now size_arg = context.get_constant(types.int32, 1) val_ptr = cgutils.alloca_once_value(builder, args[1]) out = make_array(sig.args[0])(context, builder, args[0]) call_args = [ builder.bitcast(out.data, lir.IntType(8).as_pointer()), size_arg, val_ptr, typ_arg ] fnty = lir.FunctionType(lir.VoidType(), [ lir.IntType(8).as_pointer(), lir.IntType(32), val_ptr.type, lir.IntType(32) ]) fn = cgutils.get_or_insert_function(builder.module, fnty, name="allgather") builder.call(fn, call_args) return context.get_dummy_value()
def declare_external_function(self, module, fndesc): fnty = self.get_external_function_type(fndesc) fn = cgutils.get_or_insert_function(module, fnty, fndesc.mangled_name) assert fn.is_declaration for ak, av in zip(fndesc.args, fn.args): av.name = "arg.%s" % ak return fn
def codegen(context, builder, sig, args): table_pyobject = args[1] nrt_table = context.nrt.get_nrt_api(builder) arrow_table = cgutils.create_struct_proxy(sig.return_type)(context, builder) fnty = lir.FunctionType( lir.VoidType(), [ lir.IntType(8).as_pointer(), # ptr to pyarrow table arrow_table.meminfo.type.as_pointer(), # meminfo to fill lir.IntType(8).as_pointer(), ]) # NRT API func table func_name = f"create_arrow_table" fn = cgutils.get_or_insert_function(builder.module, fnty, name=func_name) builder.call(fn, [ table_pyobject, arrow_table._get_ptr_by_name('meminfo'), nrt_table ]) arrow_table.table_ptr = context.nrt.meminfo_data( builder, arrow_table.meminfo) return arrow_table._getvalue()
def codegen(cgctx, builder, signature, args): mod = builder.module fnty = ir.FunctionType(ir.VoidType(), tuple()) breakpoint = cgutils.get_or_insert_function(mod, fnty, "numba_gdb_breakpoint") builder.call(breakpoint, tuple()) return cgctx.get_constant(types.none, None)
def _declare_function(context, builder, name, sig, cargs, mangler=mangle_c): """Insert declaration for a opencl builtin function. Uses the Itanium mangler. Args ---- context: target context builder: llvm builder name: str symbol name sig: signature function signature of the symbol being declared cargs: sequence of str C type names for the arguments mangler: a mangler function function to use to mangle the symbol """ mod = builder.module if sig.return_type == types.void: llretty = lc.Type.void() else: llretty = context.get_value_type(sig.return_type) llargs = [context.get_value_type(t) for t in sig.args] fnty = Type.function(llretty, llargs) mangled = mangler(name, cargs) fn = cgutils.get_or_insert_function(mod, fnty, mangled) fn.calling_convention = target.CC_SPIR_FUNC return fn
def codegen(context, builder, sig, args): fnty = ir.FunctionType( ll_status, [ll_dict_type, ll_bytes, ll_hash, ll_bytes, ll_bytes], ) [d, key, hashval, val] = args [td, tkey, thashval, tval] = sig.args fn = cgutils.get_or_insert_function(builder.module, fnty, 'numba_dict_insert') dm_key = context.data_model_manager[tkey] dm_val = context.data_model_manager[tval] data_key = dm_key.as_data(builder, key) data_val = dm_val.as_data(builder, val) ptr_key = cgutils.alloca_once_value(builder, data_key) cgutils.memset_padding(builder, ptr_key) ptr_val = cgutils.alloca_once_value(builder, data_val) # TODO: the ptr_oldval is not used. needed for refct ptr_oldval = cgutils.alloca_once(builder, data_val.type) dp = _container_get_data(context, builder, td, d) status = builder.call( fn, [ dp, _as_bytes(builder, ptr_key), hashval, _as_bytes(builder, ptr_val), _as_bytes(builder, ptr_oldval), ], ) return status
def impl_dict_getiter(context, builder, sig, args): """Implement iter(Dict). Semantically equivalent to dict.keys() """ [td] = sig.args [d] = args iterablety = types.DictKeysIterableType(td) it = context.make_helper(builder, iterablety.iterator_type) fnty = ir.FunctionType( ir.VoidType(), [ll_dictiter_type, ll_dict_type], ) fn = cgutils.get_or_insert_function(builder.module, fnty, 'numba_dict_iter') proto = ctypes.CFUNCTYPE(ctypes.c_size_t) dictiter_sizeof = proto(_helperlib.c_helpers['dict_iter_sizeof']) state_type = ir.ArrayType(ir.IntType(8), dictiter_sizeof()) pstate = cgutils.alloca_once(builder, state_type, zfill=True) it.state = _as_bytes(builder, pstate) it.parent = d dp = _container_get_data(context, builder, iterablety.parent, args[0]) builder.call(fn, [it.state, dp]) return impl_ret_borrowed( context, builder, sig.return_type, it._getvalue(), )
def codegen(context, builder, sig, args): fnty = ir.FunctionType( ll_status, [ll_dict_type.as_pointer(), ll_ssize_t, ll_ssize_t], ) fn = cgutils.get_or_insert_function(builder.module, fnty, 'numba_dict_new_minsize') # Determine sizeof key and value types ll_key = context.get_data_type(keyty.instance_type) ll_val = context.get_data_type(valty.instance_type) sz_key = context.get_abi_sizeof(ll_key) sz_val = context.get_abi_sizeof(ll_val) refdp = cgutils.alloca_once(builder, ll_dict_type, zfill=True) status = builder.call( fn, [refdp, ll_ssize_t(sz_key), ll_ssize_t(sz_val)], ) _raise_if_error( context, builder, status, msg="Failed to allocate dictionary", ) dp = builder.load(refdp) return dp
def ptx_round(context, builder, sig, args): fn = cgutils.get_or_insert_function( builder.module, ir.FunctionType(ir.IntType(64), (ir.DoubleType(), )), '__nv_llrint') return builder.call(fn, [ context.cast(builder, args[0], sig.args[0], types.double), ])
def copysign_float_impl(context, builder, sig, args): lty = args[0].type mod = builder.module fn = cgutils.get_or_insert_function( mod, lc.Type.function(lty, (lty, lty)), 'llvm.copysign.%s' % lty.intrinsic_name) res = builder.call(fn, args) return impl_ret_untracked(context, builder, sig.return_type, res)
def ptx_cbrt(context, builder, sig, args): ty = sig.return_type fname = cbrt_funcs[ty] fty = context.get_value_type(ty) lmod = builder.module fnty = ir.FunctionType(fty, [fty]) fn = cgutils.get_or_insert_function(lmod, fnty, fname) return builder.call(fn, args)
def pq_size_lower(context, builder, sig, args): fnty = lir.FunctionType(lir.IntType(64), [lir.IntType(8).as_pointer(), lir.IntType(64)]) fn = cgutils.get_or_insert_function(builder.module, fnty, name="pq_get_size") return builder.call(fn, args)
def ptx_brev_u8(context, builder, sig, args): # FIXME the llvm.bitreverse.i64 intrinsic isn't supported by nvcc # return builder.bitreverse(args[0]) fn = cgutils.get_or_insert_function( builder.module, ir.FunctionType(ir.IntType(64), (ir.IntType(64), )), '__nv_brevll') return builder.call(fn, args)