def add_passes(parsed_module, level):
    if level == 0:
        return
    pm = llvm.ModulePassManager()

    if level >= 1:
        pm.add_basic_alias_analysis_pass()

    if level >= 2:
        pm.add_licm_pass()

    if level >= 3:
        pm.add_dead_arg_elimination_pass()

    if level >= 4:
        pm.add_constant_merge_pass()

    if level >= 5:
        # pm.add_constant_merge_pass()
        # pm.add_dead_arg_elimination_pass()
        pm.add_function_attrs_pass()
        pm.add_function_inlining_pass(200)  # threshold = 200
        pm.add_global_dce_pass()
        pm.add_global_optimizer_pass()
        pm.add_ipsccp_pass()
        pm.add_dead_code_elimination_pass()
        pm.add_cfg_simplification_pass()
        pm.add_gvn_pass()
        pm.add_instruction_combining_pass()
        pm.add_sccp_pass()
        pm.add_sroa_pass()
        pm.add_type_based_alias_analysis_pass()

    pm.run(parsed_module)
    return parsed_module
Example #2
0
def optimize_module(module_assembly, options):
    """Verify and optimise the passed LLVM module assembly.

    Args:
        module_assembly (str): LLVM module assembly
        options (CompilerOptions): options for the compiler

    Returns:
        A llvmlite.binding.ModuleRef for the verified and optimised module.

    """
    _ensure_llvm()

    # Parse LLVM module assembly
    module = llvm.parse_assembly(module_assembly)
    module.verify()

    # Create optimiser pass manager
    pass_manager = llvm.ModulePassManager()

    # Populate with target passes
    options.machine.target_data.add_pass(pass_manager)

    # Populate with optimisation passes
    pass_manager_builder = llvm.PassManagerBuilder()
    pass_manager_builder.opt_level = options.opt_level
    pass_manager_builder.populate(pass_manager)

    # Run optimiser
    pass_manager.run(module)

    return module
Example #3
0
def _cpu_jit_constructor():
    _binding_initialize()

    # PassManagerBuilder can be shared
    __pass_manager_builder = binding.PassManagerBuilder()
    __pass_manager_builder.inlining_threshold = 99999  # Inline all function calls
    __pass_manager_builder.loop_vectorize = True
    __pass_manager_builder.slp_vectorize = True
    __pass_manager_builder.opt_level = 3  # Most aggressive optimizations

    __cpu_features = binding.get_host_cpu_features().flatten()
    __cpu_name = binding.get_host_cpu_name()

    # Create compilation target, use default triple
    __cpu_target = binding.Target.from_default_triple()
    __cpu_target_machine = __cpu_target.create_target_machine(
        cpu=__cpu_name, features=__cpu_features, opt=3)

    __cpu_pass_manager = binding.ModulePassManager()
    __cpu_target_machine.add_analysis_passes(__cpu_pass_manager)
    __pass_manager_builder.populate(__cpu_pass_manager)

    # And an execution engine with a builtins backing module
    builtins_module = _generate_cpu_builtins_module(_float_ty)
    if "llvm" in debug_env:
        with open(builtins_module.name + '.parse.ll', 'w') as dump_file:
            dump_file.write(str(builtins_module))

    __backing_mod = binding.parse_assembly(str(builtins_module))

    __cpu_jit_engine = binding.create_mcjit_compiler(__backing_mod,
                                                     __cpu_target_machine)
    return __cpu_jit_engine, __cpu_pass_manager, __cpu_target_machine
