Example #1
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")
    # Cannot inline this for refcount pruning to work
    fn_incref.attributes.add('noinline')
    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()

    if _debug_print:
        cgutils.printf(builder, "*** NRT_Incref %zu [%p]\n", builder.load(ptr),
                       ptr)
    builder.call(atomic_incr, [builder.bitcast(ptr, atomic_incr.args[0].type)])
    builder.ret_void()
Example #2
0
def _imp_dtor(context, module):
    """Define the dtor for list"""
    llvoidptr = context.get_value_type(types.voidptr)
    llsize = context.get_value_type(types.uintp)
    fnty = ir.FunctionType(ir.VoidType(), [llvoidptr, llsize, llvoidptr],)
    fname = "_numba_list_dtor"
    fn = module.get_or_insert_function(fnty, name=fname)

    if fn.is_declaration:
        # Set linkage
        fn.linkage = "linkonce_odr"
        # Define
        builder = ir.IRBuilder(fn.append_basic_block())
        lp = builder.bitcast(fn.args[0], ll_list_type.as_pointer())
        l = builder.load(lp)
        _call_list_free(context, builder, l)
        builder.ret_void()

    return fn
Example #3
0
 def check(likely):
     block = self.block(name='one')
     builder = ir.IRBuilder(block)
     z = ir.Constant(int1, 0)
     with builder.if_else(z, likely=likely) as (then, otherwise):
         with then:
             builder.branch(block)
         with otherwise:
             builder.ret_void()
     self.check_func_body(builder.function, """\
         one:
             br i1 0, label %"one.if", label %"one.else", !prof !0
         one.if:
             br label %"one"
         one.else:
             ret void
         one.endif:
         """)
     return builder
Example #4
0
    def emit_procedure(self, procedure):
        identifier, subprogram = procedure

        try:
            existing_func = self.module.get_global(identifier)
            return existing_func
        except KeyError:
            pass

        fnty = ir.FunctionType(ir.VoidType(), ())
        func = ir.Function(self.module, fnty, identifier)

        block = func.append_basic_block('entry')
        builder = ir.IRBuilder(block)

        self.emit_subprogram(subprogram.content, builder)
        builder.ret_void()

        return func
Example #5
0
    def visit_Subroutine(self, node):
        self._current_scope = node._scope
        fn = ir.FunctionType(
            ir.VoidType(),
            [ir.IntType(64).as_pointer(),
             ir.IntType(64).as_pointer()])
        func = ir.Function(self.module, fn, name=node.name)
        block = func.append_basic_block(name='.entry')
        builder = ir.IRBuilder(block)
        old = [self.func, self.builder]
        self.func, self.builder = func, builder
        for n, arg in enumerate(node.args):
            self._current_scope.resolve(arg.arg)["ptr"] = self.func.args[n]

        self.visit_sequence(node.body)
        self.builder.ret_void()

        self.func, self.builder = old
        self._current_scope = node._scope.parent_scope
Example #6
0
def _define_atomic_inc_dec(module, op, ordering):
    """Define a llvm function for atomic increment/decrement to the given module
    Argument ``op`` is the operation "add"/"sub".  Argument ``ordering`` is
    the memory ordering.  The generated function returns the new value.
    """
    ftype = ir.FunctionType(_word_type, [_word_type.as_pointer()])
    fn_atomic = ir.Function(module, ftype, name="nrt_atomic_{0}".format(op))

    [ptr] = fn_atomic.args
    bb = fn_atomic.append_basic_block()
    builder = ir.IRBuilder(bb)
    ONE = ir.Constant(_word_type, 1)
    oldval = builder.atomic_rmw(op, ptr, ONE, ordering=ordering)
    # Perform the operation on the old value so that we can pretend returning
    # the "new" value.
    res = getattr(builder, op)(oldval, ONE)
    builder.ret(res)

    return fn_atomic
Example #7
0
 def test_switch(self):
     block = self.block(name='my_block')
     builder = ir.IRBuilder(block)
     a, b = builder.function.args[:2]
     bb_onzero = builder.function.append_basic_block(name='onzero')
     bb_onone = builder.function.append_basic_block(name='onone')
     bb_ontwo = builder.function.append_basic_block(name='ontwo')
     bb_else = builder.function.append_basic_block(name='otherwise')
     sw = builder.switch(a, bb_else)
     sw.add_case(ir.Constant(int32, 0), bb_onzero)
     sw.add_case(ir.Constant(int32, 1), bb_onone)
     # A plain Python value gets converted into the right IR constant
     sw.add_case(2, bb_ontwo)
     self.assertTrue(block.is_terminated)
     self.check_block(
         block, """\
         my_block:
             switch i32 %".1", label %"otherwise" [i32 0, label %"onzero" i32 1, label %"onone" i32 2, label %"ontwo"]
         """)
