Exemple #1
1
def printf(builder, format_string, *values):
    str_const = Constant.stringz(format_string)
    global_str_const = get_module(builder).add_global_variable(
        str_const.type, '')
    global_str_const.initializer = str_const

    idx = [Constant.int(Type.int(32), 0), Constant.int(Type.int(32), 0)]
    str_addr = global_str_const.gep(idx)

    args = []
    for v in values:
        if isinstance(v, int):
            args.append(Constant.int(Type.int(), v))
        elif isinstance(v, float):
            args.append(Constant.real(Type.double(), v))
        else:
            args.append(v)
    functype = Type.function(Type.int(32), [Type.pointer(Type.int(8))], True)
    fn = get_module(builder).get_or_insert_function(functype, 'printf')
    builder.call(fn, [str_addr] + args)
Exemple #2
0
    def __init__(self, context, builder, value=None, ref=None, cast_ref=False):
        self._type = context.get_struct_type(self)
        self._context = context
        self._builder = builder
        if ref is None:
            self._value = alloca_once(builder, self._type)
            if value is not None:
                assert not is_pointer(value.type)
                assert value.type == self._type, (value.type, self._type)
                builder.store(value, self._value)
        else:
            assert value is None
            assert is_pointer(ref.type)
            if self._type != ref.type.pointee:
                if cast_ref:
                    ref = builder.bitcast(ref, Type.pointer(self._type))
                else:
                    raise TypeError(
                        "mismatching pointer type: got %s, expected %s"
                        % (ref.type.pointee, self._type))
            self._value = ref

        self._namemap = {}
        self._fdmap = []
        self._typemap = []
        base = Constant.int(Type.int(), 0)
        for i, (k, tp) in enumerate(self._fields):
            self._namemap[k] = i
            self._fdmap.append((base, Constant.int(Type.int(), i)))
            self._typemap.append(tp)
Exemple #3
0
def for_range(builder, count, intp):
    start = Constant.int(intp, 0)
    stop = count

    bbcond = append_basic_block(builder, "for.cond")
    bbbody = append_basic_block(builder, "for.body")
    bbend = append_basic_block(builder, "for.end")

    bbstart = builder.basic_block
    builder.branch(bbcond)

    ONE = Constant.int(intp, 1)

    with goto_block(builder, bbcond):
        index = builder.phi(intp, name="loop.index")
        pred = builder.icmp(lc.ICMP_SLT, index, stop)
        builder.cbranch(pred, bbbody, bbend)

    with goto_block(builder, bbbody):
        yield index
        bbbody = builder.basic_block
        incr = builder.add(index, ONE)
        terminate(builder, bbcond)

    index.add_incoming(start, bbstart)
    index.add_incoming(incr, bbbody)

    builder.position_at_end(bbend)
Exemple #4
0
def divmod_by_constant(builder, val, divisor):
    """
    Compute the (quotient, remainder) of *val* divided by the constant
    positive *divisor*.  The semantics reflects those of Python integer
    floor division, rather than C's / LLVM's signed division and modulo.
    The difference lies with a negative *val*.
    """
    assert divisor > 0
    divisor = Constant.int(val.type, divisor)
    one = Constant.int(val.type, 1)

    quot = alloca_once(builder, val.type)

    with builder.if_else(is_neg_int(builder, val)) as (if_neg, if_pos):
        with if_pos:
            # quot = val / divisor
            quot_val = builder.sdiv(val, divisor)
            builder.store(quot_val, quot)
        with if_neg:
            # quot = -1 + (val + 1) / divisor
            val_plus_one = builder.add(val, one)
            quot_val = builder.sdiv(val_plus_one, divisor)
            builder.store(builder.sub(quot_val, one), quot)

    # rem = val - quot * divisor
    # (should be slightly faster than a separate modulo operation)
    quot_val = builder.load(quot)
    rem_val = builder.sub(val, builder.mul(quot_val, divisor))
    return quot_val, rem_val
Exemple #5
0
 def timedelta_floor_div_timedelta(context, builder, sig, args):
     [va, vb] = args
     [ta, tb] = sig.args
     ll_ret_type = context.get_value_type(sig.return_type)
     not_nan = are_not_nat(builder, [va, vb])
     ret = cgutils.alloca_once(builder, ll_ret_type, name='ret')
     zero = Constant.int(ll_ret_type, 0)
     one = Constant.int(ll_ret_type, 1)
     builder.store(zero, ret)
     with cgutils.if_likely(builder, not_nan):
         va, vb = normalize_timedeltas(context, builder, va, vb, ta, tb)
         # is the denominator zero or NaT?
         denom_ok = builder.not_(builder.icmp_signed('==', vb, zero))
         with cgutils.if_likely(builder, denom_ok):
             # is either arg negative?
             vaneg = builder.icmp_signed('<', va, zero)
             neg = builder.or_(vaneg, builder.icmp_signed('<', vb, zero))
             with builder.if_else(neg) as (then, otherwise):
                 with then:  # one or more value negative
                     with builder.if_else(vaneg) as (negthen, negotherwise):
                         with negthen:
                             top = builder.sub(va, one)
                             div = builder.sdiv(top, vb)
                             builder.store(div, ret)
                         with negotherwise:
                             top = builder.add(va, one)
                             div = builder.sdiv(top, vb)
                             builder.store(div, ret)
                 with otherwise:
                     div = builder.sdiv(va, vb)
                     builder.store(div, ret)
     res = builder.load(ret)
     return impl_ret_untracked(context, builder, sig.return_type, res)
Exemple #6
0
    def get_constant(self, ty, val):
        assert not self.is_struct_type(ty)

        lty = self.get_value_type(ty)

        if ty == types.none:
            assert val is None
            return self.get_dummy_value()

        elif ty == types.boolean:
            return Constant.int(Type.int(1), int(val))

        elif ty in types.signed_domain:
            return Constant.int_signextend(lty, val)

        elif ty in types.unsigned_domain:
            return Constant.int(lty, val)

        elif ty in types.real_domain:
            return Constant.real(lty, val)

        elif isinstance(ty, types.UniTuple):
            consts = [self.get_constant(ty.dtype, v) for v in val]
            return Constant.array(consts[0].type, consts)

        raise NotImplementedError("cannot lower constant of type '%s'" % (ty,))
