示例#1
0
    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 = builder.module.get_or_insert_function(fnty,
                                                   name='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)
        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
示例#2
0
def int_divmod_signed(context, builder, ty, 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

    ZERO = y.type(0)
    ONE = y.type(1)

    # NOTE: On x86 at least, dividing the lowest representable integer
    # (e.g. 0x80000000 for int32) by -1 causes a SIFGPE (division overflow),
    # causing the process to crash.
    # We return 0, 0 instead (more or less like Numpy).

    resdiv = cgutils.alloca_once_value(builder, ZERO)
    resmod = cgutils.alloca_once_value(builder, ZERO)

    is_overflow = builder.and_(
        builder.icmp_signed("==", x, x.type(ty.minval)),
        builder.icmp_signed("==", y, y.type(-1)),
    )

    with builder.if_then(builder.not_(is_overflow), likely=True):
        # Note LLVM will optimize this to a single divmod instruction,
        # if available on the target CPU (e.g. x86).
        xdivy = builder.sdiv(x, y)
        xmody = builder.srem(x, y)

        y_xor_xmody_ltz = builder.icmp_signed("<", builder.xor(y, xmody), ZERO)
        xmody_istrue = builder.icmp_signed("!=", xmody, ZERO)
        cond = builder.and_(xmody_istrue, y_xor_xmody_ltz)

        with builder.if_else(cond) as (if_different_signs, if_same_signs):
            with if_same_signs:
                builder.store(xdivy, resdiv)
                builder.store(xmody, resmod)

            with if_different_signs:
                builder.store(builder.sub(xdivy, ONE), resdiv)
                builder.store(builder.add(xmody, y), resmod)

    return builder.load(resdiv), builder.load(resmod)
示例#3
0
def codegen_get_voidptr(context, builder, ty_var, var_val):
    dm_key = context.data_model_manager[ty_var]
    data_val = dm_key.as_data(builder, var_val)
    ptr_var = cgutils.alloca_once_value(builder, data_val)
    val_as_voidptr = _as_bytes(builder, ptr_var)

    return val_as_voidptr
示例#4
0
 def codegen(context, builder, signature, args):
     data, = args
     rawptr = cgutils.alloca_once_value(builder, value=data)
     struct = builder.load(builder.gep(rawptr,
                                       [int32_t(0)]))
     return builder.load(builder.gep(
         struct, [int32_t(0), int32_t(1)]))
示例#5
0
 def box_generator_struct(self, lower, gen_struct):
     """
     Box the raw *gen_struct* as a Python object.
     """
     gen_ptr = cgutils.alloca_once_value(lower.builder, gen_struct)
     return lower.pyapi.from_native_generator(gen_ptr, self.gentype,
                                              lower.envarg)
示例#6
0
 def from_list(cls, context, builder, iter_type, list_val):
     list_inst = ListInstance(context, builder, iter_type.container, list_val)
     self = cls(context, builder, iter_type, None)
     index = context.get_constant(types.intp, 0)
     self._iter.index = cgutils.alloca_once_value(builder, index)
     self._iter.meminfo = list_inst.meminfo
     return self
示例#7
0
def unbox_numpy_random_generator(typ, obj, c):
    """
    Here we're creating a NumPyRandomGeneratorType StructModel with following fields:
    * ('bit_generator', _bit_gen_type): The unboxed BitGenerator associated with
                                        this Generator object instance.
    * ('parent', types.pyobject): Pointer to the original Generator PyObject.
    * ('meminfo', types.MemInfoPointer(types.voidptr)): The information about the memory
        stored at the pointer (to the original Generator PyObject). This is useful for
        keeping track of reference counts within the Python runtime. Helps prevent cases
        where deletion happens in Python runtime without NRT being awareness of it. 
    """
    is_error_ptr = cgutils.alloca_once_value(c.builder, cgutils.false_bit)

    with ExitStack() as stack:
        struct_ptr = cgutils.create_struct_proxy(typ)(c.context, c.builder)
        bit_gen_inst = c.pyapi.object_getattr_string(obj, 'bit_generator')
        with early_exit_if_null(c.builder, stack, bit_gen_inst):
            c.builder.store(cgutils.true_bit, is_error_ptr)
        unboxed = c.unbox(_bit_gen_type, bit_gen_inst).value
        struct_ptr.bit_generator = unboxed
        struct_ptr.parent = obj
        NULL = cgutils.voidptr_t(None)
        struct_ptr.meminfo = c.pyapi.nrt_meminfo_new_from_pyobject(
            NULL,  # there's no data
            obj,   # the python object, the call to nrt_meminfo_new_from_pyobject
                # will py_incref
        )
        c.pyapi.decref(bit_gen_inst)

    return NativeValue(struct_ptr._getvalue(), is_error=c.builder.load(is_error_ptr))
示例#8
0
def unbox_unicodecharseq(typ, obj, c):
    lty = c.context.get_value_type(typ)

    ok, buffer, size, kind, is_ascii, hashv = \
        c.pyapi.string_as_string_size_and_kind(obj)

    # If conversion is ok, copy the buffer to the output storage.
    with cgutils.if_likely(c.builder, ok):
        # Check if the returned string size fits in the charseq
        storage_size = ir.Constant(size.type, typ.count)
        size_fits = c.builder.icmp_unsigned("<=", size, storage_size)

        # Allow truncation of string
        size = c.builder.select(size_fits, size, storage_size)

        # Initialize output to zero bytes
        null_string = ir.Constant(lty, None)
        outspace = cgutils.alloca_once_value(c.builder, null_string)

        # We don't need to set the NULL-terminator because the storage
        # is already zero-filled.
        cgutils.memcpy(c.builder, c.builder.bitcast(outspace, buffer.type),
                       buffer, size)

    ret = c.builder.load(outspace)
    return NativeValue(ret, is_error=c.builder.not_(ok))
示例#9
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))
示例#10
0
def print_varargs(context, builder, sig, args):
    """This function is a generic 'print' wrapper for arbitrary types.
    It dispatches to the appropriate 'print' implementations above
    depending on the detected real types in the signature."""

    vprint = nvvmutils.declare_vprint(builder.module)

    formats = []
    values = []

    for i, (argtype, argval) in enumerate(zip(sig.args, args)):
        argfmt, argvals = print_item(argtype, context, builder, argval)
        formats.append(argfmt)
        values.extend(argvals)

    rawfmt = " ".join(formats) + "\n"
    if len(args) > 32:
        msg = ('CUDA print() cannot print more than 32 items. '
               'The raw format string will be emitted by the kernel instead.')
        warn(msg, NumbaWarning)

        rawfmt = rawfmt.replace('%', '%%')
    fmt = context.insert_string_const_addrspace(builder, rawfmt)
    array = cgutils.make_anonymous_struct(builder, values)
    arrayptr = cgutils.alloca_once_value(builder, array)

    vprint = nvvmutils.declare_vprint(builder.module)
    builder.call(vprint, (fmt, builder.bitcast(arrayptr, voidptr)))

    return context.get_dummy_value()
