Beispiel #1
0
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 = builder.module.get_or_insert_function(
        setmethod_fnty, name='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])
Beispiel #2
0
    def codegen(context, builder, sig, args):
        vtablety = ir.LiteralStructType([
            ll_voidptr_type,  # equal
            ll_voidptr_type,  # key incref
            ll_voidptr_type,  # key decref
            ll_voidptr_type,  # val incref
            ll_voidptr_type,  # val decref
        ])
        setmethod_fnty = ir.FunctionType(
            ir.VoidType(), [ll_dict_type, vtablety.as_pointer()])
        setmethod_fn = ir.Function(
            builder.module,
            setmethod_fnty,
            name='numba_dict_set_method_table',
        )
        dp = args[0]
        vtable = cgutils.alloca_once(builder, vtablety, zfill=True)

        # install key incref/decref
        key_equal_ptr = cgutils.gep_inbounds(builder, vtable, 0, 0)
        key_incref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 1)
        key_decref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 2)
        val_incref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 3)
        val_decref_ptr = cgutils.gep_inbounds(builder, vtable, 0, 4)

        dm_key = context.data_model_manager[keyty.instance_type]
        if dm_key.contains_nrt_meminfo():
            equal = _get_equal(context, builder.module, dm_key, 'dict')
            key_incref, key_decref = _get_incref_decref(
                context, builder.module, dm_key, 'dict')
            builder.store(
                builder.bitcast(equal, key_equal_ptr.type.pointee),
                key_equal_ptr,
            )
            builder.store(
                builder.bitcast(key_incref, key_incref_ptr.type.pointee),
                key_incref_ptr,
            )
            builder.store(
                builder.bitcast(key_decref, key_decref_ptr.type.pointee),
                key_decref_ptr,
            )

        dm_val = context.data_model_manager[valty.instance_type]
        if dm_val.contains_nrt_meminfo():
            val_incref, val_decref = _get_incref_decref(
                context, builder.module, dm_val, 'dict')
            builder.store(
                builder.bitcast(val_incref, val_incref_ptr.type.pointee),
                val_incref_ptr,
            )
            builder.store(
                builder.bitcast(val_decref, val_decref_ptr.type.pointee),
                val_decref_ptr,
            )

        builder.call(setmethod_fn, [dp, vtable])
Beispiel #3
0
    def lower_finalize_func_body(self, builder, genptr):
        """
        Lower the body of the generator's finalizer: decref all live
        state variables.
        """
        pyapi = self.context.get_python_api(builder)
        resume_index_ptr = self.get_resume_index_ptr(builder, genptr)
        resume_index = builder.load(resume_index_ptr)
        # If resume_index is 0, next() was never called
        # If resume_index is -1, generator terminated cleanly
        # (note function arguments are saved in state variables,
        #  so they don't need a separate cleanup step)
        need_cleanup = builder.icmp_signed('>', resume_index,
                                           Constant.int(resume_index.type, 0))

        with cgutils.if_unlikely(builder, need_cleanup):
            # Decref all live vars (some may be NULL)
            gen_state_ptr = self.get_state_ptr(builder, genptr)
            for state_index in range(len(self.gentype.state_types)):
                state_slot = cgutils.gep_inbounds(builder, gen_state_ptr, 0,
                                                  state_index)
                ty = self.gentype.state_types[state_index]
                val = self.context.unpack_value(builder, ty, state_slot)
                pyapi.decref(val)

        builder.ret_void()
Beispiel #4
0
def iternext_zip(context, builder, sig, args, result):
    [zip_type] = sig.args
    [zipobj] = args

    zipobj = context.make_helper(builder, zip_type, value=zipobj)

    if len(zipobj) == 0:
        # zip() is an empty iterator
        result.set_exhausted()
        return

    p_ret_tup = cgutils.alloca_once(
        builder, context.get_value_type(zip_type.yield_type))
    p_is_valid = cgutils.alloca_once_value(builder, value=cgutils.true_bit)

    for i, (iterobj, srcty) in enumerate(zip(zipobj, zip_type.source_types)):
        is_valid = builder.load(p_is_valid)
        # Avoid calling the remaining iternext if a iterator has been exhausted
        with builder.if_then(is_valid):
            srcres = call_iternext(context, builder, srcty, iterobj)
            is_valid = builder.and_(is_valid, srcres.is_valid())
            builder.store(is_valid, p_is_valid)
            val = srcres.yielded_value()
            ptr = cgutils.gep_inbounds(builder, p_ret_tup, 0, i)
            builder.store(val, ptr)

    is_valid = builder.load(p_is_valid)
    result.set_valid(is_valid)

    with builder.if_then(is_valid):
        result.yield_(builder.load(p_ret_tup))