Exemple #7
0
def divmod_by_constant(builder, val, divisor):
    """
    Compute the (quotient, remainder) of *val* divided by the constant
    positive *divisor*.  The semantics reflects those of Python integer
    floor division, rather than C's / LLVM's signed division and modulo.
    The difference lies with a negative *val*.
    """
    assert divisor > 0
    divisor = Constant.int(val.type, divisor)
    one = Constant.int(val.type, 1)

    quot = alloca_once(builder, val.type)

    with ifelse(builder, is_neg_int(builder, val)) as (if_neg, if_pos):
        with if_pos:
            # quot = val / divisor
            quot_val = builder.sdiv(val, divisor)
            builder.store(quot_val, quot)
        with if_neg:
            # quot = -1 + (val + 1) / divisor
            val_plus_one = builder.add(val, one)
            quot_val = builder.sdiv(val_plus_one, divisor)
            builder.store(builder.sub(quot_val, one), quot)

    # rem = val - quot * divisor
    # (should be slightly faster than a separate modulo operation)
    quot_val = builder.load(quot)
    rem_val = builder.sub(val, builder.mul(quot_val, divisor))
    return quot_val, rem_val
    def make_exception_switch(self, api, builder, code):
        """Handle user defined exceptions.
        Build a switch to check which exception class was raised.
        """
        nexc = len(self.exceptions)
        elseblk = cgutils.append_basic_block(builder, ".invalid.user.exception")
        swt = builder.switch(code, elseblk, n=nexc)
        for num, exc in self.exceptions.items():
            bb = cgutils.append_basic_block(builder,
                                            ".user.exception.%d" % num)
            swt.add_case(Constant.int(code.type, num), bb)
            builder.position_at_end(bb)
            api.raise_exception(exc, exc)
            builder.ret(api.get_null_object())

        builder.position_at_end(elseblk)

        # Handle native error
        elseblk = cgutils.append_basic_block(builder, ".invalid.native.error")
        swt = builder.switch(code, elseblk, n=len(errcode.error_names))

        msgfmt = "{error} in native function: {fname}"
        for errnum, errname in errcode.error_names.items():
            bb = cgutils.append_basic_block(builder,
                                            ".native.error.%d" % errnum)
            swt.add_case(Constant.int(code.type, errnum), bb)
            builder.position_at_end(bb)

            api.raise_native_error(msgfmt.format(error=errname,
                                                 fname=self.fndesc.mangled_name))
            builder.ret(api.get_null_object())

        builder.position_at_end(elseblk)
        msg = "unknown error in native function: %s" % self.fndesc.mangled_name
        api.raise_native_error(msg)
Exemple #9
0
def for_range(builder, count, intp):
    start = Constant.int(intp, 0)
    stop = count

    bbcond = builder.append_basic_block("for.cond")
    bbbody = builder.append_basic_block("for.body")
    bbend = builder.append_basic_block("for.end")

    bbstart = builder.basic_block
    builder.branch(bbcond)

    ONE = Constant.int(intp, 1)

    with builder.goto_block(bbcond):
        index = builder.phi(intp, name="loop.index")
        pred = builder.icmp(lc.ICMP_SLT, index, stop)
        builder.cbranch(pred, bbbody, bbend)

    with builder.goto_block(bbbody):
        yield index
        bbbody = builder.basic_block
        incr = builder.add(index, ONE)
        terminate(builder, bbcond)

    index.add_incoming(start, bbstart)
    index.add_incoming(incr, bbbody)

    builder.position_at_end(bbend)
Exemple #10
0
    def make_exception_switch(self, api, builder, code):
        """Handle user defined exceptions.
        Build a switch to check which exception class was raised.
        """
        nexc = len(self.exceptions)
        elseblk = cgutils.append_basic_block(builder, ".invalid.user.exception")
        swt = builder.switch(code, elseblk, n=nexc)
        for num, exc in self.exceptions.items():
            bb = cgutils.append_basic_block(builder,
                                            ".user.exception.%d" % num)
            swt.add_case(Constant.int(code.type, num), bb)
            builder.position_at_end(bb)
            api.raise_exception(exc, exc)
            builder.ret(api.get_null_object())

        builder.position_at_end(elseblk)

        # Handle native error
        elseblk = cgutils.append_basic_block(builder, ".invalid.native.error")
        swt = builder.switch(code, elseblk, n=len(errcode.error_names))

        msgfmt = "{error} in native function: {fname}"
        for errnum, errname in errcode.error_names.items():
            bb = cgutils.append_basic_block(builder,
                                            ".native.error.%d" % errnum)
            swt.add_case(Constant.int(code.type, errnum), bb)
            builder.position_at_end(bb)

            api.raise_native_error(msgfmt.format(error=errname,
                                                 fname=self.fndesc.mangled_name))
            builder.ret(api.get_null_object())

        builder.position_at_end(elseblk)
        msg = "unknown error in native function: %s" % self.fndesc.mangled_name
        api.raise_native_error(msg)
def int_power_func_body(context, builder, x, y):
    pcounter = cgutils.alloca_once(builder, y.type)
    presult = cgutils.alloca_once(builder, x.type)
    result = Constant.int(x.type, 1)
    counter = y
    builder.store(counter, pcounter)
    builder.store(result, presult)

    bbcond = cgutils.append_basic_block(builder, ".cond")
    bbbody = cgutils.append_basic_block(builder, ".body")
    bbexit = cgutils.append_basic_block(builder, ".exit")

    del counter
    del result

    builder.branch(bbcond)

    with cgutils.goto_block(builder, bbcond):
        counter = builder.load(pcounter)
        ONE = Constant.int(counter.type, 1)
        ZERO = Constant.null(counter.type)
        builder.store(builder.sub(counter, ONE), pcounter)
        pred = builder.icmp(lc.ICMP_SGT, counter, ZERO)
        builder.cbranch(pred, bbbody, bbexit)

    with cgutils.goto_block(builder, bbbody):
        result = builder.load(presult)
        builder.store(builder.mul(result, x), presult)
        builder.branch(bbcond)

    builder.position_at_end(bbexit)
    return builder.load(presult)