Example #4
0
def _cpu_jit_constructor():
    _binding_initialize()

    # PassManagerBuilder can be shared
    __pass_manager_builder = binding.PassManagerBuilder()
    __pass_manager_builder.loop_vectorize = True
    __pass_manager_builder.slp_vectorize = True
    __pass_manager_builder.opt_level = 2

    __cpu_features = binding.get_host_cpu_features().flatten()
    __cpu_name = binding.get_host_cpu_name()

    # Create compilation target, use default triple
    __cpu_target = binding.Target.from_default_triple()
    # FIXME: reloc='static' is needed to avoid crashes on win64
    # see: https://github.com/numba/llvmlite/issues/457
    __cpu_target_machine = __cpu_target.create_target_machine(
        cpu=__cpu_name, features=__cpu_features, opt=2, reloc='static')

    __cpu_pass_manager = binding.ModulePassManager()
    __cpu_target_machine.add_analysis_passes(__cpu_pass_manager)
    __pass_manager_builder.populate(__cpu_pass_manager)

    # And an execution engine with a builtins backing module
    builtins_module = _generate_cpu_builtins_module(
        LLVMBuilderContext.float_ty)
    if "llvm" in debug_env:
        with open(builtins_module.name + '.parse.ll', 'w') as dump_file:
            dump_file.write(str(builtins_module))

    __backing_mod = binding.parse_assembly(str(builtins_module))

    __cpu_jit_engine = binding.create_mcjit_compiler(__backing_mod,
                                                     __cpu_target_machine)
    return __cpu_jit_engine, __cpu_pass_manager, __cpu_target_machine
Example #5
0
    def generate(self):
        self.binding.initialize()
        self.binding.initialize_native_target()
        self.binding.initialize_native_asmprinter()

        self.binding.load_library_permanently('./io.so')

        self.module = ir.Module('module')
        self.module.triple = self.binding.get_default_triple()

        target = self.binding.Target.from_default_triple()
        target_machine = target.create_target_machine()
        backing_mod = binding.parse_assembly("")
        engine = binding.create_mcjit_compiler(backing_mod, target_machine)
        self.engine = engine

        self.builder = None

        self.declare_runtime_functions()

        self.declare_functions(self.tree)
        self._traverse(self.tree)

        main = self.module.get_global("principal")
        main.name = "main"

        # pm_builder = binding.PassManagerBuilder()
        # pm_builder.populate()

        llvm_ir = str(self.module)

        print('Sem otimização')
        print(llvm_ir)

        mod = self.binding.parse_assembly(llvm_ir)
        mod.verify()

        m_pass = binding.ModulePassManager()
        m_pass.add_basic_alias_analysis_pass()
        m_pass.add_cfg_simplification_pass()
        m_pass.add_constant_merge_pass()
        m_pass.add_dead_arg_elimination_pass()
        m_pass.add_dead_code_elimination_pass()
        m_pass.add_function_attrs_pass()
        m_pass.add_global_dce_pass()
        m_pass.add_gvn_pass()
        m_pass.add_instruction_combining_pass()
        m_pass.add_global_optimizer_pass()
        m_pass.add_type_based_alias_analysis_pass()
        m_pass.run(mod)

        print('\n\nCom otimização')
        print(mod)

        self.engine.add_module(mod)
        self.engine.finalize_object()
        self.engine.run_static_constructors()

        with open('out.ll', 'w') as out:
            out.write(str(mod))
Example #6
0
def _ptx_jit_constructor():
    _binding_initialize()

    # PassManagerBuilder can be shared
    __pass_manager_builder = binding.PassManagerBuilder()
    __pass_manager_builder.inlining_threshold = 99999  # Inline all function calls
    __pass_manager_builder.loop_vectorize = True
    __pass_manager_builder.slp_vectorize = True
    __pass_manager_builder.opt_level = 3  # Most aggressive optimizations

    # Use default device
    # TODO: Add support for multiple devices
    __compute_capability = pycuda_default.device.compute_capability()
    __ptx_sm = "sm_{}{}".format(__compute_capability[0],
                                __compute_capability[1])
    # Create compilation target, use 64bit triple
    __ptx_target = binding.Target.from_triple("nvptx64-nvidia-cuda")
    __ptx_target_machine = __ptx_target.create_target_machine(
        cpu=__ptx_sm, opt=3, codemodel='small')

    __ptx_pass_manager = binding.ModulePassManager()
    __ptx_target_machine.add_analysis_passes(__ptx_pass_manager)
    #    __pass_manager_builder.populate(__ptx_pass_manager)

    return __ptx_pass_manager, __ptx_target_machine