Example #8
0
def dynamic_array_length(self, dyn_array_ptr, array_type):
    # START
    dyn_array_length_type = ir.FunctionType(type_map[INT], [dyn_array_ptr])
    dyn_array_length = ir.Function(self.module, dyn_array_length_type,
                                   '{}.array.length'.format(str(array_type)))
    dyn_array_length.args[0].name = 'self'
    dyn_array_length_entry = dyn_array_length.append_basic_block('entry')
    builder = ir.IRBuilder(dyn_array_length_entry)
    self.builder = builder
    builder.position_at_end(dyn_array_length_entry)
    array_ptr = builder.alloca(dyn_array_ptr)
    builder.store(dyn_array_length.args[0], array_ptr)

    size_ptr = builder.gep(builder.load(array_ptr), [zero_32, zero_32],
                           inbounds=True)

    # CLOSE
    self.define('{}.array.length'.format(str(array_type)), dyn_array_length)
    builder.ret(builder.load(size_ptr))
Example #9
0
def dynamic_array_append(self, dyn_array_ptr, array_type):
    # START
    dyn_array_append_type = ir.FunctionType(type_map[VOID],
                                            [dyn_array_ptr, array_type])
    dyn_array_append = ir.Function(self.module, dyn_array_append_type,
                                   '{}.array.append'.format(str(array_type)))
    dyn_array_append.args[0].name = 'self'
    dyn_array_append_entry = dyn_array_append.append_basic_block('entry')
    builder = ir.IRBuilder(dyn_array_append_entry)
    self.builder = builder
    dyn_array_append_exit = dyn_array_append.append_basic_block('exit')
    builder.position_at_end(dyn_array_append_entry)
    array_ptr = builder.alloca(dyn_array_ptr)
    builder.store(dyn_array_append.args[0], array_ptr)
    value_ptr = builder.alloca(array_type)
    builder.store(dyn_array_append.args[1], value_ptr)

    # BODY
    builder.call(
        self.module.get_global('{}.array.double_capacity_if_full'.format(
            str(array_type))), [builder.load(array_ptr)])

    size_ptr = builder.gep(builder.load(array_ptr), [zero_32, zero_32],
                           inbounds=True)
    size_val = builder.load(size_ptr)

    size_val = builder.add(size_val, one)
    builder.store(size_val, size_ptr)

    data_ptr = builder.gep(builder.load(array_ptr), [zero_32, two_32],
                           inbounds=True)

    data_element_ptr = builder.gep(builder.load(data_ptr), [size_val],
                                   inbounds=True)

    builder.store(builder.load(value_ptr), data_element_ptr)

    builder.branch(dyn_array_append_exit)

    # CLOSE
    self.define('{}.array.append'.format(str(array_type)), dyn_array_append)
    builder.position_at_end(dyn_array_append_exit)
    builder.ret_void()
Example #10
0
    def eval(self, node, builder=None):
        if builder is None:
            builder = self.builder

        identifier = Node(self.name)
        node.children.extend([
            Node("FUNCTION"),
            Node('type', self.typ), identifier,
            Node("{"),
            Node("block"),
            Node("}")
        ])

        int_ = ir.IntType(32)
        flt_ = ir.FloatType()
        f_typ = {'int': int_, 'float': flt_}

        f_args = [f_typ[i.typ] for i in self.args.get_args()]

        fnty = ir.FunctionType(f_typ[self.typ], f_args)
        func = ir.Function(self.module, fnty, name=self.name)
        fnctns[self.name] = func
        block = func.append_basic_block(name="entry")
        f_builder = ir.IRBuilder(block)
        self.state.variables[f_builder.function] = {}
        self.state.variables[f_builder.function]['args'] = {}
        types_dict = {ir.IntType(32): 'INT', ir.FloatType(): 'FLT', str: 'STR'}
        for arg_ in range(len(func.args)):
            var_name = self.args.get_args()[arg_].name.getstr()
            var_type = func.args[arg_].type
            alloc = f_builder.alloca(var_type, size=None, name=var_name)
            if f_builder.function not in self.state.variables.keys():
                self.state.variables[f_builder.function] = {}
            self.state.variables[f_builder.function][var_name] = {
                'value': func.args[arg_],
                'type': types_dict[var_type],
                'ptr': alloc
            }
            f_builder.store(func.args[arg_], alloc)

        # print(self.state.variables)

        self.block.eval(Node('block'), builder=f_builder)