Exemple #12
0
def int_power_func_body(context, builder, x, y):
    pcounter = cgutils.alloca_once(builder, y.type)
    presult = cgutils.alloca_once(builder, x.type)
    result = Constant.int(x.type, 1)
    counter = y
    builder.store(counter, pcounter)
    builder.store(result, presult)

    bbcond = cgutils.append_basic_block(builder, ".cond")
    bbbody = cgutils.append_basic_block(builder, ".body")
    bbexit = cgutils.append_basic_block(builder, ".exit")

    del counter
    del result

    builder.branch(bbcond)

    with cgutils.goto_block(builder, bbcond):
        counter = builder.load(pcounter)
        ONE = Constant.int(counter.type, 1)
        ZERO = Constant.null(counter.type)
        builder.store(builder.sub(counter, ONE), pcounter)
        pred = builder.icmp(lc.ICMP_SGT, counter, ZERO)
        builder.cbranch(pred, bbbody, bbexit)

    with cgutils.goto_block(builder, bbbody):
        result = builder.load(presult)
        builder.store(builder.mul(result, x), presult)
        builder.branch(bbcond)

    builder.position_at_end(bbexit)
    return builder.load(presult)
Exemple #13
0
    def __init__(self, context, builder, value=None, ref=None, cast_ref=False):
        self._type = context.get_struct_type(self)
        self._context = context
        self._builder = builder
        if ref is None:
            self._value = alloca_once(builder, self._type)
            if value is not None:
                assert not is_pointer(value.type)
                assert value.type == self._type, (value.type, self._type)
                builder.store(value, self._value)
        else:
            assert value is None
            assert is_pointer(ref.type)
            if self._type != ref.type.pointee:
                if cast_ref:
                    ref = builder.bitcast(ref, Type.pointer(self._type))
                else:
                    raise TypeError(
                        "mismatching pointer type: got %s, expected %s"
                        % (ref.type.pointee, self._type))
            self._value = ref

        self._namemap = {}
        self._fdmap = []
        self._typemap = []
        base = Constant.int(Type.int(), 0)
        for i, (k, tp) in enumerate(self._fields):
            self._namemap[k] = i
            self._fdmap.append((base, Constant.int(Type.int(), i)))
            self._typemap.append(tp)
Exemple #14
0
 def timedelta_floor_div_timedelta(context, builder, sig, args):
     [va, vb] = args
     [ta, tb] = sig.args
     ll_ret_type = context.get_value_type(sig.return_type)
     not_nan = are_not_nat(builder, [va, vb])
     ret = cgutils.alloca_once(builder, ll_ret_type, name='ret')
     zero = Constant.int(ll_ret_type, 0)
     one = Constant.int(ll_ret_type, 1)
     builder.store(zero, ret)
     with cgutils.if_likely(builder, not_nan):
         va, vb = normalize_timedeltas(context, builder, va, vb, ta, tb)
         # is the denominator zero or NaT?
         denom_ok = builder.not_(builder.icmp_signed('==', vb, zero))
         with cgutils.if_likely(builder, denom_ok):
             # is either arg negative?
             vaneg = builder.icmp_signed('<', va, zero)
             neg = builder.or_(vaneg, builder.icmp_signed('<', vb, zero))
             with builder.if_else(neg) as (then, otherwise):
                 with then:  # one or more value negative
                     with builder.if_else(vaneg) as (negthen, negotherwise):
                         with negthen:
                             top = builder.sub(va, one)
                             div = builder.sdiv(top, vb)
                             builder.store(div, ret)
                         with negotherwise:
                             top = builder.add(va, one)
                             div = builder.sdiv(top, vb)
                             builder.store(div, ret)
                 with otherwise:
                     div = builder.sdiv(va, vb)
                     builder.store(div, ret)
     res = builder.load(ret)
     return impl_ret_untracked(context, builder, sig.return_type, res)
Exemple #15
0
    def get_constant(self, ty, val):
        assert not self.is_struct_type(ty)

        lty = self.get_value_type(ty)

        if ty == types.none:
            assert val is None
            return self.get_dummy_value()

        elif ty == types.boolean:
            return Constant.int(Type.int(1), int(val))

        elif ty in types.signed_domain:
            return Constant.int_signextend(lty, val)

        elif ty in types.unsigned_domain:
            return Constant.int(lty, val)

        elif ty in types.real_domain:
            return Constant.real(lty, val)

        elif isinstance(ty, (types.NPDatetime, types.NPTimedelta)):
            return Constant.real(lty, val.astype(numpy.int64))

        elif isinstance(ty, (types.UniTuple, types.NamedUniTuple)):
            consts = [self.get_constant(ty.dtype, v) for v in val]
            return Constant.array(consts[0].type, consts)

        raise NotImplementedError("cannot lower constant of type '%s'" % (ty,))
Exemple #16
0
    def get_constant(self, ty, val):
        assert not self.is_struct_type(ty)

        lty = self.get_value_type(ty)

        if ty == types.none:
            assert val is None
            return self.get_dummy_value()

        elif ty == types.boolean:
            return Constant.int(Type.int(1), int(val))

        elif ty in types.signed_domain:
            return Constant.int_signextend(lty, val)

        elif ty in types.unsigned_domain:
            return Constant.int(lty, val)

        elif ty in types.real_domain:
            return Constant.real(lty, val)

        elif isinstance(ty, types.UniTuple):
            consts = [self.get_constant(ty.dtype, v) for v in val]
            return Constant.array(consts[0].type, consts)

        raise NotImplementedError(ty)
Exemple #17
0
    def _long_from_native_int(self, ival, func_name, native_int_type,
                              signed):
        fnty = Type.function(self.pyobj, [native_int_type])
        fn = self._get_function(fnty, name=func_name)
        resptr = cgutils.alloca_once(self.builder, self.pyobj)

        if PYVERSION < (3, 0):
            # Under Python 2, we try to return a PyInt object whenever
            # the given number fits in a C long.
            pyint_fnty = Type.function(self.pyobj, [self.long])
            pyint_fn = self._get_function(pyint_fnty, name="PyInt_FromLong")
            long_max = Constant.int(native_int_type, _helperlib.long_max)
            if signed:
                long_min = Constant.int(native_int_type, _helperlib.long_min)
                use_pyint = self.builder.and_(
                    self.builder.icmp(lc.ICMP_SGE, ival, long_min),
                    self.builder.icmp(lc.ICMP_SLE, ival, long_max),
                    )
            else:
                use_pyint = self.builder.icmp(lc.ICMP_ULE, ival, long_max)

            with self.builder.if_else(use_pyint) as (then, otherwise):
                with then:
                    downcast_ival = self.builder.trunc(ival, self.long)
                    res = self.builder.call(pyint_fn, [downcast_ival])
                    self.builder.store(res, resptr)
                with otherwise:
                    res = self.builder.call(fn, [ival])
                    self.builder.store(res, resptr)
        else:
            fn = self._get_function(fnty, name=func_name)
            self.builder.store(self.builder.call(fn, [ival]), resptr)

        return self.builder.load(resptr)