Example #7
0
    def optimize_module(self, level=2):
        if level == 0:
            return
        elif level < 0 or level >= 3:
            msg = 'Undefined optimization level: {}'.format(level)
            raise PCLCodegenError(msg)

        # Initialize pass manager builder
        self.pmb = binding.PassManagerBuilder()

        # Declare optimization level
        self.pmb.opt_level = level

        # Run LOCAL optimizations on functions
        self.fpm = binding.FunctionPassManager(self.module)
        self.pmb.populate(self.fpm)
        self.fpm.initialize()

        for fcn in self.module.functions:
            self.fpm.run(fcn)

        self.fpm.finalize()

        # Configure module pass manager
        self.mpm = binding.ModulePassManager()
        self.pmb.populate(self.mpm)

        # Run GLOBAL optimizations on the module
        self.mpm.run(self.module)
Example #8
0
def assemble(module):
    opt = binding.ModulePassManager()
    builder = binding.PassManagerBuilder()
    builder.opt_level = 3
    builder.populate(opt)
    mod = binding.parse_assembly(str(module))
    mod.verify()
    opt.run(mod)
    return mod
Example #9
0
def bind(module, *args, optimize=False):
    module = inject_built_in(module)

    llvm_ir_parsed = llvm.parse_assembly(str(module))
    if False:

        pmb = llvm.create_pass_manager_builder()
        pmb.opt_level = 3

        fpm = llvm.create_function_pass_manager(llvm_ir_parsed)
        pmb.populate(fpm)

        pm = llvm.create_module_pass_manager()
        pmb.populate(pm)
        a = pm.run(llvm_ir_parsed)

    if optimize:
        opt_manager = llvm.PassManagerBuilder()
        mod_manager = llvm.ModulePassManager()

        mod_manager.add_constant_merge_pass()
        mod_manager.add_dead_arg_elimination_pass()
        mod_manager.add_function_inlining_pass(225)
        mod_manager.add_global_dce_pass()
        mod_manager.add_global_optimizer_pass()
        mod_manager.add_ipsccp_pass()
        mod_manager.add_dead_code_elimination_pass()
        mod_manager.add_cfg_simplification_pass()
        mod_manager.add_gvn_pass()
        mod_manager.add_instruction_combining_pass()
        mod_manager.add_licm_pass()
        mod_manager.add_sccp_pass()
        mod_manager.add_type_based_alias_analysis_pass()
        mod_manager.add_basic_alias_analysis_pass()

        mod_manager.run(llvm_ir_parsed)

    ####################################################################

    llvm_ir_parsed.verify()

    # JIT
    target_machine = llvm.Target.from_default_triple().create_target_machine()
    engine = llvm.create_mcjit_compiler(llvm_ir_parsed, target_machine)
    engine.finalize_object()

    entry = engine.get_function_address("main")

    cfunc = CFUNCTYPE(c_int64)(entry)

    result = cfunc()
    #print()
    #print("Programa main:: {}".format(result))
    return [llvm_ir_parsed, result]
Example #10
0
 def __set_optimization_helper(self, path, pass_list):
     f = open(path, "r")
     llvm_ir = f.read()
     f.close()
     mod = llvm.parse_assembly(llvm_ir)
     mod.verify()
     moduleManager = llvm.ModulePassManager()
     for passes in pass_list:
         moduleManager = self.optimization_pass(moduleManager, passes)
         pass
     moduleManager.run(mod)
     return mod
Example #11
0
 def check(self, irmod, subgraph_limit=None):
     mod = llvm.parse_assembly(f"{self.prologue}\n{irmod}")
     pm = llvm.ModulePassManager()
     if subgraph_limit is None:
         pm.add_refprune_pass(self.refprune_bitmask)
     else:
         pm.add_refprune_pass(self.refprune_bitmask,
                              subgraph_limit=subgraph_limit)
     before = llvm.dump_refprune_stats()
     pm.run(mod)
     after = llvm.dump_refprune_stats()
     return mod, after - before
Example #12
0
    def _optimize_final_module(self):
        # Run some lightweight optimization to simplify the module.
        # This seems to workaround a libnvvm compilation bug (see #1341)
        pmb = ll.PassManagerBuilder()
        pmb.opt_level = 1
        pmb.disable_unit_at_a_time = False
        pmb.disable_unroll_loops = True
        pmb.loop_vectorize = False
        pmb.slp_vectorize = False

        pm = ll.ModulePassManager()
        pmb.populate(pm)
        pm.run(self._final_module)
