Example #1
0
 def test_array_repr(self):
     tp = ArrayType(int8, 3)
     values = [Constant(int8, x) for x in (5, 10, -15)]
     c = Constant(tp, values)
     self.assertEqual(str(c), "[3 x i8] [i8 5, i8 10, i8 -15]")
     c = Constant(tp, bytearray(b"\x01\x02\x03"))
     self.assertEqual(str(c), '[3 x i8] c"\\01\\02\\03"')
Example #2
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(ll_ret_type, 0)
     one = Constant(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)
Example #3
0
def real_sign_impl(context, builder, sig, args):
    """
    np.sign(float)
    """
    [x] = args
    POS = Constant(x.type, 1)
    NEG = Constant(x.type, -1)
    ZERO = Constant(x.type, 0)

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

    is_pos = builder.fcmp_ordered('>', x, ZERO)
    is_neg = builder.fcmp_ordered('<', x, ZERO)

    with builder.if_else(is_pos) as (gt_zero, not_gt_zero):
        with gt_zero:
            builder.store(POS, presult)
        with not_gt_zero:
            with builder.if_else(is_neg) as (lt_zero, not_lt_zero):
                with lt_zero:
                    builder.store(NEG, presult)
                with not_lt_zero:
                    # For both NaN and 0, the result of sign() is simply
                    # the input value.
                    builder.store(x, presult)

    res = builder.load(presult)
    return impl_ret_untracked(context, builder, sig.return_type, res)
Example #4
0
def is_inf(builder, val):
    """
    Return a condition testing whether *val* is an infinite.
    """
    pos_inf = Constant(val.type, float("+inf"))
    neg_inf = Constant(val.type, float("-inf"))
    isposinf = builder.fcmp_ordered('==', val, pos_inf)
    isneginf = builder.fcmp_ordered('==', val, neg_inf)
    return builder.or_(isposinf, isneginf)
Example #5
0
def test_array_repr():
    int8 = IntType(8)
    tp = ArrayType(int8, 3)
    int8_1 = Constant(int8, 1)
    tp1 = tp.gep(int8_1)
    print(tp1, type(tp1))
    values = [Constant(int8, x) for x in (5, 10, -15)]
    c = Constant(tp, values)
    print(c)
    assert str(c) == "[3 x i8] [i8 5, i8 10, i8 -15]"
    c = Constant(tp, bytearray(b"\x01\x02\x03"))
    print(c)
    assert str(c) == '[3 x i8] c"\\01\\02\\03"'
Example #6
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(DATETIME64, 1970))
    multiple_of_4 = cgutils.is_null(
        builder, builder.and_(actual_year, Constant(DATETIME64, 3)))
    not_multiple_of_100 = cgutils.is_not_null(
        builder, builder.srem(actual_year, Constant(DATETIME64, 100)))
    multiple_of_400 = cgutils.is_null(
        builder, builder.srem(actual_year, Constant(DATETIME64, 400)))
    return builder.and_(multiple_of_4,
                        builder.or_(not_multiple_of_100, multiple_of_400))
Example #7
0
    def visit_Boolean(self, node: Boolean) -> Constant:
        """Converts the boolean type to an integer (i1) constant.

        Args:
            nodo (Boolean): a token represeting a literal boolean type

        Returns:
            Constant: a constant of type IntType (1) representing the Boolean type:
                1 = True and 0 = False
        """

        if node.token.type == TokenType.FALSE:
            return Constant(IntType(1), 0)
        else:
            return Constant(IntType(1), 1)
