<commit_before>"""
Generate LLVM code for a minivect AST.
"""

import sys

try:
    import llvm.core
    import llvm.ee
    import llvm.passes
except ImportError:
    llvm = None

import codegen
import minierror
import minitypes
import minivisitor
import ctypes_conversion

class LLVMCodeGen(codegen.CodeGen):
    """
    Generate LLVM code for a minivect AST.

    Takes a regular :py:class:`minivect.minicode.CodeWriter` to which it
    writes the LLVM function and a ctypes function.
    """

    in_lhs_expr = 0

    def __init__(self, context, codewriter):
        super(LLVMCodeGen, self).__init__(context, codewriter)
        self.declared_temps = set()
        self.temp_names = set()

        self.astbuilder = context.astbuilder
        self.blocks = []
        self.symtab = {}
        self.llvm_temps = {}

        import llvm # raise an error at this point if llvm-py is not installed

        self.init_binops()
        self.init_comparisons()

        # List of LLVM call instructions to inline
        self.inline_calls = []

    def append_basic_block(self, name='unamed'):
        "append a basic block and keep track of it"
        idx = len(self.blocks)
        bb = self.lfunc.append_basic_block('%s_%d' % (name, idx))
        self.blocks.append(bb)
        return bb

    def optimize(self):
        "Run llvm optimizations on the generated LLVM code (using the old llvm-py)"
        llvm_fpm = llvm.passes.FunctionPassManager.new(self.llvm_module)
        for llvm_pass in self.context.llvm_passes():
            llvm_fpm.add(llvm_pass)

        llvm_fpm.initialize()
        llvm_fpm.run(self.lfunc)
        llvm_fpm.finalize()

        # self.context.llvm_fpm.run(self.lfunc)

    def optimize(self):
        "Run llvm optimizations on the generated LLVM code"
        for call_instr in self.inline_calls:
            # print 'inlining...', call_instr
            llvm.core.inline_function(call_instr)

        llvm_fpm = llvm.passes.FunctionPassManager.new(self.llvm_module)
        # target_data = llvm.ee.TargetData(self.context.llvm_ee)
        llvm_fpm.add(self.context.llvm_ee.target_data)
        pmb = llvm.passes.PassManagerBuilder.new()
        pmb.opt_level = 3
        pmb.vectorize = True

        pmb.populate(llvm_fpm)
        llvm_fpm.run(self.lfunc)

    def visit_FunctionNode(self, node):
        self.specializer = node.specializer
        self.function = node
        self.llvm_module = self.context.llvm_module

        name = node.name + node.specialization_name
        node.mangled_name = name

        lfunc_type = node.type.to_llvm(self.context)
        self.lfunc = self.llvm_module.add_function(lfunc_type, node.mangled_name)

        self.entry_bb = self.append_basic_block('entry')
        self.builder = llvm.core.Builder.new(self.entry_bb)

        self.add_arguments(node)
        self.visit(node.body)

        self.lfunc.verify()
        self.optimize()
        # print self.lfunc

        self.code.write(self.lfunc)
        ctypes_func = ctypes_conversion.get_ctypes_func(
                    node, self.lfunc, self.context.llvm_ee, self.context)
        self.code.write(ctypes_func)

    def add_arguments(self, function):
        "Insert function arguments into the symtab"
        i = 0
        for arg in function.arguments + function.scalar_arguments:
            if arg.used:
                for var in arg.variables:
                    llvm_arg = self.lfunc.args[i]
                    self.symtab[var.name] = llvm_arg
                    llvm_arg.add_attribute(llvm.core.ATTR_NO_ALIAS)
                    llvm_arg.add_attribute(llvm.core.ATTR_NO_CAPTURE)
                    i += 1
            else:
                for var in arg.variables:<commit_msg>Only set no-alias and no-capture for python arguments<commit_after>"""
Generate LLVM code for a minivect AST.
"""

import sys

try:
    import llvm.core
    import llvm.ee
    import llvm.passes