Beispiel #5
0
    def codegen(context, builder, signature, args):
        [obj] = args
        [ty] = signature.args
        # A sequence of (type, meminfo)
        meminfos = []
        if context.enable_nrt:
            tmp_mis = context.nrt.get_meminfos(builder, ty, obj)
            meminfos.extend(tmp_mis)

        if meminfos:
            pyapi = context.get_python_api(builder)
            gil_state = pyapi.gil_ensure()
            pyapi.print_string("dump refct of {}".format(ty))
            for ty, mi in meminfos:
                miptr = builder.bitcast(mi, _meminfo_struct_type.as_pointer())
                refctptr = cgutils.gep_inbounds(builder, miptr, 0, 0)
                refct = builder.load(refctptr)

                pyapi.print_string(" | {} refct=".format(ty))
                # "%zu" is not portable.  just truncate refcount to 32-bit.
                # that's good enough for a debugging util.
                refct_32bit = builder.trunc(refct, ir.IntType(32))
                printed = cgutils.snprintf_stackbuffer(
                    builder,
                    30,
                    "%d".format(ty),
                    refct_32bit,
                )
                pyapi.sys_write_stdout(printed)

            pyapi.print_string(";\n")
            pyapi.gil_release(gil_state)
            return cgutils.true_bit
        else:
            return cgutils.false_bit
Beispiel #6
0
 def _do_load(self, builder, ptr, formal_list=None):
     res = []
     for i, i_formal in enumerate(self._pack_map):
         elem_ptr = cgutils.gep_inbounds(builder, ptr, 0, i)
         val = self._models[i_formal].load_from_data_pointer(builder, elem_ptr)
         if formal_list is None:
             res.append((self._fe_types[i_formal], val))
         else:
             formal_list[i_formal] = val
     return res
Beispiel #7
0
    def load_from_data_pointer(self, builder, ptr, align=None):
        values = []
        for i, model in enumerate(self._models):
            elem_ptr = cgutils.gep_inbounds(builder, ptr, 0, i)
            val = model.load_from_data_pointer(builder, elem_ptr, align)
            values.append(val)

        struct = ir.Constant(self.get_value_type(), ir.Undefined)
        for i, val in enumerate(values):
            struct = self.set(builder, struct, val, i)
        return struct
Beispiel #8
0
 def lower_yield_resume(self):
     # Emit resumption point
     self.genlower.create_resumption_block(self.lower, self.inst.index)
     self.lower.debug_print("# generator resume")
     # Reload live vars from state
     for state_index, name in zip(self.live_var_indices, self.live_vars):
         state_slot = cgutils.gep_inbounds(self.builder, self.gen_state_ptr,
                                           0, state_index)
         ty = self.gentype.state_types[state_index]
         val = self.context.unpack_value(self.builder, ty, state_slot)
         self.lower.storevar(val, name)
         # Previous storevar is making an extra incref
         if self.context.enable_nrt:
             self.context.nrt.decref(self.builder, ty, val)
     self.lower.debug_print("# generator resume end")
Beispiel #9
0
 def codegen(context, builder, signature, args):
     [obj] = args
     [ty] = signature.args
     # A sequence of (type, meminfo)
     meminfos = []
     if context.enable_nrt:
         tmp_mis = context.nrt.get_meminfos(builder, ty, obj)
         meminfos.extend(tmp_mis)
     refcounts = []
     if meminfos:
         for ty, mi in meminfos:
             miptr = builder.bitcast(mi, _meminfo_struct_type.as_pointer())
             refctptr = cgutils.gep_inbounds(builder, miptr, 0, 0)
             refct = builder.load(refctptr)
             refct_32bit = builder.trunc(refct, ir.IntType(32))
             refcounts.append(refct_32bit)
     return refcounts[0]