Example #11
0
    def visit_FunctionDef(self, node):
        # 引数の内容をたどる
        for a in (node.args.args):
            self.visit(a)

        # 関数の返り値と引数、関数名をセット
        self.fnty = ir.FunctionType(
            self.ret_type, tuple(self.arg_types))
        self.func = ir.Function(self.module, self.fnty, node.name)
        self.func_name = node.name

        # entry
        bb_entry = self.func.append_basic_block()
        self.builder = ir.IRBuilder()
        self.builder.position_at_end(bb_entry)

        # 関数の内容をたどる
        for b in node.body:
            self.visit(b)
Example #12
0
def test_union(builder: AstBuilder):
    cases = [
        ('float', itype, False),
        ('float', ftype, True),
        ('int', itype, True),
        ('int', ftype, False),
        ('a', ftype, False),
        ('b', itype, False),
    ]

    for (name, type, should_work) in cases:
        try:
            union_obj = builder.call(
                builder.reference('FloatOrInt'),
                [builder.named_arg(name, builder.value(3, type))])

            type_trace(union_obj, ctx)
            show_result(union_obj, ctx)

            bind = builder.bind('val', union_obj)

            module = ir.Module(name='test')

            # -- dummy main function
            fun = ir.Function(module,
                              ftype=ir.FunctionType(ir.VoidType(), []),
                              name='main')
            block = fun.append_basic_block('main_block')
            irbuilder = ir.IRBuilder(block)
            # ----

            llvm_union = llvm_codegen(module=module,
                                      scope=ctx,
                                      expr=bind,
                                      builder=irbuilder)
            print()
            print(llvm_union.expr)

        except Exception as e:
            is_error(should_work, e)

        print('-' * 80)
Example #13
0
    def test_as_arg(self):
        """
        - Is as_arg() and from_arg() implemented?
        - Are they the inverse of each other?
        """
        fnty = ir.FunctionType(ir.VoidType(), [])
        function = ir.Function(self.module, fnty, name="test_as_arg")
        builder = ir.IRBuilder()
        builder.position_at_end(function.append_basic_block())

        undef_value = ir.Constant(self.datamodel.get_value_type(), None)
        args = self.datamodel.as_argument(builder, undef_value)
        self.assertIsNot(args, NotImplemented, "as_argument returned "
                                               "NotImplementedError")

        if isinstance(args, (tuple, list)):
            def recur_tuplize(args, func=None):
                for arg in args:
                    if isinstance(arg, (tuple, list)):
                        yield tuple(recur_tuplize(arg, func=func))
                    else:
                        if func is None:
                            yield arg
                        else:
                            yield func(arg)

            argtypes = tuple(recur_tuplize(args, func=lambda x: x.type))
            exptypes = tuple(recur_tuplize(
                self.datamodel.get_argument_type()))
            self.assertEqual(exptypes, argtypes)
        else:
            self.assertEqual(args.type,
                             self.datamodel.get_argument_type())

        rev_value = self.datamodel.from_argument(builder, args)
        self.assertEqual(rev_value.type, self.datamodel.get_value_type())

        builder.ret_void()  # end function

        # Ensure valid LLVM generation
        materialized = ll.parse_assembly(str(self.module))
        str(materialized)
Example #14
0
    def gen_new_fields(self, cls: Class):
        name = cls.qualified_name.replace('.', '_') + '_init'
        if name in self.methods:
            return self.methods[name]
        cls_type = gen_class_struct(cls)
        func_type = ir.FunctionType(ir.VoidType(), [cls_type.as_pointer()])
        func = ir.Function(self.module, func_type, name=name)
        self.methods[name] = func
        if cls.is_native:
            return self.methods[name]

        with self.new_env():
            from cgen import RuntimeGen
            builder = ir.IRBuilder(func.append_basic_block('entry'))
            func = self.gen_new_fields(cls.superclass)
            builder.call(func, [
                builder.bitcast(builder.function.args[0], func.ftype.args[0])
            ])

            ptr = builder.gep(builder.function.args[0],
                              [ir.Constant(int32, 0),
                               ir.Constant(int32, 0)],
                              inbounds=True,
                              name='classId_ptr')
            builder.store(ir.Constant(int32,
                                      RuntimeGen().classes.index(cls)), ptr)

            for field in cls.fields:
                if field.initializer:
                    value = self.expr(field.initializer)
                    ptr = self.builder.gep(self.builder.function.args[0], [
                        ir.Constant(int32, 0),
                        ir.Constant(
                            int32,
                            field.owner.inherited_fields.index(field) + 1)
                    ],
                                           inbounds=True,
                                           name=field.name + '_ptr')
                    builder.store(value, ptr)
            builder.ret_void()

        return self.methods[name]