def execute(module, optimization):
    parsed_module = llvm.parse_assembly(str(module))

    if optimization:
        # initialize pass manager builder
        pmb = llvm.PassManagerBuilder()
        pmb.opt_level = 3

        # initialize function pass manager
        fpm = llvm.create_function_pass_manager(parsed_module)
        pmb.populate(fpm)

        # initialize module pass manager
        pm = llvm.ModulePassManager()
        pmb.populate(pm)

        # add optimization passes
        pm.add_constant_merge_pass()
        pm.add_dead_arg_elimination_pass()
        pm.add_function_attrs_pass()
        pm.add_function_inlining_pass(200)  # threshold = 200
        pm.add_global_dce_pass()
        pm.add_global_optimizer_pass()
        pm.add_ipsccp_pass()
        pm.add_dead_code_elimination_pass()
        pm.add_cfg_simplification_pass()
        pm.add_gvn_pass()
        pm.add_instruction_combining_pass()
        pm.add_licm_pass()
        pm.add_sccp_pass()
        pm.add_sroa_pass()
        pm.add_type_based_alias_analysis_pass()
        pm.add_basic_alias_analysis_pass()

        # run optimization passes on the module
        is_modified = pm.run(parsed_module)

        # check if the optimizations made any modification to the module
        print("Optimizations made modification to the module: ", is_modified)

    parsed_module.verify()
    target_machine = llvm.Target.from_default_triple().create_target_machine()
    engine = llvm.create_mcjit_compiler(parsed_module, target_machine)
    engine.finalize_object()
    entry = engine.get_function_address("run")
    cfunc = CFUNCTYPE(c_int)(entry)
    result = cfunc()
    print("\nexit: {}".format(result))
    return parsed_module
Example #14
0
    def _optimize_final_module(self):
        # Run some lightweight optimization to simplify the module.
        pmb = ll.PassManagerBuilder()

        # Make optimization level depending on config.OPT variable
        pmb.opt_level = config.OPT

        pmb.disable_unit_at_a_time = False
        pmb.disable_unroll_loops = True
        pmb.loop_vectorize = False
        pmb.slp_vectorize = False

        pm = ll.ModulePassManager()
        pmb.populate(pm)
        pm.run(self._final_module)
Example #15
0
    def _compile_ir_module(self, ir_module):
        module = llvm.parse_assembly(str(ir_module))
        module.name = ir_module.name
        module.verify()
        self.engine.add_module(module)
        self.engine.finalize_object()

        pmb = llvm.PassManagerBuilder()
        pmb.opt_level = 0
        pm = llvm.ModulePassManager()
        pmb.populate(pm)
        #pm.add_dead_code_elimination_pass()
        pm.run(module)

        return module
Example #16
0
    def compile_ir(self, llvm_ir, name, verbose, optimize=True):
        """
        Compile the LLVM IR string with the given engine.
        The compiled module object is returned.
        """
        engine = self.engine

        # Create a LLVM module object from the IR
        mod = binding.parse_assembly(llvm_ir)
        mod.verify()
        # Assign triple, so the IR can be saved and compiled with llc
        mod.triple = self.triple
        if verbose:
            print('====== IR (parsed) ======')
            print(mod)

        # Optimize
        if optimize:
            pmb = binding.PassManagerBuilder()
            pmb.opt_level = 2  # 0-3 (default=2)
            pmb.loop_vectorize = True

            mpm = binding.ModulePassManager()
            # Needed for automatic vectorization
            triple = binding.get_process_triple()
            target = binding.Target.from_triple(triple)
            tm = target.create_target_machine()
            tm.add_analysis_passes(mpm)

            pmb.populate(mpm)
            mpm.run(mod)

            if verbose:
                print('====== IR (optimized) ======')
                print(mod)

        # Now add the module and make sure it is ready for execution
        engine.add_module(mod)
        engine.finalize_object()
        engine.run_static_constructors()

        return mod
Example #17
0
def codegen(ast, specializer, retty, argtys):
    cgen = LLVMEmitter(specializer, retty, argtys)
    cgen.visit(ast)

    mod = llvm.parse_assembly(str(module))
    mod.verify()

    pmb = llvm.PassManagerBuilder()
    pmb.opt_level=3
    pmb.loop_vectorize = True

    pm = llvm.ModulePassManager()
    pmb.populate(pm)

    pm.run(mod)

    engine.add_module(mod)

    debug(cgen.function)
    debug(target_machine.emit_assembly(mod))
    return cgen.function
