Пример #1
0
def build_llvm(ast):

    assert (ast.get_node(ast.root).tag == "program")

    # Type dictionary used in parsing the AST
    type_dict = {
        "int": ir.IntType(8),  # Assuming 8 bit ints for testing
        "double": ir.DoubleType(),
        "void": ir.VoidType()
    }

    ir_funcs = {}  # Stores function objects for use when calling functions

    # Create module
    module = ir.Module(name="program")  # Module object stores all program data

    # Iterate through children of root
    for node in ast.children(ast.root):
        if (node.tag.index("func:") == 0):
            # Function definition found
            func_name = node.tag[5:]
            func_return = ""
            func_params = []

            # Iterate through node children to:
            #   Define type
            #   Define params
            #   Find body

            func_body = None  # Used to keep track of the func_body node

            for child in ast.children(node.identifier):
                if (child.tag == "return_type"):
                    func_return = ast.children(child.identifier)[0].tag
                    assert (len(func_return) > 0)

                elif (child.tag == "params"):
                    for param in ast.children(child.identifier):
                        param_type = param.tag
                        param_name = ast.children(param.identifier)[0].tag
                        func_params.append([param_type, param_name])

                elif (child.tag == "func_body"):
                    func_body = child

            assert (func_body is not None)  # Check that we found the func_body

            # Verify that types are known and update from strings to IR type objects
            if (func_return in type_dict):
                func_return = type_dict[func_return]
            else:
                raise Exception("Unknown Type: " + func_return)

            for param in func_params:
                if (param[0] in type_dict):
                    param[0] = type_dict[param[0]]
                else:
                    raise Exception("Unknown Type: " + param[0])

            # Create function in LLVM
            func_type = ir.FunctionType(
                func_return,  # Return type
                tuple([p[0] for p in func_params])  # Tuple of param types
            )

            function = ir.Function(module, func_type, name=func_name)
            ir_funcs[func_name] = function  # Store function object by name

            # Build function
            block = function.append_basic_block(
                name="entry")  # Create function block
            builder = ir.IRBuilder(
                block)  # Create builder object to work within block

            # FUNCTION IMPLEMENTATION BUILT HERE
            traversal_stack = []  # Used to traverse tree build node_stack
            node_stack = [
            ]  # Used to build function. Nodes pushed in level order, popped in reverse level order
            traversal_stack.append(func_body)

            while (len(traversal_stack) > 0):
                iter_node = traversal_stack.pop(
                )  # Get next node from traversal_stack
                node_stack.append(iter_node)  # Add current node to node_stack

                # Add children to the traversal_stack
                for child in ast.children(iter_node.identifier):
                    traversal_stack.append(child)

            # Use reverse level order traversal to build function by popping node_stack
            node_results = {
            }  # Used to keep track of IR results by node ID (intermediate steps)

            func_locals = {
            }  # Used to keep track of local variable names by node tag
            # dictionary key (node tag) is the variable's name in the parse tree
            # dictionary value is the variable's name generated by the IR builder

            # Begin reverse level order traversal of parse tree

            bin_ops = [
                '=', '+', '-', '*', '/', '%', '&&', '||', '<', '>', "<=", '>=',
                '==', '+=', '-=', '*=', '/=', '<<', '>>'
            ]
            una_ops = ['++', '--']

            while (len(node_stack) > 0):

                iter_node = node_stack.pop()
                '''
                TO DO:
                - Test unary operations
                - Flow control
                - Test variable assignment (=)
                - Constant types other than int or float?
                - Global variables?
                '''

                if (iter_node.tag == "func_body"):
                    # First node in subtree is just for finding the children
                    # Can be ignored in function building
                    pass
                elif (iter_node.tag in bin_ops):
                    # Binary operation

                    # Get operand node identifiers
                    child_l = ast.children(iter_node.identifier)[0].identifier
                    child_r = ast.children(iter_node.identifier)[1].identifier

                    # Get IR representations of operand nodes
                    operand_l = node_results[child_l]
                    operand_r = node_results[child_r]

                    result = None

                    if (iter_node.tag in ['+=', '-=', '*=', '/=', '%=', '=']):
                        # Local variables only exist in the builder and not the final IR
                        # Values are stored in the func_locals dictionary
                        #   Key = variable name as seen in iter_node.tag
                        #   Value = IR generated result from right hand of assignment
                        var_name = ast.children(iter_node.identifier)[0].tag

                        if (iter_node.tag in ['+=', '-=', '*=', '/=', '%=']):
                            # Get current value of left operand
                            if (var_name in func_locals):
                                operand_l = func_locals[var_name]

                            elif (var_name in [p[1] for p in func_params]):
                                operand_l = function.args[[
                                    p[1] for p in func_params
                                ].index(var_name)]

                            else:
                                assert (False)

                            # Evaluate right side operand
                            if (iter_node.tag == '+='):
                                operand_r = builder.fadd(operand_l, operand_r)

                            elif (iter_node.tag == '-='):
                                operand_r = builder.fsub(operand_l, operand_r)

                            elif (iter_node.tag == '*='):
                                operand_r = builder.fmul(operand_l, operand_r)

                            elif (iter_node.tag == '/='):
                                operand_r = builder.fdiv(operand_l, operand_r)

                            elif (iter_node.tag == '%='):
                                operand_r = builder.frem(operand_l, operand_r)

                        # Assign new value where appropriate
                        if (var_name in func_locals):
                            # Assigning new value to existing local variable
                            func_locals[var_name] = operand_r

                        elif (var_name in [p[1] for p in func_params]):
                            # Assigning new value to function parameter
                            # Create "copy" of parameter as local variable
                            func_locals[var_name] = operand_r

                        else:
                            # Defining new local variable
                            func_locals[var_name] = operand_r

                    elif (iter_node.tag == '+'):
                        result = builder.fadd(operand_l, operand_r)

                    elif (iter_node.tag == '-'):
                        result = builder.fsub(operand_l, operand_r)

                    elif (iter_node.tag == '*'):
                        result = builder.fmul(operand_l, operand_r)

                    elif (iter_node.tag == '/'):
                        result = builder.fdiv(operand_l, operand_r)

                    elif (iter_node.tag == '%'):
                        result = builder.frem(operand_l, operand_r)

                    elif (iter_node.tag == '&&'):
                        # Must be implmemented using other operators
                        # (x && y) is equivialent to ((x * y) != 0)
                        step_1 = builder.fmul(operand_l, operand_r)
                        step_2 = ir.Constant(type_dict["int"], 0)
                        result = builder.icmp_signed('!=', step_1, step_2)

                    elif (iter_node.tag == '||'):
                        # Must be implmemented using other operators
                        # (x || y) is equivialent to ((x + y)+(x * y) != 0)
                        step_1 = builder.fadd(operand_l, operand_r)
                        step_2 = builder.fmul(operand_l, operand_r)
                        step_3 = builder.fadd(step_1, step_2)
                        step_4 = ir.Constant(type_dict["int"], 0)
                        result = builder.icmp_signed('!=', step_3, step_4)

                    elif (iter_node.tag in ['<', '>', '<=', '>=', '==', '!=']):
                        result = builder.icmp_signed(iter_node.tag, operand_l,
                                                     operand_r)
                        # This is the signed comparison.
                        # There's also an unsigned comparison if we care about that

                    elif (iter_node.tag == '<<'):
                        result = builder.shl(operand_l, operand_r)

                    elif (iter_node.tag == '>>'):
                        # Using arithmetic right shift (C/C++ norm) instead of logical shift
                        result = builder.ashr(operand_l, operand_r)

                    assert (
                        result is not None
                    )  # Verify that one of the above cases was satisfied
                    node_results[
                        iter_node.identifier] = result  # Store IR result

                elif (iter_node.tag in una_ops):
                    # Unary operation

                    # Get operand node identifiers
                    child = ast.children(iter_node.identifier)[0].identifier
                    # Get IR representations of operand nodes
                    operand = node_results[child]
                    var_name = ast.children(iter_node.identifier)[0].tag

                    result = None

                    # Construct arithmetic statement
                    if (iter_node.tag in ['++', '--']):
                        print(
                            "Unary Ops: ++ and -- modify value but act like assignment"
                        )

                        # Get current value of left operand
                        if (var_name in func_locals):
                            operand = func_locals[var_name]
                        elif (var_name in [p[1] for p in func_params]):
                            operand = function.args[[
                                p[1] for p in func_params
                            ].index(var_name)]
                        else:
                            assert (False)

                        if (iter_node.tag == '++'):
                            result = builder.fadd(
                                operand, ir.Constant(type_dict["int"], 1))

                        elif (iter_node.tag == '--'):
                            result = builder.fsub(
                                operand, ir.Constant(type_dict["int"], 1))

                        assert (result is not None)

                        # Assign new value where appropriate
                        if (var_name in func_locals):
                            # Assigning new value to existing local variable
                            func_locals[var_name] = operand_r

                        elif (var_name in [p[1] for p in func_params]):
                            # Assigning new value to function parameter
                            # Create "copy" of parameter as local variable
                            func_locals[var_name] = operand_r

                        else:
                            # Defining new local variable
                            func_locals[var_name] = operand_r

                    assert (
                        result is not None
                    )  # Verify that one of the above cases was satisfied
                    node_results[
                        iter_node.identifier] = result  # Store IR result

                elif (iter_node.tag == 'return'):
                    if (len(ast.children(iter_node.identifier)) == 0):
                        # Void return
                        assert (func_return == type_dict["void"])
                        builder.ret_void()
                    else:
                        # Returning an expression
                        child_id = ast.children(
                            iter_node.identifier)[0].identifier
                        result = node_results[child_id]
                        builder.ret(result)
                else:
                    # Node is either a constant, variable ID, or function call
                    if (iter_node.tag in ir_funcs):
                        # Function call
                        arg_list = []
                        for child in ast.children(iter_node.identifier):
                            arg_list.append(node_results[child.identifier])

                        builder.call(ir_funcs[iter_node.tag], arg_list)

                    else:
                        # Constant or variable
                        assert (len(ast.children(iter_node.identifier)) == 0)

                        var_type = ""
                        is_numeral = uf.IsInt(
                            iter_node.tag)  # if true, then int

                        if (is_numeral):
                            var_type = "int"
                        else:
                            try:
                                float(iter_node.tag)
                                var_type = "float"
                                is_numeral = True
                            except:
                                pass

                        if (is_numeral):
                            # Constant
                            assert (len(var_type) > 0)
                            assert (type_dict[var_type] is not None)

                            constant = 0
                            if (var_type == "int"):
                                constant = int(iter_node.tag)
                            elif (var_type == "float"):
                                constant = float(iter_node.tag)
                            else:
                                print("Unaccounted for type")

                            result = ir.Constant(type_dict[var_type], constant)

                        else:
                            # Variable
                            if (iter_node.tag
                                    not in [p[1] for p in func_params]):
                                # Local variable

                                # NOTE: Check locals first because arguments
                                # that are changed by assignment are copied to
                                # local variables, so thats where the most up
                                # to date value will be stroed

                                result = func_locals[iter_node.tag]
                            else:
                                # Function argument
                                result = function.args[[
                                    p[1] for p in func_params
                                ].index(iter_node.tag)]

                    node_results[iter_node.identifier] = result

        elif (True):
            print("Handle case for global variables")

    # Return LLVM module
    return module