Example #15
0
 def test_float_comparisons(self):
     block = self.block(name='my_block')
     builder = ir.IRBuilder(block)
     a, b = builder.function.args[:2]
     builder.fcmp_ordered('==', a, b, 'c')
     builder.fcmp_ordered('!=', a, b, 'd')
     builder.fcmp_ordered('<', a, b, 'e')
     builder.fcmp_ordered('<=', a, b, 'f')
     builder.fcmp_ordered('>', a, b, 'g')
     builder.fcmp_ordered('>=', a, b, 'h')
     builder.fcmp_unordered('==', a, b, 'i')
     builder.fcmp_unordered('!=', a, b, 'j')
     builder.fcmp_unordered('<', a, b, 'k')
     builder.fcmp_unordered('<=', a, b, 'l')
     builder.fcmp_unordered('>', a, b, 'm')
     builder.fcmp_unordered('>=', a, b, 'n')
     # fcmp_ordered and fcmp_unordered are the same for these cases
     builder.fcmp_ordered('ord', a, b, 'u')
     builder.fcmp_ordered('uno', a, b, 'v')
     builder.fcmp_unordered('ord', a, b, 'w')
     builder.fcmp_unordered('uno', a, b, 'x')
     self.assertFalse(block.is_terminated)
     self.check_block(
         block, """\
         my_block:
             %"c" = fcmp oeq i32 %".1", %".2"
             %"d" = fcmp one i32 %".1", %".2"
             %"e" = fcmp olt i32 %".1", %".2"
             %"f" = fcmp ole i32 %".1", %".2"
             %"g" = fcmp ogt i32 %".1", %".2"
             %"h" = fcmp oge i32 %".1", %".2"
             %"i" = fcmp ueq i32 %".1", %".2"
             %"j" = fcmp une i32 %".1", %".2"
             %"k" = fcmp ult i32 %".1", %".2"
             %"l" = fcmp ule i32 %".1", %".2"
             %"m" = fcmp ugt i32 %".1", %".2"
             %"n" = fcmp uge i32 %".1", %".2"
             %"u" = fcmp ord i32 %".1", %".2"
             %"v" = fcmp uno i32 %".1", %".2"
             %"w" = fcmp ord i32 %".1", %".2"
             %"x" = fcmp uno i32 %".1", %".2"
         """)
Example #16
0
    def gen_function_declaration(self, root):
        name = TppSemantic.get_function_name(root)
        body = TppSemantic.get_function_body(root)
        fn = self.module.get_global(name)

        self.current_scope = name
        entryBlock = fn.append_basic_block('entry')
        self.builder = ir.IRBuilder(entryBlock)

        i = 0
        for var_symbol in self.context.symbols:
            if isinstance(
                    var_symbol, VarSymbol
            ) and var_symbol.used and var_symbol.scope == fn.name and var_symbol.parameter:
                fn.args[i].name = var_symbol.name

                type_ = self.type_to_llvmlite_type(var_symbol.type_,
                                                   var_symbol.index_list)

                a = self.builder.alloca(type_, name=var_symbol.name)
                self.builder.store(fn.args[i], a)
                a.align = 4
                var_symbol.llvm_ref = a

                i += 1

        self._traverse(body)

        fn_symbol = self.context.get_symbol(name, '@global')
        if fn_symbol.type_ == "vazio":
            self.builder.ret_void()

        self.current_scope = '@global'

        if self.last_block and not self.builder.block.is_terminated:
            if fn_symbol.type_ == "vazio":
                self.builder.ret_void()
            elif fn_symbol.type_ == "inteiro":
                self.builder.ret(ir.Constant(ir.IntType(32), 0))
            else:
                self.builder.ret(ir.Constant(ir.DoubleType(), 0.0))
            self.last_block = None
