def _list_length(typingctx, l): """Wrap numba_list_length Returns the length of the list. """ sig = types.intp(l) def codegen(context, builder, sig, args): [tl] = sig.args [l] = args fnty = ir.FunctionType( ll_ssize_t, [ll_list_type], ) fname = 'numba_list_size_address' fn = builder.module.get_or_insert_function(fnty, name=fname) fn.attributes.add('alwaysinline') fn.attributes.add('readonly') fn.attributes.add('nounwind') lp = _container_get_data(context, builder, tl, l) len_addr = builder.call( fn, [ lp, ], ) ptr = builder.inttoptr(len_addr, cgutils.intp_t.as_pointer()) return builder.load(ptr) return sig, codegen
def fix_index(tyctx, list_ty, index_ty): sig = types.intp(list_ty, index_ty) def codegen(context, builder, sig, args): [list_ty, index_ty] = sig.args [ll_list, ll_idx] = args is_negative = builder.icmp_signed('<', ll_idx, ir.Constant(ll_idx.type, 0)) fast_len_sig, length_fn = _list_length._defn(context.typing_context, list_ty) length = length_fn(context, builder, fast_len_sig, (ll_list, )) # length is an intp # index can be any sort of int # indexing in general is done with a ssize_t which correlates to an # intp. In llvmlite sext and trunc are guarded to return the value # itself if the types are the same, so there's no need to handle the # "equal widths" case separately. This sexts/truncs the index to the # length type such that `add` works for the wraparound case. st = 'sext' if ll_idx.type.width < length.type.width else 'trunc' op = getattr(builder, st) fixedup_idx = op(ll_idx, length.type) wrapped_index = builder.add(fixedup_idx, length) return builder.select(is_negative, wrapped_index, fixedup_idx) return sig, codegen
def iternext_BufferPointer(context, builder, sig, args, result): [iterbufty] = sig.args [bufiter] = args iterval = context.make_helper(builder, iterbufty, value=bufiter) buf = iterval.buffer idx = builder.load(iterval.index) len_fn = context.typing_context.resolve_value_type(len) len_sig = types.intp(sig.args[0].buffer_type) # if the intrinsic was not called before, one need to "register" it first len_fn.get_call_type(context.typing_context, len_sig.args, {}) count = context.get_function(len_fn, len_sig)(builder, [buf]) is_valid = builder.icmp_signed('<', idx, count) result.set_valid(is_valid) with builder.if_then(is_valid): getitem_fn = context.typing_context.resolve_value_type( operator.getitem) getitem_sig = iterbufty.buffer_type.eltype(iterbufty.buffer_type, types.intp) # same here, "register" the intrinsic before calling it getitem_fn.get_call_type(context.typing_context, getitem_sig.args, {}) getitem_out = context.get_function(getitem_fn, getitem_sig)(builder, [buf, idx]) result.yield_(getitem_out) nidx = builder.add(idx, context.get_constant(types.intp, 1)) builder.store(nidx, iterval.index)
def _prng_random_hash(tyctx): def impl(cgctx, builder, signature, args): state_ptr = get_state_ptr(cgctx, builder, "internal") bits = const_int(types.intp.bitwidth) value = get_next_int(cgctx, builder, state_ptr, bits, False) return value sig = types.intp() return sig, impl
# 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). < 0 : Failed to broadcast onto destination axis, at axis number ==