Exemple #18
0
    def _long_from_native_int(self, ival, func_name, native_int_type,
                              signed):
        fnty = Type.function(self.pyobj, [native_int_type])
        fn = self._get_function(fnty, name=func_name)
        resptr = cgutils.alloca_once(self.builder, self.pyobj)

        if PYVERSION < (3, 0):
            # Under Python 2, we try to return a PyInt object whenever
            # the given number fits in a C long.
            pyint_fnty = Type.function(self.pyobj, [self.long])
            pyint_fn = self._get_function(pyint_fnty, name="PyInt_FromLong")
            long_max = Constant.int(native_int_type, _helperlib.long_max)
            if signed:
                long_min = Constant.int(native_int_type, _helperlib.long_min)
                use_pyint = self.builder.and_(
                    self.builder.icmp(lc.ICMP_SGE, ival, long_min),
                    self.builder.icmp(lc.ICMP_SLE, ival, long_max),
                    )
            else:
                use_pyint = self.builder.icmp(lc.ICMP_ULE, ival, long_max)

            with self.builder.if_else(use_pyint) as (then, otherwise):
                with then:
                    downcast_ival = self.builder.trunc(ival, self.long)
                    res = self.builder.call(pyint_fn, [downcast_ival])
                    self.builder.store(res, resptr)
                with otherwise:
                    res = self.builder.call(fn, [ival])
                    self.builder.store(res, resptr)
        else:
            fn = self._get_function(fnty, name=func_name)
            self.builder.store(self.builder.call(fn, [ival]), resptr)

        return self.builder.load(resptr)
Exemple #19
0
 def unpack_tuple(self, args, name, n_min, n_max, *objs):
     charptr = Type.pointer(Type.int(8))
     argtypes = [self.pyobj, charptr, self.py_ssize_t, self.py_ssize_t]
     fnty = Type.function(Type.int(), argtypes, var_arg=True)
     fn = self._get_function(fnty, name="PyArg_UnpackTuple")
     n_min = Constant.int(self.py_ssize_t, n_min)
     n_max = Constant.int(self.py_ssize_t, n_max)
     if isinstance(name, str):
         name = self.context.insert_const_string(self.builder.module, name)
     return self.builder.call(fn, [args, name, n_min, n_max] + list(objs))
Exemple #20
0
 def unpack_tuple(self, args, name, n_min, n_max, *objs):
     charptr = Type.pointer(Type.int(8))
     argtypes = [self.pyobj, charptr, self.py_ssize_t, self.py_ssize_t]
     fnty = Type.function(Type.int(), argtypes, var_arg=True)
     fn = self._get_function(fnty, name="PyArg_UnpackTuple")
     n_min = Constant.int(self.py_ssize_t, n_min)
     n_max = Constant.int(self.py_ssize_t, n_max)
     if isinstance(name, str):
         name = self.context.insert_const_string(self.builder.module, name)
     return self.builder.call(fn, [args, name, n_min, n_max] + list(objs))
Exemple #21
0
def get_item_pointer2(builder,
                      data,
                      shape,
                      strides,
                      layout,
                      inds,
                      wraparound=False):
    if wraparound:
        # Wraparound
        indices = []
        for ind, dimlen in zip(inds, shape):
            ZERO = Constant.null(ind.type)
            negative = builder.icmp(lc.ICMP_SLT, ind, ZERO)
            wrapped = builder.add(dimlen, ind)
            selected = builder.select(negative, wrapped, ind)
            indices.append(selected)
    else:
        indices = inds
    if not indices:
        # Indexing with empty tuple
        return builder.gep(data, [get_null_value(Type.int(32))])
    intp = indices[0].type
    # Indexing code
    if layout in 'CF':
        steps = []
        # Compute steps for each dimension
        if layout == 'C':
            # C contiguous
            for i in range(len(shape)):
                last = Constant.int(intp, 1)
                for j in shape[i + 1:]:
                    last = builder.mul(last, j)
                steps.append(last)
        elif layout == 'F':
            # F contiguous
            for i in range(len(shape)):
                last = Constant.int(intp, 1)
                for j in shape[:i]:
                    last = builder.mul(last, j)
                steps.append(last)
        else:
            raise Exception("unreachable")

        # Compute index
        loc = Constant.int(intp, 0)
        for i, s in zip(indices, steps):
            tmp = builder.mul(i, s)
            loc = builder.add(loc, tmp)
        ptr = builder.gep(data, [loc])
        return ptr
    else:
        # Any layout
        dimoffs = [builder.mul(s, i) for s, i in zip(strides, indices)]
        offset = functools.reduce(builder.add, dimoffs)
        return pointer_add(builder, data, offset)
Exemple #22
0
def is_leap_year(builder, year_val):
    """
    Return a predicate indicating whether *year_val* (offset by 1970) is a
    leap year.
    """
    actual_year = builder.add(year_val, Constant.int(DATETIME64, 1970))
    multiple_of_4 = cgutils.is_null(
        builder, builder.and_(actual_year, Constant.int(DATETIME64, 3)))
    not_multiple_of_100 = cgutils.is_not_null(
        builder, builder.srem(actual_year, Constant.int(DATETIME64, 100)))
    multiple_of_400 = cgutils.is_null(
        builder, builder.srem(actual_year, Constant.int(DATETIME64, 400)))
    return builder.and_(multiple_of_4,
                        builder.or_(not_multiple_of_100, multiple_of_400))