Example #17
0
 def test_binops_with_overflow(self):
     block = self.block(name='my_block')
     builder = ir.IRBuilder(block)
     a, b = builder.function.args[:2]
     builder.sadd_with_overflow(a, b, 'c')
     builder.smul_with_overflow(a, b, 'd')
     builder.ssub_with_overflow(a, b, 'e')
     builder.uadd_with_overflow(a, b, 'f')
     builder.umul_with_overflow(a, b, 'g')
     builder.usub_with_overflow(a, b, 'h')
     self.check_block(
         block, """\
         my_block:
             %"c" = call {i32, i1} (i32, i32)* @"llvm.sadd.with.overflow.i32"(i32 %".1", i32 %".2")
             %"d" = call {i32, i1} (i32, i32)* @"llvm.smul.with.overflow.i32"(i32 %".1", i32 %".2")
             %"e" = call {i32, i1} (i32, i32)* @"llvm.ssub.with.overflow.i32"(i32 %".1", i32 %".2")
             %"f" = call {i32, i1} (i32, i32)* @"llvm.uadd.with.overflow.i32"(i32 %".1", i32 %".2")
             %"g" = call {i32, i1} (i32, i32)* @"llvm.umul.with.overflow.i32"(i32 %".1", i32 %".2")
             %"h" = call {i32, i1} (i32, i32)* @"llvm.usub.with.overflow.i32"(i32 %".1", i32 %".2")
         """)
Example #18
0
    def _codegen_FunctionAST(self, node):
        # Reset the symbol table. Prototype generation will pre-populate it with
        # function arguments.
        self.func_symtab = {}
        # Create the function skeleton from the prototype.
        func = self._codegen(node.proto)
        # Create the entry BB in the function and set the builder to it.
        bb_entry = func.append_basic_block('entry')
        self.builder = ir.IRBuilder(bb_entry)

        # Add all arguments to the symbol table and create their allocas
        for i, arg in enumerate(func.args):
            arg.name = node.proto.argnames[i]
            alloca = self.builder.alloca(ir.DoubleType(), name=arg.name)
            self.builder.store(arg, alloca)
            self.func_symtab[arg.name] = alloca

        retval = self._codegen(node.body)
        self.builder.ret(retval)
        return func
Example #19
0
    def gen_new(self, cls):
        name = cls.qualified_name.replace('.', '_') + '_new'
        if name in self.methods:
            return self.methods[name]
        cls_type = gen_class_struct(cls)
        return_type = cls_type.as_pointer()
        func_type = ir.FunctionType(return_type, [])
        func = ir.Function(self.module, func_type, name=name)
        self.methods[name] = func
        if cls.is_native:
            return self.methods[name]
        with self.new_env():
            builder = ir.IRBuilder(func.append_basic_block('entry'))
            ret = builder.call(self.functions['new'],
                               [ir.Constant(int32, cls_type.size)])
            ret = builder.bitcast(ret, return_type)
            builder.call(self.gen_new_fields(cls), [ret])
            builder.ret(builder.bitcast(ret, return_type))

        return self.methods[name]
Example #20
0
    def compile(self, error_logger):
        """Compile the whole program as an LLVM module."""
        global_scope = Scope()
        module = ir.Module()

        ir.Function(
            module,
            ir.FunctionType(i32_t, [ir.IntType(8).as_pointer()], var_arg=True),
            "printf")
        main_function = ir.Function(module,
                                    ir.FunctionType(i32_t, []),
                                    name="main")
        block = main_function.append_basic_block()
        builder = ir.IRBuilder(block)

        _compile_logging_errors(self.parts, global_scope, builder,
                                error_logger)

        builder.ret(i32_t(0))
        return module
Example #21
0
    def generate(self, module, scope):
        self.function = self._create_function(module)

        # Adds itself to scope
        scope[self.name] = self

        # Append block
        block = self.function.append_basic_block(self.name)
        builder = ir.IRBuilder(block)

        with scope() as scop:
            # allocate parameters
            self._allocate_args(builder, scop)

            # generate body
            block = builder.append_basic_block('body')
            builder.branch(block)
            with builder.goto_block(block):
                self.block.generate(builder, scop)
        return builder