Example #18
0
def _ptx_jit_constructor():
    _binding_initialize()

    # PassManagerBuilder can be shared
    __pass_manager_builder = binding.PassManagerBuilder()
    __pass_manager_builder.opt_level = 1  # Basic optimizations
    __pass_manager_builder.size_level = 1  # asic size optimizations

    # Use default device
    # TODO: Add support for multiple devices
    __compute_capability = pycuda_default.device.compute_capability()
    __ptx_sm = "sm_{}{}".format(__compute_capability[0],
                                __compute_capability[1])
    # Create compilation target, use 64bit triple
    __ptx_target = binding.Target.from_triple("nvptx64-nvidia-cuda")
    __ptx_target_machine = __ptx_target.create_target_machine(cpu=__ptx_sm)

    __ptx_pass_manager = binding.ModulePassManager()
    __ptx_target_machine.add_analysis_passes(__ptx_pass_manager)
    __pass_manager_builder.populate(__ptx_pass_manager)

    return __ptx_pass_manager, __ptx_target_machine
def bind(module, *args, optimize = False):
    module = inject_built_in(module)

    llvm_ir_parsed = llvm.parse_assembly(str(module))
    if False:
        #general way of optimizing
        # print("from optimize")
        pmb = llvm.create_pass_manager_builder()
        pmb.opt_level = 3

        fpm = llvm.create_function_pass_manager(llvm_ir_parsed)
        pmb.populate(fpm)

        pm = llvm.create_module_pass_manager()
        pmb.populate(pm)
        a = pm.run(llvm_ir_parsed)
        # print(f'something was optimized {a}')


    ####################################################################
    if optimize:
        #more specific way of optimizing 
        opt_manager = llvm.PassManagerBuilder()
        mod_manager = llvm.ModulePassManager()

        mod_manager.add_constant_merge_pass()
        mod_manager.add_dead_arg_elimination_pass()
        mod_manager.add_function_inlining_pass(225)
        mod_manager.add_global_dce_pass()
        mod_manager.add_global_optimizer_pass()
        mod_manager.add_ipsccp_pass()
        mod_manager.add_dead_code_elimination_pass()
        mod_manager.add_cfg_simplification_pass()   
        mod_manager.add_gvn_pass()
        mod_manager.add_instruction_combining_pass()
        mod_manager.add_licm_pass()
        mod_manager.add_sccp_pass()
        mod_manager.add_type_based_alias_analysis_pass()
        mod_manager.add_basic_alias_analysis_pass()

        mod_manager.run(llvm_ir_parsed)

    ####################################################################

    llvm_ir_parsed.verify()


    # JIT
    target_machine = llvm.Target.from_default_triple().create_target_machine()
    engine = llvm.create_mcjit_compiler(llvm_ir_parsed, target_machine)
    engine.finalize_object()

    entry = engine.get_function_address("run")

    # arg_types = []
    # for arg in args:
    #     if type(arg) == int:
    #         arg_types.append(c_int)
    #     elif type(arg) == float:
    #         arg_types.append(c_float)
    #
    cfunc = CFUNCTYPE(c_int)(entry)
    # if len(arg_types) != 0:
    #     cfunc = CFUNCTYPE(*arg_types)(entry)

    # arg_values = []
    # for arg in args:
    #     if type(arg) == int:
    #         arg_values.append(arg)
    #     elif type(arg) == float:
    #         arg_values.append(c_float(arg))

    # result = cfunc(*arg_values)
    result = cfunc()
    print()
    print("program returns: {}".format(result))
    return llvm_ir_parsed
