class LLVM::JITCompiler def initialize(mod) # JIT compilers own an LLVM::Module, and when they are disposed the module is disposed, # so we must prevent the module from being dispose when the GC will want to free it. mod.take_ownership { raise "Can't create two JIT compilers for the same module" } # if LibLLVM.create_jit_compiler_for_module(out @unwrap, mod, 3, out error) != 0 if LibLLVM.create_mc_jit_compiler_for_module(out @unwrap, mod, nil, 0, out error) != 0 raise LLVM.string_and_dispose(error) end # FIXME: We need to disable global isel until https://reviews.llvm.org/D80898 is released, # or we fixed generating values for 0 sized types. # When removing this, also remove it from the ABI specs and Crystal::Codegen::Target. # See https://github.com/crystal-lang/crystal/issues/9297#issuecomment-636512270 # for background info target_machine = LibLLVM.get_execution_engine_target_machine(@unwrap) {{ LibLLVM::IS_LT_180 ? LibLLVMExt : LibLLVM }}.set_target_machine_global_isel(target_machine, 0) @finalized = false end def self.new(mod, &) jit = new(mod) yield jit ensure jit.dispose end def run_function(func, context : Context) ret = LibLLVM.run_function(self, func, 0, nil) GenericValue.new(ret, context) end def run_function(func, args : Array(LLVM::GenericValue), context : Context) ret = LibLLVM.run_function(self, func, args.size, (args.to_unsafe.as(LibLLVM::GenericValueRef*))) GenericValue.new(ret, context) end def get_pointer_to_global(value) LibLLVM.get_pointer_to_global(self, value) end def function_address(name : String) : Void* Pointer(Void).new(LibLLVM.get_function_address(self, name.check_no_null_byte)) end def to_unsafe @unwrap end def dispose return if @finalized @finalized = true finalize end def finalize return if @finalized LibLLVM.dispose_execution_engine(@unwrap) end end