Example #22
0
def dynamic_array_append(compiler, dyn_array_struct_ptr):
    # START
    dyn_array_append_type = ir.FunctionType(
        type_map[VOID], [dyn_array_struct_ptr, type_map[INT]])
    dyn_array_append = ir.Function(compiler.module, dyn_array_append_type,
                                   'dyn_array_append')
    dyn_array_append_entry = dyn_array_append.append_basic_block('entry')
    builder = ir.IRBuilder(dyn_array_append_entry)
    compiler.builder = builder
    dyn_array_append_exit = dyn_array_append.append_basic_block('exit')
    builder.position_at_end(dyn_array_append_entry)
    array_ptr = builder.alloca(dyn_array_struct_ptr)
    builder.store(dyn_array_append.args[0], array_ptr)
    value_ptr = builder.alloca(type_map[INT])
    builder.store(dyn_array_append.args[1], value_ptr)

    # BODY
    builder.call(
        compiler.module.get_global('dyn_array_double_capacity_if_full'),
        [builder.load(array_ptr)])

    size_ptr = builder.gep(builder.load(array_ptr), [zero_32, zero_32],
                           inbounds=True)
    size_val = builder.load(size_ptr)

    size_val = builder.add(size_val, one)
    builder.store(size_val, size_ptr)

    data_ptr = builder.gep(builder.load(array_ptr), [zero_32, two_32],
                           inbounds=True)

    data_element_ptr = builder.gep(builder.load(data_ptr), [size_val],
                                   inbounds=True)

    builder.store(builder.load(value_ptr), data_element_ptr)

    builder.branch(dyn_array_append_exit)

    # CLOSE
    builder.position_at_end(dyn_array_append_exit)
    builder.ret_void()
Example #23
0
def convert_var(exp, irb=ir.IRBuilder(), value=None):
    if exp['varname'] == 'M':
        # This shouldn't happen anymore
        assert False
        return M, lambda irb: irb.load(M)

    if exp['varid'] not in vars:
        if exp['varname'] == 'rsp_0':
            typ = pointertype
        else:
            typ = ir.IntType(int(exp['width']))

        # Use registers for temporaries
        if exp['varname'] == "":
            if value is not None:
                vars[exp['varid']] = None
                exps[exp['varid']] = lambda irb: value
            else:
                varname = "v%d" % int(exp['varid'])
                print(
                    "WARNING: %s accessed before defined. This should not happen."
                    % exp,
                    file=sys.stderr)
                assert False
                vars[exp['varid']] = irb.alloca(typ, name=varname)
                exps[exp['varid']] = lambda irb: irb.load(vars[exp['varid']])
        else:
            varname = "pharos.reg." + exp['varname']
            var = ir.GlobalVariable(module, typ, varname)
            var.initializer = ir.Constant(typ, None)
            var.linkage = 'internal'
            vars[exp['varid']] = var
            if exp['varname'] == 'rsp_0':
                # Most of the time we don't want to access rsp as a pointer
                exps[exp['varid']] = lambda irb: irb.ptrtoint(
                    irb.load(vars[exp['varid']]), ir.IntType(int(exp['width']))
                )
            else:
                exps[exp['varid']] = lambda irb: irb.load(vars[exp['varid']])

    return (vars[exp['varid']], exps[exp['varid']])
Example #24
0
def test_helper_fclamp(mode):

    with pnlvm.LLVMBuilderContext() as ctx:
        local_vec = copy.deepcopy(VECTOR)
        double_ptr_ty = ctx.float_ty.as_pointer()
        func_ty = ir.FunctionType(ir.VoidType(),
                                  (double_ptr_ty, ctx.int32_ty, double_ptr_ty))

        # Create clamp function
        custom_name = ctx.get_unique_name("clamp")
        function = ir.Function(ctx.module, func_ty, name=custom_name)
        vec, count, bounds = function.args
        block = function.append_basic_block(name="entry")
        builder = ir.IRBuilder(block)

        tst_min = builder.load(builder.gep(bounds, [ctx.int32_ty(0)]))
        tst_max = builder.load(builder.gep(bounds, [ctx.int32_ty(1)]))

        index = None
        with pnlvm.helpers.for_loop_zero_inc(builder, count,
                                             "linear") as (b1, index):
            val_ptr = b1.gep(vec, [index])
            val = b1.load(val_ptr)
            val = pnlvm.helpers.fclamp(b1, val, tst_min, tst_max)
            b1.store(val, val_ptr)

        builder.ret_void()

    ref = np.clip(VECTOR, TST_MIN, TST_MAX)
    bounds = np.asfarray([TST_MIN, TST_MAX])
    bin_f = pnlvm.LLVMBinaryFunction.get(custom_name)
    if mode == 'CPU':
        ct_ty = pnlvm._convert_llvm_ir_to_ctype(double_ptr_ty)
        ct_vec = local_vec.ctypes.data_as(ct_ty)
        ct_bounds = bounds.ctypes.data_as(ct_ty)

        bin_f(ct_vec, DIM_X, ct_bounds)
    else:
        bin_f.cuda_wrap_call(local_vec, np.int32(DIM_X), bounds)

    assert np.array_equal(local_vec, ref)