except ImportError:
    llvm = None

import codegen
import minierror
import minitypes
import minivisitor
import ctypes_conversion

class LLVMCodeGen(codegen.CodeGen):
    """
    Generate LLVM code for a minivect AST.

    Takes a regular :py:class:`minivect.minicode.CodeWriter` to which it
    writes the LLVM function and a ctypes function.
    """

    in_lhs_expr = 0

    def __init__(self, context, codewriter):
        super(LLVMCodeGen, self).__init__(context, codewriter)
        self.declared_temps = set()
        self.temp_names = set()

        self.astbuilder = context.astbuilder
        self.blocks = []
        self.symtab = {}
        self.llvm_temps = {}

        import llvm # raise an error at this point if llvm-py is not installed

        self.init_binops()
        self.init_comparisons()

        # List of LLVM call instructions to inline
        self.inline_calls = []

    def append_basic_block(self, name='unamed'):
        "append a basic block and keep track of it"
        idx = len(self.blocks)
        bb = self.lfunc.append_basic_block('%s_%d' % (name, idx))
        self.blocks.append(bb)
        return bb

    def optimize(self):
        "Run llvm optimizations on the generated LLVM code (using the old llvm-py)"
        llvm_fpm = llvm.passes.FunctionPassManager.new(self.llvm_module)
        for llvm_pass in self.context.llvm_passes():
            llvm_fpm.add(llvm_pass)

        llvm_fpm.initialize()
        llvm_fpm.run(self.lfunc)
        llvm_fpm.finalize()

        # self.context.llvm_fpm.run(self.lfunc)

    def optimize(self):
        "Run llvm optimizations on the generated LLVM code"
        for call_instr in self.inline_calls:
            # print 'inlining...', call_instr
            llvm.core.inline_function(call_instr)

        llvm_fpm = llvm.passes.FunctionPassManager.new(self.llvm_module)
        # target_data = llvm.ee.TargetData(self.context.llvm_ee)
        llvm_fpm.add(self.context.llvm_ee.target_data)
        pmb = llvm.passes.PassManagerBuilder.new()
        pmb.opt_level = 3
        pmb.vectorize = True

        pmb.populate(llvm_fpm)
        llvm_fpm.run(self.lfunc)

    def visit_FunctionNode(self, node):
        self.specializer = node.specializer
        self.function = node
        self.llvm_module = self.context.llvm_module

        name = node.name + node.specialization_name
        node.mangled_name = name

        lfunc_type = node.type.to_llvm(self.context)
        self.lfunc = self.llvm_module.add_function(lfunc_type, node.mangled_name)

        self.entry_bb = self.append_basic_block('entry')
        self.builder = llvm.core.Builder.new(self.entry_bb)

        self.add_arguments(node)
        self.visit(node.body)

        self.lfunc.verify()
        self.optimize()
        # print self.lfunc

        self.code.write(self.lfunc)
        ctypes_func = ctypes_conversion.get_ctypes_func(
                    node, self.lfunc, self.context.llvm_ee, self.context)
        self.code.write(ctypes_func)

    def add_arguments(self, function):
        "Insert function arguments into the symtab"
        i = 0
        for arg in function.arguments + function.scalar_arguments:
            if arg.used:
                for var in arg.variables:
                    llvm_arg = self.lfunc.args[i]
                    self.symtab[var.name] = llvm_arg
                    if var.type.is_pointer:
                        llvm_arg.add_attribute(llvm.core.ATTR_NO_ALIAS)
                        llvm_arg.add_attribute(llvm.core.ATTR_NO_CAPTURE)
                    i += 1
            else:
                for var in arg.variables:
{'fraction_non_alphanumeric': 0.08920996818663839, 'fraction_numerical': 0.0010604453870625664, 'mean_word_length': 2.2271171941830623, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '793261', 'n_tokens_mistral': 2366, 'n_tokens_neox': 2318, 'n_words': 498}