Пример #2
0
    def generate_kernel_wrapper(self, library, fndesc, kernel_name, debug,
                                filename, linenum):
        """
        Generate the kernel wrapper in the given ``library``.
        The function being wrapped is described by ``fndesc``.
        The wrapper function is returned.
        """

        argtypes = fndesc.argtypes
        arginfo = self.get_arg_packer(argtypes)
        argtys = list(arginfo.argument_types)
        wrapfnty = ir.FunctionType(ir.VoidType(), argtys)
        wrapper_module = self.create_module("cuda.kernel.wrapper")
        fnty = ir.FunctionType(
            ir.IntType(32),
            [self.call_conv.get_return_type(types.pyobject)] + argtys)
        func = ir.Function(wrapper_module, fnty, fndesc.llvm_func_name)

        prefixed = itanium_mangler.prepend_namespace(func.name, ns='cudapy')
        wrapfn = ir.Function(wrapper_module, wrapfnty, prefixed)
        builder = ir.IRBuilder(wrapfn.append_basic_block(''))

        if debug:
            debuginfo = self.DIBuilder(
                module=wrapper_module,
                filepath=filename,
                cgctx=self,
            )
            debuginfo.mark_subprogram(
                wrapfn,
                kernel_name,
                fndesc.args,
                argtypes,
                linenum,
            )
            debuginfo.mark_location(builder, linenum)

        # Define error handling variable
        def define_error_gv(postfix):
            name = wrapfn.name + postfix
            gv = cgutils.add_global_variable(wrapper_module, ir.IntType(32),
                                             name)
            gv.initializer = ir.Constant(gv.type.pointee, None)
            return gv

        gv_exc = define_error_gv("__errcode__")
        gv_tid = []
        gv_ctaid = []
        for i in 'xyz':
            gv_tid.append(define_error_gv("__tid%s__" % i))
            gv_ctaid.append(define_error_gv("__ctaid%s__" % i))

        callargs = arginfo.from_arguments(builder, wrapfn.args)
        status, _ = self.call_conv.call_function(builder, func, types.void,
                                                 argtypes, callargs)

        if debug:
            # Check error status
            with cgutils.if_likely(builder, status.is_ok):
                builder.ret_void()

            with builder.if_then(builder.not_(status.is_python_exc)):
                # User exception raised
                old = ir.Constant(gv_exc.type.pointee, None)

                # Use atomic cmpxchg to prevent rewriting the error status
                # Only the first error is recorded

                if nvvm.NVVM().is_nvvm70:
                    xchg = builder.cmpxchg(gv_exc, old, status.code,
                                           'monotonic', 'monotonic')
                    changed = builder.extract_value(xchg, 1)
                else:
                    casfnty = ir.FunctionType(
                        old.type, [gv_exc.type, old.type, old.type])

                    cas_hack = "___numba_atomic_i32_cas_hack"
                    casfn = ir.Function(wrapper_module, casfnty, name=cas_hack)
                    xchg = builder.call(casfn, [gv_exc, old, status.code])
                    changed = builder.icmp_unsigned('==', xchg, old)

                # If the xchange is successful, save the thread ID.
                sreg = nvvmutils.SRegBuilder(builder)
                with builder.if_then(changed):
                    for dim, ptr, in zip("xyz", gv_tid):
                        val = sreg.tid(dim)
                        builder.store(val, ptr)

                    for dim, ptr, in zip("xyz", gv_ctaid):
                        val = sreg.ctaid(dim)
                        builder.store(val, ptr)

        builder.ret_void()

        nvvm.set_cuda_kernel(wrapfn)
        library.add_ir_module(wrapper_module)
        if debug:
            debuginfo.finalize()
        library.finalize()
        wrapfn = library.get_function(wrapfn.name)
        return wrapfn