Example #25
0
 def declaracao_funcao(self, no):
     self.variaveis = self.variaveisGlobais
     args = []
     nomes = []
     if len(no.filhos) > 1:
         nome = no.filhos[1].valor
         self.escopo = nome
         if no.filhos[1].filhos[0] is not None:
             args = self.tipoDaFuncao(no.filhos[1].filhos[0], [])
             nomes = self.nomeDaFuncao(no.filhos[1].filhos[0], [])
         tipo = no.filhos[0].tipo
         if tipo == 'inteiro':
             t_func = ir.FunctionType(ir.IntType(32), (args))
         else:
             t_func = ir.FunctionType(ir.FloatType(), (args))
     else:
         nome = no.filhos[0].valor
         self.escopo = nome
         if no.filhos[0].filhos[0] is not None:
             args = self.tipoDaFuncao(no.filhos[0].filhos[0], [])
             nomes = self.nomeDaFuncao(no.filhos[0].filhos[0], [])
         t_func = ir.FunctionType(ir.VoidType(), (args))
     func = ir.Function(self.module, t_func, nome)
     self.funcs.append(func)
     argumentos_llvm = func.args
     self.funcllvm = func
     entryBlock = func.append_basic_block('entry' + nome)
     builder = ir.IRBuilder(entryBlock)
     for x in range(0, len(argumentos_llvm)):
         if str(argumentos_llvm[x].tipo) == 'i32':
             var = builder.alloca(ir.IntType(32), name=str(nomes[x]))
             var.align = 4
             self.variaveis.append(var)
         elif str(argumentos_llvm[x].tipo) == 'float':
             var = builder.alloca(ir.FloatType(), name=str(nomes[x]))
             var.align = 4
             self.variaveis.append(var)
     self.redirecionamentoDoNo(no, builder)
     endBasicBlock = func.append_basic_block('exit' + nome)
     self.endBlock = endBasicBlock
     self.retorna(no, builder)
Example #26
0
    def visitForexpr(self, ctx: sadbeepParser.ForexprContext):
        self.visitAssign(ctx.init())

        block_while = self.builder.append_basic_block(name='loop')
        block_next = self.builder.append_basic_block(name='next')

        self.builder.branch(block_while)  # End the current block

        # Switch contex for the loop block
        with self.builder.goto_block(block_while):
            if self.visit(ctx.expr()).type != self.visit(ctx.cond).type:
                raise TypeError(
                    f"{self.file_name} com erros na linha {ctx.start.line}:{ctx.start.column}"
                    f" ({ctx.getText()}). Tipos diferentes!")

            if self.visit(ctx.expr()).type.__class__ == ir.FloatType:
                zero = ir.Constant(ir.FloatType(), 0)
                result = self.builder.fcmp_unordered('<',
                                                     zero,
                                                     self.visit(ctx.cond),
                                                     name='tmp_w_cmp_float')
            elif self.visit(ctx.expr()).type.__class__ == ir.IntType:
                zero = ir.Constant(ir.IntType(32), 0)
                result = self.builder.icmp_signed('<',
                                                  zero,
                                                  self.visit(ctx.cond),
                                                  name='tmp_w_cmp_float')
            else:
                raise TypeError(
                    f"{self.file_name}:{ctx.start.line}:{ctx.start.column} - Tipo não reconhecido e/ou tratado!"
                )

            with self.builder.if_then(result):  # Execute if 0 < cond
                self.visit(ctx.block())  # Build while body
                self.visitAssign(ctx.finish())
                self.builder.branch(block_while)  # Loop
            self.builder.branch(block_next)  # End loop
        #################################

        self.builder = ir.IRBuilder(
            block_next)  # Set the builder for the next block out of the loop
Example #27
0
    def test_cache(self):
        def times2(i):
            return 2*i

        def times3(i):
            return i*3

        with self._context_builder_sig_args() as (
            context, builder, sig, args,
        ):
            # Ensure the cache is empty to begin with
            self.assertEqual(0, len(context.cached_internal_func))

            # After one compile, it should contain one entry
            context.compile_internal(builder, times2, sig, args)
            self.assertEqual(1, len(context.cached_internal_func))

            # After a second compilation of the same thing, it should still contain
            # one entry
            context.compile_internal(builder, times2, sig, args)
            self.assertEqual(1, len(context.cached_internal_func))

            # After compilation of another function, the cache should have grown by
            # one more.
            context.compile_internal(builder, times3, sig, args)
            self.assertEqual(2, len(context.cached_internal_func))

            sig2 = typing.signature(types.float64, types.float64)
            llvm_fnty2 = context.call_conv.get_function_type(sig2.return_type,
                                                            sig2.args)
            function2 = cgutils.get_or_insert_function(builder.module,
                                                       llvm_fnty2, 'test_fn_2')
            args2 = context.call_conv.get_arguments(function2)
            assert function2.is_declaration
            entry_block2 = function2.append_basic_block('entry')
            builder2 = ir.IRBuilder(entry_block2)

            # Ensure that the same function with a different signature does not
            # reuse an entry from the cache in error
            context.compile_internal(builder2, times3, sig2, args2)
            self.assertEqual(3, len(context.cached_internal_func))