Exemple #23
0
def get_item_pointer2(builder, data, shape, strides, layout, inds,
                      wraparound=False):
    if wraparound:
        # Wraparound
        indices = []
        for ind, dimlen in zip(inds, shape):
            ZERO = Constant.null(ind.type)
            negative = builder.icmp(lc.ICMP_SLT, ind, ZERO)
            wrapped = builder.add(dimlen, ind)
            selected = builder.select(negative, wrapped, ind)
            indices.append(selected)
    else:
        indices = inds
    if not indices:
        # Indexing with empty tuple
        return builder.gep(data, [get_null_value(Type.int(32))])
    intp = indices[0].type
    # Indexing code
    if layout in 'CF':
        steps = []
        # Compute steps for each dimension
        if layout == 'C':
            # C contiguous
            for i in range(len(shape)):
                last = Constant.int(intp, 1)
                for j in shape[i + 1:]:
                    last = builder.mul(last, j)
                steps.append(last)
        elif layout == 'F':
            # F contiguous
            for i in range(len(shape)):
                last = Constant.int(intp, 1)
                for j in shape[:i]:
                    last = builder.mul(last, j)
                steps.append(last)
        else:
            raise Exception("unreachable")

        # Compute index
        loc = Constant.int(intp, 0)
        for i, s in zip(indices, steps):
            tmp = builder.mul(i, s)
            loc = builder.add(loc, tmp)
        ptr = builder.gep(data, [loc])
        return ptr
    else:
        # Any layout
        dimoffs = [builder.mul(s, i) for s, i in zip(strides, indices)]
        offset = functools.reduce(builder.add, dimoffs)
        return pointer_add(builder, data, offset)
Exemple #24
0
def is_leap_year(builder, year_val):
    """
    Return a predicate indicating whether *year_val* (offset by 1970) is a
    leap year.
    """
    actual_year = builder.add(year_val, Constant.int(DATETIME64, 1970))
    multiple_of_4 = cgutils.is_null(
        builder, builder.and_(actual_year, Constant.int(DATETIME64, 3)))
    not_multiple_of_100 = cgutils.is_not_null(
        builder, builder.srem(actual_year, Constant.int(DATETIME64, 100)))
    multiple_of_400 = cgutils.is_null(
        builder, builder.srem(actual_year, Constant.int(DATETIME64, 400)))
    return builder.and_(multiple_of_4,
                        builder.or_(not_multiple_of_100, multiple_of_400))
Exemple #25
0
def memset(builder, ptr, size, value):
    """
    Fill *size* bytes starting from *ptr* with *value*.
    """
    sizety = size.type
    memset = "llvm.memset.p0i8.i%d" % (sizety.width)
    i32 = lc.Type.int(32)
    i8 = lc.Type.int(8)
    i8_star = i8.as_pointer()
    i1 = lc.Type.int(1)
    fn = builder.module.declare_intrinsic('llvm.memset', (i8_star, size.type))
    ptr = builder.bitcast(ptr, i8_star)
    if isinstance(value, int):
        value = Constant.int(i8, value)
    builder.call(fn, [ptr, value, size,
                      Constant.int(i32, 0), Constant.int(i1, 0)])
Exemple #26
0
    def lower_finalize_func_body(self, builder, genptr):
        """
        Lower the body of the generator's finalizer: decref all live
        state variables.
        """
        pyapi = self.context.get_python_api(builder)
        resume_index_ptr = self.get_resume_index_ptr(builder, genptr)
        resume_index = builder.load(resume_index_ptr)
        # If resume_index is 0, next() was never called
        # If resume_index is -1, generator terminated cleanly
        # (note function arguments are saved in state variables,
        #  so they don't need a separate cleanup step)
        need_cleanup = builder.icmp_signed('>', resume_index,
                                           Constant.int(resume_index.type, 0))

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

        builder.ret_void()
Exemple #27
0
 def return_from_generator(self, lower):
     """
     Emit a StopIteration at generator end and mark the generator exhausted.
     """
     indexval = Constant.int(self.resume_index_ptr.type.pointee, -1)
     lower.builder.store(indexval, self.resume_index_ptr)
     self.call_conv.return_stop_iteration(lower.builder)
Exemple #28
0
    def lower_finalize_func_body(self, builder, genptr):
        """
        Lower the body of the generator's finalizer: decref all live
        state variables.
        """
        pyapi = self.context.get_python_api(builder)
        resume_index_ptr = self.get_resume_index_ptr(builder, genptr)
        resume_index = builder.load(resume_index_ptr)
        # If resume_index is 0, next() was never called
        # If resume_index is -1, generator terminated cleanly
        # (note function arguments are saved in state variables,
        #  so they don't need a separate cleanup step)
        need_cleanup = builder.icmp_signed(
            '>', resume_index, Constant.int(resume_index.type, 0))

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

        builder.ret_void()
Exemple #29
0
 def return_from_generator(self, lower):
     """
     Emit a StopIteration at generator end and mark the generator exhausted.
     """
     indexval = Constant.int(self.resume_index_ptr.type.pointee, -1)
     lower.builder.store(indexval, self.resume_index_ptr)
     self.call_conv.return_stop_iteration(lower.builder)
Exemple #30
0
def timedelta_sign_impl(context, builder, sig, args):
    val, = args
    ret = alloc_timedelta_result(builder)
    zero = Constant.int(TIMEDELTA64, 0)
    with cgutils.ifelse(builder, builder.icmp(lc.ICMP_SGT, val, zero)
                        ) as (gt_zero, le_zero):
        with gt_zero:
            builder.store(Constant.int(TIMEDELTA64, 1), ret)
        with le_zero:
            with cgutils.ifelse(builder, builder.icmp(lc.ICMP_EQ, val, zero)
                                ) as (eq_zero, lt_zero):
                with eq_zero:
                    builder.store(Constant.int(TIMEDELTA64, 0), ret)
                with lt_zero:
                    builder.store(Constant.int(TIMEDELTA64, -1), ret)
    return builder.load(ret)
Exemple #31
0
def timedelta_sign_impl(context, builder, sig, args):
    val, = args
    ret = alloc_timedelta_result(builder)
    zero = Constant.int(TIMEDELTA64, 0)
    with builder.if_else(builder.icmp(lc.ICMP_SGT, val,
                                      zero)) as (gt_zero, le_zero):
        with gt_zero:
            builder.store(Constant.int(TIMEDELTA64, 1), ret)
        with le_zero:
            with builder.if_else(builder.icmp(lc.ICMP_EQ, val,
                                              zero)) as (eq_zero, lt_zero):
                with eq_zero:
                    builder.store(Constant.int(TIMEDELTA64, 0), ret)
                with lt_zero:
                    builder.store(Constant.int(TIMEDELTA64, -1), ret)
    return builder.load(ret)