Пример #3
0
 def _declare_print(self):
     voidptr_type = ir.IntType(8).as_pointer()
     printf_type = ir.FunctionType(ir.IntType(32), [voidptr_type],
                                   var_arg=True)
     ir.Function(self.module, printf_type, name='printf')
Пример #4
0
def _seed_impl(context, builder, sig, args, state_ptr):
    seed_value, = args
    fnty = ir.FunctionType(ir.VoidType(), (rnd_state_ptr_t, int32_t))
    fn = builder.function.module.get_or_insert_function(fnty, "numba_rnd_init")
    builder.call(fn, (state_ptr, seed_value))
    return context.get_constant(types.none, None)
Пример #5
0
def define_bool_to_str(self, dyn_array_ptr):
    # START
    func_type = ir.FunctionType(type_map[VOID],
                                [dyn_array_ptr, type_map[BOOL]])
    func = ir.Function(self.module, func_type, 'bool_to_str')
    entry_block = func.append_basic_block('entry')
    builder = ir.IRBuilder(entry_block)
    self.builder = builder
    exit_block = func.append_basic_block('exit')
    array_ptr = builder.alloca(dyn_array_ptr)
    builder.store(func.args[0], array_ptr)

    # BODY
    equalszero = builder.icmp_signed(EQUALS, func.args[1],
                                     ir.Constant(type_map[BOOL], 0))
    dyn_array_append = self.module.get_global('i64_array_append')

    with builder.if_else(equalszero) as (then, otherwise):
        with then:
            builder.call(
                dyn_array_append,
                [builder.load(array_ptr),
                 ir.Constant(type_map[INT], 102)])
            builder.call(
                dyn_array_append,
                [builder.load(array_ptr),
                 ir.Constant(type_map[INT], 97)])
            builder.call(
                dyn_array_append,
                [builder.load(array_ptr),
                 ir.Constant(type_map[INT], 108)])
            builder.call(
                dyn_array_append,
                [builder.load(array_ptr),
                 ir.Constant(type_map[INT], 115)])
            builder.call(
                dyn_array_append,
                [builder.load(array_ptr),
                 ir.Constant(type_map[INT], 101)])
        with otherwise:
            builder.call(
                dyn_array_append,
                [builder.load(array_ptr),
                 ir.Constant(type_map[INT], 116)])
            builder.call(
                dyn_array_append,
                [builder.load(array_ptr),
                 ir.Constant(type_map[INT], 114)])
            builder.call(
                dyn_array_append,
                [builder.load(array_ptr),
                 ir.Constant(type_map[INT], 117)])
            builder.call(
                dyn_array_append,
                [builder.load(array_ptr),
                 ir.Constant(type_map[INT], 101)])

    builder.branch(exit_block)

    # CLOSE
    builder.position_at_end(exit_block)
    builder.ret_void()
