def build_wrapper(self, api, builder, closure, args, kws): nargs = len(self.fndesc.args) keywords = self.make_keywords(self.fndesc.args) fmt = self.make_const_string("O" * nargs) objs = [api.alloca_obj() for _ in range(nargs)] parseok = api.parse_tuple_and_keywords(args, kws, fmt, keywords, *objs) pred = builder.icmp(lc.ICMP_EQ, parseok, Constant.null(parseok.type)) with cgutils.if_unlikely(builder, pred): builder.ret(api.get_null_object()) # Block that returns after erroneous argument unboxing/cleanup endblk = cgutils.append_basic_block(builder, "arg.end") with cgutils.goto_block(builder, endblk): builder.ret(api.get_null_object()) cleanup_manager = _ArgManager(builder, api, endblk, nargs) innerargs = [] for obj, ty in zip(objs, self.fndesc.argtypes): val = cleanup_manager.add_arg(obj, ty) innerargs.append(val) if self.release_gil: cleanup_manager = _GilManager(builder, api, cleanup_manager) # The wrapped function doesn't take a full closure, only # the Environment object. env = self.context.get_env_from_closure(builder, closure) status, res = self.context.call_function(builder, self.func, self.fndesc.restype, self.fndesc.argtypes, innerargs, env) # Do clean up cleanup_manager.emit_cleanup() # Determine return status with cgutils.if_likely(builder, status.ok): with cgutils.ifthen(builder, status.none): api.return_none() retval = api.from_native_return(res, self.fndesc.restype) builder.ret(retval) with cgutils.ifthen(builder, builder.not_(status.exc)): # !ok && !exc # User exception raised self.make_exception_switch(api, builder, status.code) # !ok && exc builder.ret(api.get_null_object())
def build_wrapper(self, api, builder, closure, args, kws): nargs = len(self.fndesc.args) objs = [api.alloca_obj() for _ in range(nargs)] parseok = api.unpack_tuple(args, self.fndesc.qualname, nargs, nargs, *objs) pred = builder.icmp(lc.ICMP_EQ, parseok, Constant.null(parseok.type)) with cgutils.if_unlikely(builder, pred): builder.ret(api.get_null_object()) # Block that returns after erroneous argument unboxing/cleanup endblk = cgutils.append_basic_block(builder, "arg.end") with cgutils.goto_block(builder, endblk): builder.ret(api.get_null_object()) cleanup_manager = _ArgManager(self.context, builder, api, endblk, nargs) innerargs = [] for obj, ty in zip(objs, self.fndesc.argtypes): val = cleanup_manager.add_arg(obj, ty) innerargs.append(val) if self.release_gil: cleanup_manager = _GilManager(builder, api, cleanup_manager) # Extract the Environment object from the Closure envptr = self.context.get_env_from_closure(builder, closure) env_body = self.context.get_env_body(builder, envptr) env_manager = api.get_env_manager(self.env, env_body) status, res = self.context.call_conv.call_function( builder, self.func, self.fndesc.restype, self.fndesc.argtypes, innerargs, envptr) # Do clean up cleanup_manager.emit_cleanup() # Determine return status with cgutils.if_likely(builder, status.is_ok): # Ok => return boxed Python value with cgutils.ifthen(builder, status.is_none): api.return_none() retval = api.from_native_return(res, self._simplified_return_type(), env_manager) builder.ret(retval) with cgutils.ifthen(builder, builder.not_(status.is_python_exc)): # User exception raised self.make_exception_switch(api, builder, status) # Error out builder.ret(api.get_null_object())
def build_wrapper(self, api, builder, closure, args, kws): nargs = len(self.fndesc.args) keywords = self.make_keywords(self.fndesc.args) fmt = self.make_const_string("O" * nargs) objs = [api.alloca_obj() for _ in range(nargs)] parseok = api.parse_tuple_and_keywords(args, kws, fmt, keywords, *objs) pred = builder.icmp(lc.ICMP_EQ, parseok, Constant.null(parseok.type)) with cgutils.if_unlikely(builder, pred): builder.ret(api.get_null_object()) innerargs = [] cleanups = [] for obj, ty in zip(objs, self.fndesc.argtypes): #api.context.debug_print(builder, "%s -> %s" % (obj, ty)) #api.print_object(builder.load(obj)) val, dtor = api.to_native_arg(builder.load(obj), ty) innerargs.append(val) cleanups.append(dtor) # The wrapped function doesn't take a full closure, only # the Environment object. env = self.context.get_env_from_closure(builder, closure) status, res = self.context.call_function(builder, self.func, self.fndesc.restype, self.fndesc.argtypes, innerargs, env) # Do clean up for dtor in cleanups: dtor() # Determine return status with cgutils.if_likely(builder, status.ok): with cgutils.ifthen(builder, status.none): api.return_none() retval = api.from_native_return(res, self.fndesc.restype) builder.ret(retval) with cgutils.ifthen(builder, builder.not_(status.exc)): # !ok && !exc # User exception raised self.make_exception_switch(api, builder, status.code) # !ok && exc builder.ret(api.get_null_object())
def return_optional_value(self, builder, retty, valty, value): if valty == types.none: self.return_native_none(builder) elif retty == valty: optcls = self.context.make_optional(retty) optval = optcls(self.context, builder, value=value) validbit = cgutils.as_bool_bit(builder, optval.valid) with cgutils.ifthen(builder, validbit): self.return_value(builder, optval.data) self.return_native_none(builder) elif not isinstance(valty, types.Optional): if valty != retty.type: value = self.context.cast(builder, value, fromty=valty, toty=retty.type) self.return_value(builder, value) else: raise NotImplementedError("returning {0} for {1}".format( valty, retty))
def lower_global(self, name, value): """ 1) Check global scope dictionary. 2) Check __builtins__. 2a) is it a dictionary (for non __main__ module) 2b) is it a module (for __main__ module) """ moddict = self.pyapi.get_module_dict() obj = self.pyapi.dict_getitem_string(moddict, name) self.incref(obj) # obj is borrowed if hasattr(builtins, name): obj_is_null = self.is_null(obj) bbelse = self.builder.basic_block with cgutils.ifthen(self.builder, obj_is_null): mod = self.pyapi.dict_getitem_string(moddict, "__builtins__") builtin = self.builtin_lookup(mod, name) bbif = self.builder.basic_block retval = self.builder.phi(self.pyapi.pyobj) retval.add_incoming(obj, bbelse) retval.add_incoming(builtin, bbif) else: retval = obj with cgutils.if_unlikely(self.builder, self.is_null(retval)): self.pyapi.raise_missing_global_error(name) self.return_exception_raised() self.incref(retval) return retval
def build_increment_blocks(inp_indices, inp_shape, inp_ndim, inp_num): bb_inc_inp_index = [ cgutils.append_basic_block( builder, '.inc_inp{0}_index{1}'.format(inp_num, str(i))) for i in range(inp_ndim) ] bb_end_inc_index = cgutils.append_basic_block( builder, '.end_inc{0}_index'.format(inp_num)) builder.branch(bb_inc_inp_index[0]) for i in range(inp_ndim): with cgutils.goto_block(builder, bb_inc_inp_index[i]): # If the shape of this dimension is 1, then leave the # index at 0 so that this dimension is broadcasted over # the corresponding input and output dimensions. cond = builder.icmp(ICMP_UGT, inp_shape[i], ONE) with cgutils.ifthen(builder, cond): builder.store(indices[out_ndim - inp_ndim + i], inp_indices[i]) if i + 1 == inp_ndim: builder.branch(bb_end_inc_index) else: builder.branch(bb_inc_inp_index[i + 1]) builder.position_at_end(bb_end_inc_index)
def iternext_array(context, builder, sig, args, result): [iterty] = sig.args [iter] = args arrayty = iterty.array_type if arrayty.ndim != 1: # TODO raise NotImplementedError("iterating over %dD array" % arrayty.ndim) iterobj = make_arrayiter_cls(iterty)(context, builder, value=iter) ary = make_array(arrayty)(context, builder, value=iterobj.array) nitems, = cgutils.unpack_tuple(builder, ary.shape, count=1) index = builder.load(iterobj.index) is_valid = builder.icmp(lc.ICMP_SLT, index, nitems) result.set_valid(is_valid) with cgutils.ifthen(builder, is_valid): value = _getitem_array1d(context, builder, arrayty, ary, index, wraparound=False) result.yield_(value) nindex = builder.add(index, context.get_constant(types.intp, 1)) builder.store(nindex, iterobj.index)
def build_wrapper(self, api, builder, args, kws): nargs = len(self.fndesc.args) keywords = self.make_keywords(self.fndesc.args) fmt = self.make_const_string("O" * nargs) objs = [api.alloca_obj() for _ in range(nargs)] parseok = api.parse_tuple_and_keywords(args, kws, fmt, keywords, *objs) pred = builder.icmp(lc.ICMP_EQ, parseok, Constant.null(parseok.type)) with cgutils.if_unlikely(builder, pred): builder.ret(api.get_null_object()) innerargs = [] cleanups = [] for obj, ty in zip(objs, self.fndesc.argtypes): #api.context.debug_print(builder, "%s -> %s" % (obj, ty)) #api.print_object(builder.load(obj)) val, dtor = api.to_native_arg(builder.load(obj), ty) innerargs.append(val) cleanups.append(dtor) status, res = self.context.call_function(builder, self.func, self.fndesc.restype, self.fndesc.argtypes, innerargs) # Do clean up for dtor in cleanups: dtor() # Determine return status with cgutils.if_likely(builder, status.ok): with cgutils.ifthen(builder, status.none): api.return_none() retval = api.from_native_return(res, self.fndesc.restype) builder.ret(retval) with cgutils.ifthen(builder, builder.not_(status.exc)): # !ok && !exc # User exception raised self.make_exception_switch(api, builder, status.code) # !ok && exc builder.ret(api.get_null_object())
def poisson_impl(context, builder, sig, args): state_ptr = get_np_state_ptr(context, builder) retptr = cgutils.alloca_once(builder, int64_t, name="ret") bbcont = cgutils.append_basic_block(builder, "bbcont") bbend = cgutils.append_basic_block(builder, "bbend") if len(args) == 1: lam, = args big_lam = builder.fcmp_ordered('>=', lam, ir.Constant(double, 10.0)) with cgutils.ifthen(builder, big_lam): # For lambda >= 10.0, we switch to a more accurate # algorithm (see _helperlib.c). fnty = ir.FunctionType(int64_t, (rnd_state_ptr_t, double)) fn = builder.function.module.get_or_insert_function(fnty, "numba_poisson_ptrs") ret = builder.call(fn, (state_ptr, lam)) builder.store(ret, retptr) builder.branch(bbend) builder.branch(bbcont) builder.position_at_end(bbcont) _random = np.random.random _exp = math.exp def poisson_impl(lam): """Numpy's algorithm for poisson() on small *lam*. This method is invoked only if the parameter lambda of the distribution is small ( < 10 ). The algorithm used is described in "Knuth, D. 1969. 'Seminumerical Algorithms. The Art of Computer Programming' vol 2. """ if lam < 0.0: raise ValueError("poisson(): lambda < 0") if lam == 0.0: return 0 enlam = _exp(-lam) X = 0 prod = 1.0 while 1: U = _random() prod *= U if prod <= enlam: return X X += 1 if len(args) == 0: sig = signature(sig.return_type, types.float64) args = (ir.Constant(double, 1.0),) ret = context.compile_internal(builder, poisson_impl, sig, args) builder.store(ret, retptr) builder.branch(bbend) builder.position_at_end(bbend) return builder.load(retptr)
def _emit_python_wrapper(self, llvm_module): # Figure out the Python C API module creation function, and # get a LLVM function for it. create_module_fn = llvm_module.add_function(*self.module_create_definition) create_module_fn.linkage = lc.LINKAGE_EXTERNAL # Define a constant string for the module name. mod_name_init = lc.Constant.stringz(self.module_name) mod_name_const = llvm_module.add_global_variable(mod_name_init.type, '.module_name') mod_name_const.initializer = mod_name_init mod_name_const.linkage = lc.LINKAGE_INTERNAL mod_def_base_init = lc.Constant.struct( (lt._pyobject_head_init, # PyObject_HEAD lc.Constant.null(self.m_init_ty), # m_init lc.Constant.null(lt._llvm_py_ssize_t), # m_index lc.Constant.null(lt._pyobject_head_p), # m_copy ) ) mod_def_base = llvm_module.add_global_variable(mod_def_base_init.type, '.module_def_base') mod_def_base.initializer = mod_def_base_init mod_def_base.linkage = lc.LINKAGE_INTERNAL mod_def_init = lc.Constant.struct( (mod_def_base_init, # m_base lc.Constant.gep(mod_name_const, [ZERO, ZERO]), # m_name lc.Constant.null(self._char_star), # m_doc lc.Constant.int(lt._llvm_py_ssize_t, -1), # m_size self._emit_method_array(llvm_module), # m_methods lc.Constant.null(self.inquiry_ty), # m_reload lc.Constant.null(self.traverseproc_ty), # m_traverse lc.Constant.null(self.inquiry_ty), # m_clear lc.Constant.null(self.freefunc_ty) # m_free ) ) # Define a constant string for the module name. mod_def = llvm_module.add_global_variable(mod_def_init.type, '.module_def') mod_def.initializer = mod_def_init mod_def.linkage = lc.LINKAGE_INTERNAL # Define the module initialization function. mod_init_fn = llvm_module.add_function(*self.module_init_definition) entry = mod_init_fn.append_basic_block('Entry') builder = lc.Builder.new(entry) mod = builder.call(create_module_fn, (mod_def, lc.Constant.int(lt._int32, sys.api_version))) # Test if module has been created correctly. # (XXX for some reason comparing with the NULL constant fails llvm # with an assertion in pydebug mode) with cgutils.ifthen(builder, cgutils.is_null(builder, mod)): builder.ret(NULL) builder.ret(mod)
def _randrange_impl(context, builder, start, stop, step, state): state_ptr = get_state_ptr(context, builder, state) ty = stop.type zero = ir.Constant(ty, 0) one = ir.Constant(ty, 1) nptr = cgutils.alloca_once(builder, ty, name="n") # n = stop - start builder.store(builder.sub(stop, start), nptr) with cgutils.ifthen(builder, builder.icmp_signed('<', step, zero)): # n = (n + step + 1) // step w = builder.add(builder.add(builder.load(nptr), step), one) n = builder.sdiv(w, step) builder.store(n, nptr) with cgutils.ifthen(builder, builder.icmp_signed('>', step, one)): # n = (n + step - 1) // step w = builder.sub(builder.add(builder.load(nptr), step), one) n = builder.sdiv(w, step) builder.store(n, nptr) n = builder.load(nptr) with cgutils.if_unlikely(builder, builder.icmp_signed('<=', n, zero)): # n <= 0 msg = "empty range for randrange()" context.call_conv.return_user_exc(builder, ValueError, (msg, )) fnty = ir.FunctionType(ty, [ty, cgutils.true_bit.type]) fn = builder.function.module.get_or_insert_function( fnty, "llvm.ctlz.%s" % ty) nbits = builder.trunc(builder.call(fn, [n, cgutils.true_bit]), int32_t) nbits = builder.sub(ir.Constant(int32_t, ty.width), nbits) bbwhile = cgutils.append_basic_block(builder, "while") bbend = cgutils.append_basic_block(builder, "while.end") builder.branch(bbwhile) builder.position_at_end(bbwhile) r = get_next_int(context, builder, state_ptr, nbits) r = builder.trunc(r, ty) too_large = builder.icmp_signed('>=', r, n) builder.cbranch(too_large, bbwhile, bbend) builder.position_at_end(bbend) return builder.add(start, builder.mul(r, step))
def _emit_python_wrapper(self, llvm_module): # Figure out the Python C API module creation function, and # get a LLVM function for it. create_module_fn = llvm_module.add_function(*self.module_create_definition) create_module_fn.linkage = lc.LINKAGE_EXTERNAL # Define a constant string for the module name. mod_name_init = lc.Constant.stringz(self.module_name) mod_name_const = llvm_module.add_global_variable(mod_name_init.type, '.module_name') mod_name_const.initializer = mod_name_init mod_name_const.linkage = lc.LINKAGE_INTERNAL mod_def_base_init = lc.Constant.struct( (lt._pyobject_head_init, # PyObject_HEAD lc.Constant.null(self.m_init_ty), # m_init lc.Constant.null(lt._llvm_py_ssize_t), # m_index lc.Constant.null(lt._pyobject_head_p), # m_copy ) ) mod_def_base = llvm_module.add_global_variable(mod_def_base_init.type, '.module_def_base') mod_def_base.initializer = mod_def_base_init mod_def_base.linkage = lc.LINKAGE_INTERNAL mod_def_init = lc.Constant.struct( (mod_def_base_init, # m_base lc.Constant.gep(mod_name_const, [ZERO, ZERO]), # m_name lc.Constant.null(self._char_star), # m_doc lc.Constant.int(lt._llvm_py_ssize_t, -1), # m_size self._emit_method_array(llvm_module), # m_methods lc.Constant.null(self.inquiry_ty), # m_reload lc.Constant.null(self.traverseproc_ty), # m_traverse lc.Constant.null(self.inquiry_ty), # m_clear lc.Constant.null(self.freefunc_ty) # m_free ) ) # Define a constant string for the module name. mod_def = llvm_module.add_global_variable(mod_def_init.type, '.module_def') mod_def.initializer = mod_def_init mod_def.linkage = lc.LINKAGE_INTERNAL # Define the module initialization function. mod_init_fn = llvm_module.add_function(*self.module_init_definition) entry = mod_init_fn.append_basic_block('Entry') builder = lc.Builder.new(entry) mod = builder.call(create_module_fn, (mod_def, lc.Constant.int(lt._int32, sys.api_version))) # Test if module has been created correctly. # (XXX for some reason comparing with the NULL constant fails llvm # with an assertion in pydebug mode) with cgutils.ifthen(builder, cgutils.is_null(builder, mod)): builder.ret(NULL.bitcast(mod_init_fn.type.pointee.return_type)) builder.ret(mod)
def _randrange_impl(context, builder, start, stop, step, state): state_ptr = get_state_ptr(context, builder, state) ty = stop.type zero = ir.Constant(ty, 0) one = ir.Constant(ty, 1) nptr = cgutils.alloca_once(builder, ty, name="n") # n = stop - start builder.store(builder.sub(stop, start), nptr) with cgutils.ifthen(builder, builder.icmp_signed('<', step, zero)): # n = (n + step + 1) // step w = builder.add(builder.add(builder.load(nptr), step), one) n = builder.sdiv(w, step) builder.store(n, nptr) with cgutils.ifthen(builder, builder.icmp_signed('>', step, one)): # n = (n + step - 1) // step w = builder.sub(builder.add(builder.load(nptr), step), one) n = builder.sdiv(w, step) builder.store(n, nptr) n = builder.load(nptr) with cgutils.if_unlikely(builder, builder.icmp_signed('<=', n, zero)): # n <= 0 msg = "empty range for randrange()" context.call_conv.return_user_exc(builder, ValueError, (msg,)) fnty = ir.FunctionType(ty, [ty, cgutils.true_bit.type]) fn = builder.function.module.get_or_insert_function(fnty, "llvm.ctlz.%s" % ty) nbits = builder.trunc(builder.call(fn, [n, cgutils.true_bit]), int32_t) nbits = builder.sub(ir.Constant(int32_t, ty.width), nbits) bbwhile = cgutils.append_basic_block(builder, "while") bbend = cgutils.append_basic_block(builder, "while.end") builder.branch(bbwhile) builder.position_at_end(bbwhile) r = get_next_int(context, builder, state_ptr, nbits) r = builder.trunc(r, ty) too_large = builder.icmp_signed('>=', r, n) builder.cbranch(too_large, bbwhile, bbend) builder.position_at_end(bbend) return builder.add(start, builder.mul(r, step))
def make_exception_switch(self, api, builder, status): """ Handle user exceptions. Unserialize the exception info and raise it. """ code = status.code # Handle user exceptions with cgutils.ifthen(builder, status.is_user_exc): exc = api.unserialize(status.excinfoptr) with cgutils.if_likely(builder, cgutils.is_not_null(builder, exc)): api.raise_object(exc) # steals ref builder.ret(api.get_null_object()) with cgutils.ifthen(builder, status.is_stop_iteration): api.err_set_none("PyExc_StopIteration") builder.ret(api.get_null_object()) msg = "unknown error in native function: %s" % self.fndesc.mangled_name api.err_set_string("PyExc_SystemError", msg)
def imp(context, builder, typ, value): api = context.get_python_api(builder) aval = api.object_getattr_string(value, attr) with cgutils.ifthen(builder, cgutils.is_null(builder, aval)): context.return_exc(builder) if isinstance(atyp, types.Method): return aval else: nativevalue = api.to_native_value(aval, atyp) api.decref(aval) return nativevalue
def build_wrapper(self, api, builder, args, kws): nargs = len(self.fndesc.args) keywords = self.make_keywords(self.fndesc.args) fmt = self.make_const_string("O" * nargs) objs = [api.alloca_obj() for _ in range(nargs)] parseok = api.parse_tuple_and_keywords(args, kws, fmt, keywords, *objs) pred = builder.icmp(lc.ICMP_EQ, parseok, Constant.null(parseok.type)) with cgutils.if_unlikely(builder, pred): builder.ret(api.get_null_object()) innerargs = [] for obj, ty in zip(objs, self.fndesc.argtypes): #api.context.debug_print(builder, "%s -> %s" % (obj, ty)) #api.print_object(builder.load(obj)) val = api.to_native_arg(builder.load(obj), ty) innerargs.append(val) status, res = self.context.call_function(builder, self.func, self.fndesc.restype, self.fndesc.argtypes, innerargs) with cgutils.if_likely(builder, status.ok): with cgutils.ifthen(builder, status.none): api.return_none() retval = api.from_native_return(res, self.fndesc.restype) builder.ret(retval) with cgutils.ifthen(builder, builder.not_(status.exc)): # User exception raised # TODO we will just raise a RuntimeError for now. api.raise_native_error("error in native function: %s" % self.fndesc.mangled_name) builder.ret(api.get_null_object())
def iternext(self, context, builder, result): zero = context.get_constant(int_type, 0) countptr = self.count count = builder.load(countptr) is_valid = builder.icmp(lc.ICMP_SGT, count, zero) result.set_valid(is_valid) with cgutils.ifthen(builder, is_valid): value = builder.load(self.iter) result.yield_(value) one = context.get_constant(int_type, 1) builder.store(builder.sub(count, one), countptr) builder.store(builder.add(value, self.step), self.iter)
def iternext_enumerate(context, builder, sig, args, result): [enumty] = sig.args [enum] = args enumcls = make_enumerate_cls(enumty) enum = enumcls(context, builder, value=enum) count = builder.load(enum.count) ncount = builder.add(count, context.get_constant(types.intp, 1)) builder.store(ncount, enum.count) srcres = call_iternext(context, builder, enumty.source_type, enum.iter) is_valid = srcres.is_valid() result.set_valid(is_valid) with cgutils.ifthen(builder, is_valid): srcval = srcres.yielded_value() result.yield_(cgutils.make_anonymous_struct(builder, [count, srcval]))
def int_divmod(context, builder, x, y): """ Reference Objects/intobject.c xdivy = x / y; xmody = (long)(x - (unsigned long)xdivy * y); /* If the signs of x and y differ, and the remainder is non-0, * C89 doesn't define whether xdivy is now the floor or the * ceiling of the infinitely precise quotient. We want the floor, * and we have it iff the remainder's sign matches y's. */ if (xmody && ((y ^ xmody) < 0) /* i.e. and signs differ */) { xmody += y; --xdivy; assert(xmody && ((y ^ xmody) >= 0)); } *p_xdivy = xdivy; *p_xmody = xmody; """ assert x.type == y.type xdivy = builder.sdiv(x, y) xmody = builder.srem(x, y) # Intel has divmod instruction ZERO = Constant.null(y.type) ONE = Constant.int(y.type, 1) y_xor_xmody_ltz = builder.icmp(lc.ICMP_SLT, builder.xor(y, xmody), ZERO) xmody_istrue = builder.icmp(lc.ICMP_NE, xmody, ZERO) cond = builder.and_(xmody_istrue, y_xor_xmody_ltz) bb1 = builder.basic_block with cgutils.ifthen(builder, cond): xmody_plus_y = builder.add(xmody, y) xdivy_minus_1 = builder.sub(xdivy, ONE) bb2 = builder.basic_block resdiv = builder.phi(y.type) resdiv.add_incoming(xdivy, bb1) resdiv.add_incoming(xdivy_minus_1, bb2) resmod = builder.phi(x.type) resmod.add_incoming(xmody, bb1) resmod.add_incoming(xmody_plus_y, bb2) return resdiv, resmod
def iternext_unituple(context, builder, sig, args, result): [tupiterty] = sig.args [tupiter] = args tupitercls = make_unituple_iter(tupiterty) iterval = tupitercls(context, builder, value=tupiter) tup = iterval.tuple idxptr = iterval.index idx = builder.load(idxptr) count = context.get_constant(types.intp, tupiterty.unituple.count) is_valid = builder.icmp(lc.ICMP_SLT, idx, count) result.set_valid(is_valid) with cgutils.ifthen(builder, is_valid): getitem_sig = typing.signature(sig.return_type, tupiterty.unituple, types.intp) result.yield_(getitem_unituple(context, builder, getitem_sig, [tup, idx])) nidx = builder.add(idx, context.get_constant(types.intp, 1)) builder.store(nidx, iterval.index)
def lower_global(self, name, value): """ 1) Check global scope dictionary. 2) Check __builtins__. 2a) is it a dictionary (for non __main__ module) 2b) is it a module (for __main__ module) """ moddict = self.get_module_dict() obj = self.pyapi.dict_getitem(moddict, self._freeze_string(name)) self.incref(obj) # obj is borrowed try: if value in _unsupported_builtins: raise ForbiddenConstruct("builtins %s() is not supported" % name, loc=self.loc) except TypeError: # `value` is unhashable, ignore pass if hasattr(builtins, name): obj_is_null = self.is_null(obj) bbelse = self.builder.basic_block with cgutils.ifthen(self.builder, obj_is_null): mod = self.pyapi.dict_getitem( moddict, self._freeze_string("__builtins__")) builtin = self.builtin_lookup(mod, name) bbif = self.builder.basic_block retval = self.builder.phi(self.pyapi.pyobj) retval.add_incoming(obj, bbelse) retval.add_incoming(builtin, bbif) else: retval = obj with cgutils.if_unlikely(self.builder, self.is_null(retval)): self.pyapi.raise_missing_global_error(name) self.return_exception_raised() return retval
def return_optional_value(self, builder, retty, valty, value): if valty == types.none: self.return_native_none(builder) elif retty == valty: optcls = self.make_optional(retty) optval = optcls(self, builder, value=value) validbit = builder.trunc(optval.valid, lc.Type.int(1)) with cgutils.ifthen(builder, validbit): self.return_value(builder, optval.data) self.return_native_none(builder) elif not isinstance(valty, types.Optional): if valty != retty.type: value = self.cast(builder, value, fromty=valty, toty=retty.type) self.return_value(builder, value) else: raise NotImplementedError("returning {0} for {1}".format(valty, retty))
def build_increment_blocks(inp_indices, inp_shape, inp_ndim, inp_num): bb_inc_inp_index = [cgutils.append_basic_block(builder, '.inc_inp{0}_index{1}'.format(inp_num, str(i))) for i in range(inp_ndim)] bb_end_inc_index = cgutils.append_basic_block(builder, '.end_inc{0}_index'.format(inp_num)) builder.branch(bb_inc_inp_index[0]) for i in range(inp_ndim): with cgutils.goto_block(builder, bb_inc_inp_index[i]): # If the shape of this dimension is 1, then leave the # index at 0 so that this dimension is broadcasted over # the corresponding input and output dimensions. cond = builder.icmp(ICMP_UGT, inp_shape[i], ONE) with cgutils.ifthen(builder, cond): builder.store(indices[out_ndim-inp_ndim+i], inp_indices[i]) if i + 1 == inp_ndim: builder.branch(bb_end_inc_index) else: builder.branch(bb_inc_inp_index[i+1]) builder.position_at_end(bb_end_inc_index)
def lower_global(self, name, value): """ 1) Check global scope dictionary. 2) Check __builtins__. 2a) is it a dictionary (for non __main__ module) 2b) is it a module (for __main__ module) """ moddict = self.get_module_dict() obj = self.pyapi.dict_getitem(moddict, self._freeze_string(name)) self.incref(obj) # obj is borrowed try: if value in _unsupported_builtins: raise ForbiddenConstruct("builtins %s() is not supported" % name, loc=self.loc) except TypeError: # `value` is unhashable, ignore pass if hasattr(builtins, name): obj_is_null = self.is_null(obj) bbelse = self.builder.basic_block with cgutils.ifthen(self.builder, obj_is_null): mod = self.pyapi.dict_getitem(moddict, self._freeze_string("__builtins__")) builtin = self.builtin_lookup(mod, name) bbif = self.builder.basic_block retval = self.builder.phi(self.pyapi.pyobj) retval.add_incoming(obj, bbelse) retval.add_incoming(builtin, bbif) else: retval = obj with cgutils.if_unlikely(self.builder, self.is_null(retval)): self.pyapi.raise_missing_global_error(name) self.return_exception_raised() return retval
def call_class_method(self, builder, func, signature, args): api = self.get_python_api(builder) tys = signature.args retty = signature.return_type pyargs = [api.from_native_value(av, at) for av, at in zip(args, tys)] res = api.call_function_objargs(func, pyargs) # clean up api.decref(func) for obj in pyargs: api.decref(obj) with cgutils.ifthen(builder, cgutils.is_null(builder, res)): self.return_exc(builder) if retty == types.none: api.decref(res) return self.get_dummy_value() else: nativeresult = api.to_native_value(res, retty) api.decref(res) return nativeresult
def iternext_array(context, builder, sig, args, result): [iterty] = sig.args [iter] = args arrayty = iterty.array_type if arrayty.ndim != 1: # TODO raise NotImplementedError("iterating over %dD array" % arrayty.ndim) iterobj = make_arrayiter_cls(iterty)(context, builder, value=iter) ary = make_array(arrayty)(context, builder, value=iterobj.array) nitems, = cgutils.unpack_tuple(builder, ary.shape, count=1) index = builder.load(iterobj.index) is_valid = builder.icmp(lc.ICMP_SLT, index, nitems) result.set_valid(is_valid) with cgutils.ifthen(builder, is_valid): value = _getitem_array1d(context, builder, arrayty, ary, index) result.yield_(value) nindex = builder.add(index, context.get_constant(types.intp, 1)) builder.store(nindex, iterobj.index)
def iternext_zip(context, builder, sig, args, result): [zip_type] = sig.args [zipobj] = args zipcls = make_zip_cls(zip_type) zipobj = zipcls(context, builder, value=zipobj) if len(zipobj) == 0: # zip() is an empty iterator result.set_exhausted() return is_valid = context.get_constant(types.boolean, True) values = [] for iterobj, srcty in zip(zipobj, zip_type.source_types): srcres = call_iternext(context, builder, srcty, iterobj) is_valid = builder.and_(is_valid, srcres.is_valid()) values.append(srcres.yielded_value()) result.set_valid(is_valid) with cgutils.ifthen(builder, is_valid): result.yield_(cgutils.make_anonymous_struct(builder, values))
def generate_kernel_wrapper(self, func, argtypes): module = func.module argtys = self.get_arguments(func.type.pointee) fnty = Type.function(Type.void(), argtys) wrapfn = module.add_function(fnty, name="cudaPy_" + func.name) builder = Builder.new(wrapfn.append_basic_block('')) # Define error handling variables def define_error_gv(postfix): gv = module.add_global_variable(Type.int(), name=wrapfn.name + postfix) gv.initializer = Constant.null(gv.type.pointee) return gv gv_exc = define_error_gv("__errcode__") gv_tid = [] gv_ctaid = [] for i in 'xyz': gv_tid.append(define_error_gv("__tid%s__" % i)) gv_ctaid.append(define_error_gv("__ctaid%s__" % i)) callargs = [] for at, av in zip(argtypes, wrapfn.args): av = self.get_argument_value(builder, at, av) callargs.append(av) status, _ = self.call_function(builder, func, types.void, argtypes, callargs) # Check error status with cgutils.if_likely(builder, status.ok): builder.ret_void() with cgutils.ifthen(builder, builder.not_(status.exc)): # User exception raised old = Constant.null(gv_exc.type.pointee) # Use atomic cmpxchg to prevent rewriting the error status # Only the first error is recorded xchg = builder.atomic_cmpxchg(gv_exc, old, status.code, "monotonic") changed = builder.icmp(ICMP_EQ, xchg, old) # If the xchange is successful, save the thread ID. sreg = nvvmutils.SRegBuilder(builder) with cgutils.ifthen(builder, changed): for dim, ptr, in zip("xyz", gv_tid): val = sreg.tid(dim) builder.store(val, ptr) for dim, ptr, in zip("xyz", gv_ctaid): val = sreg.ctaid(dim) builder.store(val, ptr) builder.ret_void() # force inline inline_function(status.code) module.verify() return wrapfn
def real_divmod_func_body(context, builder, vx, wx): # Reference Objects/floatobject.c # # float_divmod(PyObject *v, PyObject *w) # { # double vx, wx; # double div, mod, floordiv; # CONVERT_TO_DOUBLE(v, vx); # CONVERT_TO_DOUBLE(w, wx); # mod = fmod(vx, wx); # /* fmod is typically exact, so vx-mod is *mathematically* an # exact multiple of wx. But this is fp arithmetic, and fp # vx - mod is an approximation; the result is that div may # not be an exact integral value after the division, although # it will always be very close to one. # */ # div = (vx - mod) / wx; # if (mod) { # /* ensure the remainder has the same sign as the denominator */ # if ((wx < 0) != (mod < 0)) { # mod += wx; # div -= 1.0; # } # } # else { # /* the remainder is zero, and in the presence of signed zeroes # fmod returns different results across platforms; ensure # it has the same sign as the denominator; we'd like to do # "mod = wx * 0.0", but that may get optimized away */ # mod *= mod; /* hide "mod = +0" from optimizer */ # if (wx < 0.0) # mod = -mod; # } # /* snap quotient to nearest integral value */ # if (div) { # floordiv = floor(div); # if (div - floordiv > 0.5) # floordiv += 1.0; # } # else { # /* div is zero - get the same sign as the true quotient */ # div *= div; /* hide "div = +0" from optimizers */ # floordiv = div * vx / wx; /* zero w/ sign of vx/wx */ # } # return Py_BuildValue("(dd)", floordiv, mod); # } pmod = builder.alloca(vx.type) pdiv = builder.alloca(vx.type) pfloordiv = builder.alloca(vx.type) mod = builder.frem(vx, wx) div = builder.fdiv(builder.fsub(vx, mod), wx) builder.store(mod, pmod) builder.store(div, pdiv) ZERO = Constant.real(vx.type, 0) ONE = Constant.real(vx.type, 1) mod_istrue = builder.fcmp(lc.FCMP_ONE, mod, ZERO) wx_ltz = builder.fcmp(lc.FCMP_OLT, wx, ZERO) mod_ltz = builder.fcmp(lc.FCMP_OLT, mod, ZERO) with cgutils.ifthen(builder, mod_istrue): wx_ltz_ne_mod_ltz = builder.icmp(lc.ICMP_NE, wx_ltz, mod_ltz) with cgutils.ifthen(builder, wx_ltz_ne_mod_ltz): mod = builder.fadd(mod, wx) div = builder.fsub(div, ONE) builder.store(mod, pmod) builder.store(div, pdiv) del mod del div with cgutils.ifnot(builder, mod_istrue): mod = builder.load(pmod) mod = builder.fmul(mod, mod) builder.store(mod, pmod) del mod with cgutils.ifthen(builder, wx_ltz): mod = builder.load(pmod) mod = builder.fsub(ZERO, mod) builder.store(mod, pmod) del mod div = builder.load(pdiv) div_istrue = builder.fcmp(lc.FCMP_ONE, div, ZERO) with cgutils.ifthen(builder, div_istrue): module = cgutils.get_module(builder) floorfn = lc.Function.intrinsic(module, lc.INTR_FLOOR, [wx.type]) floordiv = builder.call(floorfn, [div]) floordivdiff = builder.fsub(div, floordiv) floordivincr = builder.fadd(floordiv, ONE) HALF = Constant.real(wx.type, 0.5) pred = builder.fcmp(lc.FCMP_OGT, floordivdiff, HALF) floordiv = builder.select(pred, floordivincr, floordiv) builder.store(floordiv, pfloordiv) with cgutils.ifnot(builder, div_istrue): div = builder.fmul(div, div) builder.store(div, pdiv) floordiv = builder.fdiv(builder.fmul(div, vx), wx) builder.store(floordiv, pfloordiv) return builder.load(pfloordiv), builder.load(pmod)
def impl(context, builder, sig, args): [tyinp, tyout] = sig.args [inp, out] = args if isinstance(tyinp, types.Array): scalar_inp = False scalar_tyinp = tyinp.dtype inp_ndim = tyinp.ndim elif tyinp in types.number_domain: scalar_inp = True scalar_tyinp = tyinp inp_ndim = 1 else: raise TypeError('unknown type for input operand') out_ndim = tyout.ndim if asfloat: promote_type = types.float64 elif scalar_tyinp in types.real_domain: promote_type = types.float64 elif scalar_tyinp in types.signed_domain: promote_type = types.int64 else: promote_type = types.uint64 result_type = promote_type # Temporary hack for __ftol2 llvm bug. Don't allow storing # float results in uint64 array on windows. if result_type in types.real_domain and \ tyout.dtype is types.uint64 and \ sys.platform.startswith('win32'): raise TypeError('Cannot store result in uint64 array') sig = typing.signature(result_type, promote_type) if not scalar_inp: iary = context.make_array(tyinp)(context, builder, inp) oary = context.make_array(tyout)(context, builder, out) fnwork = context.get_function(funckey, sig) intpty = context.get_value_type(types.intp) if not scalar_inp: inp_shape = cgutils.unpack_tuple(builder, iary.shape, inp_ndim) inp_strides = cgutils.unpack_tuple(builder, iary.strides, inp_ndim) inp_data = iary.data inp_layout = tyinp.layout out_shape = cgutils.unpack_tuple(builder, oary.shape, out_ndim) out_strides = cgutils.unpack_tuple(builder, oary.strides, out_ndim) out_data = oary.data out_layout = tyout.layout ZERO = Constant.int(Type.int(intpty.width), 0) ONE = Constant.int(Type.int(intpty.width), 1) inp_indices = None if not scalar_inp: inp_indices = [] for i in range(inp_ndim): x = builder.alloca(Type.int(intpty.width)) builder.store(ZERO, x) inp_indices.append(x) loopshape = cgutils.unpack_tuple(builder, oary.shape, out_ndim) with cgutils.loop_nest(builder, loopshape, intp=intpty) as indices: # Increment input indices. # Since the output dimensions are already being incremented, # we'll use that to set the input indices. In order to # handle broadcasting, any input dimension of size 1 won't be # incremented. if not scalar_inp: bb_inc_inp_index = [cgutils.append_basic_block(builder, '.inc_inp_index' + str(i)) for i in range(inp_ndim)] bb_end_inc_index = cgutils.append_basic_block(builder, '.end_inc_index') builder.branch(bb_inc_inp_index[0]) for i in range(inp_ndim): with cgutils.goto_block(builder, bb_inc_inp_index[i]): # If the shape of this dimension is 1, then leave the # index at 0 so that this dimension is broadcasted over # the corresponding output dimension. cond = builder.icmp(ICMP_UGT, inp_shape[i], ONE) with cgutils.ifthen(builder, cond): # If number of input dimensions is less than output # dimensions, the input shape is right justified so # that last dimension of input shape corresponds to # last dimension of output shape. Therefore, index # output dimension starting at offset of diff of # input and output dimension count. builder.store(indices[out_ndim-inp_ndim+i], inp_indices[i]) # We have to check if this is last dimension and add # appropriate block terminator before beginning next # loop. if i + 1 == inp_ndim: builder.branch(bb_end_inc_index) else: builder.branch(bb_inc_inp_index[i+1]) builder.position_at_end(bb_end_inc_index) inds = [builder.load(index) for index in inp_indices] px = cgutils.get_item_pointer2(builder, data=inp_data, shape=inp_shape, strides=inp_strides, layout=inp_layout, inds=inds) x = builder.load(px) else: x = inp po = cgutils.get_item_pointer2(builder, data=out_data, shape=out_shape, strides=out_strides, layout=out_layout, inds=indices) d_x = context.cast(builder, x, scalar_tyinp, promote_type) tempres = fnwork(builder, [d_x]) res = context.cast(builder, tempres, result_type, tyout.dtype) builder.store(res, po) return out
def generate_kernel_wrapper(self, func, argtypes): module = func.module argtys = [self.get_argument_type(ty) for ty in argtypes] wrapfnty = Type.function(Type.void(), argtys) wrapper_module = self.create_module("cuda.kernel.wrapper") fnty = Type.function(Type.int(), [self.get_return_type(types.pyobject)] + argtys) func = wrapper_module.add_function(fnty, name=func.name) wrapfn = wrapper_module.add_function(wrapfnty, name="cudaPy_" + func.name) builder = Builder.new(wrapfn.append_basic_block('')) # Define error handling variables def define_error_gv(postfix): gv = wrapper_module.add_global_variable(Type.int(), name=wrapfn.name + postfix) gv.initializer = Constant.null(gv.type.pointee) return gv gv_exc = define_error_gv("__errcode__") gv_tid = [] gv_ctaid = [] for i in 'xyz': gv_tid.append(define_error_gv("__tid%s__" % i)) gv_ctaid.append(define_error_gv("__ctaid%s__" % i)) callargs = [] for at, av in zip(argtypes, wrapfn.args): av = self.get_argument_value(builder, at, av) callargs.append(av) status, _ = self.call_function(builder, func, types.void, argtypes, callargs) # Check error status with cgutils.if_likely(builder, status.ok): builder.ret_void() with cgutils.ifthen(builder, builder.not_(status.exc)): # User exception raised old = Constant.null(gv_exc.type.pointee) # Use atomic cmpxchg to prevent rewriting the error status # Only the first error is recorded casfnty = lc.Type.function(old.type, [gv_exc.type, old.type, old.type]) casfn = wrapper_module.add_function(casfnty, name="___numba_cas_hack") xchg = builder.call(casfn, [gv_exc, old, status.code]) changed = builder.icmp(ICMP_EQ, xchg, old) # If the xchange is successful, save the thread ID. sreg = nvvmutils.SRegBuilder(builder) with cgutils.ifthen(builder, changed): for dim, ptr, in zip("xyz", gv_tid): val = sreg.tid(dim) builder.store(val, ptr) for dim, ptr, in zip("xyz", gv_ctaid): val = sreg.ctaid(dim) builder.store(val, ptr) builder.ret_void() # force inline # inline_function(status.code) nvvm.set_cuda_kernel(wrapfn) module.link_in(ll.parse_assembly(str(wrapper_module))) module.verify() wrapfn = module.get_function(wrapfn.name) return wrapfn
def setitem_array1d_slice(context, builder, sig, args): aryty, idxty, valty = sig.args ary, idx, val = args arystty = make_array(aryty) ary = arystty(context, builder, ary) shapes = cgutils.unpack_tuple(builder, ary.shape, aryty.ndim) slicestruct = Slice(context, builder, value=idx) # the logic here follows that of Python's Objects/sliceobject.c # in particular PySlice_GetIndicesEx function ZERO = Constant.int(slicestruct.step.type, 0) NEG_ONE = Constant.int(slicestruct.start.type, -1) b_step_eq_zero = builder.icmp(lc.ICMP_EQ, slicestruct.step, ZERO) # bail if step is 0 with cgutils.ifthen(builder, b_step_eq_zero): context.return_errcode(builder, errcode.ASSERTION_ERROR) # adjust for negative indices for start start = cgutils.alloca_once_value(builder, slicestruct.start) b_start_lt_zero = builder.icmp(lc.ICMP_SLT, builder.load(start), ZERO) with cgutils.ifthen(builder, b_start_lt_zero): add = builder.add(builder.load(start), shapes[0]) builder.store(add, start) b_start_lt_zero = builder.icmp(lc.ICMP_SLT, builder.load(start), ZERO) with cgutils.ifthen(builder, b_start_lt_zero): b_step_lt_zero = builder.icmp(lc.ICMP_SLT, slicestruct.step, ZERO) cond = builder.select(b_step_lt_zero, NEG_ONE, ZERO) builder.store(cond, start) b_start_geq_len = builder.icmp(lc.ICMP_SGE, builder.load(start), shapes[0]) ONE = Constant.int(shapes[0].type, 1) with cgutils.ifthen(builder, b_start_geq_len): b_step_lt_zero = builder.icmp(lc.ICMP_SLT, slicestruct.step, ZERO) cond = builder.select(b_step_lt_zero, builder.sub(shapes[0], ONE), shapes[0]) builder.store(cond, start) # adjust stop for negative value stop = cgutils.alloca_once_value(builder, slicestruct.stop) b_stop_lt_zero = builder.icmp(lc.ICMP_SLT, builder.load(stop), ZERO) with cgutils.ifthen(builder, b_stop_lt_zero): add = builder.add(builder.load(stop), shapes[0]) builder.store(add, stop) b_stop_lt_zero = builder.icmp(lc.ICMP_SLT, builder.load(stop), ZERO) with cgutils.ifthen(builder, b_stop_lt_zero): b_step_lt_zero = builder.icmp(lc.ICMP_SLT, slicestruct.step, ZERO) cond = builder.select(b_step_lt_zero, NEG_ONE, ZERO) builder.store(cond, start) b_stop_geq_len = builder.icmp(lc.ICMP_SGE, builder.load(stop), shapes[0]) ONE = Constant.int(shapes[0].type, 1) with cgutils.ifthen(builder, b_stop_geq_len): b_step_lt_zero = builder.icmp(lc.ICMP_SLT, slicestruct.step, ZERO) cond = builder.select(b_step_lt_zero, builder.sub(shapes[0], ONE), shapes[0]) builder.store(cond, stop) b_step_gt_zero = builder.icmp(lc.ICMP_SGT, slicestruct.step, ZERO) with cgutils.ifelse(builder, b_step_gt_zero) as (then0, otherwise0): with then0: with cgutils.for_range_slice(builder, builder.load(start), builder.load(stop), slicestruct.step, slicestruct.start.type) as loop_idx1: ptr = cgutils.get_item_pointer(builder, aryty, ary, [loop_idx1], wraparound=True) context.pack_value(builder, aryty.dtype, val, ptr) with otherwise0: with cgutils.for_range_slice(builder, builder.load(start), builder.load(stop), slicestruct.step, slicestruct.start.type, inc=False) as loop_idx2: ptr = cgutils.get_item_pointer(builder, aryty, ary, [loop_idx2], wraparound=True) context.pack_value(builder, aryty.dtype, val, ptr)
def setitem_array1d_slice(context, builder, sig, args): aryty, idxty, valty = sig.args ary, idx, val = args arystty = make_array(aryty) ary = arystty(context, builder, ary) shapes = cgutils.unpack_tuple(builder, ary.shape, aryty.ndim) slicestruct = Slice(context, builder, value=idx) # the logic here follows that of Python's Objects/sliceobject.c # in particular PySlice_GetIndicesEx function ZERO = Constant.int(slicestruct.step.type, 0) NEG_ONE = Constant.int(slicestruct.start.type, -1) b_step_eq_zero = builder.icmp(lc.ICMP_EQ, slicestruct.step, ZERO) # bail if step is 0 with cgutils.ifthen(builder, b_step_eq_zero): context.call_conv.return_user_exc(builder, ValueError, ("slice step cannot be zero", )) # adjust for negative indices for start start = cgutils.alloca_once_value(builder, slicestruct.start) b_start_lt_zero = builder.icmp(lc.ICMP_SLT, builder.load(start), ZERO) with cgutils.ifthen(builder, b_start_lt_zero): add = builder.add(builder.load(start), shapes[0]) builder.store(add, start) b_start_lt_zero = builder.icmp(lc.ICMP_SLT, builder.load(start), ZERO) with cgutils.ifthen(builder, b_start_lt_zero): b_step_lt_zero = builder.icmp(lc.ICMP_SLT, slicestruct.step, ZERO) cond = builder.select(b_step_lt_zero, NEG_ONE, ZERO) builder.store(cond, start) b_start_geq_len = builder.icmp(lc.ICMP_SGE, builder.load(start), shapes[0]) ONE = Constant.int(shapes[0].type, 1) with cgutils.ifthen(builder, b_start_geq_len): b_step_lt_zero = builder.icmp(lc.ICMP_SLT, slicestruct.step, ZERO) cond = builder.select(b_step_lt_zero, builder.sub(shapes[0], ONE), shapes[0]) builder.store(cond, start) # adjust stop for negative value stop = cgutils.alloca_once_value(builder, slicestruct.stop) b_stop_lt_zero = builder.icmp(lc.ICMP_SLT, builder.load(stop), ZERO) with cgutils.ifthen(builder, b_stop_lt_zero): add = builder.add(builder.load(stop), shapes[0]) builder.store(add, stop) b_stop_lt_zero = builder.icmp(lc.ICMP_SLT, builder.load(stop), ZERO) with cgutils.ifthen(builder, b_stop_lt_zero): b_step_lt_zero = builder.icmp(lc.ICMP_SLT, slicestruct.step, ZERO) cond = builder.select(b_step_lt_zero, NEG_ONE, ZERO) builder.store(cond, start) b_stop_geq_len = builder.icmp(lc.ICMP_SGE, builder.load(stop), shapes[0]) ONE = Constant.int(shapes[0].type, 1) with cgutils.ifthen(builder, b_stop_geq_len): b_step_lt_zero = builder.icmp(lc.ICMP_SLT, slicestruct.step, ZERO) cond = builder.select(b_step_lt_zero, builder.sub(shapes[0], ONE), shapes[0]) builder.store(cond, stop) b_step_gt_zero = builder.icmp(lc.ICMP_SGT, slicestruct.step, ZERO) with cgutils.ifelse(builder, b_step_gt_zero) as (then0, otherwise0): with then0: with cgutils.for_range_slice(builder, builder.load(start), builder.load(stop), slicestruct.step, slicestruct.start.type) as loop_idx1: ptr = cgutils.get_item_pointer(builder, aryty, ary, [loop_idx1], wraparound=True) context.pack_value(builder, aryty.dtype, val, ptr) with otherwise0: with cgutils.for_range_slice(builder, builder.load(start), builder.load(stop), slicestruct.step, slicestruct.start.type, inc=False) as loop_idx2: ptr = cgutils.get_item_pointer(builder, aryty, ary, [loop_idx2], wraparound=True) context.pack_value(builder, aryty.dtype, val, ptr)
def cleanup(): with cgutils.ifthen(self.builder, is_not_none): native.cleanup()