示例#11
0
def box_list(typ, val, c):
    """
    Convert native list *val* to a list object.
    """
    list = listobj.ListInstance(c.context, c.builder, typ, val)
    obj = list.parent
    res = cgutils.alloca_once_value(c.builder, obj)
    with c.builder.if_else(cgutils.is_not_null(c.builder, obj)) as (has_parent,
                                                                    otherwise):
        with has_parent:
            # List is actually reflected => return the original object
            # (note not all list instances whose *type* is reflected are
            #  actually reflected; see numba.tests.test_lists for an example)
            c.pyapi.incref(obj)

        with otherwise:
            # Build a new Python list
            nitems = list.size
            obj = c.pyapi.list_new(nitems)
            with c.builder.if_then(cgutils.is_not_null(c.builder, obj),
                                   likely=True):
                with cgutils.for_range(c.builder, nitems) as loop:
                    item = list.getitem(loop.index)
                    list.incref_value(item)
                    itemobj = c.box(typ.dtype, item)
                    c.pyapi.list_setitem(obj, loop.index, itemobj)

            c.builder.store(obj, res)

    # Steal NRT ref
    c.context.nrt.decref(c.builder, typ, val)
    return c.builder.load(res)
示例#12
0
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 = builder.module.get_or_insert_function(fnty, name="allgather")
    builder.call(fn, call_args)
    return context.get_dummy_value()