Пример #6
0
def dict_empty_int32(context, builder, fromty, toty, val):
    fnty = lir.FunctionType(lir.IntType(1), [lir.IntType(8).as_pointer()])
    fn = builder.module.get_or_insert_function(
        fnty, name="dict_int32_int32_not_empty")
    return builder.call(fn, (val, ))
Пример #7
0
 def function(self, module=None, name='my_func'):
     module = module or self.module()
     fnty = ir.FunctionType(int32, (int32, int32, dbl, ir.PointerType(int32)))
     return ir.Function(self.module(), fnty, name)
Пример #8
0
import llvmlite.ir as ir
Пример #9
0
 def ll_type(self):
     args = [a.ll_type() for a in self.arg_types]
     return ll.FunctionType(self.ret_type.ll_type(), args)
Пример #10
0
    import faulthandler
    faulthandler.enable()
except ImportError:
    pass

llvm.initialize()
llvm.initialize_native_target()
llvm.initialize_native_asmprinter()

i8 = ll.IntType(8)
i32 = ll.IntType(32)
i64 = ll.IntType(64)

MEMORY_SIZE = 1 << 16

COMPILED_FN_TYPE = ll.FunctionType(ll.VoidType(), [])
MEMORY_TYPE = ll.ArrayType(i8, MEMORY_SIZE)

ZERO_i8 = ll.Constant(i8, 0)
ZERO_i32 = ll.Constant(i8, 0)
ONE_i8 = ll.Constant(i8, 1)
ONE_i32 = ll.Constant(i32, 1)
MEMORY_MASK_i32 = ll.Constant(i32, MEMORY_SIZE - 1)


def getc():
    return sys.stdin.read(1)


def putc(c):
    sys.stdout.write(chr(c & 0x7f))