Exemple #32
0
    def timedelta_mod_timedelta(context, builder, sig, args):
        # inspired by https://github.com/numpy/numpy/blob/fe8072a12d65e43bd2e0b0f9ad67ab0108cc54b3/numpy/core/src/umath/loops.c.src#L1424
        # alg is basically as `a % b`:
        # if a or b is NaT return NaT
        # elseif b is 0 return NaT
        # else pretend a and b are int and do pythonic int modulus

        [va, vb] = args
        [ta, tb] = sig.args
        not_nan = are_not_nat(builder, [va, vb])
        ll_ret_type = context.get_value_type(sig.return_type)
        ret = alloc_timedelta_result(builder)
        builder.store(NAT, ret)
        zero = Constant.int(ll_ret_type, 0)
        with cgutils.if_likely(builder, not_nan):
            va, vb = normalize_timedeltas(context, builder, va, vb, ta, tb)
            # is the denominator zero or NaT?
            denom_ok = builder.not_(builder.icmp_signed('==', vb, zero))
            with cgutils.if_likely(builder, denom_ok):
                # is either arg negative?
                vapos = builder.icmp_signed('>', va, zero)
                vbpos = builder.icmp_signed('>', vb, zero)
                rem = builder.srem(va, vb)
                cond = builder.or_(builder.and_(vapos, vbpos),
                                   builder.icmp_signed('==', rem, zero))
                with builder.if_else(cond) as (then, otherwise):
                    with then:
                        builder.store(rem, ret)
                    with otherwise:
                        builder.store(builder.add(rem, vb), ret)

        res = builder.load(ret)
        return impl_ret_untracked(context, builder, sig.return_type, res)
Exemple #33
0
    def timedelta_mod_timedelta(context, builder, sig, args):
        # inspired by https://github.com/numpy/numpy/blob/fe8072a12d65e43bd2e0b0f9ad67ab0108cc54b3/numpy/core/src/umath/loops.c.src#L1424
        # alg is basically as `a % b`:
        # if a or b is NaT return NaT
        # elseif b is 0 return NaT
        # else pretend a and b are int and do pythonic int modulus

        [va, vb] = args
        [ta, tb] = sig.args
        not_nan = are_not_nat(builder, [va, vb])
        ll_ret_type = context.get_value_type(sig.return_type)
        ret = alloc_timedelta_result(builder)
        builder.store(NAT, ret)
        zero = Constant.int(ll_ret_type, 0)
        with cgutils.if_likely(builder, not_nan):
            va, vb = normalize_timedeltas(context, builder, va, vb, ta, tb)
            # is the denominator zero or NaT?
            denom_ok = builder.not_(builder.icmp_signed('==', vb, zero))
            with cgutils.if_likely(builder, denom_ok):
                # is either arg negative?
                vapos = builder.icmp_signed('>', va, zero)
                vbpos = builder.icmp_signed('>', vb, zero)
                rem = builder.srem(va, vb)
                cond = builder.or_(builder.and_(vapos, vbpos),
                                   builder.icmp_signed('==', rem, zero))
                with builder.if_else(cond) as (then, otherwise):
                    with then:
                        builder.store(rem, ret)
                    with otherwise:
                        builder.store(builder.add(rem, vb), ret)

        res = builder.load(ret)
        return impl_ret_untracked(context, builder, sig.return_type, res)
Exemple #34
0
    def gen_prologue(self, builder, pyapi):
        #  Get an environment object for the function
        ll_intp = self.context.get_value_type(types.intp)
        ll_pyobj = self.context.get_value_type(types.pyobject)
        self.envptr = Constant.int(ll_intp, id(self.env)).inttoptr(ll_pyobj)

        # Acquire the GIL
        self.gil = pyapi.gil_ensure()
Exemple #35
0
    def gen_prologue(self, builder, pyapi):
        #  Get an environment object for the function
        ll_intp = self.context.get_value_type(types.intp)
        ll_pyobj = self.context.get_value_type(types.pyobject)
        self.envptr = Constant.int(ll_intp, id(self.env)).inttoptr(ll_pyobj)

        # Acquire the GIL
        self.gil = pyapi.gil_ensure()
Exemple #36
0
def inbound_gep(builder, ptr, *inds):
    idx = []
    for i in inds:
        if isinstance(i, int):
            ind = Constant.int(Type.int(32), i)
        else:
            ind = i
        idx.append(ind)
    return builder.gep(ptr, idx, inbounds=True)
Exemple #37
0
def gep(builder, ptr, *inds):
    idx = []
    for i in inds:
        if isinstance(i, int):
            ind = Constant.int(Type.int(64), i)
        else:
            ind = i
        idx.append(ind)
    return builder.gep(ptr, idx)
Exemple #38
0
def gep(builder, ptr, *inds):
    idx = []
    for i in inds:
        if isinstance(i, int):
            ind = Constant.int(Type.int(64), i)
        else:
            ind = i
        idx.append(ind)
    return builder.gep(ptr, idx)
Exemple #39
0
def increment_index(builder, val):
    """
    Increment an index *val*.
    """
    one = Constant.int(val.type, 1)
    # We pass the "nsw" flag in the hope that LLVM understands the index
    # never changes sign.  Unfortunately this doesn't always work
    # (e.g. ndindex()).
    return builder.add(val, one, flags=['nsw'])
Exemple #40
0
def increment_index(builder, val):
    """
    Increment an index *val*.
    """
    one = Constant.int(val.type, 1)
    # We pass the "nsw" flag in the hope that LLVM understands the index
    # never changes sign.  Unfortunately this doesn't always work
    # (e.g. ndindex()).
    return builder.add(val, one, flags=['nsw'])
Exemple #41
0
def inbound_gep(builder, ptr, *inds):
    idx = []
    for i in inds:
        if isinstance(i, int):
            ind = Constant.int(Type.int(32), i)
        else:
            ind = i
        idx.append(ind)
    return builder.gep(ptr, idx, inbounds=True)
Exemple #42
0
 def dict_new(self, presize=0):
     if presize == 0:
         fnty = Type.function(self.pyobj, ())
         fn = self._get_function(fnty, name="PyDict_New")
         return self.builder.call(fn, ())
     else:
         fnty = Type.function(self.pyobj, [self.py_ssize_t])
         fn = self._get_function(fnty, name="_PyDict_NewPresized")
         return self.builder.call(fn,
                                  [Constant.int(self.py_ssize_t, presize)])