示例#13
0
def box_set(typ, val, c):
    """
    Convert native set *val* to a set object.
    """
    inst = setobj.SetInstance(c.context, c.builder, typ, val)
    obj = inst.parent
    res = cgutils.alloca_once_value(c.builder, obj)

    with c.builder.if_else(cgutils.is_not_null(c.builder, obj)) as (has_parent,
                                                                    otherwise):
        with has_parent:
            # Set is actually reflected => return the original object
            # (note not all set instances whose *type* is reflected are
            #  actually reflected; see numba.tests.test_sets for an example)
            c.pyapi.incref(obj)

        with otherwise:
            # Build a new Python list and then create a set from that
            payload = inst.payload
            ok, listobj = _native_set_to_python_list(typ, payload, c)
            with c.builder.if_then(ok, likely=True):
                obj = c.pyapi.set_new(listobj)
                c.pyapi.decref(listobj)
                c.builder.store(obj, res)

    # Steal NRT ref
    c.context.nrt.decref(c.builder, typ, val)
    return c.builder.load(res)
示例#14
0
    def codegen(context, builder, sig, args):
        fnty = ir.FunctionType(
            ll_status,
            [ll_list_type, ll_bytes],
        )
        [l, item] = args
        [tl, titem] = sig.args
        fn = builder.module.get_or_insert_function(fnty,
                                                   name='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
示例#15
0
def unbox_optional(typ, obj, c):
    """
    Convert object *obj* to a native optional structure.
    """
    noneval = c.context.make_optional_none(c.builder, typ.type)
    is_not_none = c.builder.icmp_signed('!=', obj, c.pyapi.borrow_none())

    retptr = cgutils.alloca_once(c.builder, noneval.type)
    errptr = cgutils.alloca_once_value(c.builder, cgutils.false_bit)

    with c.builder.if_else(is_not_none) as (then, orelse):
        with then:
            native = c.unbox(typ.type, obj)
            just = c.context.make_optional_value(c.builder, typ.type,
                                                 native.value)
            c.builder.store(just, retptr)
            c.builder.store(native.is_error, errptr)

        with orelse:
            c.builder.store(noneval, retptr)

    if native.cleanup is not None:

        def cleanup():
            with c.builder.if_then(is_not_none):
                native.cleanup()
    else:
        cleanup = None

    ret = c.builder.load(retptr)
    return NativeValue(ret, is_error=c.builder.load(errptr), cleanup=cleanup)
示例#16
0
    def codegen(context, builder, sig, args):
        fnty = ir.FunctionType(ll_status, [ll_list_type, ll_ssize_t, ll_bytes],)
        [tl, tindex] = sig.args
        [l, index] = args
        fn = builder.module.get_or_insert_function(
            fnty, name="numba_list_{}".format(op)
        )

        dm_item = context.data_model_manager[tl.item_type]
        ll_item = context.get_data_type(tl.item_type)
        ptr_item = cgutils.alloca_once(builder, ll_item)

        lp = _container_get_data(context, builder, tl, l)
        status = builder.call(fn, [lp, index, _as_bytes(builder, ptr_item),],)
        # Load item if output is available
        found = builder.icmp_signed(">=", status, status.type(int(ListStatus.LIST_OK)))
        out = context.make_optional_none(
            builder, tl.item_type if IS_NOT_NONE else types.int64
        )
        pout = cgutils.alloca_once_value(builder, out)

        with builder.if_then(found):
            if IS_NOT_NONE:
                item = dm_item.load_from_data_pointer(builder, ptr_item)
                context.nrt.incref(builder, tl.item_type, item)
                loaded = context.make_optional_value(builder, tl.item_type, item)
                builder.store(loaded, pout)

        out = builder.load(pout)
        return context.make_tuple(builder, resty, [status, out])
示例#17
0
def unbox_set(typ, obj, c):
    """
    Convert set *obj* to a native set.

    If set was previously unboxed, we reuse the existing native set
    to ensure consistency.
    """
    size = c.pyapi.set_size(obj)

    errorptr = cgutils.alloca_once_value(c.builder, cgutils.false_bit)
    setptr = cgutils.alloca_once(c.builder, c.context.get_value_type(typ))

    # See if the set was previously unboxed, if so, re-use the meminfo.
    ptr = c.pyapi.object_get_private_data(obj)

    with c.builder.if_else(cgutils.is_not_null(c.builder, ptr)) \
        as (has_meminfo, otherwise):

        with has_meminfo:
            # Set was previously unboxed => reuse meminfo
            inst = setobj.SetInstance.from_meminfo(c.context, c.builder, typ, ptr)
            if typ.reflected:
                inst.parent = obj
            c.builder.store(inst.value, setptr)

        with otherwise:
            _python_set_to_native(typ, obj, c, size, setptr, errorptr)

    def cleanup():
        # Clean up the associated pointer, as the meminfo is now invalid.
        c.pyapi.object_reset_private_data(obj)

    return NativeValue(c.builder.load(setptr),
                       is_error=c.builder.load(errorptr),
                       cleanup=cleanup)
示例#18
0
def _unbox_native_field(typ, obj, field_name: str, c):
    ret_ptr = cgutils.alloca_once(c.builder, c.context.get_value_type(typ))
    is_error_ptr = cgutils.alloca_once_value(c.builder, cgutils.false_bit)
    fail_obj = c.context.get_constant_null(typ)

    with local_return(c.builder) as ret:
        fail_blk = c.builder.append_basic_block("fail")
        with c.builder.goto_block(fail_blk):
            c.builder.store(cgutils.true_bit, is_error_ptr)
            c.builder.store(fail_obj, ret_ptr)
            ret()

        field_obj = c.pyapi.object_getattr_string(obj, field_name)
        with cgutils.if_unlikely(c.builder,
                                 cgutils.is_null(c.builder, field_obj)):
            c.builder.branch(fail_blk)

        field_native = c.unbox(typ, field_obj)
        c.pyapi.decref(field_obj)
        with cgutils.if_unlikely(c.builder, field_native.is_error):
            c.builder.branch(fail_blk)

        c.builder.store(cgutils.false_bit, is_error_ptr)
        c.builder.store(field_native.value, ret_ptr)

    return NativeValue(c.builder.load(ret_ptr),
                       is_error=c.builder.load(is_error_ptr))
示例#19
0
def _python_set_to_native(typ, obj, c, size, setptr, errorptr):
    """
    Construct a new native set from a Python set.
    """
    # Allocate a new native set
    ok, inst = setobj.SetInstance.allocate_ex(c.context, c.builder, typ, size)
    with c.builder.if_else(ok, likely=True) as (if_ok, if_not_ok):
        with if_ok:
            # Traverse Python set and unbox objects into native set
            typobjptr = cgutils.alloca_once_value(
                c.builder, ir.Constant(c.pyapi.pyobj, None))

            with c.pyapi.set_iterate(obj) as loop:
                itemobj = loop.value
                # Mandate that objects all have the same exact type
                typobj = c.pyapi.get_type(itemobj)
                expected_typobj = c.builder.load(typobjptr)

                with c.builder.if_else(cgutils.is_null(c.builder,
                                                       expected_typobj),
                                       likely=False) as (if_first,
                                                         if_not_first):
                    with if_first:
                        # First iteration => store item type
                        c.builder.store(typobj, typobjptr)
                    with if_not_first:
                        # Otherwise, check item type
                        type_mismatch = c.builder.icmp_signed(
                            '!=', typobj, expected_typobj)
                        with c.builder.if_then(type_mismatch, likely=False):
                            c.builder.store(cgutils.true_bit, errorptr)
                            c.pyapi.err_set_string(
                                "PyExc_TypeError",
                                "can't unbox heterogeneous set")
                            loop.do_break()

                # XXX we don't call native cleanup for each set element,
                # since that would require keeping track
                # of which unboxings have been successful.
                native = c.unbox(typ.dtype, itemobj)
                with c.builder.if_then(native.is_error, likely=False):
                    c.builder.store(cgutils.true_bit, errorptr)
                inst.add_pyapi(c.pyapi, native.value, do_resize=False)

            if typ.reflected:
                inst.parent = obj
            # Associate meminfo pointer with the Python object for later reuse.
            with c.builder.if_then(c.builder.not_(c.builder.load(errorptr)),
                                   likely=False):
                c.pyapi.object_set_private_data(obj, inst.meminfo)
            inst.set_dirty(False)
            c.builder.store(inst.value, setptr)

        with if_not_ok:
            c.builder.store(cgutils.true_bit, errorptr)

    # If an error occurred, drop the whole native set
    with c.builder.if_then(c.builder.load(errorptr)):
        c.context.nrt.decref(c.builder, typ, inst.value)
示例#20
0
def StructureNumbaPointerType_getattr_impl(context, builder, sig, struct,
                                           attr):
    typ = sig.dtype
    model = datamodel.default_manager.lookup(typ)
    index = model.get_field_position(attr)
    rawptr = cgutils.alloca_once_value(builder, value=struct)
    struct = builder.load(builder.gep(rawptr, [int32_t(0)]))
    return builder.load(builder.gep(struct, [int32_t(0), int32_t(index)]))
示例#21
0
 def from_list(cls, context, builder, iter_type, list_val):
     self = cls(context, builder, iter_type, None)
     index = context.get_constant(types.intp, 0)
     self._iter.index = cgutils.alloca_once_value(builder, index)
     self._iter.parent = list_val
     self._iter.size = cls._size_of_list(context, builder, self._list_ty,
                                         self._iter.parent)
     return self
示例#22
0
    def codegen(context, builder, signature, args):
        data, index = args
        rawptr = cgutils.alloca_once_value(builder, value=data)
        buf = builder.load(builder.gep(rawptr, [int32_t(0)]))
        ptr = builder.load(builder.gep(buf, [int32_t(0), int32_t(0)]))
        res = builder.load(builder.gep(ptr, [index]))

        return res
示例#23
0
def box_numpy_random_generator(typ, val, c):
    inst = c.context.make_helper(c.builder, typ, val)
    obj = inst.parent
    res = cgutils.alloca_once_value(c.builder, obj)
    c.pyapi.incref(obj)
    # Steal NRT ref
    c.context.nrt.decref(c.builder, typ, val)
    return c.builder.load(res)
示例#24
0
def StructureNumbaPointerType_setattr_impl(context, builder, sig, args, attr):
    typ = sig.args[0].dtype
    struct, value = args
    model = datamodel.default_manager.lookup(typ)
    index = model.get_field_position(attr)
    rawptr = cgutils.alloca_once_value(builder, value=struct)
    ptr = builder.load(rawptr)
    buf = builder.load(builder.gep(ptr, [int32_t(0), int32_t(index)]))
    builder.store(value, buf.operands[0])
示例#25
0
    def codegen(context, builder, sig, args):
        fnty = ir.FunctionType(
            ll_ssize_t,
            [ll_dict_type, ll_bytes, ll_hash, ll_bytes],
        )
        [td, tkey, thashval] = sig.args
        [d, key, hashval] = args
        fn = cgutils.get_or_insert_function(builder.module, fnty,
                                            'numba_dict_lookup')

        dm_key = context.data_model_manager[tkey]
        dm_val = context.data_model_manager[td.value_type]

        data_key = dm_key.as_data(builder, key)
        ptr_key = cgutils.alloca_once_value(builder, data_key)
        cgutils.memset_padding(builder, ptr_key)

        ll_val = context.get_data_type(td.value_type)
        ptr_val = cgutils.alloca_once(builder, ll_val)

        dp = _container_get_data(context, builder, td, d)
        ix = builder.call(
            fn,
            [
                dp,
                _as_bytes(builder, ptr_key),
                hashval,
                _as_bytes(builder, ptr_val),
            ],
        )
        # Load value if output is available
        found = builder.icmp_signed('>', ix, ix.type(int(DKIX.EMPTY)))

        out = context.make_optional_none(builder, td.value_type)
        pout = cgutils.alloca_once_value(builder, out)

        with builder.if_then(found):
            val = dm_val.load_from_data_pointer(builder, ptr_val)
            context.nrt.incref(builder, td.value_type, val)
            loaded = context.make_optional_value(builder, td.value_type, val)
            builder.store(loaded, pout)

        out = builder.load(pout)
        return context.make_tuple(builder, resty, [ix, out])
示例#26
0
    def codegen(context, builder, signature, args):
        zero = int32_t(0)

        data, index, value = args

        rawptr = cgutils.alloca_once_value(builder, value=data)
        ptr = builder.load(rawptr)

        arr = builder.load(builder.gep(ptr, [zero, zero]))
        builder.store(value, builder.gep(arr, [index]))
示例#27
0
def box_optional(typ, val, c):
    optval = c.context.make_helper(c.builder, typ, val)
    ret = cgutils.alloca_once_value(c.builder, c.pyapi.borrow_none())
    with c.builder.if_else(optval.valid) as (then, otherwise):
        with then:
            validres = c.box(typ.type, optval.data)
            c.builder.store(validres, ret)
        with otherwise:
            c.builder.store(c.pyapi.make_none(), ret)
    return c.builder.load(ret)
示例#28
0
    def codegen(context, builder, signature, args):
        zero = int32_t(0)

        data, index, value = args

        rawptr = cgutils.alloca_once_value(builder, value=data)
        ptr = builder.load(rawptr)

        buf = builder.load(builder.gep(ptr, [zero, zero]))
        value = truncate_or_extend(builder, nb_value, eltype, value, buf.type.pointee)
        builder.store(value, builder.gep(buf, [index]))
示例#29
0
def unbox_tuple(typ, obj, c):
    """
    Convert tuple *obj* to a native array (if homogeneous) or structure.
    """
    n = len(typ)
    values = []
    cleanups = []
    lty = c.context.get_value_type(typ)

    is_error_ptr = cgutils.alloca_once_value(c.builder, cgutils.false_bit)
    value_ptr = cgutils.alloca_once(c.builder, lty)

    # Issue #1638: need to check the tuple size
    actual_size = c.pyapi.tuple_size(obj)
    size_matches = c.builder.icmp_unsigned(
        "==", actual_size, ir.Constant(actual_size.type, n)
    )
    with c.builder.if_then(c.builder.not_(size_matches), likely=False):
        c.pyapi.err_format(
            "PyExc_ValueError",
            "size mismatch for tuple, expected %d element(s) but got %%zd" % (n,),
            actual_size,
        )
        c.builder.store(cgutils.true_bit, is_error_ptr)

    # We unbox the items even if not `size_matches`, to avoid issues with
    # the generated IR (instruction doesn't dominate all uses)
    for i, eltype in enumerate(typ):
        elem = c.pyapi.tuple_getitem(obj, i)
        native = c.unbox(eltype, elem)
        values.append(native.value)
        with c.builder.if_then(native.is_error, likely=False):
            c.builder.store(cgutils.true_bit, is_error_ptr)
        if native.cleanup is not None:
            cleanups.append(native.cleanup)

    value = c.context.make_tuple(c.builder, typ, values)
    c.builder.store(value, value_ptr)

    if cleanups:
        with c.builder.if_then(size_matches, likely=True):

            def cleanup():
                for func in reversed(cleanups):
                    func()

    else:
        cleanup = None

    return NativeValue(
        c.builder.load(value_ptr),
        cleanup=cleanup,
        is_error=c.builder.load(is_error_ptr),
    )
示例#30
0
def box_charseq(typ, val, c):
    rawptr = cgutils.alloca_once_value(c.builder, value=val)
    strptr = c.builder.bitcast(rawptr, c.pyapi.cstring)
    fullsize = c.context.get_constant(types.intp, typ.count)
    zero = fullsize.type(0)
    one = fullsize.type(1)
    count = cgutils.alloca_once_value(c.builder, zero)

    # Find the length of the string, mimicking Numpy's behaviour:
    # search for the last non-null byte in the underlying storage
    # (e.g. b'A\0\0B\0\0\0' will return the logical string b'A\0\0B')
    with cgutils.loop_nest(c.builder, [fullsize], fullsize.type) as [idx]:
        # Get char at idx
        ch = c.builder.load(c.builder.gep(strptr, [idx]))
        # If the char is a non-null-byte, store the next index as count
        with c.builder.if_then(cgutils.is_not_null(c.builder, ch)):
            c.builder.store(c.builder.add(idx, one), count)

    strlen = c.builder.load(count)
    return c.pyapi.bytes_from_string_and_size(strptr, strlen)