Example #28
0
    def compile(self, module: ir.Module, builder: ir.IRBuilder,
                symbols: SymbolTable) -> ir.Value:
        if not self.compiled:
            self.compiled = True

            parameters = []
            for p in self.parameters:
                ir_type = p[1].ir_type
                if isinstance(p[1], Class):
                    ir_type = ir_type.as_pointer()

                parameters.append(ir_type)

            self.func_type = ir.FunctionType(self.ret_type.ir_type, parameters)

            self.func = ir.Function(module, self.func_type, name=self.ID)

            symbols = SymbolTable(parent=symbols)

            for i, p in enumerate(self.parameters):
                self.func.args[i].name = p[0]

                symbols.add_symbol(p[0], self.func.args[i])

            block = self.func.append_basic_block('entry')

            builder = ir.IRBuilder(block)

            self.block.compile(module, builder, symbols)

            block = builder.block
            if not builder.block.is_terminated:
                if self.ret_type == UnitType:
                    builder.ret_void()

                else:
                    builder.unreachable()

            return self.func
        else:
            return self.func
Example #29
0
    def visitFuncdef(self, ctx: EasyParser.FuncdefContext):
        """
        This function handles function traslation
        :param ctx:
        :return:
        """
        #It resets symbolic table -> so no global variables are allowed
        self.funcs_symtab.reset()
        funcname = str(ctx.NAME())
        param = utils.getVarArgList(ctx.varparameters().varargslist())
        arg_types = list(map(lambda x: x[1], param))

        functype = ir.FunctionType(utils.getDtype(ctx.d_type()), arg_types)

        if funcname in self.module.globals:
            utils.printError(ctx, "Function already declared")
            sys.exit(0)

        else:
            func = ir.Function(self.module, functype, funcname)

        entry = func.append_basic_block('entry')
        self.builder = ir.IRBuilder(entry)

        for i, arg in enumerate(func.args):
            alloca = self.alloc(*param[i])
            self.builder.store(arg, alloca)
            self.funcs_symtab.set(ctx, param[i][0], alloca)

        self.generateCode(ctx.block())  # Build the inner body of function

        if not self.builder.block.is_terminated:
            if functype.return_type == ir.VoidType():
                # if the function is void type, we automatcaly
                # add return void
                self.builder.ret_void()
            else:
                utils.printError(
                    ctx, "Function :{} is not terminated!!! "
                    "by  return statement".format(funcname))
                sys.exit(0)
Example #30
0
    def build_ir(self):
        assert not self.captured_context.is_terminated
        with self.captured_context.use_pos(self.ast.pos):
            if self.ast.is_extern:
                if self.captured_symbol_table.has_extern_func(
                        self.ast.identifier):
                    extern_concrete_func = self.captured_symbol_table.get_extern_func(
                        self.ast.identifier)
                    if not extern_concrete_func.has_same_signature_as(self):
                        raise_error(
                            'Cannot redefine extern func %r previously declared as %s with new signature %s'
                            %
                            (self.ast.identifier,
                             extern_concrete_func.signature.to_signature_str(),
                             self.signature.to_signature_str()), self.ast.pos)
                else:
                    self.captured_symbol_table.add_extern_func(
                        self.ast.identifier, self)
                return

            if self.ast.is_inline:
                # check symbol tables without emitting ir
                self.ast.build_body_ir(
                    parent_symbol_table=self.captured_symbol_table,
                    concrete_func=self,
                    body_context=self.captured_context.copy_without_builder())
            else:
                assert not self.is_inline
                if self.captured_context.emits_ir:
                    body_block = self.ir_func.append_basic_block(name='entry')
                    body_context = self.captured_context.copy_with_func(
                        self, builder=ir.IRBuilder(body_block))
                else:
                    body_context = self.captured_context.copy_with_func(
                        self, builder=None)  # proceed without emitting ir.
                self.ast.build_body_ir(
                    parent_symbol_table=self.captured_symbol_table,
                    concrete_func=self,
                    body_context=body_context,
                    ir_func_args=self.ir_func.args
                    if body_context.emits_ir else None)