Exemple #43
0
 def dict_new(self, presize=0):
     if presize == 0:
         fnty = Type.function(self.pyobj, ())
         fn = self._get_function(fnty, name="PyDict_New")
         return self.builder.call(fn, ())
     else:
         fnty = Type.function(self.pyobj, [self.py_ssize_t])
         fn = self._get_function(fnty, name="_PyDict_NewPresized")
         return self.builder.call(fn,
                                  [Constant.int(self.py_ssize_t, presize)])
Exemple #44
0
def set_cuda_kernel(lfunc):
    from llvmlite.llvmpy.core import MetaData, MetaDataString, Constant, Type

    m = lfunc.module

    ops = lfunc, MetaDataString.get(m, "kernel"), Constant.int(Type.int(), 1)
    md = MetaData.get(m, ops)

    nmd = m.get_or_insert_named_metadata('nvvm.annotations')
    nmd.add(md)
Exemple #45
0
def for_range(builder, count, start=None, intp=None):
    """
    Generate LLVM IR for a for-loop in [start, count).
    *start* is equal to 0 by default.

    Yields a Loop namedtuple with the following members:
    - `index` is the loop index's value
    - `do_break` is a no-argument callable to break out of the loop
    """
    if intp is None:
        intp = count.type
    if start is None:
        start = Constant.int(intp, 0)
    stop = count

    bbcond = builder.append_basic_block("for.cond")
    bbbody = builder.append_basic_block("for.body")
    bbend = builder.append_basic_block("for.end")

    def do_break():
        builder.branch(bbend)

    bbstart = builder.basic_block
    builder.branch(bbcond)

    ONE = Constant.int(intp, 1)

    with builder.goto_block(bbcond):
        index = builder.phi(intp, name="loop.index")
        pred = builder.icmp(lc.ICMP_SLT, index, stop)
        builder.cbranch(pred, bbbody, bbend)

    with builder.goto_block(bbbody):
        yield Loop(index, do_break)
        # Update bbbody as a new basic block may have been activated
        bbbody = builder.basic_block
        incr = builder.add(index, ONE)
        terminate(builder, bbcond)

    index.add_incoming(start, bbstart)
    index.add_incoming(incr, bbbody)

    builder.position_at_end(bbend)
Exemple #46
0
def gep(builder, ptr, *inds):
    idx = []
    for i in inds:
        if isinstance(i, int):
            # NOTE: llvm only accepts int32 inside structs, not int64
            ind = Constant.int(Type.int(32), i)
        else:
            ind = i
        idx.append(ind)
    return builder.gep(ptr, idx)
 def lower_yield_suspend(self):
     # Save live vars in state
     for state_index, name in zip(self.live_var_indices, self.live_vars):
         state_slot = cgutils.gep(self.builder, self.gen_state_ptr, 0, state_index)
         ty = self.gentype.state_types[state_index]
         val = self.lower.loadvar(name)
         self.context.pack_value(self.builder, ty, val, state_slot)
     # Save resume index
     indexval = Constant.int(self.resume_index_ptr.type.pointee, self.inst.index)
     self.builder.store(indexval, self.resume_index_ptr)
Exemple #48
0
def memset(builder, ptr, size, value):
    """
    Fill *size* bytes starting from *ptr* with *value*.
    """
    sizety = size.type
    memset = "llvm.memset.p0i8.i%d" % (sizety.width)
    module = get_module(builder)
    i32 = lc.Type.int(32)
    i8 = lc.Type.int(8)
    i1 = lc.Type.int(1)
    # void @llvm.memset.p0i8.iXY(i8* <dest>, i8 <val>,
    #                            iXY <len>, i32 <align>, i1 <isvolatile>)
    ptr = builder.bitcast(ptr, lc.Type.pointer(i8))
    fnty = lc.Type.function(lc.Type.void(),
                            [ptr.type, i8, sizety, i32, i1])
    fn = module.get_or_insert_function(fnty, name=memset)
    if isinstance(value, int):
        value = Constant.int(i8, value)
    builder.call(fn, [ptr, value, size,
                      Constant.int(i32, 0), Constant.int(i1, 0)])
Exemple #49
0
def printf(builder, format_string, *values):
    str_const = Constant.stringz(format_string)
    global_str_const = get_module(builder).add_global_variable(str_const.type,
                                                               '')
    global_str_const.initializer = str_const

    idx = [Constant.int(Type.int(32), 0), Constant.int(Type.int(32), 0)]
    str_addr = global_str_const.gep(idx)

    args = []
    for v in values:
        if isinstance(v, int):
            args.append(Constant.int(Type.int(), v))
        elif isinstance(v, float):
            args.append(Constant.real(Type.double(), v))
        else:
            args.append(v)
    functype = Type.function(Type.int(32), [Type.pointer(Type.int(8))], True)
    fn = get_module(builder).get_or_insert_function(functype, 'printf')
    builder.call(fn, [str_addr] + args)
Exemple #50
0
def gep(builder, ptr, *inds, **kws):
    name = kws.pop('name', '')
    idx = []
    for i in inds:
        if isinstance(i, int):
            # NOTE: llvm only accepts int32 inside structs, not int64
            ind = Constant.int(Type.int(32), i)
        else:
            ind = i
        idx.append(ind)
    return builder.gep(ptr, idx, name=name)
Exemple #51
0
def timedelta_sign_impl(context, builder, sig, args):
    """
    np.sign(timedelta64)
    """
    val, = args
    ret = alloc_timedelta_result(builder)
    zero = Constant.int(TIMEDELTA64, 0)
    with builder.if_else(builder.icmp(lc.ICMP_SGT, val, zero)
                         ) as (gt_zero, le_zero):
        with gt_zero:
            builder.store(Constant.int(TIMEDELTA64, 1), ret)
        with le_zero:
            with builder.if_else(builder.icmp(lc.ICMP_EQ, val, zero)
                                 ) as (eq_zero, lt_zero):
                with eq_zero:
                    builder.store(Constant.int(TIMEDELTA64, 0), ret)
                with lt_zero:
                    builder.store(Constant.int(TIMEDELTA64, -1), ret)
    res = builder.load(ret)
    return impl_ret_untracked(context, builder, sig.return_type, res)
