From 805f6cc8c90a989b915732c324a5fb30a6f5ffc8 Mon Sep 17 00:00:00 2001 From: Jan Hoenig <hrominium@gmail.com> Date: Fri, 17 Mar 2017 21:46:55 +0100 Subject: [PATCH] LLVM-Backend can create a CFUNCTYPES function and run it. --- llvm/jit.py | 120 +++++++++++++++++++---------------------- llvm/kernelcreation.py | 2 + 2 files changed, 58 insertions(+), 64 deletions(-) diff --git a/llvm/jit.py b/llvm/jit.py index 8cd67cd06..aa53eb285 100644 --- a/llvm/jit.py +++ b/llvm/jit.py @@ -1,89 +1,81 @@ import llvmlite.ir as ir import llvmlite.binding as llvm -import logging.config from ..types import toCtypes, createType - import ctypes as ct -logger = logging.getLogger(__name__) - def compileLLVM(module): - return Eval().compile(module) + jit = Jit() + jit.parse(module) + jit.optimize() + jit.compile() + return jit -class Eval(object): +class Jit(object): def __init__(self): llvm.initialize() llvm.initialize_all_targets() llvm.initialize_native_target() llvm.initialize_native_asmprinter() + + self.module = None + self.llvmmod = None self.target = llvm.Target.from_default_triple() + self.cpu = llvm.get_host_cpu_name() + self.cpu_features = llvm.get_host_cpu_features() + self.target_machine = self.target.create_target_machine(cpu=self.cpu, features=self.cpu_features.flatten(), opt=2) + self.ee = None + self.fptr = None - def compile(self, module): - logger.debug('=============Preparse') - logger.debug(str(module)) + def parse(self, module): + self.module = module llvmmod = llvm.parse_assembly(str(module)) llvmmod.verify() - logger.debug('=============Function in IR') - logger.debug(str(llvmmod)) - # TODO cpu, features, opt - cpu = llvm.get_host_cpu_name() - features = llvm.get_host_cpu_features() - logger.debug('=======Things') - logger.debug(cpu) - logger.debug(features.flatten()) - target_machine = self.target.create_target_machine(cpu=cpu, features=features.flatten(), opt=2) + self.llvmmod = llvmmod - logger.debug('Machine = ' + str(target_machine.target_data)) + def write_ll(self, file): + with open(file, 'w') as f: + f.write(str(self.llvmmod)) - with open('gen.ll', 'w') as f: - f.write(str(llvmmod)) - optimize = True - if optimize: - pmb = llvm.create_pass_manager_builder() - pmb.opt_level = 2 - pmb.disable_unit_at_a_time = False - pmb.loop_vectorize = True - pmb.slp_vectorize = True - # TODO possible to pass for functions - pm = llvm.create_module_pass_manager() - pm.add_instruction_combining_pass() - pm.add_function_attrs_pass() - pm.add_constant_merge_pass() - pm.add_licm_pass() - pmb.populate(pm) - pm.run(llvmmod) - logger.debug("==========Opt") - logger.debug(str(llvmmod)) - with open('gen_opt.ll', 'w') as f: - f.write(str(llvmmod)) + def optimize(self): + pmb = llvm.create_pass_manager_builder() + pmb.opt_level = 2 + pmb.disable_unit_at_a_time = False + pmb.loop_vectorize = True + pmb.slp_vectorize = True + # TODO possible to pass for functions + pm = llvm.create_module_pass_manager() + pm.add_instruction_combining_pass() + pm.add_function_attrs_pass() + pm.add_constant_merge_pass() + pm.add_licm_pass() + pmb.populate(pm) + pm.run(self.llvmmod) - with llvm.create_mcjit_compiler(llvmmod, target_machine) as ee: - ee.finalize_object() + def compile(self, assembly_file=None, object_file=None): + ee = llvm.create_mcjit_compiler(self.llvmmod, self.target_machine) + ee.finalize_object() - logger.debug('==========Machine code') - logger.debug(target_machine.emit_assembly(llvmmod)) - with open('gen.S', 'w') as f: - f.write(target_machine.emit_assembly(llvmmod)) - with open('gen.o', 'wb') as f: - f.write(target_machine.emit_object(llvmmod)) + if assembly_file is not None: + with open(assembly_file, 'w') as f: + f.write(self.target_machine.emit_assembly(self.llvmmod)) + if object_file is not None: + with open(object_file, 'wb') as f: + f.write(self.target_machine.emit_object(self.llvmmod)) - fptr = {} - for function in module.functions: - if not function.is_declaration: + fptr = {} + for function in self.module.functions: + if not function.is_declaration: + return_type = None + if function.ftype.return_type != ir.VoidType(): + return_type = toCtypes(createType(str(function.ftype.return_type))) + args = [toCtypes(createType(str(arg))) for arg in function.ftype.args] + function_address = ee.get_function_address(function.name) + fptr[function.name] = ct.CFUNCTYPE(return_type, *args)(function_address) + self.ee = ee + self.fptr = fptr - print(function.name) - print(type(function)) - print(function.ftype.return_type) - print(type(function.ftype.return_type)) - return_type = None - if function.ftype.return_type != ir.VoidType(): - return_type = toCtypes(createType(str(function.ftype.return_type))) - args = [toCtypes(createType(str(arg))) for arg in function.ftype.args] - function_address = ee.get_function_address(function.name) - fptr[function.name] = ct.CFUNCTYPE(return_type, *args)(function_address) - # result = fptr(2, 3) - # print(result) - return fptr + def __call__(self, function, *args, **kwargs): + self.fptr[function](*args, **kwargs) diff --git a/llvm/kernelcreation.py b/llvm/kernelcreation.py index 7ac669686..5473b9ce7 100644 --- a/llvm/kernelcreation.py +++ b/llvm/kernelcreation.py @@ -60,8 +60,10 @@ def createKernel(listOfEquations, functionName="kernel", typeForSymbol=None, spl resolveFieldAccesses(code, readOnlyFields, fieldToBasePointerInfo=basePointerInfos) moveConstantsBeforeLoop(code) + print('Ast:') print(code) desympy_ast(code) + print('Desympied ast:') print(code) insert_casts(code) -- GitLab