/// <inheritdoc/> public void AddLazyFunctionGenerator(string name, LazyFunctionCompiler generator, IntPtr context) { LLVMOrcGetMangledSymbol(JitStackHandle, out string mangledName, name); // wrap the provided generator function for a safe native callback UInt64 CompileAction(LLVMOrcJITStackRef jitStackHandle, IntPtr ctx) { try { (string implName, BitcodeModule module) = generator( ); if (module == null) { return(0); } AddEagerlyCompiledModule(module, DefaultSymbolResolver); // Workaround OrcJit+Windows/COFF bug/limitation where functions in the generated obj are // not marked as exported, so the official llvm-c API doesn't see the symbol to get the address // LibLLVM variant takes the additional bool so that is used on Windows to find non-exported symbols. bool exportedOnly = Environment.OSVersion.Platform != PlatformID.Win32NT; var e = LibLLVMOrcGetSymbolAddress(JitStackHandle, out UInt64 implAddr, name, exportedOnly); if (!e.IsInvalid) { throw new LlvmException(e.ToString()); } e = LLVMOrcSetIndirectStubPointer(JitStackHandle, mangledName, implAddr); if (!e.IsInvalid) { throw new LlvmException(e.ToString()); } LazyFunctionGenerators.Remove(mangledName); return(implAddr); } #pragma warning disable CA1031 // Do not catch general exception types catch { // native callback - MUST NOT leak exceptions out of this call. return(0); } #pragma warning restore CA1031 // Do not catch general exception types } var callbackAction = new WrappedNativeCallback <LLVMOrcLazyCompileCallbackFn>(CompileAction); LazyFunctionGenerators.Add(mangledName, callbackAction); var err = LLVMOrcCreateLazyCompileCallback(JitStackHandle, out UInt64 stubAddr, callbackAction, context); if (!err.IsInvalid) { throw new LlvmException(err.ToString()); } err = LLVMOrcCreateIndirectStub(JitStackHandle, mangledName, stubAddr); if (!err.IsInvalid) { throw new LlvmException(err.ToString( )); } }
/// <summary>Add a lazy function generator</summary> /// <param name="jit">JIT to add the module to</param> /// <param name="name">name of the function</param> /// <param name="generator">Generator that will generate the bit-code module for the function on demand</param> /// <remarks> /// A lazy function generator is an engine callback that is called when the JIT engine first encounters /// a symbol name during execution. If the function is never called, then the code is never generated (e.g. /// this is the real "JIT" part of a JIT engine.) /// <para>The <paramref name="generator"/> generates the IR module for the function. For this overload, the generator /// must contain everything necessary to generate the <see cref="BitcodeModule"/> for the function. Typically, this is /// a closure that captured the AST for the language and generates the IR from that state.</para> /// </remarks> public static void AddLazyFunctionGenerator([ValidatedNotNull] this ILazyCompileExecutionEngine jit, string name, LazyFunctionCompiler generator) { jit.ValidateNotNull(nameof(jit)); jit.AddLazyFunctionGenerator(name, generator, IntPtr.Zero); }
/// <summary>Add a lazy function generator</summary> /// <param name="jit">JIT to add the module to</param> /// <param name="name">name of the function</param> /// <param name="generator">Generator that will generate the bit-code module for the function on demand</param> /// <remarks> /// A lazy function generator is an engine callback that is called when the JIT engine first encounters /// a symbol name during execution. If the function is never called, then the code is never generated (e.g. /// this is the real "JIT" part of a JIT engine.) /// <para>The <paramref name="generator"/> generates the IR module for the function. For this overload, the generator /// must contain everything necessary to generate the <see cref="BitcodeModule"/> for the function. Typically, this is /// a closure that captured the AST for the language and generates the IR from that state.</para> /// </remarks> public static void AddLazyFunctionGenerator(this ILazyCompileExecutionEngine jit, string name, LazyFunctionCompiler generator) { jit.AddLazyFunctionGenerator(name, generator, IntPtr.Zero); }