Example #20
0
def main():
    argp = argparse.ArgumentParser()

    argp.add_argument("filename", help="The brainfuck code file.")
    argp.add_argument("-i",
                      "--ir",
                      action="store_true",
                      help="Print out the human-readable LLVM IR to stderr")
    argp.add_argument('-r',
                      '--run',
                      action="store_true",
                      help="Run the brainfuck code with McJIT.")
    argp.add_argument('-c',
                      '--bitcode',
                      action="store_true",
                      help="Emit a bitcode file.")
    argp.add_argument('-o',
                      '--optimize',
                      action="store_true",
                      help="Optimize the bitcode.")

    argv = argp.parse_args()

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

    with open(argv.filename) as bf_file:
        ir_module = bf_to_ir(bf_file.read())

    basename = os.path.basename(argv.filename)
    basename = os.path.splitext(basename)[0]

    if argv.ir:
        with open(basename + ".ll", "w") as f:
            f.write(str(ir_module))

        print("Wrote IR to", basename + ".ll")

    binding_module = llvm.parse_assembly(str(ir_module))
    binding_module.verify()

    if argv.optimize:
        # TODO: We should define our own pass order.
        llvm.ModulePassManager().run(binding_module)

    if argv.bitcode:
        bitcode = binding_module.as_bitcode()

        with open(basename + ".bc", "wb") as output_file:
            output_file.write(bitcode)

        print("Wrote bitcode to", basename + ".bc")

    if argv.run:
        with create_execution_engine() as engine:
            engine.add_module(binding_module)
            engine.finalize_object()
            engine.run_static_constructors()

            func_ptr = engine.get_function_address("main")
            asm_main = ctypes.CFUNCTYPE(ctypes.c_int)(func_ptr)
            result = asm_main()
            sys.exit(result)
Example #21
0
disasm = disassemble(code)
module = translate(disasm)

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

llvm_module = llvm.parse_assembly(str(module))

tm = llvm.Target.from_default_triple().create_target_machine()

pmb = llvm.PassManagerBuilder()
pmb.inlining_threshold = 10000

mpm = llvm.ModulePassManager()
pmb.populate(mpm)
mpm.add_dead_arg_elimination_pass()
mpm.add_cfg_simplification_pass()
tm.add_analysis_passes(mpm)
mpm.run(llvm_module)

print(llvm_module)

with llvm.create_mcjit_compiler(llvm_module, tm) as ee:
	ee.finalize_object()
	obj = tm.emit_object(llvm_module)

with open(sys.argv[2], 'wb') as f:
	f.write(obj)
Example #22
0
 def apply_refprune(self, irmod):
     mod = llvm.parse_assembly(str(irmod))
     pm = llvm.ModulePassManager()
     pm.add_refprune_pass()
     pm.run(mod)
     return mod
Example #23
0
import os
from contextlib import contextmanager

import llvmlite.binding as llvm
from llvmlite.binding import ExecutionEngine

LIBRARY_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'std/lib')
PREAMBLE_BINARIES_PATH = os.path.join(os.path.dirname(os.path.abspath(__file__)), 'std/build/libstd')

llvm.initialize()
llvm.initialize_native_target()
llvm.initialize_all_asmprinters()

pass_manager = llvm.ModulePassManager()
pass_manager.add_instruction_combining_pass()
pass_manager.add_gvn_pass()
pass_manager.add_cfg_simplification_pass()


@contextmanager
def make_execution_engine():
  """
  Initialize just-in-time execution engine.

  :rtype: ExecutionEngine
  """
  target = llvm.Target.from_default_triple()
  target_machine = target.create_target_machine()
  backing_mod = llvm.parse_assembly('')
  engine = llvm.create_mcjit_compiler(backing_mod, target_machine)
  llvm.load_library_permanently(PREAMBLE_BINARIES_PATH + '.so')
Example #24
0
    mod = llvm.parse_assembly(llvm_ir)
    mod.verify()
    # Now add the module and make sure it is ready for execution
    engine.add_module(mod)
    engine.finalize_object()
    return mod


engine = create_execution_engine()
mod = compile_ir(engine, llvm_ir)
mod2= compile_ir(engine, llvm_ir2)
#llvm.ModulePassManager(mod)

print(mod2.as_bitcode())
PassManagerBuilder=llvm.PassManagerBuilder()
PassManagerBuilder.opt_level=3
#PassManagerBuilder.opt_level(3)

PassManager=llvm.create_module_pass_manager()
PassManagerBuilder.populate(PassManager)

if llvm.ModulePassManager(PassManager).run(mod2):
    print(mod2.as_bitcode())