Beispiel #10
0
    def lower_yield_suspend(self):
        self.lower.debug_print("# generator suspend")
        # Save live vars in state
        for state_index, name in zip(self.live_var_indices, self.live_vars):
            state_slot = cgutils.gep_inbounds(self.builder, self.gen_state_ptr,
                                              0, state_index)
            ty = self.gentype.state_types[state_index]
            val = self.lower.loadvar(name)
            # IncRef newly stored value
            if self.context.enable_nrt:
                self.context.nrt.incref(self.builder, ty, val)

            self.context.pack_value(self.builder, ty, val, state_slot)
        # Save resume index
        indexval = Constant.int(self.resume_index_ptr.type.pointee,
                                self.inst.index)
        self.builder.store(indexval, self.resume_index_ptr)
        self.lower.debug_print("# generator suspend end")
Beispiel #11
0
def string_split_impl(context, builder, sig, args):
    nitems = cgutils.alloca_once(builder, lir.IntType(64))
    # input str, sep, size pointer
    fnty = lir.FunctionType(lir.IntType(8).as_pointer().as_pointer(),
                            [lir.IntType(8).as_pointer(), lir.IntType(8).as_pointer(),
                             lir.IntType(64).as_pointer()])
    fn = cgutils.get_or_insert_function(builder.module, fnty, name="str_split")
    ptr = builder.call(fn, args + [nitems])
    size = builder.load(nitems)
    # TODO: use ptr instead of allocating and copying, use NRT_MemInfo_new
    # TODO: deallocate ptr
    _list = numba.cpython.listobj.ListInstance.allocate(context, builder,
                                                        sig.return_type, size)
    _list.size = size
    with cgutils.for_range(builder, size) as loop:
        value = builder.load(cgutils.gep_inbounds(builder, ptr, loop.index))
        # TODO: refcounted str
        _list.setitem(loop.index, value, incref=False)
    return impl_ret_new_ref(context, builder, sig.return_type, _list.value)
Beispiel #12
0
    def lower_yield_suspend(self):
        self.lower.debug_print("# generator suspend")
        # Save live vars in state
        for state_index, name in zip(self.live_var_indices, self.live_vars):
            state_slot = cgutils.gep_inbounds(self.builder, self.gen_state_ptr,
                                              0, state_index)
            ty = self.gentype.state_types[state_index]
            # The yield might be in a loop, in which case the state might
            # contain a predicate var that branches back to the loop head, in
            # this case the var is live but in sequential lowering won't have
            # been alloca'd yet, so do this here.
            fetype = self.lower.typeof(name)
            self.lower._alloca_var(name, fetype)
            val = self.lower.loadvar(name)
            # IncRef newly stored value
            if self.context.enable_nrt:
                self.context.nrt.incref(self.builder, ty, val)

            self.context.pack_value(self.builder, ty, val, state_slot)
        # Save resume index
        indexval = Constant.int(self.resume_index_ptr.type.pointee,
                                self.inst.index)
        self.builder.store(indexval, self.resume_index_ptr)
        self.lower.debug_print("# generator suspend end")
def get_next_int32(context, builder, state_ptr):
    """
    Get the next int32 generated by the PRNG at *state_ptr*.
    """
    idxptr = get_index_ptr(builder, state_ptr)
    idx = builder.load(idxptr)
    need_reshuffle = builder.icmp_unsigned(">=", idx, N_const)
    with cgutils.if_unlikely(builder, need_reshuffle):
        fn = get_rnd_shuffle(builder)
        builder.call(fn, (state_ptr, ))
        builder.store(const_int(0), idxptr)
    idx = builder.load(idxptr)
    array_ptr = get_array_ptr(builder, state_ptr)
    y = builder.load(cgutils.gep_inbounds(builder, array_ptr, 0, idx))
    idx = builder.add(idx, const_int(1))
    builder.store(idx, idxptr)
    # Tempering
    y = builder.xor(y, builder.lshr(y, const_int(11)))
    y = builder.xor(
        y, builder.and_(builder.shl(y, const_int(7)), const_int(0x9D2C5680)))
    y = builder.xor(
        y, builder.and_(builder.shl(y, const_int(15)), const_int(0xEFC60000)))
    y = builder.xor(y, builder.lshr(y, const_int(18)))
    return y
Beispiel #14
0
 def get_args_ptr(self, builder, genptr):
     return cgutils.gep_inbounds(builder, genptr, 0, 1)
def get_array_ptr(builder, state_ptr):
    return cgutils.gep_inbounds(builder, state_ptr, 0, 1)
def get_gauss_ptr(builder, state_ptr):
    return cgutils.gep_inbounds(builder, state_ptr, 0, 3)