Пример #11
0
def compile_bf(prog):
    """
    Compiles the given BF program text into a llvm.ModuleRef object.

    The module will contain 3 globals:
        - the main function, void bfmain()
        - the memory, int8_t memory[]
        - the memory index, int32_t index
    """
    module = ll.Module()
    func = ll.Function(module, ll.FunctionType(ll.VoidType(), []), 'bfmain')
    builder = ll.IRBuilder()
    g_memory = ll.GlobalVariable(module, MEMORY_TYPE, 'memory')
    g_index = ll.GlobalVariable(module, i32, 'index')

    # Initialize the memory and index pointer to 0.
    g_memory.initializer = ll.Constant(MEMORY_TYPE, None)
    g_index.initializer = ll.Constant(i32, None)

    # Create the "putc" function.
    putc_type = ll.FunctionType(ll.VoidType(), [i8])
    getc_type = ll.FunctionType(i8, [])
    f_putc = create_thunk(module, putc_type, PUTC_WRAPPER, 'putc')
    f_getc = create_thunk(module, getc_type, GETC_WRAPPER, 'getc')

    # The block_stack tracks the current block and remaining blocks. The top
    # block is what we currently compile into, the one below it is the block
    # that follows the next ] (if we're in a loop).
    block_stack = [func.append_basic_block('entry')]
    loop_stack = []
    builder.position_at_end(block_stack[-1])

    def current_index_ptr():
        index = builder.load(g_index)
        # The extra dereference here with ZERO is required because g_memory is
        # itself a pointer, so this becomes &g_memory[0][index]. Yeah, it's
        # weird.
        # Ref: https://llvm.org/docs/GetElementPtr.html
        return builder.gep(g_memory, [ZERO_i32, index])

    line = 1
    col = 1
    for ch in prog:
        col += 1
        if ch == '\n':
            col = 1
            line += 1

        elif ch == '.':
            ptr = current_index_ptr()
            value = builder.load(ptr)
            builder.call(f_putc, [value])

        elif ch == ',':
            res = builder.call(f_getc, [])
            ptr = current_index_ptr()
            builder.store(res, ptr)

        elif ch == '>':
            # builder.call(f_putc, [ll.Constant(i8, ord('>'))])
            index = builder.load(g_index)
            index = builder.add(index, ONE_i32)
            index = builder.and_(index, MEMORY_MASK_i32)
            builder.store(index, g_index)

        elif ch == '<':
            # builder.call(f_putc, [ll.Constant(i8, ord('<'))])
            index = builder.load(g_index)
            index = builder.sub(index, ONE_i32)
            index = builder.and_(index, MEMORY_MASK_i32)
            builder.store(index, g_index)

        elif ch == '+':
            # builder.call(f_putc, [ll.Constant(i8, ord('+'))])
            ptr = current_index_ptr()
            value = builder.load(ptr)
            value = builder.add(value, ONE_i8)
            builder.store(value, ptr)

        elif ch == '-':
            # builder.call(f_putc, [ll.Constant(i8, ord('-'))])
            ptr = current_index_ptr()
            value = builder.load(ptr)
            value = builder.sub(value, ONE_i8)
            builder.store(value, ptr)

        elif ch == '[':  # start a loop
            # builder.call(f_putc, [ll.Constant(i8, ord('['))])
            loop_block = func.append_basic_block()
            tail_block = func.append_basic_block()

            # If memory[index] != 0, enter loop, otherwise skip.
            ptr = current_index_ptr()
            value = builder.load(ptr)
            nonzero = builder.icmp_unsigned('!=', value, ZERO_i8)
            builder.cbranch(nonzero, loop_block, tail_block)

            # Update our block stack. The current block is finished.
            block_stack.pop()
            block_stack.append(tail_block)
            block_stack.append(loop_block)
            loop_stack.append(loop_block)
            builder.position_at_end(block_stack[-1])

        elif ch == ']':  # end a loop
            # builder.call(f_putc, [ll.Constant(i8, ord(']'))])
            if len(block_stack) <= 1:
                raise ValueError('{}:{}: unmatched ]'.format(line, col))

            # If memory[index] != 0, repeat current loop, otherwise break.
            ptr = current_index_ptr()
            value = builder.load(ptr)
            nonzero = builder.icmp_unsigned('!=', value, ZERO_i8)
            builder.cbranch(nonzero, loop_stack[-1], block_stack[-2])

            # Update our block stack. The current block is finished.
            block_stack.pop()
            loop_stack.pop()
            builder.position_at_end(block_stack[-1])

        else:
            continue

    if len(block_stack) != 1:
        raise ValueError('{}:{}: unmatched ['.format(line, col))

    # Finish the function.
    builder.ret_void()

    assembly = str(module)
    # print(assembly)

    return llvm.parse_assembly(assembly)
Пример #12
0
    def _codegen_Prototype(self, node):
        funcname = node.name

        # Create a function type

        vartypes = []
        vartypes_with_defaults = []

        append_to = vartypes

        for x in node.argnames:
            s = x.vartype
            if x.initializer is not None:
                append_to = vartypes_with_defaults
            append_to.append(s)

        # TODO: it isn't yet possible to have an implicitly
        # typed function that just uses the return type of the body
        # we might be able to do this by way of a special call
        # to this function
        # note that Extern functions MUST be typed

        if node.vartype is None:
            node.vartype = self.vartypes._DEFAULT_TYPE

        functype = ir.FunctionType(node.vartype,
                                   vartypes + vartypes_with_defaults)

        public_name = funcname

        opt_args = None

        linkage = None

        # TODO: identify anonymous functions with a property
        # not by way of their nomenclature

        if node.extern is False and not funcname.startswith(
                '_ANONYMOUS.') and funcname != 'main':
            linkage = 'private'
            if len(vartypes) > 0:
                funcname = public_name + mangle_args(vartypes)
            else:
                funcname = public_name + '@'

            required_args = funcname

            if len(vartypes_with_defaults) > 0:
                opt_args = mangle_optional_args(vartypes_with_defaults)
                funcname += opt_args

        # If a function with this name already exists in the module...
        if funcname in self.module.globals:

            # We only allow the case in which a declaration exists and now the
            # function is defined (or redeclared) with the same number of args.

            func = existing_func = self.module.globals[funcname]

            if not isinstance(existing_func, ir.Function):
                raise CodegenError(
                    f'Function/universal name collision {funcname}',
                    node.position)

            # If we're redefining a forward declaration,
            # erase the existing function body

            if not existing_func.is_declaration:
                existing_func.blocks = []

            if len(existing_func.function_type.args) != len(functype.args):
                raise CodegenError(
                    f'Redefinition of function "{public_name}" with different number of arguments',
                    node.position)
        else:
            # Otherwise create a new function

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

            # Name the arguments
            for i, arg in enumerate(func.args):
                arg.name = node.argnames[i].name

        if opt_args is not None:
            self.opt_args_funcs[required_args] = func

        # Set defaults (if any)

        for x, n in enumerate(node.argnames):
            if n.initializer is not None:
                func.args[x].default_value = self._codegen(
                    n.initializer, False)

        if node.varargs:
            func.ftype.var_arg = True

        func.public_name = public_name

        func.returns = []

        ##############################################################
        # Set LLVM function attributes
        ##############################################################

        # First, extract a copy of the function decorators
        # and use that to set up other attributes

        decorators = [n.name for n in self.func_decorators]

        varfunc = 'varfunc' in decorators

        for a, b in decorator_collisions:
            if a in decorators and b in decorators:
                raise CodegenError(
                    f'Function cannot be decorated with both "@{a}" and "@{b}"',
                    node.position)

        # Calling convention.
        # This is the default with no varargs

        if node.varargs is None:
            if not node.extern:
                func.calling_convention = 'fastcc'

        # Linkage.
        # Default is 'private' if it's not extern, an anonymous function, or main

        if linkage:
            func.linkage = linkage

        # Address is not relevant by default
        func.unnamed_addr = True

        # Enable optnone for main() or anything
        # designated as a target for a function pointer.
        if funcname == 'main' or varfunc:
            func.attributes.add('optnone')
            func.attributes.add('noinline')

        # Inlining. Operator functions are inlined by default.

        if (
                # function is manually inlined
            ('inline' in decorators) or
                # function is an operator, not @varfunc,
                # and not @noinline
            (node.isoperator and not varfunc and 'noinline' not in decorators
             )):
            func.attributes.add('alwaysinline')

        # function is @noinline
        # or function is @varfunc
        if 'noinline' in decorators:
            func.attributes.add('noinline')

        # End inlining.

        # External calls, by default, no recursion
        if node.extern:
            func.attributes.add('norecurse')
            func.linkage = 'dllimport'

        # By default, no lazy binding
        func.attributes.add('nonlazybind')

        # By default, no stack unwinding
        func.attributes.add('nounwind')

        func.decorators = decorators

        return func
