Exemple #1
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))
Exemple #2
0
def _define_nrt_decref(module, atomic_decr):
    """
    Implement NRT_decref in the module
    """
    fn_decref = module.get_or_insert_function(incref_decref_ty,
                                              name="NRT_decref")
    calldtor = module.add_function(ir.FunctionType(ir.VoidType(), [_pointer_type]),
                                   name="NRT_MemInfo_call_dtor")

    builder = ir.IRBuilder(fn_decref.append_basic_block())
    [ptr] = fn_decref.args
    is_null = builder.icmp_unsigned("==", ptr, cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()

    if _debug_print:
        cgutils.printf(builder, "*** NRT_Decref %zu [%p]\n", builder.load(ptr),
                       ptr)
    newrefct = builder.call(atomic_decr,
                            [builder.bitcast(ptr, atomic_decr.args[0].type)])

    refct_eq_0 = builder.icmp_unsigned("==", newrefct,
                                       ir.Constant(newrefct.type, 0))
    with cgutils.if_unlikely(builder, refct_eq_0):
        builder.call(calldtor, [ptr])
    builder.ret_void()
Exemple #3
0
def _define_decref(module, atomic_decr):
    """
    Implement NRT_decref in the module
    """
    if "NRT_decref" not in module.globals:
        return
    fn_decref = module.get_global_variable_named("NRT_decref")
    fn_decref.linkage = 'linkonce_odr'
    calldtor = module.add_function(ir.FunctionType(
        ir.VoidType(), [ir.IntType(8).as_pointer(),
                        ir.IntType(32)]),
                                   name="NRT_MemInfo_call_dtor")

    builder = ir.IRBuilder(fn_decref.append_basic_block())
    [ptr] = fn_decref.args
    is_null = builder.icmp_unsigned("==", ptr,
                                    cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()
    newrefct = builder.call(atomic_decr,
                            [builder.bitcast(ptr, atomic_decr.args[0].type)])

    refct_eq_0 = builder.icmp_unsigned("==", newrefct,
                                       ir.Constant(newrefct.type, 0))
    with cgutils.if_unlikely(builder, refct_eq_0):
        do_defer = ir.Constant(ir.IntType(32), 0)
        builder.call(calldtor, [ptr, do_defer])
    builder.ret_void()
Exemple #4
0
    def builtin_lookup(self, mod, name):
        """
        Args
        ----
        mod:
            The __builtins__ dictionary or module, as looked up in
            a module's globals.
        name: str
            The object to lookup
        """
        fromdict = self.pyapi.dict_getitem_string(mod, name)
        self.incref(fromdict)  # fromdict is borrowed
        bbifdict = self.builder.basic_block

        with cgutils.if_unlikely(self.builder, self.is_null(fromdict)):
            # This happen if we are using the __main__ module
            frommod = self.pyapi.object_getattr_string(mod, name)

            with cgutils.if_unlikely(self.builder, self.is_null(frommod)):
                self.pyapi.raise_missing_global_error(name)
                self.return_exception_raised()

            bbifmod = self.builder.basic_block

        builtin = self.builder.phi(self.pyapi.pyobj)
        builtin.add_incoming(fromdict, bbifdict)
        builtin.add_incoming(frommod, bbifmod)

        return builtin
Exemple #5
0
def _define_decref(module, atomic_decr):
    """
    Implement NRT_decref in the module
    """
    if "NRT_decref" not in module.globals:
        return
    fn_decref = module.get_global_variable_named("NRT_decref")
    fn_decref.linkage = 'linkonce_odr'
    calldtor = module.add_function(ir.FunctionType(ir.VoidType(),
        [ir.IntType(8).as_pointer(), ir.IntType(32)]),
        name="NRT_MemInfo_call_dtor")

    builder = ir.IRBuilder(fn_decref.append_basic_block())
    [ptr] = fn_decref.args
    is_null = builder.icmp_unsigned("==", ptr, cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()
    newrefct = builder.call(atomic_decr,
                            [builder.bitcast(ptr, atomic_decr.args[0].type)])

    refct_eq_0 = builder.icmp_unsigned("==", newrefct,
                                       ir.Constant(newrefct.type, 0))
    with cgutils.if_unlikely(builder, refct_eq_0):
        do_defer = ir.Constant(ir.IntType(32), 0)
        builder.call(calldtor, [ptr, do_defer])
    builder.ret_void()
    def builtin_lookup(self, mod, name):
        """
        Args
        ----
        mod:
            The __builtins__ dictionary or module, as looked up in
            a module's globals.
        name: str
            The object to lookup
        """
        fromdict = self.pyapi.dict_getitem(mod, self._freeze_string(name))
        self.incref(fromdict)       # fromdict is borrowed
        bbifdict = self.builder.basic_block

        with cgutils.if_unlikely(self.builder, self.is_null(fromdict)):
            # This happen if we are using the __main__ module
            frommod = self.pyapi.object_getattr(mod, self._freeze_string(name))

            with cgutils.if_unlikely(self.builder, self.is_null(frommod)):
                self.pyapi.raise_missing_global_error(name)
                self.return_exception_raised()

            bbifmod = self.builder.basic_block

        builtin = self.builder.phi(self.pyapi.pyobj)
        builtin.add_incoming(fromdict, bbifdict)
        builtin.add_incoming(frommod, bbifmod)

        return builtin
Exemple #7
0
def _define_nrt_decref(module, atomic_decr):
    """
    Implement NRT_decref in the module
    """
    fn_decref = module.get_or_insert_function(incref_decref_ty,
                                              name="NRT_decref")
    # Cannot inline this for refcount pruning to work
    fn_decref.attributes.add('noinline')
    calldtor = module.add_function(ir.FunctionType(ir.VoidType(),
                                                   [_pointer_type]),
                                   name="NRT_MemInfo_call_dtor")

    builder = ir.IRBuilder(fn_decref.append_basic_block())
    [ptr] = fn_decref.args
    is_null = builder.icmp_unsigned("==", ptr,
                                    cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()

    if _debug_print:
        cgutils.printf(builder, "*** NRT_Decref %zu [%p]\n", builder.load(ptr),
                       ptr)
    newrefct = builder.call(atomic_decr,
                            [builder.bitcast(ptr, atomic_decr.args[0].type)])

    refct_eq_0 = builder.icmp_unsigned("==", newrefct,
                                       ir.Constant(newrefct.type, 0))
    with cgutils.if_unlikely(builder, refct_eq_0):
        builder.call(calldtor, [ptr])
    builder.ret_void()
Exemple #8
0
def iternext_zip(context, builder, sig, args, result):
    genty, = sig.args
    gen, = args
    # XXX We should link with the generator's library.
    # Currently, this doesn't make a difference as the library has already
    # been linked for the generator init function.
    impl = context.get_generator_impl(genty)
    status, retval = impl(context, builder, sig, args)
    with cgutils.if_likely(builder, status.is_ok):
        result.set_valid(True)
        result.yield_(retval)
    with cgutils.if_unlikely(builder, status.is_stop_iteration):
        result.set_exhausted()
    with cgutils.if_unlikely(builder, builder.and_(status.is_error, builder.not_(status.is_stop_iteration))):
        context.call_conv.return_status_propagate(builder, status)
Exemple #9
0
    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
Exemple #10
0
    def check_occurred(self):
        err_occurred = cgutils.is_not_null(self.builder,
                                           self.pyapi.err_occurred())

        with cgutils.if_unlikely(self.builder, err_occurred):
            # FIXME: this should decref all live variables before returning
            self.return_exception_raised()
Exemple #11
0
    def set_iter_valid(self, state, item):
        iterstate = PyIterState(self.context, self.builder, ref=state)
        iterstate.valid = cgutils.as_bool_byte(
            self.builder, cgutils.is_not_null(self.builder, item))

        with cgutils.if_unlikely(self.builder, self.is_null(item)):
            self.check_occurred()
Exemple #12
0
    def to_native_arg(self, obj, typ):
        if isinstance(typ, types.Record):
            # Generate a dummy integer type that has the size of Py_buffer
            dummy_py_buffer_type = Type.int(_helperlib.py_buffer_size * 8)
            # Allocate the Py_buffer
            py_buffer = cgutils.alloca_once(self.builder, dummy_py_buffer_type)

            # Zero-fill the py_buffer. where the obj field in Py_buffer is NULL
            # PyBuffer_Release has no effect.
            zeroed_buffer = lc.Constant.null(dummy_py_buffer_type)
            self.builder.store(zeroed_buffer, py_buffer)

            buf_as_voidptr = self.builder.bitcast(py_buffer, self.voidptr)
            ptr = self.extract_record_data(obj, buf_as_voidptr)

            with cgutils.if_unlikely(self.builder,
                                     cgutils.is_null(self.builder, ptr)):
                self.builder.ret(ptr)

            ltyp = self.context.get_value_type(typ)
            val = cgutils.init_record_by_ptr(self.builder, ltyp, ptr)

            def dtor():
                self.release_record_buffer(buf_as_voidptr)

        else:
            val = self.to_native_value(obj, typ)

            def dtor():
                pass

        return val, dtor
Exemple #13
0
def iternext_zip(context, builder, sig, args, result):
    genty, = sig.args
    gen, = args
    impl = context.get_generator_impl(genty)
    status, retval = impl(context, builder, sig, args)
    context.add_linking_libs(getattr(impl, 'libs', ()))

    with cgutils.if_likely(builder, status.is_ok):
        result.set_valid(True)
        result.yield_(retval)
    with cgutils.if_unlikely(builder, status.is_stop_iteration):
        result.set_exhausted()
    with cgutils.if_unlikely(builder,
                             builder.and_(status.is_error,
                                          builder.not_(status.is_stop_iteration))):
        context.call_conv.return_status_propagate(builder, status)
Exemple #14
0
    def add_arg(self, obj, ty):
        """
        Unbox argument and emit code that handles any error during unboxing.
        Args are cleaned up in reverse order of the parameter list, and
        cleanup begins as soon as unboxing of any argument fails. E.g. failure
        on arg2 will result in control flow going through:

            arg2.err -> arg1.err -> arg0.err -> arg.end (returns)
        """
        # Unbox argument
        val, dtor = self.api.to_native_arg(self.builder.load(obj), ty)

        # check for Python C-API Error
        error_check = self.api.err_occurred()
        err_happened = self.builder.icmp(lc.ICMP_NE, error_check,
                                         self.api.get_null_object())

        # Write the cleanup block
        cleanupblk = cgutils.append_basic_block(self.builder,
                                                "arg%d.err" % self.arg_count)
        with cgutils.goto_block(self.builder, cleanupblk):
            dtor()
            # Go to next cleanup block
            self.builder.branch(self.nextblk)

        # If an error occurred, go to the cleanup block
        with cgutils.if_unlikely(self.builder, err_happened):
            self.builder.branch(cleanupblk)

        self.cleanups.append(dtor)
        self.nextblk = cleanupblk
        self.arg_count += 1
        return val
Exemple #15
0
 def imp(context, builder, sig, args):
     func = context.declare_function(cgutils.get_module(builder), fndesc)
     status, retval = context.call_function(builder, func, fndesc.restype,
                                            fndesc.argtypes, args)
     with cgutils.if_unlikely(builder, status.err):
         context.return_errcode_propagate(builder, status.code)
     return retval
Exemple #16
0
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):
        fnty = ir.FunctionType(ir.VoidType(), (rnd_state_ptr_t,))
        fn = builder.function.module.get_or_insert_function(fnty, "numba_rnd_shuffle")
        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(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
Exemple #17
0
            def init_specific(self, context, builder, arrty, arr):
                zero = context.get_constant(types.intp, 0)
                data = arr.data
                ndim = arrty.ndim
                shapes = cgutils.unpack_tuple(builder, arr.shape, ndim)

                indices = cgutils.alloca_once(builder, zero.type,
                                              size=context.get_constant(types.intp,
                                                                        arrty.ndim))
                pointers = cgutils.alloca_once(builder, data.type,
                                               size=context.get_constant(types.intp,
                                                                         arrty.ndim))
                strides = cgutils.unpack_tuple(builder, arr.strides, ndim)
                exhausted = cgutils.alloca_once_value(builder, cgutils.false_byte)

                # Initialize indices and pointers with their start values.
                for dim in range(ndim):
                    idxptr = cgutils.gep(builder, indices, dim)
                    ptrptr = cgutils.gep(builder, pointers, dim)
                    builder.store(data, ptrptr)
                    builder.store(zero, idxptr)
                    # 0-sized dimensions really indicate an empty array,
                    # but we have to catch that condition early to avoid
                    # a bug inside the iteration logic (see issue #846).
                    dim_size = shapes[dim]
                    dim_is_empty = builder.icmp(lc.ICMP_EQ, dim_size, zero)
                    with cgutils.if_unlikely(builder, dim_is_empty):
                        builder.store(cgutils.true_byte, exhausted)

                self.indices = indices
                self.pointers = pointers
                self.exhausted = exhausted
Exemple #18
0
            def init_specific(self, context, builder, arrty, arr):
                zero = context.get_constant(types.intp, 0)
                data = arr.data
                ndim = arrty.ndim
                shapes = cgutils.unpack_tuple(builder, arr.shape, ndim)

                indices = cgutils.alloca_once(builder,
                                              zero.type,
                                              size=context.get_constant(
                                                  types.intp, arrty.ndim))
                pointers = cgutils.alloca_once(builder,
                                               data.type,
                                               size=context.get_constant(
                                                   types.intp, arrty.ndim))
                strides = cgutils.unpack_tuple(builder, arr.strides, ndim)
                exhausted = cgutils.alloca_once_value(builder,
                                                      cgutils.false_byte)

                # Initialize indices and pointers with their start values.
                for dim in range(ndim):
                    idxptr = cgutils.gep(builder, indices, dim)
                    ptrptr = cgutils.gep(builder, pointers, dim)
                    builder.store(data, ptrptr)
                    builder.store(zero, idxptr)
                    # 0-sized dimensions really indicate an empty array,
                    # but we have to catch that condition early to avoid
                    # a bug inside the iteration logic (see issue #846).
                    dim_size = shapes[dim]
                    dim_is_empty = builder.icmp(lc.ICMP_EQ, dim_size, zero)
                    with cgutils.if_unlikely(builder, dim_is_empty):
                        builder.store(cgutils.true_byte, exhausted)

                self.indices = indices
                self.pointers = pointers
                self.exhausted = exhausted
Exemple #19
0
 def imp(context, builder, sig, args):
     func = context.declare_function(cgutils.get_module(builder), fndesc)
     status, retval = context.call_function(builder, func, fndesc.restype,
                                            fndesc.argtypes, args)
     with cgutils.if_unlikely(builder, status.err):
         context.return_errcode_propagate(builder, status.code)
     return retval
Exemple #20
0
def iternext_zip(context, builder, sig, args, result):
    genty, = sig.args
    gen, = args
    impl = context.get_generator_impl(genty)
    status, retval = impl(context, builder, sig, args)
    context.add_linking_libs(getattr(impl, 'libs', ()))

    with cgutils.if_likely(builder, status.is_ok):
        result.set_valid(True)
        result.yield_(retval)
    with cgutils.if_unlikely(builder, status.is_stop_iteration):
        result.set_exhausted()
    with cgutils.if_unlikely(builder,
                             builder.and_(status.is_error,
                                          builder.not_(status.is_stop_iteration))):
        context.call_conv.return_status_propagate(builder, status)
Exemple #21
0
    def add_arg(self, obj, ty):
        """
        Unbox argument and emit code that handles any error during unboxing.
        Args are cleaned up in reverse order of the parameter list, and
        cleanup begins as soon as unboxing of any argument fails. E.g. failure
        on arg2 will result in control flow going through:

            arg2.err -> arg1.err -> arg0.err -> arg.end (returns)
        """
        # Unbox argument
        native = self.api.to_native_value(self.builder.load(obj), ty)

        # If an error occurred, go to the cleanup block for the previous argument.
        with cgutils.if_unlikely(self.builder, native.is_error):
            self.builder.branch(self.nextblk)

        # Write the cleanup block for this argument
        cleanupblk = cgutils.append_basic_block(self.builder,
                                                "arg%d.err" % self.arg_count)
        with cgutils.goto_block(self.builder, cleanupblk):
            if native.cleanup is not None:
                native.cleanup()
                self.cleanups.append(native.cleanup)
            # Go to next cleanup block
            self.builder.branch(self.nextblk)

        self.nextblk = cleanupblk
        self.arg_count += 1
        return native.value
Exemple #22
0
    def build_wrapper(self, api, builder, closure, args, kws):
        nargs = len(self.fndesc.argtypes)

        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 = builder.append_basic_block("arg.end")
        with builder.goto_block(endblk):
            builder.ret(api.get_null_object())

        # Extract the Environment object from the Closure
        envptr, env_manager = self.get_env(api, builder, closure)

        cleanup_manager = _ArgManager(self.context, builder, api, env_manager,
                                      endblk, nargs)

        # Compute the arguments to the compiled Numba function.
        innerargs = []
        for obj, ty in zip(objs, self.fndesc.argtypes):
            if isinstance(ty, types.Omitted):
                # It's an omitted value => ignore dummy Python object
                innerargs.append(None)
            else:
                val = cleanup_manager.add_arg(builder.load(obj), ty)
                innerargs.append(val)

        if self.release_gil:
            cleanup_manager = _GilManager(builder, api, cleanup_manager)

        status, retval = self.context.call_conv.call_function(
            builder,
            self.func,
            self.fndesc.restype,
            self.fndesc.argtypes,
            innerargs,
            env=envptr)
        # Do clean up
        self.debug_print(builder, "# callwrapper: emit_cleanup")
        cleanup_manager.emit_cleanup()
        self.debug_print(builder, "# callwrapper: emit_cleanup end")

        # Determine return status
        with builder.if_then(status.is_ok, likely=True):
            # Ok => return boxed Python value
            with builder.if_then(status.is_none):
                api.return_none()

            retty = self._simplified_return_type()
            obj = api.from_native_return(retty, retval, env_manager)
            builder.ret(obj)

        # Error out
        self.context.call_conv.raise_error(builder, api, status)
        builder.ret(api.get_null_object())
Exemple #23
0
    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 add_arg(self, obj, ty):
        """
        Unbox argument and emit code that handles any error during unboxing.
        Args are cleaned up in reverse order of the parameter list, and
        cleanup begins as soon as unboxing of any argument fails. E.g. failure
        on arg2 will result in control flow going through:

            arg2.err -> arg1.err -> arg0.err -> arg.end (returns)
        """
        # Unbox argument
        val, dtor = self.api.to_native_arg(self.builder.load(obj), ty)

        # check for Python C-API Error
        error_check = self.api.err_occurred()
        err_happened = self.builder.icmp(lc.ICMP_NE, error_check,
                                         self.api.get_null_object())

        # Write the cleanup block
        cleanupblk = cgutils.append_basic_block(self.builder,
                                                "arg%d.err" % self.arg_count)
        with cgutils.goto_block(self.builder, cleanupblk):
            dtor()
            # Go to next cleanup block
            self.builder.branch(self.nextblk)

        # If an error occurred, go to the cleanup block
        with cgutils.if_unlikely(self.builder, err_happened):
            self.builder.branch(cleanupblk)

        self.cleanups.append(dtor)
        self.nextblk = cleanupblk
        self.arg_count += 1
        return val
Exemple #25
0
def getiter_range_generic(context, builder, iterobj, start, stop, step):
    diff = builder.sub(stop, start)
    intty = start.type
    zero = Constant.int(intty, 0)
    one = Constant.int(intty, 1)
    pos_diff = builder.icmp(lc.ICMP_SGT, diff, zero)
    pos_step = builder.icmp(lc.ICMP_SGT, step, zero)
    sign_differs = builder.xor(pos_diff, pos_step)
    zero_step = builder.icmp(lc.ICMP_EQ, step, zero)

    with cgutils.if_unlikely(builder, zero_step):
        # step shouldn't be zero
        context.return_errcode(builder, 1)

    with cgutils.ifelse(builder, sign_differs) as (then, orelse):
        with then:
            builder.store(zero, iterobj.count)

        with orelse:
            rem = builder.srem(diff, step)
            uneven = builder.icmp(lc.ICMP_SGT, rem, zero)
            newcount = builder.add(builder.sdiv(diff, step),
                                   builder.select(uneven, one, zero))
            builder.store(newcount, iterobj.count)

    return iterobj._getvalue()
Exemple #26
0
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):
        fnty = ir.FunctionType(ir.VoidType(), (rnd_state_ptr_t,))
        fn = builder.function.module.get_or_insert_function(fnty, "numba_rnd_shuffle")
        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(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
Exemple #27
0
    def to_native_arg(self, obj, typ):
        if isinstance(typ, types.Record):
            # Generate a dummy integer type that has the size of Py_buffer
            dummy_py_buffer_type = Type.int(_helperlib.py_buffer_size * 8)
            # Allocate the Py_buffer
            py_buffer = cgutils.alloca_once(self.builder, dummy_py_buffer_type)

            # Zero-fill the py_buffer. where the obj field in Py_buffer is NULL
            # PyBuffer_Release has no effect.
            zeroed_buffer = lc.Constant.null(dummy_py_buffer_type)
            self.builder.store(zeroed_buffer, py_buffer)

            buf_as_voidptr = self.builder.bitcast(py_buffer, self.voidptr)
            ptr = self.extract_record_data(obj, buf_as_voidptr)

            with cgutils.if_unlikely(self.builder,
                                     cgutils.is_null(self.builder, ptr)):
                self.builder.ret(ptr)

            ltyp = self.context.get_value_type(typ)
            val = cgutils.init_record_by_ptr(self.builder, ltyp, ptr)

            def dtor():
                self.release_record_buffer(buf_as_voidptr)

        else:
            val = self.to_native_value(obj, typ)

            def dtor():
                pass

        return val, dtor
Exemple #28
0
def getitem_array1d(context, builder, sig, args):
    aryty, _ = sig.args
    if aryty.ndim != 1:
        # TODO
        raise NotImplementedError("1D indexing into %dD array" % aryty.ndim)

    ary, idx = args

    arystty = make_array(aryty)
    ary = arystty(context, builder, ary)
    dataptr = ary.data

    if True or WARPAROUND:  # TODO target flag
        ZERO = context.get_constant(types.intp, 0)
        negative = builder.icmp(lc.ICMP_SLT, idx, ZERO)
        bbnormal = builder.basic_block
        with cgutils.if_unlikely(builder, negative):
            # Index is negative, wraparound
            [nelem] = cgutils.unpack_tuple(builder, ary.shape, 1)
            wrapped = builder.add(nelem, idx)
            bbwrapped = builder.basic_block

        where = builder.phi(idx.type)
        where.add_incoming(idx, bbnormal)
        where.add_incoming(wrapped, bbwrapped)

        ptr = builder.gep(dataptr, [where])
    else:
        # No wraparound
        ptr = builder.gep(dataptr, [idx])

    if context.is_struct_type(aryty.dtype):
        return ptr
    else:
        return builder.load(ptr)
Exemple #29
0
        def iternext_specific(self, context, builder, result):
            zero = context.get_constant(types.intp, 0)
            one = context.get_constant(types.intp, 1)

            bbend = cgutils.append_basic_block(builder, 'end')

            exhausted = cgutils.as_bool_bit(builder,
                                            builder.load(self.exhausted))
            with cgutils.if_unlikely(builder, exhausted):
                result.set_valid(False)
                builder.branch(bbend)

            indices = [
                builder.load(cgutils.gep(builder, self.indices, dim))
                for dim in range(ndim)
            ]
            result.yield_(cgutils.pack_array(builder, indices))
            result.set_valid(True)

            shape = cgutils.unpack_tuple(builder, self.shape, ndim)
            _increment_indices(context, builder, ndim, shape, self.indices,
                               self.exhausted)

            builder.branch(bbend)
            builder.position_at_end(bbend)
Exemple #30
0
 def check_int_status(self, num, ok_value=0):
     """
     Raise an exception if *num* is smaller than *ok_value*.
     """
     ok = lc.Constant.int(num.type, ok_value)
     pred = self.builder.icmp(lc.ICMP_SLT, num, ok)
     with cgutils.if_unlikely(self.builder, pred):
         self.return_exception_raised()
Exemple #31
0
    def set_iter_valid(self, state, item):
        iterstate = PyIterState(self.context, self.builder, ref=state)
        iterstate.valid = cgutils.as_bool_byte(self.builder,
                                               cgutils.is_not_null(self.builder,
                                                                   item))

        with cgutils.if_unlikely(self.builder, self.is_null(item)):
            self.check_occurred()
Exemple #32
0
def iternext_zip(context, builder, sig, args, result):
    genty, = sig.args
    gen, = args
    # XXX We should link with the generator's library.
    # Currently, this doesn't make a difference as the library has already
    # been linked for the generator init function.
    impl = context.get_generator_impl(genty)
    status, retval = impl(context, builder, sig, args)
    with cgutils.if_likely(builder, status.is_ok):
        result.set_valid(True)
        result.yield_(retval)
    with cgutils.if_unlikely(builder, status.is_stop_iteration):
        result.set_exhausted()
    with cgutils.if_unlikely(builder,
                             builder.and_(status.is_error,
                                          builder.not_(status.is_stop_iteration))):
        context.call_conv.return_status_propagate(builder, status)
 def check_int_status(self, num, ok_value=0):
     """
     Raise an exception if *num* is smaller than *ok_value*.
     """
     ok = lc.Constant.int(num.type, ok_value)
     pred = self.builder.icmp(lc.ICMP_SLT, num, ok)
     with cgutils.if_unlikely(self.builder, pred):
         self.return_exception_raised()
Exemple #34
0
def getrandbits_impl(context, builder, sig, args):
    nbits, = args
    too_large = builder.icmp_unsigned(">=", nbits, const_int(65))
    too_small = builder.icmp_unsigned("==", nbits, const_int(0))
    with cgutils.if_unlikely(builder, builder.or_(too_large, too_small)):
        msg = "getrandbits() limited to 64 bits"
        context.call_conv.return_user_exc(builder, OverflowError, (msg,))
    state_ptr = get_state_ptr(context, builder, "py")
    return get_next_int(context, builder, state_ptr, nbits)
Exemple #35
0
def getrandbits_impl(context, builder, sig, args):
    nbits, = args
    too_large = builder.icmp_unsigned(">=", nbits, const_int(65))
    too_small = builder.icmp_unsigned("==", nbits, const_int(0))
    with cgutils.if_unlikely(builder, builder.or_(too_large, too_small)):
        msg = "getrandbits() limited to 64 bits"
        context.call_conv.return_user_exc(builder, OverflowError, (msg,))
    state_ptr = get_state_ptr(context, builder, "py")
    return get_next_int(context, builder, state_ptr, nbits)
Exemple #36
0
def iternext_numpy_flatiter(context, builder, sig, args, result):
    [flatiterty] = sig.args
    [flatiter] = args

    flatitercls = make_array_flat_cls(flatiterty)
    flatiter = flatitercls(context, builder, value=flatiter)

    arrty = flatiterty.array_type
    arrcls = context.make_array(arrty)
    arr = arrcls(context, builder, value=builder.load(flatiter.array))

    ndim = arrty.ndim
    shapes = cgutils.unpack_tuple(builder, arr.shape, ndim)
    indptr = flatiter.iters

    # Load indices and check if they are valid
    indices = []
    is_valid = cgutils.true_bit
    zero = context.get_constant(types.intp, 0)
    one = context.get_constant(types.intp, 1)
    for ax in range(ndim):
        axsize = shapes[ax]
        idxptr = builder.gep(indptr, [context.get_constant(types.intp, ax)])
        idx = builder.load(idxptr)
        ax_valid = builder.icmp(lc.ICMP_SLT, idx, axsize)

        indices.append(idx)
        is_valid = builder.and_(is_valid, ax_valid)

    result.set_valid(is_valid)

    with cgutils.if_likely(builder, is_valid):
        # Get yielded value
        valptr = cgutils.get_item_pointer(builder, arrty, arr, indices)
        yield_value = builder.load(valptr)
        result.yield_(yield_value)

        # Increment iterator indices
        carry_flags = [cgutils.true_bit]
        for ax, (idx, axsize) in reversed(list(enumerate(zip(indices,
                                                             shapes)))):
            idxptr = builder.gep(indptr,
                                 [context.get_constant(types.intp, ax)])
            lastcarry = carry_flags[-1]
            idxp1 = builder.add(idx, one)
            carry = builder.icmp(lc.ICMP_SGE, idxp1, axsize)
            idxfinal = builder.select(lastcarry,
                                      builder.select(carry, zero, idxp1), idx)
            builder.store(idxfinal, idxptr)
            carry_flags.append(builder.and_(carry, lastcarry))

        with cgutils.if_unlikely(builder, carry_flags[-1]):
            # If we have iterated all elements,
            # Set first index to out-of-bound
            idxptr = builder.gep(indptr, [context.get_constant(types.intp, 0)])
            builder.store(shapes[0], idxptr)
Exemple #37
0
def iternext_numpy_flatiter(context, builder, sig, args, result):
    [flatiterty] = sig.args
    [flatiter] = args

    flatitercls = make_array_flat_cls(flatiterty)
    flatiter = flatitercls(context, builder, value=flatiter)

    arrty = flatiterty.array_type
    arrcls = context.make_array(arrty)
    arr = arrcls(context, builder, value=builder.load(flatiter.array))

    ndim = arrty.ndim
    shapes = cgutils.unpack_tuple(builder, arr.shape, ndim)
    indptr = flatiter.iters

    # Load indices and check if they are valid
    indices = []
    is_valid = cgutils.true_bit
    zero = context.get_constant(types.intp, 0)
    one = context.get_constant(types.intp, 1)
    for ax in range(ndim):
        axsize = shapes[ax]
        idxptr = builder.gep(indptr, [context.get_constant(types.intp, ax)])
        idx = builder.load(idxptr)
        ax_valid = builder.icmp(lc.ICMP_SLT, idx, axsize)

        indices.append(idx)
        is_valid = builder.and_(is_valid, ax_valid)

    result.set_valid(is_valid)

    with cgutils.if_likely(builder, is_valid):
        # Get yielded value
        valptr = cgutils.get_item_pointer(builder, arrty, arr, indices)
        yield_value = builder.load(valptr)
        result.yield_(yield_value)

        # Increment iterator indices
        carry_flags = [cgutils.true_bit]
        for ax, (idx, axsize) in reversed(list(enumerate(zip(indices,
                                                             shapes)))):
            idxptr = builder.gep(indptr, [context.get_constant(types.intp, ax)])
            lastcarry = carry_flags[-1]
            idxp1 = builder.add(idx, one)
            carry = builder.icmp(lc.ICMP_SGE, idxp1, axsize)
            idxfinal = builder.select(lastcarry,
                                      builder.select(carry, zero, idxp1),
                                      idx)
            builder.store(idxfinal, idxptr)
            carry_flags.append(builder.and_(carry, lastcarry))

        with cgutils.if_unlikely(builder, carry_flags[-1]):
            # If we have iterated all elements,
            # Set first index to out-of-bound
            idxptr = builder.gep(indptr, [context.get_constant(types.intp, 0)])
            builder.store(shapes[0], idxptr)
Exemple #38
0
    def build_wrapper(self, api, builder, closure, args, kws):
        nargs = len(self.fndesc.argtypes)

        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 = builder.append_basic_block("arg.end")
        with builder.goto_block(endblk):
            builder.ret(api.get_null_object())

        # Extract the Environment object from the Closure
        envptr, env_manager = self.get_env(api, builder, closure)

        cleanup_manager = _ArgManager(self.context, builder, api,
                                      env_manager, endblk, nargs)

        # Compute the arguments to the compiled Numba function.
        innerargs = []
        for obj, ty in zip(objs, self.fndesc.argtypes):
            if isinstance(ty, types.Omitted):
                # It's an omitted value => ignore dummy Python object
                innerargs.append(None)
            else:
                val = cleanup_manager.add_arg(builder.load(obj), ty)
                innerargs.append(val)

        if self.release_gil:
            cleanup_manager = _GilManager(builder, api, cleanup_manager)

        status, retval = self.context.call_conv.call_function(
            builder, self.func, self.fndesc.restype, self.fndesc.argtypes,
            innerargs, env=envptr)
        # Do clean up
        self.debug_print(builder, "# callwrapper: emit_cleanup")
        cleanup_manager.emit_cleanup()
        self.debug_print(builder, "# callwrapper: emit_cleanup end")

        # Determine return status
        with builder.if_then(status.is_ok, likely=True):
            # Ok => return boxed Python value
            with builder.if_then(status.is_none):
                api.return_none()

            retty = self._simplified_return_type()
            obj = api.from_native_return(retty, retval, env_manager)
            builder.ret(obj)

        # Error out
        self.context.call_conv.raise_error(builder, api, status)
        builder.ret(api.get_null_object())
Exemple #39
0
 def pre_lower(self):
     # Store environment argument for later use
     self.envarg = self.context.get_env_argument(self.function)
     with cgutils.if_unlikely(self.builder, self.is_null(self.envarg)):
         self.pyapi.err_set_string(
             "PyExc_SystemError",
             "Numba internal error: object mode function called "
             "without an environment")
         self.return_exception_raised()
     self.env_body = self.context.get_env_body(self.builder, self.envarg)
 def pre_lower(self):
     # Store environment argument for later use
     self.envarg = self.context.get_env_argument(self.function)
     with cgutils.if_unlikely(self.builder, self.is_null(self.envarg)):
         self.pyapi.err_set_string(
             "PyExc_SystemError",
             "Numba internal error: object mode function called "
             "without an environment")
         self.return_exception_raised()
     self.env_body = self.context.get_env_body(self.builder, self.envarg)
 def loadvar(self, name):
     """
     Load the llvm value of the variable named *name*.
     """
     ptr = self.varmap[name]
     val = self.builder.load(ptr)
     with cgutils.if_unlikely(self.builder, self.is_null(val)):
         self.pyapi.raise_missing_name_error(name)
         self.return_error_occurred()
     return val
Exemple #42
0
 def loadvar(self, name):
     """
     Load the llvm value of the variable named *name*.
     """
     ptr = self.varmap[name]
     val = self.builder.load(ptr)
     with cgutils.if_unlikely(self.builder, self.is_null(val)):
         self.pyapi.raise_missing_name_error(name)
         self.return_error_occurred()
     return val
Exemple #43
0
    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 = builder.append_basic_block("arg.end")
        with builder.goto_block(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, env_manager = self.get_env(api, builder, closure)

        status, res = self.context.call_conv.call_function(
            builder, self.func, self.fndesc.restype, self.fndesc.argtypes,
            innerargs, envptr)
        # Do clean up
        self.debug_print(builder, "# callwrapper: emit_cleanup")
        cleanup_manager.emit_cleanup()
        self.debug_print(builder, "# callwrapper: emit_cleanup end")

        # Determine return status
        with cgutils.if_likely(builder, status.is_ok):
            # Ok => return boxed Python value
            with builder.if_then(status.is_none):
                api.return_none()

            retval = api.from_native_return(res,
                                            self._simplified_return_type(),
                                            env_manager)
            builder.ret(retval)

        with builder.if_then(builder.not_(status.is_python_exc)):
            # User exception raised
            self.make_exception_switch(api, builder, status)

        # Error out
        builder.ret(api.get_null_object())
Exemple #44
0
    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())
Exemple #45
0
def _define_nrt_incref(module, atomic_incr):
    """
    Implement NRT_incref in the module
    """
    fn_incref = module.get_or_insert_function(incref_decref_ty, name="NRT_incref")
    builder = ir.IRBuilder(fn_incref.append_basic_block())
    [ptr] = fn_incref.args
    is_null = builder.icmp_unsigned("==", ptr, cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()
    builder.call(atomic_incr, [builder.bitcast(ptr, atomic_incr.args[0].type)])
    builder.ret_void()
Exemple #46
0
    def call_internal(self, builder, fndesc, sig, args):
        """Given the function descriptor of an internally compiled function,
        emit a call to that function with the given arguments.
        """
        # Add call to the generated function
        llvm_mod = builder.module
        fn = self.declare_function(llvm_mod, fndesc)
        status, res = self.call_conv.call_function(builder, fn, sig.return_type, sig.args, args)

        with cgutils.if_unlikely(builder, status.is_error):
            self.call_conv.return_status_propagate(builder, status)
        return res
    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())
Exemple #48
0
    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 = builder.append_basic_block("arg.end")
        with builder.goto_block(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, env_manager = self.get_env(api, builder, closure)

        status, retval = self.context.call_conv.call_function(
            builder, self.func, self.fndesc.restype, self.fndesc.argtypes,
            innerargs, envptr)
        # Do clean up
        self.debug_print(builder, "# callwrapper: emit_cleanup")
        cleanup_manager.emit_cleanup()
        self.debug_print(builder, "# callwrapper: emit_cleanup end")

        # Determine return status
        with cgutils.if_likely(builder, status.is_ok):
            # Ok => return boxed Python value
            with builder.if_then(status.is_none):
                api.return_none()

            retty = self._simplified_return_type()
            obj = api.from_native_return(retval, retty, env_manager)
            builder.ret(obj)

        with builder.if_then(builder.not_(status.is_python_exc)):
            # User exception raised
            self.make_exception_switch(api, builder, status)

        # Error out
        builder.ret(api.get_null_object())
Exemple #49
0
def unbox_COO(typ: COOType, obj: COO, c) -> NativeValue:
    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()

        data = _unbox_native_field(typ.data_type, obj, "data", c)
        with cgutils.if_unlikely(c.builder, data.is_error):
            c.builder.branch(fail_blk)

        coords = _unbox_native_field(typ.coords_type, obj, "coords", c)
        with cgutils.if_unlikely(c.builder, coords.is_error):
            c.builder.branch(fail_blk)

        shape = _unbox_native_field(typ.shape_type, obj, "shape", c)
        with cgutils.if_unlikely(c.builder, shape.is_error):
            c.builder.branch(fail_blk)

        fill_value = _unbox_native_field(typ.fill_value_type, obj,
                                         "fill_value", c)
        with cgutils.if_unlikely(c.builder, fill_value.is_error):
            c.builder.branch(fail_blk)

        coo = cgutils.create_struct_proxy(typ)(c.context, c.builder)
        coo.coords = coords.value
        coo.data = data.value
        coo.shape = shape.value
        coo.fill_value = fill_value.value
        c.builder.store(cgutils.false_bit, is_error_ptr)
        c.builder.store(coo._getvalue(), ret_ptr)

    return NativeValue(c.builder.load(ret_ptr),
                       is_error=c.builder.load(is_error_ptr))
Exemple #50
0
    def get_env_from_closure(self, builder, clo):
        """
        From the pointer *clo* to a _dynfunc.Closure, get a pointer
        to the enclosed _dynfunc.Environment.
        """
        with cgutils.if_unlikely(builder, cgutils.is_null(builder, clo)):
            self.debug_print(builder, "Fatal error: missing _dynfunc.Closure")
            builder.unreachable()

        clo_body_ptr = cgutils.pointer_add(
            builder, clo, _dynfunc._impl_info['offsetof_closure_body'])
        clo_body = ClosureBody(self, builder, ref=clo_body_ptr, cast_ref=True)
        return clo_body.env
Exemple #51
0
    def get_env_from_closure(self, builder, clo):
        """
        From the pointer *clo* to a _dynfunc.Closure, get a pointer
        to the enclosed _dynfunc.Environment.
        """
        with cgutils.if_unlikely(builder, cgutils.is_null(builder, clo)):
            self.debug_print(builder, "Fatal error: missing _dynfunc.Closure")
            builder.unreachable()

        clo_body_ptr = cgutils.pointer_add(
            builder, clo, _dynfunc._impl_info['offsetof_closure_body'])
        clo_body = ClosureBody(self, builder, ref=clo_body_ptr, cast_ref=True)
        return clo_body.env
Exemple #52
0
def _define_nrt_decref(module, atomic_decr):
    """
    Implement NRT_decref in the module
    """
    fn_decref = module.get_or_insert_function(incref_decref_ty,
                                              name="NRT_decref")
    # Cannot inline this for refcount pruning to work
    fn_decref.attributes.add('noinline')
    calldtor = module.add_function(ir.FunctionType(ir.VoidType(),
                                                   [_pointer_type]),
                                   name="NRT_MemInfo_call_dtor")

    builder = ir.IRBuilder(fn_decref.append_basic_block())
    [ptr] = fn_decref.args
    is_null = builder.icmp_unsigned("==", ptr,
                                    cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()

    if _debug_print:
        cgutils.printf(builder, "*** NRT_Decref %zu [%p]\n", builder.load(ptr),
                       ptr)

    # For memory fence usage, see https://llvm.org/docs/Atomics.html

    # A release fence is used before the relevant write operation.
    # No-op on x86.  On POWER, it lowers to lwsync.
    builder.fence("release")
    newrefct = builder.call(atomic_decr,
                            [builder.bitcast(ptr, atomic_decr.args[0].type)])

    refct_eq_0 = builder.icmp_unsigned("==", newrefct,
                                       ir.Constant(newrefct.type, 0))
    with cgutils.if_unlikely(builder, refct_eq_0):
        # An acquire fence is used after the relevant read operation.
        # No-op on x86.  On POWER, it lowers to lwsync.
        builder.fence("acquire")
        builder.call(calldtor, [ptr])
    builder.ret_void()
Exemple #53
0
    def call_internal(self, builder, fndesc, sig, args):
        """Given the function descriptor of an internally compiled function,
        emit a call to that function with the given arguments.
        """
        # Add call to the generated function
        llvm_mod = builder.module
        fn = self.declare_function(llvm_mod, fndesc)
        status, res = self.call_conv.call_function(builder, fn, sig.return_type,
                                                   sig.args, args)

        with cgutils.if_unlikely(builder, status.is_error):
            self.call_conv.return_status_propagate(builder, status)
        return res
Exemple #54
0
def _define_nrt_incref(module, atomic_incr):
    """
    Implement NRT_incref in the module
    """
    fn_incref = module.get_or_insert_function(incref_decref_ty,
                                              name="NRT_incref")
    builder = ir.IRBuilder(fn_incref.append_basic_block())
    [ptr] = fn_incref.args
    is_null = builder.icmp_unsigned("==", ptr,
                                    cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()
    builder.call(atomic_incr, [builder.bitcast(ptr, atomic_incr.args[0].type)])
    builder.ret_void()
Exemple #55
0
 def emit_environment_sentry(self, envptr, return_pyobject=False):
     """Emits LLVM code to ensure the `envptr` is not NULL
     """
     is_null = cgutils.is_null(self.builder, envptr)
     with cgutils.if_unlikely(self.builder, is_null):
         if return_pyobject:
             fnty = self.builder.function.type.pointee
             assert fnty.return_type == self.pyobj
             self.err_set_string("PyExc_RuntimeError",
                                 "missing Environment")
             self.builder.ret(self.get_null_object())
         else:
             self.context.call_conv.return_user_exc(
                 self.builder, RuntimeError, ("missing Environment", ))
Exemple #56
0
    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())
Exemple #57
0
def _define_nrt_decref(module, atomic_decr):
    """
    Implement NRT_decref in the module
    """
    fn_decref = module.get_or_insert_function(incref_decref_ty,
                                              name="NRT_decref")
    # Cannot inline this for refcount pruning to work
    fn_decref.attributes.add('noinline')
    calldtor = module.add_function(ir.FunctionType(ir.VoidType(), [_pointer_type]),
                                   name="NRT_MemInfo_call_dtor")

    builder = ir.IRBuilder(fn_decref.append_basic_block())
    [ptr] = fn_decref.args
    is_null = builder.icmp_unsigned("==", ptr, cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()

    if _debug_print:
        cgutils.printf(builder, "*** NRT_Decref %zu [%p]\n", builder.load(ptr),
                       ptr)

    # For memory fence usage, see https://llvm.org/docs/Atomics.html

    # A release fence is used before the relevant write operation.
    # No-op on x86.  On POWER, it lowers to lwsync.
    builder.fence("release")
    newrefct = builder.call(atomic_decr,
                            [builder.bitcast(ptr, atomic_decr.args[0].type)])

    refct_eq_0 = builder.icmp_unsigned("==", newrefct,
                                       ir.Constant(newrefct.type, 0))
    with cgutils.if_unlikely(builder, refct_eq_0):
        # An acquire fence is used after the relevant read operation.
        # No-op on x86.  On POWER, it lowers to lwsync.
        builder.fence("acquire")
        builder.call(calldtor, [ptr])
    builder.ret_void()
Exemple #58
0
def _define_nrt_decref(module, atomic_decr):
    """
    Implement NRT_decref in the module
    """
    fn_decref = module.get_or_insert_function(incref_decref_ty,
                                              name="NRT_decref")
    calldtor = module.add_function(ir.FunctionType(ir.VoidType(),
                                                   [_pointer_type]),
                                   name="NRT_MemInfo_call_dtor")

    builder = ir.IRBuilder(fn_decref.append_basic_block())
    [ptr] = fn_decref.args
    is_null = builder.icmp_unsigned("==", ptr,
                                    cgutils.get_null_value(ptr.type))
    with cgutils.if_unlikely(builder, is_null):
        builder.ret_void()
    newrefct = builder.call(atomic_decr,
                            [builder.bitcast(ptr, atomic_decr.args[0].type)])

    refct_eq_0 = builder.icmp_unsigned("==", newrefct,
                                       ir.Constant(newrefct.type, 0))
    with cgutils.if_unlikely(builder, refct_eq_0):
        builder.call(calldtor, [ptr])
    builder.ret_void()
Exemple #59
0
 def emit_environment_sentry(self, envptr, return_pyobject=False):
     """Emits LLVM code to ensure the `envptr` is not NULL
     """
     is_null = cgutils.is_null(self.builder, envptr)
     with cgutils.if_unlikely(self.builder, is_null):
         if return_pyobject:
             fnty = self.builder.function.type.pointee
             assert fnty.return_type == self.pyobj
             self.err_set_string("PyExc_RuntimeError",
                                 "missing Environment")
             self.builder.ret(self.get_null_object())
         else:
             self.context.call_conv.return_user_exc(self.builder,
                                                    RuntimeError,
                                                    ("missing Environment",))
Exemple #60
0
 def to_native_array(self, typ, ary):
     # TODO check matching dtype.
     #      currently, mismatching dtype will still work and causes
     #      potential memory corruption
     voidptr = Type.pointer(Type.int(8))
     nativearycls = self.context.make_array(typ)
     nativeary = nativearycls(self.context, self.builder)
     aryptr = nativeary._getpointer()
     ptr = self.builder.bitcast(aryptr, voidptr)
     errcode = self.numba_array_adaptor(ary, ptr)
     failed = cgutils.is_not_null(self.builder, errcode)
     with cgutils.if_unlikely(self.builder, failed):
         # TODO
         self.builder.unreachable()
     return self.builder.load(aryptr)