Beispiel #17
0
 def get_resume_index_ptr(self, builder, genptr):
     return cgutils.gep_inbounds(builder,
                                 genptr,
                                 0,
                                 0,
                                 name='gen.resume_index')
def get_index_ptr(builder, state_ptr):
    return cgutils.gep_inbounds(builder, state_ptr, 0, 0)
Beispiel #19
0
 def as_data(self, builder, value):
     values = [
         builder.load(cgutils.gep_inbounds(builder, value, i))
         for i in range(self._fe_type.count)
     ]
     return cgutils.pack_array(builder, values)
Beispiel #20
0
 def get_state_ptr(self, builder, genptr):
     return cgutils.gep_inbounds(builder, genptr, 0, 2, name='gen.state')
Beispiel #21
0
def _build_array(context, builder, array_ty, input_types, inputs):
    """Utility function to handle allocation of an implicit output array
    given the target context, builder, output array type, and a list of
    _ArrayHelper instances.
    """
    # First, strip optional types, ufunc loops are typed on concrete types
    input_types = [
        x.type if isinstance(x, types.Optional) else x for x in input_types
    ]

    intp_ty = context.get_value_type(types.intp)

    def make_intp_const(val):
        return context.get_constant(types.intp, val)

    ZERO = make_intp_const(0)
    ONE = make_intp_const(1)

    src_shape = cgutils.alloca_once(builder, intp_ty, array_ty.ndim,
                                    "src_shape")
    dest_ndim = make_intp_const(array_ty.ndim)
    dest_shape = cgutils.alloca_once(builder, intp_ty, array_ty.ndim,
                                     "dest_shape")
    dest_shape_addrs = tuple(
        cgutils.gep_inbounds(builder, dest_shape, index)
        for index in range(array_ty.ndim))

    # Initialize the destination shape with all ones.
    for dest_shape_addr in dest_shape_addrs:
        builder.store(ONE, dest_shape_addr)

    # For each argument, try to broadcast onto the destination shape,
    # mutating along any axis where the argument shape is not one and
    # the destination shape is one.
    for arg_number, arg in enumerate(inputs):
        if not hasattr(arg, "ndim"):  # Skip scalar arguments
            continue
        arg_ndim = make_intp_const(arg.ndim)
        for index in range(arg.ndim):
            builder.store(arg.shape[index],
                          cgutils.gep_inbounds(builder, src_shape, index))
        arg_result = context.compile_internal(
            builder, _broadcast_onto, _broadcast_onto_sig,
            [arg_ndim, src_shape, dest_ndim, dest_shape])
        with cgutils.if_unlikely(builder,
                                 builder.icmp(lc.ICMP_SLT, arg_result, ONE)):
            msg = "unable to broadcast argument %d to output array" % (
                arg_number, )

            loc = errors.loc_info.get('loc', None)
            if loc is not None:
                msg += '\nFile "%s", line %d, ' % (loc.filename, loc.line)

            context.call_conv.return_user_exc(builder, ValueError, (msg, ))

    real_array_ty = array_ty.as_array

    dest_shape_tup = tuple(
        builder.load(dest_shape_addr) for dest_shape_addr in dest_shape_addrs)
    array_val = arrayobj._empty_nd_impl(context, builder, real_array_ty,
                                        dest_shape_tup)

    # Get the best argument to call __array_wrap__ on
    array_wrapper_index = select_array_wrapper(input_types)
    array_wrapper_ty = input_types[array_wrapper_index]
    try:
        # __array_wrap__(source wrapped array, out array) -> out wrapped array
        array_wrap = context.get_function(
            '__array_wrap__', array_ty(array_wrapper_ty, real_array_ty))
    except NotImplementedError:
        # If it's the same priority as a regular array, assume we
        # should use the allocated array unchanged.
        if array_wrapper_ty.array_priority != types.Array.array_priority:
            raise
        out_val = array_val._getvalue()
    else:
        wrap_args = (inputs[array_wrapper_index].return_val,
                     array_val._getvalue())
        out_val = array_wrap(builder, wrap_args)

    ndim = array_ty.ndim
    shape = cgutils.unpack_tuple(builder, array_val.shape, ndim)
    strides = cgutils.unpack_tuple(builder, array_val.strides, ndim)
    return _ArrayHelper(context, builder, shape, strides, array_val.data,
                        array_ty.layout, array_ty.dtype, ndim, out_val)