def delitem_list(context, builder, sig, args): inst = ListInstance(context, builder, sig.args[0], args[0]) slice = context.make_helper(builder, sig.args[1], args[1]) slicing.guard_invalid_slice(context, builder, sig.args[1], slice) inst.fix_slice(slice) slice_len = slicing.get_slice_length(builder, slice) one = ir.Constant(slice_len.type, 1) with builder.if_then(builder.icmp_signed('!=', slice.step, one), likely=False): msg = "unsupported del list[start:stop:step] with step != 1" context.call_conv.return_user_exc(builder, NotImplementedError, (msg,)) # Compute the real stop, e.g. for dest[2:0] start = slice.start real_stop = builder.add(start, slice_len) # Decref the removed range with cgutils.for_range_slice( builder, start, real_stop, start.type(1) ) as (idx, _): inst.decref_value(inst.getitem(idx)) # Size of the list tail, after the end of slice tail_size = builder.sub(inst.size, real_stop) inst.move(start, real_stop, tail_size) inst.resize(builder.sub(inst.size, slice_len)) return context.get_dummy_value()
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 = mod.get_or_insert_function(fnty, name='.dtor.list.{}'.format(self.dtype)) if not fn.is_declaration: # End early if the dtor is already defined return fn fn.linkage = 'internal' # 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 list_mul_inplace(context, builder, sig, args): inst = ListInstance(context, builder, sig.args[0], args[0]) src_size = inst.size mult = args[1] zero = ir.Constant(mult.type, 0) mult = builder.select(cgutils.is_neg_int(builder, mult), zero, mult) nitems = builder.mul(mult, src_size) inst.resize(nitems) with cgutils.for_range_slice(builder, src_size, nitems, src_size, inc=True) as (dest_offset, _): with cgutils.for_range(builder, src_size) as loop: value = inst.getitem(loop.index) inst.setitem(builder.add(loop.index, dest_offset), value) return impl_ret_borrowed(context, builder, sig.return_type, inst.value)
def list_mul(context, builder, sig, args): src = ListInstance(context, builder, sig.args[0], args[0]) src_size = src.size mult = args[1] zero = ir.Constant(mult.type, 0) mult = builder.select(cgutils.is_neg_int(builder, mult), zero, mult) nitems = builder.mul(mult, src_size) dest = ListInstance.allocate(context, builder, sig.return_type, nitems) dest.size = nitems with cgutils.for_range_slice(builder, zero, nitems, src_size, inc=True) as (dest_offset, _): with cgutils.for_range(builder, src_size) as loop: value = src.getitem(loop.index) dest.setitem(builder.add(loop.index, dest_offset), value) return impl_ret_new_ref(context, builder, sig.return_type, dest.value)
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)