# Look up the function pointer (a Python int)
func_ptr = engine.get_function_address("fpadd")

# Run the function via ctypes
cfunc = CFUNCTYPE(c_double, c_double, c_double)(func_ptr)
res = cfunc(1.0, 3.5)
print("fpadd(...) =", res)
Example #25
0
 def _optimize_ir(self):
     self.module_ref = binding.parse_assembly(str(self.module))
     self.module_pass_manager = binding.ModulePassManager()
     self.module_pass_manager.run(self.module_ref)
Example #26
0
def main():
  """
  Main entry point.
  """
  better_exchook.install()
  parser = argparse.ArgumentParser(description='Compile a Sleepy program to object code.')
  parser.add_argument('program', help='Path to source code')
  parser.add_argument(
    '--execute', dest='execute', default=False, action='store_true', help='Run program after compilation using JIT.')
  parser.add_argument(
    '--emit-ir', '-ir', dest='emit_ir', action='store_true', help='Emit LLVM intermediate representation.')
  parser.add_argument(
    '--emit-object', '-c', dest='emit_object', action='store_true', help='Emit object code, but do not link.')
  parser.add_argument('--compile-libs', '-libs', nargs='*', help='External libraries to link with', default=['m'])
  parser.add_argument(
    '--verbose', dest='verbose', action='store_true', help='Print full stacktrace for all compiler errors.')
  parser.add_argument(
    '--Optimization', '-O', dest='opt', action='store', type=int, default=0, help='Optimize code.')
  parser.add_argument('--no-preamble', default=False, action='store_true', help='Do not add preamble to source code.')
  parser.add_argument('--debug', default=False, action='store_true', help='Add debug symbols.')
  parser.add_argument('--output', default=None, action='store', help='output file path')

  args = parser.parse_args()

  main_func_identifier = 'main'
  source_file_path: Path = Path(args.program)
  try:
    ast = make_translation_unit_ast(source_file_path, add_preamble=not args.no_preamble)
    module_ir, symbol_table, exported_functions = ast.make_module_ir_and_symbol_table(
      module_name='default_module',
      emit_debug=args.debug,
      main_file_path=source_file_path,
      implicitly_exported_functions={main_func_identifier})
  except CompilerError as ce:
    if args.verbose:
      raise ce
    else:
      print(str(ce))
      exit(1)
      return

  if args.execute:
    # Execute directly using JIT compilation.
    concrete_main_func = next((func for func in exported_functions if func.identifier == main_func_identifier), None)
    assert concrete_main_func is not None, 'main function not exported'
    with make_execution_engine() as engine:
      compile_ir(engine, module_ir)
      py_func = concrete_main_func.make_py_func(engine)
      return_val = py_func()
    print('\nExited with return value %r of type %r' % (return_val, concrete_main_func.return_type))
    return

  object_file_name = _make_file_name(source_file_path, '.o', allow_exist=True)
  module_ref = llvm.parse_assembly(str(module_ir))

  print(f'Opt: {args.opt}')
  if args.opt != 0:
    # run optimizations on module, optimizations during emit_object are different and less powerful
    module_passes = llvm.ModulePassManager()
    builder = llvm.PassManagerBuilder()
    builder.opt_level = args.opt
    builder.inlining_threshold = 250
    builder.populate(module_passes)
    module_passes.run(module_ref)

  if args.emit_ir:
    ir_file_name = _make_file_name(source_file_path, '.ll', allow_exist=True)
    with open(ir_file_name, 'w') as file:
      file.write(str(module_ir))
    return

  target = llvm.Target.from_default_triple()
  machine = target.create_target_machine(opt=args.opt)
  with open(object_file_name, 'wb') as file:
    file.write(machine.emit_object(module_ref))
  if args.emit_object:
    return

  if args.output is not None: exec_file_name = args.output
  else: exec_file_name = _make_file_name(source_file_path, '', allow_exist=True)

  import subprocess
  subprocess.run(
    ['gcc'] + (['-g'] if args.debug else [])
    + ['-o', exec_file_name, object_file_name, PREAMBLE_BINARIES_PATH + '_static.a']
    + ['-l%s' % lib_name for lib_name in args.compile_libs])