Example #8
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(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()
Example #9
0
 def init_generator_state(self, lower):
     """
     NULL-initialize all generator state variables, to avoid spurious
     decref's on cleanup.
     """
     lower.builder.store(Constant(self.gen_state_ptr.type.pointee, None),
                         self.gen_state_ptr)
Example #10
0
 def return_from_generator(self, lower):
     """
     Emit a StopIteration at generator end and mark the generator exhausted.
     """
     indexval = Constant(self.resume_index_ptr.type.pointee, -1)
     lower.builder.store(indexval, self.resume_index_ptr)
     self.call_conv.return_stop_iteration(lower.builder)
Example #11
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(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)
Example #12
0
    def __call__(self, value):
        """
        Create a LLVM constant of this type with the given Python value.
        """
        from llvmlite.ir import Constant

        return Constant(self, value)
Example #13
0
 def wrap_constant_value(self, values):
     from . import Value, Constant
     if not isinstance(values, (list, tuple)):
         if isinstance(values, Constant):
             if values.type != self.element:
                 raise TypeError("expected {} for {}".format(
                     self.element, values.type))
             return (values, ) * self.count
         return (Constant(self.element, values), ) * self.count
     if len(values) != len(self):
         raise ValueError("wrong constant size for %s: got %d elements" %
                          (self, len(values)))
     return [
         Constant(ty, val) if not isinstance(val, Value) else val
         for ty, val in zip(self.elements, values)
     ]
Example #14
0
def int_invert_impl(context, builder, sig, args):
    [typ] = sig.args
    [val] = args
    # Invert before upcasting, for unsigned numbers
    res = builder.xor(val, Constant(val.type, int('1' * val.type.width, 2)))
    res = context.cast(builder, res, typ, sig.return_type)
    return impl_ret_untracked(context, builder, sig.return_type, res)
Example #15
0
def int_abs_impl(context, builder, sig, args):
    [x] = args
    ZERO = Constant(x.type, None)
    ltz = builder.icmp_signed('<', x, ZERO)
    negated = builder.neg(x)
    res = builder.select(ltz, negated, x)
    return impl_ret_untracked(context, builder, sig.return_type, res)
Example #16
0
    def visit_Writeln(self, node: Writeln) -> None:
        """Converts the contents of the command writeln to LLVM ir code and adds the
        print call to the operating system.

        Args:
            node (Writeln): content passed in the command writeln
        """

        self.printf_counter += 1
        output_operation_type = "%s"

        if isinstance(node.content[0], BinaryOperator):
            self._create_instruct("BinaryOperator", is_printf=True)

        writeln_content = self.visit(node.content[0])

        if isinstance(writeln_content, VarSymbol):
            content = self.GLOBAL_MEMORY[writeln_content.name]
        else:
            content = writeln_content

        content_type = type(content.type).__name__

        if self.builder.block.is_terminated:
            self._create_instruct(typ=content_type, is_printf=True)

        if isinstance(content.type, DoubleType):
            output_operation_type = "%f"

        output_format = f"{output_operation_type}\n\0"
        printf_format = Constant(
            ArrayType(IntType(8), len(output_format)),
            bytearray(output_format.encode("utf8")),
        )

        fstr = GlobalVariable(self.module,
                              printf_format.type,
                              name=f"fstr_{self.printf_counter}")
        fstr.linkage = "internal"
        fstr.global_constant = True
        fstr.initializer = printf_format

        writeln_type = FunctionType(IntType(32), [], var_arg=True)
        writeln = Function(
            self.module,
            writeln_type,
            name=f"printf_{content_type}_{self.printf_counter}",
        )

        body = self.builder.alloca(content.type)
        temp_loaded = self.builder.load(body)
        self.builder.store(temp_loaded, body)

        void_pointer_type = IntType(8).as_pointer()
        casted_arg = self.builder.bitcast(fstr, void_pointer_type)
        self.builder.call(writeln, [casted_arg, body])
        self.builder.ret_void()
Example #17
0
def complex_as_bool(context, builder, sig, args):
    [typ] = sig.args
    [val] = args
    cmplx = context.make_complex(builder, typ, val)
    real, imag = cmplx.real, cmplx.imag
    zero = Constant(real.type, 0.0)
    real_istrue = builder.fcmp_unordered('!=', real, zero)
    imag_istrue = builder.fcmp_unordered('!=', imag, zero)
    return builder.or_(real_istrue, imag_istrue)
Example #18
0
 def insert_const_bytes(self, mod, bytes, name=None):
     """
     Insert constant *byte* (a `bytes` object) into module *mod*.
     """
     stringtype = GENERIC_POINTER
     name = ".bytes.%s" % (name or hash(bytes))
     text = cgutils.make_bytearray(bytes)
     gv = self.insert_unique_const(mod, name, text)
     return Constant.bitcast(gv, stringtype)
Example #19
0
 def insert_const_string(self, mod, string):
     """
     Insert constant *string* (a str object) into module *mod*.
     """
     stringtype = GENERIC_POINTER
     name = ".const.%s" % string
     text = cgutils.make_bytearray(string.encode("utf-8") + b"\x00")
     gv = self.insert_unique_const(mod, name, text)
     return Constant.bitcast(gv, stringtype)
Example #20
0
    def visit_Num(self, node: Num) -> Constant:
        """Set the Double Type to a specific number.

        Args:
            node (Num): a token represeting a number (constant)

        Returns:
            Constant: a LLVM IR Constant representing the number.
        """
        return Constant(DoubleType(), float(node.value))
Example #21
0
    def visit_UnaryOperator(self, node: UnaryOperator) -> Constant:
        """Performs Unary Operations according to the arithmetic operator (PLUS and MINUS)
        transforming them into a LLVM IR Constant.

        Args:
            node (UnaryOperator): node containing the variables (or numbers) and the
            arithmetic operators (PLUS and MINUS)

        Returns:
            Constant: a LLVM IR Constant representing the number or variable.
        """

        operator = node.operator.type
        if operator == TokenType.PLUS:
            expression = self.visit(node.expression)
            return Constant(DoubleType(), float(+expression.constant))
        elif operator == TokenType.MINUS:
            expression = self.visit(node.expression)
            return Constant(DoubleType(), float(-expression.constant))
Example #22
0
    def wrap_constant_value(self, values):
        from . import Value, Constant

        if not isinstance(values, (list, tuple)):
            return values
        if len(values) != len(self):
            raise ValueError("wrong constant size for %s: got %d elements" %
                             (self, len(values)))
        return [
            Constant(ty, val) if not isinstance(val, Value) else val
            for ty, val in zip(self.elements, values)
        ]
Example #23
0
def timedelta_sign_impl(context, builder, sig, args):
    """
    np.sign(timedelta64)
    """
    val, = args
    ret = alloc_timedelta_result(builder)
    zero = Constant(TIMEDELTA64, 0)
    with builder.if_else(builder.icmp_signed('>', val,
                                             zero)) as (gt_zero, le_zero):
        with gt_zero:
            builder.store(Constant(TIMEDELTA64, 1), ret)
        with le_zero:
            with builder.if_else(builder.icmp_unsigned('==', val,
                                                       zero)) as (eq_zero,
                                                                  lt_zero):
                with eq_zero:
                    builder.store(Constant(TIMEDELTA64, 0), ret)
                with lt_zero:
                    builder.store(Constant(TIMEDELTA64, -1), ret)
    res = builder.load(ret)
    return impl_ret_untracked(context, builder, sig.return_type, res)
Example #24
0
def int_sign_impl(context, builder, sig, args):
    """
    np.sign(int)
    """
    [x] = args
    POS = Constant(x.type, 1)
    NEG = Constant(x.type, -1)
    ZERO = Constant(x.type, 0)

    cmp_zero = builder.icmp_unsigned('==', x, ZERO)
    cmp_pos = builder.icmp_signed('>', 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)
Example #25
0
    def generate_functions(self, functions):
        type_dict = {
            'int': int_type,
            'float': float_type,
            'byte': byte_type,
            'bool': int_type,
            'void': void_type
        }
        for function in functions:
            # register function
            name = function.name if function.name != 'main' else '_gone_main'
            return_type = type_dict[function.return_type]
            param_types = [type_dict[t] for t in function.param_types]
            function_type = FunctionType(return_type, param_types)
            self.function = Function(self.module, function_type, name=name)
            self.globals[name] = self.function
            self.blocks = {}
            self.block = self.function.append_basic_block('entry')
            self.blocks['entry'] = self.block
            self.builder = IRBuilder(self.block)

            # local scope
            self.vars = self.vars.new_child()
            self.temps = {}
            for n, (param_name, param_type) in enumerate(
                    zip(function.param_names, param_types)):
                var = self.builder.alloca(param_type, name=param_name)
                var.initializer = Constant(param_type, 0)
                self.vars[param_name] = var
                self.builder.store(self.function.args[n],
                                   self.vars[param_name])

            # alloc return var / block
            if function.return_type != 'void':
                self.vars['return'] = self.builder.alloca(return_type,
                                                          name='return')
            self.return_block = self.function.append_basic_block('return')

            # generate instructions
            self.generate_code(function)

            # return
            if not self.block.is_terminated:
                self.builder.branch(self.return_block)

            self.builder.position_at_end(self.return_block)
            if function.return_type != 'void':
                self.builder.ret(
                    self.builder.load(self.vars['return'], 'return'))
            else:
                self.builder.ret_void()
            self.vars = self.vars.parents
Example #26
0
    def visit_String(self, node: String) -> Constant:
        """Converts the literal string to an array of characters.

        Args:
            node (String): a token represeting a string (literal)

        Returns:
            Constant: a constant containing a array of characters
        """

        content = node.value
        return Constant(ArrayType(IntType(8), len(content)),
                        bytearray(content.encode("utf8")))
Example #27
0
def timedelta_over_timedelta(context, builder, sig, args):
    [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 = cgutils.alloca_once(builder, ll_ret_type, name='ret')
    builder.store(Constant(ll_ret_type, float('nan')), ret)
    with cgutils.if_likely(builder, not_nan):
        va, vb = normalize_timedeltas(context, builder, va, vb, ta, tb)
        va = builder.sitofp(va, ll_ret_type)
        vb = builder.sitofp(vb, ll_ret_type)
        builder.store(builder.fdiv(va, vb), ret)
    res = builder.load(ret)
    return impl_ret_untracked(context, builder, sig.return_type, res)
Example #28
0
    def lower_init_func(self, lower):
        """
        Lower the generator's initialization function (which will fill up
        the passed-by-reference generator structure).
        """
        lower.setup_function(self.fndesc)

        builder = lower.builder

        # Insert the generator into the target context in order to allow
        # calling from other Numba-compiled functions.
        lower.context.insert_generator(self.gentype, self.gendesc,
                                       [self.library])

        # Init argument values
        lower.extract_function_arguments()

        lower.pre_lower()

        # Initialize the return structure (i.e. the generator structure).
        retty = self.context.get_return_type(self.gentype)
        # Structure index #0: the initial resume index (0 == start of generator)
        resume_index = self.context.get_constant(types.int32, 0)
        # Structure index #1: the function arguments
        argsty = retty.elements[1]
        statesty = retty.elements[2]

        lower.debug_print("# low_init_func incref")
        # Incref all NRT arguments before storing into generator states
        if self.context.enable_nrt:
            for argty, argval in zip(self.fndesc.argtypes, lower.fnargs):
                self.context.nrt.incref(builder, argty, argval)

        # Filter out omitted arguments
        argsval = self.arg_packer.as_data(builder, lower.fnargs)

        # Zero initialize states
        statesval = Constant(statesty, None)
        gen_struct = cgutils.make_anonymous_struct(builder,
                                                   [resume_index, argsval,
                                                    statesval],
                                                   retty)

        retval = self.box_generator_struct(lower, gen_struct)

        lower.debug_print("# low_init_func before return")
        self.call_conv.return_value(builder, retval)
        lower.post_lower()
Example #29
0
    def details(context, builder, signature, args):
        [kind_val, char_bytes_val, length_val] = args

        # fill the struct
        uni_str_ctor = cgutils.create_struct_proxy(types.unicode_type)
        uni_str = uni_str_ctor(context, builder)
        # add null padding character
        nbytes_val = builder.mul(char_bytes_val,
                                 builder.add(length_val,
                                             Constant(length_val.type, 1)))
        uni_str.meminfo = context.nrt.meminfo_alloc(builder, nbytes_val)
        uni_str.kind = kind_val
        uni_str.length = length_val
        uni_str.data = context.nrt.meminfo_data(builder, uni_str.meminfo)
        # Set parent to NULL
        uni_str.parent = cgutils.get_null_value(uni_str.parent.type)
        return uni_str._getvalue()
Example #30
0
    def details(context, builder, signature, args):
        [kind_val, char_bytes_val, length_val, is_ascii_val] = args

        # fill the struct
        uni_str_ctor = cgutils.create_struct_proxy(types.unicode_type)
        uni_str = uni_str_ctor(context, builder)
        # add null padding character
        nbytes_val = builder.mul(char_bytes_val,
                                 builder.add(length_val,
                                             Constant(length_val.type, 1)))
        uni_str.meminfo = context.nrt.meminfo_alloc(builder, nbytes_val)
        uni_str.kind = kind_val
        uni_str.is_ascii = is_ascii_val
        uni_str.length = length_val
        # empty string has hash value -1 to indicate "need to compute hash"
        uni_str.hash = context.get_constant(_Py_hash_t, -1)
        uni_str.data = context.nrt.meminfo_data(builder, uni_str.meminfo)
        # Set parent to NULL
        uni_str.parent = cgutils.get_null_value(uni_str.parent.type)
        return uni_str._getvalue()