def timedelta_sign_impl(context, builder, sig, args):
    """
    np.sign(timedelta64)
    """
    (val,) = args
    ret = alloc_timedelta_result(builder)
    zero = Constant.int(TIMEDELTA64, 0)
    with builder.if_else(builder.icmp(lc.ICMP_SGT, val, zero)) as (gt_zero, le_zero):
        with gt_zero:
            builder.store(Constant.int(TIMEDELTA64, 1), ret)
        with le_zero:
            with builder.if_else(builder.icmp(lc.ICMP_EQ, val, zero)) as (
                eq_zero,
                lt_zero,
            ):
                with eq_zero:
                    builder.store(Constant.int(TIMEDELTA64, 0), ret)
                with lt_zero:
                    builder.store(Constant.int(TIMEDELTA64, -1), ret)
    res = builder.load(ret)
    return impl_ret_untracked(context, builder, sig.return_type, res)
Exemple #53
0
    def gen_prologue(self, builder):
        # Create an environment object for the function
        moduledict = self.fndesc.lookup_module().__dict__
        self.env = _dynfunc.Environment(globals=moduledict)

        ll_intp = self.context.get_value_type(types.intp)
        ll_pyobj = self.context.get_value_type(types.pyobject)
        self.envptr = Constant.int(ll_intp, id(self.env)).inttoptr(ll_pyobj)

        # Acquire the GIL
        self.pyapi = self.context.get_python_api(builder)
        self.gil = self.pyapi.gil_ensure()
Exemple #54
0
 def lower_yield_suspend(self):
     # Save live vars in state
     for state_index, name in zip(self.live_var_indices, self.live_vars):
         state_slot = cgutils.gep(self.builder, self.gen_state_ptr,
                                  0, state_index)
         ty = self.gentype.state_types[state_index]
         val = self.lower.loadvar(name)
         self.context.pack_value(self.builder, ty, val, state_slot)
     # Save resume index
     indexval = Constant.int(self.resume_index_ptr.type.pointee,
                             self.inst.index)
     self.builder.store(indexval, self.resume_index_ptr)
Exemple #55
0
def int_sign_impl(context, builder, sig, args):
    """
    np.sign(int)
    """
    [x] = args
    POS = Constant.int(x.type, 1)
    NEG = Constant.int(x.type, -1)
    ZERO = Constant.int(x.type, 0)

    cmp_zero = builder.icmp(lc.ICMP_EQ, x, ZERO)
    cmp_pos = builder.icmp(lc.ICMP_SGT, x, ZERO)

    presult = cgutils.alloca_once(builder, x.type)

    bb_zero = builder.append_basic_block(".zero")
    bb_postest = builder.append_basic_block(".postest")
    bb_pos = builder.append_basic_block(".pos")
    bb_neg = builder.append_basic_block(".neg")
    bb_exit = builder.append_basic_block(".exit")

    builder.cbranch(cmp_zero, bb_zero, bb_postest)

    with builder.goto_block(bb_zero):
        builder.store(ZERO, presult)
        builder.branch(bb_exit)

    with builder.goto_block(bb_postest):
        builder.cbranch(cmp_pos, bb_pos, bb_neg)

    with builder.goto_block(bb_pos):
        builder.store(POS, presult)
        builder.branch(bb_exit)

    with builder.goto_block(bb_neg):
        builder.store(NEG, presult)
        builder.branch(bb_exit)

    builder.position_at_end(bb_exit)
    res = builder.load(presult)
    return impl_ret_untracked(context, builder, sig.return_type, res)
Exemple #56
0
def for_range(builder, count, intp=None):
    """
    Generate LLVM IR for a for-loop in [0, count).  Yields a
    Loop namedtuple with the following members:
    - `index` is the loop index's value
    - `do_break` is a no-argument callable to break out of the loop
    """
    if intp is None:
        intp = count.type
    start = Constant.int(intp, 0)
    stop = count

    bbcond = builder.append_basic_block("for.cond")
    bbbody = builder.append_basic_block("for.body")
    bbend = builder.append_basic_block("for.end")

    def do_break():
        builder.branch(bbend)

    bbstart = builder.basic_block
    builder.branch(bbcond)

    ONE = Constant.int(intp, 1)

    with builder.goto_block(bbcond):
        index = builder.phi(intp, name="loop.index")
        pred = builder.icmp(lc.ICMP_SLT, index, stop)
        builder.cbranch(pred, bbbody, bbend)

    with builder.goto_block(bbbody):
        yield Loop(index, do_break)
        # Update bbbody as a new basic block may have been activated
        bbbody = builder.basic_block
        incr = builder.add(index, ONE)
        terminate(builder, bbcond)

    index.add_incoming(start, bbstart)
    index.add_incoming(incr, bbbody)

    builder.position_at_end(bbend)
Exemple #57
0
def int_sign_impl(context, builder, sig, args):
    """
    np.sign(int)
    """
    [x] = args
    POS = Constant.int(x.type, 1)
    NEG = Constant.int(x.type, -1)
    ZERO = Constant.int(x.type, 0)

    cmp_zero = builder.icmp(lc.ICMP_EQ, x, ZERO)
    cmp_pos = builder.icmp(lc.ICMP_SGT, x, ZERO)

    presult = cgutils.alloca_once(builder, x.type)

    bb_zero = builder.append_basic_block(".zero")
    bb_postest = builder.append_basic_block(".postest")
    bb_pos = builder.append_basic_block(".pos")
    bb_neg = builder.append_basic_block(".neg")
    bb_exit = builder.append_basic_block(".exit")

    builder.cbranch(cmp_zero, bb_zero, bb_postest)

    with builder.goto_block(bb_zero):
        builder.store(ZERO, presult)
        builder.branch(bb_exit)

    with builder.goto_block(bb_postest):
        builder.cbranch(cmp_pos, bb_pos, bb_neg)

    with builder.goto_block(bb_pos):
        builder.store(POS, presult)
        builder.branch(bb_exit)

    with builder.goto_block(bb_neg):
        builder.store(NEG, presult)
        builder.branch(bb_exit)

    builder.position_at_end(bb_exit)
    res = builder.load(presult)
    return impl_ret_untracked(context, builder, sig.return_type, res)
Exemple #58
0
def pointer_add(builder, ptr, offset, return_type=None):
    """
    Add an integral *offset* to pointer *ptr*, and return a pointer
    of *return_type* (or, if omitted, the same type as *ptr*).

    Note the computation is done in bytes, and ignores the width of
    the pointed item type.
    """
    intptr = builder.ptrtoint(ptr, intp_t)
    if isinstance(offset, int):
        offset = Constant.int(intp_t, offset)
    intptr = builder.add(intptr, offset)
    return builder.inttoptr(intptr, return_type or ptr.type)