Пример #13
0
	int soma = (x + y);
	int subtracao = (x - y);
	int multiplicacao = (x * y);
	int divisao = (x / y);
	int modulo = (x % y);
	int shiftDireita = (x >> 1);
	int shiftEsquerda = (x << 1);
    return 0;
}
'''

# Cria o módulo.
module = ir.Module('meu_modulo.bc')
module.triple = binding.get_default_triple()

main_ftype = ir.FunctionType(ir.IntType(32), ())
main_func = ir.Function(module, main_ftype, 'main')

entry_block = main_func.append_basic_block('entry')
exit_block = main_func.append_basic_block('exit')

builder = ir.IRBuilder(entry_block)

return_val = builder.alloca(ir.IntType(32), name='ret_val')
builder.store(value=ir.Constant(ir.IntType(32), 0), ptr=return_val, align=4)

x = builder.alloca(ir.IntType(32), name='x')
builder.store(value=ir.Constant(ir.IntType(32), 2), ptr=x, align=4)
y = builder.alloca(ir.IntType(32), name='y')
builder.store(value=ir.Constant(ir.IntType(32), 1), ptr=y, align=4)
Пример #14
0
listVariables = {"global": []}
listaFuncs = {}

llvm.initialize()
llvm.initialize_all_targets()
llvm.initialize_native_target()
llvm.initialize_native_asmprinter()

module = ir.Module('module.bc')
module.triple = "x86_64-pc-linux-gnu" #llvm.get_default_triple()
target = llvm.Target.from_triple(module.triple)
target_machine = target.create_target_machine()
module.data_layout = target_machine.target_data

escrevaInteiro = ir.Function(module,ir.FunctionType(ir.VoidType(), [ir.IntType(32)]),name="escrevaInteiro")
escrevaFlutuante = ir.Function(module,ir.FunctionType(ir.VoidType(),[ir.FloatType()]),name="escrevaFlutuante")
leiaInteiro = ir.Function(module,ir.FunctionType(ir.IntType(32),[]),name="leiaInteiro")
leiaFlutuante = ir.Function(module,ir.FunctionType(ir.FloatType(),[]),name="leiaFlutuante")

def splite_tree(node):
    if len(node.children) >= 1:
        listOfParents.append(node)
        for i in node.children:
            splite_tree(i)
    else:
        listOfTerminals.append(node)

def splite_node_tree(node):
    tempListOfParents.clear()
    tempListOfTerminals.clear()
Пример #15
0
def impl_dict_int32_int32(context, builder, sig, args):
    fnty = lir.FunctionType(lir.IntType(8).as_pointer(), [])
    fn = builder.module.get_or_insert_function(fnty,
                                               name="dict_int32_int32_init")
    return builder.call(fn, [])
Пример #16
0
typeA = ir.ArrayType(ir.IntType(64), 1024)

arrayA = ir.GlobalVariable(module, typeA, "A")

# arrayA.initializer = ir.IntType(64)
arrayA.linkage = "common"
# arrayA.initializer = ir.Constant(ir.IntType(64), 0)
arrayA.align = 16

# Cria um valor zero para colocar no retorno.
Zero64 = ir.Constant(ir.IntType(64), 0)

# Declara o tipo do retorno da função main.
mainFnReturnType = ir.IntType(64)
# Cria a função main.
t_func_main = ir.FunctionType(mainFnReturnType, ())

# Declara a função main.
main = ir.Function(module, t_func_main, name='main')

# Declara o bloco de entrada.
entryBlock = main.append_basic_block('entry')
endBasicBlock = main.append_basic_block('exit')

# Adiciona o bloco de entrada.
builder = ir.IRBuilder(entryBlock)

# Cria o valor de retorno e inicializa com zero.
returnVal = builder.alloca(ir.IntType(64), name='retorno')
builder.store(Zero64, returnVal)
Пример #17
0
def lower_dict_max_int32(context, builder, sig, args):
    fnty = lir.FunctionType(lir.IntType(32), [lir.IntType(8).as_pointer()])
    fn = builder.module.get_or_insert_function(fnty,
                                               name="dict_int32_int32_max")
    return builder.call(fn, args)
Пример #18
0
def dist_get_time(context, builder, sig, args):
    fnty = lir.FunctionType(lir.DoubleType(), [])
    fn = builder.module.get_or_insert_function(fnty, name="hpat_get_time")
    return builder.call(fn, [])
Пример #19
0
import sys
from collections import namedtuple

import llvmlite.ir as ir
import llvmlite.binding as llvm

from ctypes import CFUNCTYPE

# main (and only) module
module = ir.Module()

# main (and only) function
func_t = ir.FunctionType(ir.VoidType(), [])
func = ir.Function(module, func_t, "func")

# entry point of func
bb_entry = func.append_basic_block('entry')
irbuilder = ir.IRBuilder(bb_entry)

# memory size
NUM_CELLS = 30000

# Types
cell_t = ir.IntType(8)
pcell_t = cell_t.as_pointer()
memory_t = ir.ArrayType(cell_t, NUM_CELLS)
int32_t = ir.IntType(32)

# Constants
zero = cell_t(0)
one = cell_t(1)
Пример #20
0
def lower_dist_wait(context, builder, sig, args):
    fnty = lir.FunctionType(lir.IntType(32), [lir.IntType(32), lir.IntType(1)])
    fn = builder.module.get_or_insert_function(fnty, name="hpat_dist_wait")
    return builder.call(fn, args)
Пример #21
0
def pq_size_lower(context, builder, sig, args):
    fnty = lir.FunctionType(lir.IntType(64),
                            [lir.IntType(8).as_pointer(),
                             lir.IntType(64)])
    fn = builder.module.get_or_insert_function(fnty, name="pq_get_size")
    return builder.call(fn, args)
Пример #22
0
def dist_get_size(context, builder, sig, args):
    fnty = lir.FunctionType(lir.IntType(32), [])
    fn = builder.module.get_or_insert_function(fnty, name="hpat_dist_get_size")
    return builder.call(fn, [])
Пример #23
0
def dynamic_array_set(self, dyn_array_ptr, array_type):
    # START
    dyn_array_set_type = ir.FunctionType(
        type_map[VOID],
        [dyn_array_ptr, type_map[INT], llvm_type_map[array_type]])
    dyn_array_set = ir.Function(self.module, dyn_array_set_type,
                                '{}_array_set'.format(array_type))
    dyn_array_set_entry = dyn_array_set.append_basic_block('entry')
    builder = ir.IRBuilder(dyn_array_set_entry)
    self.builder = builder
    dyn_array_set_exit = dyn_array_set.append_basic_block('exit')
    dyn_array_set_index_out_of_bounds = dyn_array_set.append_basic_block(
        'index_out_of_bounds')
    dyn_array_set_is_index_less_than_zero = dyn_array_set.append_basic_block(
        'is_index_less_than_zero')
    dyn_array_set_negative_index = dyn_array_set.append_basic_block(
        'negative_index')
    dyn_array_set_block = dyn_array_set.append_basic_block('set')
    builder.position_at_end(dyn_array_set_entry)
    array_ptr = builder.alloca(dyn_array_ptr)
    builder.store(dyn_array_set.args[0], array_ptr)
    index_ptr = builder.alloca(type_map[INT])
    builder.store(dyn_array_set.args[1], index_ptr)
    value_ptr = builder.alloca(llvm_type_map[array_type])
    builder.store(dyn_array_set.args[2], value_ptr)

    # BODY
    index_val = builder.load(index_ptr)

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

    compare_index_to_size = builder.icmp_signed(GREATER_THAN_OR_EQUAL_TO,
                                                index_val, size_val)

    builder.cbranch(compare_index_to_size, dyn_array_set_index_out_of_bounds,
                    dyn_array_set_is_index_less_than_zero)

    builder.position_at_end(dyn_array_set_index_out_of_bounds)
    self.print_string('Array index out of bounds')
    builder.call(self.module.get_global('exit'), [one_32])
    builder.unreachable()

    builder.position_at_end(dyn_array_set_is_index_less_than_zero)

    compare_index_to_zero = builder.icmp_signed(LESS_THAN, index_val, zero)

    builder.cbranch(compare_index_to_zero, dyn_array_set_negative_index,
                    dyn_array_set_block)

    builder.position_at_end(dyn_array_set_negative_index)

    add = builder.add(size_val, index_val)
    builder.store(add, index_ptr)
    builder.branch(dyn_array_set_block)

    builder.position_at_end(dyn_array_set_block)

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

    add_1 = builder.add(one, index_val)
    builder.store(add_1, index_ptr)
    index_val = builder.load(index_ptr)

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

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

    builder.branch(dyn_array_set_exit)

    # CLOSE
    builder.position_at_end(dyn_array_set_exit)
    builder.ret_void()
Пример #24
0
def lower_open_bag(context, builder, sig, args):
    fnty = lir.FunctionType(lir.IntType(8).as_pointer(),
                            [lir.IntType(8).as_pointer()])
    fn = builder.module.get_or_insert_function(fnty, name="open_bag")
    return builder.call(fn, args)
Пример #25
0
 def function(res, args, var_arg=False):
     return ir.FunctionType(res, args, var_arg=var_arg)
Пример #26
0
def lower_get_msg_count(context, builder, sig, args):
    fnty = lir.FunctionType(lir.IntType(64),
                            [lir.IntType(8).as_pointer()])
    fn = builder.module.get_or_insert_function(fnty, name="get_msg_count")
    return builder.call(fn, args)
Пример #27
0
 def _declare_print_function(self):
     # Declare Printf function
     voidptr_ty = ir.IntType(8).as_pointer()
     printf_ty = ir.FunctionType(ir.IntType(32), [voidptr_ty], var_arg=True)
     printf = ir.Function(self.module, printf_ty, name="printf")
     self.printf = printf
Пример #28
0
def _randrange_impl(context, builder, start, stop, step, state):
    state_ptr = get_state_ptr(context, builder, state)
    ty = stop.type
    zero = ir.Constant(ty, 0)
    one = ir.Constant(ty, 1)
    nptr = cgutils.alloca_once(builder, ty, name="n")
    # n = stop - start
    builder.store(builder.sub(stop, start), nptr)

    with builder.if_then(builder.icmp_signed("<", step, zero)):
        # n = (n + step + 1) // step
        w = builder.add(builder.add(builder.load(nptr), step), one)
        n = builder.sdiv(w, step)
        builder.store(n, nptr)
    with builder.if_then(builder.icmp_signed(">", step, one)):
        # n = (n + step - 1) // step
        w = builder.sub(builder.add(builder.load(nptr), step), one)
        n = builder.sdiv(w, step)
        builder.store(n, nptr)

    n = builder.load(nptr)
    with cgutils.if_unlikely(builder, builder.icmp_signed("<=", n, zero)):
        # n <= 0
        msg = "empty range for randrange()"
        context.call_conv.return_user_exc(builder, ValueError, (msg, ))

    fnty = ir.FunctionType(ty, [ty, cgutils.true_bit.type])
    fn = builder.function.module.get_or_insert_function(
        fnty, "llvm.ctlz.%s" % ty)
    # Since the upper bound is exclusive, we need to subtract one before
    # calculating the number of bits. This leads to a special case when
    # n == 1; there's only one possible result, so we don't need bits from
    # the PRNG. This case is handled separately towards the end of this
    # function. CPython's implementation is simpler and just runs another
    # iteration of the while loop when the resulting number is too large
    # instead of subtracting one, to avoid needing to handle a special
    # case. Thus, we only perform this subtraction for the NumPy case.
    nm1 = builder.sub(n, one) if state == "np" else n
    nbits = builder.trunc(builder.call(fn, [nm1, cgutils.true_bit]), int32_t)
    nbits = builder.sub(ir.Constant(int32_t, ty.width), nbits)

    rptr = cgutils.alloca_once(builder, ty, name="r")

    def get_num():
        bbwhile = builder.append_basic_block("while")
        bbend = builder.append_basic_block("while.end")
        builder.branch(bbwhile)

        builder.position_at_end(bbwhile)
        r = get_next_int(context, builder, state_ptr, nbits, state == "np")
        r = builder.trunc(r, ty)
        too_large = builder.icmp_signed(">=", r, n)
        builder.cbranch(too_large, bbwhile, bbend)

        builder.position_at_end(bbend)
        builder.store(r, rptr)

    if state == "np":
        # Handle n == 1 case, per previous comment.
        with builder.if_else(builder.icmp_signed("==", n,
                                                 one)) as (is_one, is_not_one):
            with is_one:
                builder.store(zero, rptr)
            with is_not_one:
                get_num()
    else:
        get_num()

    return builder.add(start, builder.mul(builder.load(rptr), step))
Пример #29
0
llvm.initialize()
llvm.initialize_all_targets()
llvm.initialize_native_target()
llvm.initialize_native_asmprinter()

modulo = ir.Module('module.bc')
modulo.triple = llvm.get_default_triple()

target = llvm.Target.from_triple(modulo.triple)
target_machine = target.create_target_machine()

modulo.data_layout = target_machine.target_data

escrevaInteiro = ir.Function(modulo,
                             ir.FunctionType(ir.VoidType(), [ir.IntType(32)]),
                             name="escrevaInteiro")
escrevaFlutuante = ir.Function(modulo,
                               ir.FunctionType(ir.VoidType(),
                                               [ir.FloatType()]),
                               name="escrevaFlutuante")
leiaInteiro = ir.Function(modulo,
                          ir.FunctionType(ir.IntType(32), []),
                          name="leiaInteiro")
leiaFlutuante = ir.Function(modulo,
                            ir.FunctionType(ir.FloatType(), []),
                            name="leiaFlutuante")

# Dicionario de variaveis globais
info = {"variaveis_globais": []}
Пример #30
0
def h5_size(context, builder, sig, args):
    fnty = lir.FunctionType(lir.IntType(64),
                            [h5file_lir_type, lir.IntType(32)])
    fn = builder.module.get_or_insert_function(fnty, name="hpat_h5_size")
    return builder.call(fn, [args[0], args[1]])