backpatch "jit: Add support for LLVM 12."

As there haven't been problem on the buildfarm due to this change,
backpatch 6c57f2ed16 now.

Author: Andres Freund
Discussion: https://postgr.es/m/20201016011244.pmyvr3ee2gbzplq4@alap3.anarazel.de
Backpatch: 11-, where jit support was added
This commit is contained in:
Andres Freund 2020-11-09 20:01:33 -08:00
parent 10d9c9d03c
commit 90eb343ef3
2 changed files with 375 additions and 86 deletions

View File

@ -29,7 +29,13 @@
#include <llvm-c/BitWriter.h> #include <llvm-c/BitWriter.h>
#include <llvm-c/Core.h> #include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h> #include <llvm-c/ExecutionEngine.h>
#if LLVM_VERSION_MAJOR > 11
#include <llvm-c/Orc.h>
#include <llvm-c/OrcEE.h>
#include <llvm-c/LLJIT.h>
#else
#include <llvm-c/OrcBindings.h> #include <llvm-c/OrcBindings.h>
#endif
#include <llvm-c/Support.h> #include <llvm-c/Support.h>
#include <llvm-c/Target.h> #include <llvm-c/Target.h>
#include <llvm-c/Transforms/IPO.h> #include <llvm-c/Transforms/IPO.h>
@ -43,8 +49,13 @@
/* Handle of a module emitted via ORC JIT */ /* Handle of a module emitted via ORC JIT */
typedef struct LLVMJitHandle typedef struct LLVMJitHandle
{ {
#if LLVM_VERSION_MAJOR > 11
LLVMOrcLLJITRef lljit;
LLVMOrcResourceTrackerRef resource_tracker;
#else
LLVMOrcJITStackRef stack; LLVMOrcJITStackRef stack;
LLVMOrcModuleHandle orc_handle; LLVMOrcModuleHandle orc_handle;
#endif
} LLVMJitHandle; } LLVMJitHandle;
@ -94,12 +105,15 @@ static const char *llvm_triple = NULL;
static const char *llvm_layout = NULL; static const char *llvm_layout = NULL;
static LLVMTargetMachineRef llvm_opt0_targetmachine;
static LLVMTargetMachineRef llvm_opt3_targetmachine;
static LLVMTargetRef llvm_targetref; static LLVMTargetRef llvm_targetref;
#if LLVM_VERSION_MAJOR > 11
static LLVMOrcThreadSafeContextRef llvm_ts_context;
static LLVMOrcLLJITRef llvm_opt0_orc;
static LLVMOrcLLJITRef llvm_opt3_orc;
#else /* LLVM_VERSION_MAJOR > 11 */
static LLVMOrcJITStackRef llvm_opt0_orc; static LLVMOrcJITStackRef llvm_opt0_orc;
static LLVMOrcJITStackRef llvm_opt3_orc; static LLVMOrcJITStackRef llvm_opt3_orc;
#endif /* LLVM_VERSION_MAJOR > 11 */
static void llvm_release_context(JitContext *context); static void llvm_release_context(JitContext *context);
@ -111,6 +125,10 @@ static void llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module);
static void llvm_create_types(void); static void llvm_create_types(void);
static uint64_t llvm_resolve_symbol(const char *name, void *ctx); static uint64_t llvm_resolve_symbol(const char *name, void *ctx);
#if LLVM_VERSION_MAJOR > 11
static LLVMOrcLLJITRef llvm_create_jit_instance(LLVMTargetMachineRef tm);
static char *llvm_error_message(LLVMErrorRef error);
#endif /* LLVM_VERSION_MAJOR > 11 */
PG_MODULE_MAGIC; PG_MODULE_MAGIC;
@ -170,24 +188,47 @@ llvm_release_context(JitContext *context)
* have occurred from within LLVM, we do not want to risk reentering. All * have occurred from within LLVM, we do not want to risk reentering. All
* resource cleanup is going to happen through process exit. * resource cleanup is going to happen through process exit.
*/ */
if (!proc_exit_inprogress) if (proc_exit_inprogress)
return;
if (llvm_context->module)
{ {
if (llvm_context->module) LLVMDisposeModule(llvm_context->module);
llvm_context->module = NULL;
}
while (llvm_context->handles != NIL)
{
LLVMJitHandle *jit_handle;
jit_handle = (LLVMJitHandle *) linitial(llvm_context->handles);
llvm_context->handles = list_delete_first(llvm_context->handles);
#if LLVM_VERSION_MAJOR > 11
{ {
LLVMDisposeModule(llvm_context->module); LLVMOrcExecutionSessionRef ee;
llvm_context->module = NULL; LLVMOrcSymbolStringPoolRef sp;
LLVMOrcResourceTrackerRemove(jit_handle->resource_tracker);
LLVMOrcReleaseResourceTracker(jit_handle->resource_tracker);
/*
* Without triggering cleanup of the string pool, we'd leak
* memory. It'd be sufficient to do this far less often, but in
* experiments the required time was small enough to just always
* do it.
*/
ee = LLVMOrcLLJITGetExecutionSession(jit_handle->lljit);
sp = LLVMOrcExecutionSessionGetSymbolStringPool(ee);
LLVMOrcSymbolStringPoolClearDeadEntries(sp);
} }
#else /* LLVM_VERSION_MAJOR > 11 */
while (llvm_context->handles != NIL)
{ {
LLVMJitHandle *jit_handle;
jit_handle = (LLVMJitHandle *) linitial(llvm_context->handles);
llvm_context->handles = list_delete_first(llvm_context->handles);
LLVMOrcRemoveModule(jit_handle->stack, jit_handle->orc_handle); LLVMOrcRemoveModule(jit_handle->stack, jit_handle->orc_handle);
pfree(jit_handle);
} }
#endif /* LLVM_VERSION_MAJOR > 11 */
pfree(jit_handle);
} }
} }
@ -243,8 +284,8 @@ llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
void * void *
llvm_get_function(LLVMJitContext *context, const char *funcname) llvm_get_function(LLVMJitContext *context, const char *funcname)
{ {
LLVMOrcTargetAddress addr = 0; #if LLVM_VERSION_MAJOR > 11 || \
#if defined(HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN) && HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN defined(HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN) && HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN
ListCell *lc; ListCell *lc;
#endif #endif
@ -264,10 +305,41 @@ llvm_get_function(LLVMJitContext *context, const char *funcname)
* to mangle here. * to mangle here.
*/ */
#if defined(HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN) && HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN #if LLVM_VERSION_MAJOR > 11
foreach(lc, context->handles) foreach(lc, context->handles)
{ {
LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc); LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc);
instr_time starttime;
instr_time endtime;
LLVMErrorRef error;
LLVMOrcJITTargetAddress addr;
INSTR_TIME_SET_CURRENT(starttime);
addr = 0;
error = LLVMOrcLLJITLookup(handle->lljit, &addr, funcname);
if (error)
elog(ERROR, "failed to look up symbol \"%s\": %s",
funcname, llvm_error_message(error));
/*
* LLJIT only actually emits code the first time a symbol is
* referenced. Thus add lookup time to emission time. That's counting
* a bit more than with older LLVM versions, but unlikely to ever
* matter.
*/
INSTR_TIME_SET_CURRENT(endtime);
INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
endtime, starttime);
if (addr)
return (void *) (uintptr_t) addr;
}
#elif defined(HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN) && HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN
foreach(lc, context->handles)
{
LLVMOrcTargetAddress addr;
LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc);
addr = 0; addr = 0;
if (LLVMOrcGetSymbolAddressIn(handle->stack, &addr, handle->orc_handle, funcname)) if (LLVMOrcGetSymbolAddressIn(handle->stack, &addr, handle->orc_handle, funcname))
@ -275,26 +347,29 @@ llvm_get_function(LLVMJitContext *context, const char *funcname)
if (addr) if (addr)
return (void *) (uintptr_t) addr; return (void *) (uintptr_t) addr;
} }
#elif LLVM_VERSION_MAJOR < 5
{
LLVMOrcTargetAddress addr;
if ((addr = LLVMOrcGetSymbolAddress(llvm_opt0_orc, funcname)))
return (void *) (uintptr_t) addr;
if ((addr = LLVMOrcGetSymbolAddress(llvm_opt3_orc, funcname)))
return (void *) (uintptr_t) addr;
}
#else #else
{
LLVMOrcTargetAddress addr;
#if LLVM_VERSION_MAJOR < 5 if (LLVMOrcGetSymbolAddress(llvm_opt0_orc, &addr, funcname))
if ((addr = LLVMOrcGetSymbolAddress(llvm_opt0_orc, funcname))) elog(ERROR, "failed to look up symbol \"%s\"", funcname);
return (void *) (uintptr_t) addr; if (addr)
if ((addr = LLVMOrcGetSymbolAddress(llvm_opt3_orc, funcname))) return (void *) (uintptr_t) addr;
return (void *) (uintptr_t) addr; if (LLVMOrcGetSymbolAddress(llvm_opt3_orc, &addr, funcname))
#else elog(ERROR, "failed to look up symbol \"%s\"", funcname);
if (LLVMOrcGetSymbolAddress(llvm_opt0_orc, &addr, funcname)) if (addr)
elog(ERROR, "failed to look up symbol \"%s\"", funcname); return (void *) (uintptr_t) addr;
if (addr) }
return (void *) (uintptr_t) addr; #endif
if (LLVMOrcGetSymbolAddress(llvm_opt3_orc, &addr, funcname))
elog(ERROR, "failed to look up symbol \"%s\"", funcname);
if (addr)
return (void *) (uintptr_t) addr;
#endif /* LLVM_VERSION_MAJOR */
#endif /* HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN */
elog(ERROR, "failed to JIT: %s", funcname); elog(ERROR, "failed to JIT: %s", funcname);
@ -425,6 +500,8 @@ llvm_function_reference(LLVMJitContext *context,
v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname); v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname);
LLVMSetInitializer(v_fn, v_fn_addr); LLVMSetInitializer(v_fn, v_fn_addr);
LLVMSetGlobalConstant(v_fn, true); LLVMSetGlobalConstant(v_fn, true);
LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
LLVMSetUnnamedAddr(v_fn, true);
return LLVMBuildLoad(builder, v_fn, ""); return LLVMBuildLoad(builder, v_fn, "");
} }
@ -516,11 +593,15 @@ llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
static void static void
llvm_compile_module(LLVMJitContext *context) llvm_compile_module(LLVMJitContext *context)
{ {
LLVMOrcModuleHandle orc_handle; LLVMJitHandle *handle;
MemoryContext oldcontext; MemoryContext oldcontext;
static LLVMOrcJITStackRef compile_orc;
instr_time starttime; instr_time starttime;
instr_time endtime; instr_time endtime;
#if LLVM_VERSION_MAJOR > 11
LLVMOrcLLJITRef compile_orc;
#else
LLVMOrcJITStackRef compile_orc;
#endif
if (context->base.flags & PGJIT_OPT3) if (context->base.flags & PGJIT_OPT3)
compile_orc = llvm_opt3_orc; compile_orc = llvm_opt3_orc;
@ -567,6 +648,9 @@ llvm_compile_module(LLVMJitContext *context)
pfree(filename); pfree(filename);
} }
handle = (LLVMJitHandle *)
MemoryContextAlloc(TopMemoryContext, sizeof(LLVMJitHandle));
/* /*
* Emit the code. Note that this can, depending on the optimization * Emit the code. Note that this can, depending on the optimization
* settings, take noticeable resources as code emission executes low-level * settings, take noticeable resources as code emission executes low-level
@ -574,13 +658,42 @@ llvm_compile_module(LLVMJitContext *context)
* faster instruction selection mechanism is used. * faster instruction selection mechanism is used.
*/ */
INSTR_TIME_SET_CURRENT(starttime); INSTR_TIME_SET_CURRENT(starttime);
#if LLVM_VERSION_MAJOR > 6 #if LLVM_VERSION_MAJOR > 11
{ {
if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &orc_handle, context->module, LLVMOrcThreadSafeModuleRef ts_module;
LLVMErrorRef error;
LLVMOrcJITDylibRef jd = LLVMOrcLLJITGetMainJITDylib(compile_orc);
ts_module = LLVMOrcCreateNewThreadSafeModule(context->module, llvm_ts_context);
handle->lljit = compile_orc;
handle->resource_tracker = LLVMOrcJITDylibCreateResourceTracker(jd);
/*
* NB: This doesn't actually emit code. That happens lazily the first
* time a symbol defined in the module is requested. Due to that
* llvm_get_function() also accounts for emission time.
*/
context->module = NULL; /* will be owned by LLJIT */
error = LLVMOrcLLJITAddLLVMIRModuleWithRT(compile_orc,
handle->resource_tracker,
ts_module);
if (error)
elog(ERROR, "failed to JIT module: %s",
llvm_error_message(error));
handle->lljit = compile_orc;
/* LLVMOrcLLJITAddLLVMIRModuleWithRT takes ownership of the module */
}
#elif LLVM_VERSION_MAJOR > 6
{
handle->stack = compile_orc;
if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &handle->orc_handle, context->module,
llvm_resolve_symbol, NULL)) llvm_resolve_symbol, NULL))
{
elog(ERROR, "failed to JIT module"); elog(ERROR, "failed to JIT module");
}
/* LLVMOrcAddEagerlyCompiledIR takes ownership of the module */ /* LLVMOrcAddEagerlyCompiledIR takes ownership of the module */
} }
@ -589,20 +702,23 @@ llvm_compile_module(LLVMJitContext *context)
LLVMSharedModuleRef smod; LLVMSharedModuleRef smod;
smod = LLVMOrcMakeSharedModule(context->module); smod = LLVMOrcMakeSharedModule(context->module);
if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &orc_handle, smod, handle->stack = compile_orc;
if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &handle->orc_handle, smod,
llvm_resolve_symbol, NULL)) llvm_resolve_symbol, NULL))
{
elog(ERROR, "failed to JIT module"); elog(ERROR, "failed to JIT module");
}
LLVMOrcDisposeSharedModuleRef(smod); LLVMOrcDisposeSharedModuleRef(smod);
} }
#else /* LLVM 4.0 and 3.9 */ #else /* LLVM 4.0 and 3.9 */
{ {
orc_handle = LLVMOrcAddEagerlyCompiledIR(compile_orc, context->module, handle->stack = compile_orc;
llvm_resolve_symbol, NULL); handle->orc_handle = LLVMOrcAddEagerlyCompiledIR(compile_orc, context->module,
llvm_resolve_symbol, NULL);
LLVMDisposeModule(context->module); LLVMDisposeModule(context->module);
} }
#endif #endif
INSTR_TIME_SET_CURRENT(endtime); INSTR_TIME_SET_CURRENT(endtime);
INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter, INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
endtime, starttime); endtime, starttime);
@ -612,15 +728,7 @@ llvm_compile_module(LLVMJitContext *context)
/* remember emitted code for cleanup and lookups */ /* remember emitted code for cleanup and lookups */
oldcontext = MemoryContextSwitchTo(TopMemoryContext); oldcontext = MemoryContextSwitchTo(TopMemoryContext);
{ context->handles = lappend(context->handles, handle);
LLVMJitHandle *handle;
handle = (LLVMJitHandle *) palloc(sizeof(LLVMJitHandle));
handle->stack = compile_orc;
handle->orc_handle = orc_handle;
context->handles = lappend(context->handles, handle);
}
MemoryContextSwitchTo(oldcontext); MemoryContextSwitchTo(oldcontext);
ereport(DEBUG1, ereport(DEBUG1,
@ -642,6 +750,8 @@ llvm_session_initialize(void)
char *error = NULL; char *error = NULL;
char *cpu = NULL; char *cpu = NULL;
char *features = NULL; char *features = NULL;
LLVMTargetMachineRef opt0_tm;
LLVMTargetMachineRef opt3_tm;
if (llvm_session_initialized) if (llvm_session_initialized)
return; return;
@ -674,12 +784,12 @@ llvm_session_initialize(void)
elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"", elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"",
cpu, features); cpu, features);
llvm_opt0_targetmachine = opt0_tm =
LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features, LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
LLVMCodeGenLevelNone, LLVMCodeGenLevelNone,
LLVMRelocDefault, LLVMRelocDefault,
LLVMCodeModelJITDefault); LLVMCodeModelJITDefault);
llvm_opt3_targetmachine = opt3_tm =
LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features, LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
LLVMCodeGenLevelAggressive, LLVMCodeGenLevelAggressive,
LLVMRelocDefault, LLVMRelocDefault,
@ -693,27 +803,41 @@ llvm_session_initialize(void)
/* force symbols in main binary to be loaded */ /* force symbols in main binary to be loaded */
LLVMLoadLibraryPermanently(NULL); LLVMLoadLibraryPermanently(NULL);
llvm_opt0_orc = LLVMOrcCreateInstance(llvm_opt0_targetmachine); #if LLVM_VERSION_MAJOR > 11
llvm_opt3_orc = LLVMOrcCreateInstance(llvm_opt3_targetmachine); {
llvm_ts_context = LLVMOrcCreateNewThreadSafeContext();
llvm_opt0_orc = llvm_create_jit_instance(opt0_tm);
opt0_tm = 0;
llvm_opt3_orc = llvm_create_jit_instance(opt3_tm);
opt3_tm = 0;
}
#else /* LLVM_VERSION_MAJOR > 11 */
{
llvm_opt0_orc = LLVMOrcCreateInstance(opt0_tm);
llvm_opt3_orc = LLVMOrcCreateInstance(opt3_tm);
#if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER #if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
if (jit_debugging_support) if (jit_debugging_support)
{ {
LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener(); LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l); LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l);
LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l); LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l);
} }
#endif #endif
#if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER #if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
if (jit_profiling_support) if (jit_profiling_support)
{ {
LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener(); LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l); LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l);
LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l); LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l);
} }
#endif #endif
}
#endif /* LLVM_VERSION_MAJOR > 11 */
before_shmem_exit(llvm_shutdown, 0); before_shmem_exit(llvm_shutdown, 0);
@ -725,27 +849,49 @@ llvm_session_initialize(void)
static void static void
llvm_shutdown(int code, Datum arg) llvm_shutdown(int code, Datum arg)
{ {
/* unregister profiling support, needs to be flushed to be useful */ #if LLVM_VERSION_MAJOR > 11
if (llvm_opt3_orc)
{ {
#if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF if (llvm_opt3_orc)
if (jit_profiling_support) {
LLVMOrcUnregisterPerf(llvm_opt3_orc); LLVMOrcDisposeLLJIT(llvm_opt3_orc);
#endif llvm_opt3_orc = NULL;
LLVMOrcDisposeInstance(llvm_opt3_orc); }
llvm_opt3_orc = NULL; if (llvm_opt0_orc)
{
LLVMOrcDisposeLLJIT(llvm_opt0_orc);
llvm_opt0_orc = NULL;
}
if (llvm_ts_context)
{
LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
llvm_ts_context = NULL;
}
} }
#else /* LLVM_VERSION_MAJOR > 11 */
if (llvm_opt0_orc)
{ {
/* unregister profiling support, needs to be flushed to be useful */
if (llvm_opt3_orc)
{
#if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF
if (jit_profiling_support) if (jit_profiling_support)
LLVMOrcUnregisterPerf(llvm_opt0_orc); LLVMOrcUnregisterPerf(llvm_opt3_orc);
#endif #endif
LLVMOrcDisposeInstance(llvm_opt0_orc); LLVMOrcDisposeInstance(llvm_opt3_orc);
llvm_opt0_orc = NULL; llvm_opt3_orc = NULL;
}
if (llvm_opt0_orc)
{
#if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF
if (jit_profiling_support)
LLVMOrcUnregisterPerf(llvm_opt0_orc);
#endif
LLVMOrcDisposeInstance(llvm_opt0_orc);
llvm_opt0_orc = NULL;
}
} }
#endif /* LLVM_VERSION_MAJOR > 11 */
} }
/* helper for llvm_create_types, returning a global var's type */ /* helper for llvm_create_types, returning a global var's type */
@ -941,3 +1087,145 @@ llvm_resolve_symbol(const char *symname, void *ctx)
return (uint64_t) addr; return (uint64_t) addr;
} }
#if LLVM_VERSION_MAJOR > 11
static LLVMErrorRef
llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx,
LLVMOrcLookupStateRef *LookupState, LLVMOrcLookupKind Kind,
LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags JDLookupFlags,
LLVMOrcCLookupSet LookupSet, size_t LookupSetSize)
{
LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMJITCSymbolMapPair) * LookupSetSize);
LLVMErrorRef error;
LLVMOrcMaterializationUnitRef mu;
for (int i = 0; i < LookupSetSize; i++)
{
const char *name = LLVMOrcSymbolStringPoolEntryStr(LookupSet[i].Name);
symbols[i].Name = LookupSet[i].Name;
symbols[i].Sym.Address = llvm_resolve_symbol(name, NULL);
symbols[i].Sym.Flags.GenericFlags = LLVMJITSymbolGenericFlagsExported;
}
mu = LLVMOrcAbsoluteSymbols(symbols, LookupSetSize);
error = LLVMOrcJITDylibDefine(JD, mu);
if (error != LLVMErrorSuccess)
LLVMOrcDisposeMaterializationUnit(mu);
pfree(symbols);
return error;
}
/*
* We cannot throw errors through LLVM (without causing a FATAL at least), so
* just use WARNING here. That's OK anyway, as the error is also reported at
* the top level action (with less detail) and there might be multiple
* invocations of errors with details.
*
* This doesn't really happen during normal operation, but in cases like
* symbol resolution breakage. So just using elog(WARNING) is fine.
*/
static void
llvm_log_jit_error(void *ctx, LLVMErrorRef error)
{
elog(WARNING, "error during JITing: %s",
llvm_error_message(error));
}
/*
* Create our own object layer, so we can add event listeners.
*/
static LLVMOrcObjectLayerRef
llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
{
LLVMOrcObjectLayerRef objlayer =
LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
#if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
if (jit_debugging_support)
{
LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
}
#endif
#if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
if (jit_profiling_support)
{
LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
}
#endif
return objlayer;
}
/*
* Create LLJIT instance, using the passed in target machine. Note that the
* target machine afterwards is owned by the LLJIT instance.
*/
static LLVMOrcLLJITRef
llvm_create_jit_instance(LLVMTargetMachineRef tm)
{
LLVMOrcLLJITRef lljit;
LLVMOrcJITTargetMachineBuilderRef tm_builder;
LLVMOrcLLJITBuilderRef lljit_builder;
LLVMErrorRef error;
LLVMOrcDefinitionGeneratorRef main_gen;
LLVMOrcDefinitionGeneratorRef ref_gen;
lljit_builder = LLVMOrcCreateLLJITBuilder();
tm_builder = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm);
LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(lljit_builder, tm_builder);
LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(lljit_builder,
llvm_create_object_layer,
NULL);
error = LLVMOrcCreateLLJIT(&lljit, lljit_builder);
if (error)
elog(ERROR, "failed to create lljit instance: %s",
llvm_error_message(error));
LLVMOrcExecutionSessionSetErrorReporter(LLVMOrcLLJITGetExecutionSession(lljit),
llvm_log_jit_error, NULL);
/*
* Symbol resolution support for symbols in the postgres binary /
* libraries already loaded.
*/
error = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(&main_gen,
LLVMOrcLLJITGetGlobalPrefix(lljit),
0, NULL);
if (error)
elog(ERROR, "failed to create generator: %s",
llvm_error_message(error));
LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), main_gen);
/*
* Symbol resolution support for "special" functions, e.g. a call into an
* SQL callable function.
*/
ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL);
LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), ref_gen);
return lljit;
}
static char *
llvm_error_message(LLVMErrorRef error)
{
char *orig = LLVMGetErrorMessage(error);
char *msg = pstrdup(orig);
LLVMDisposeErrorMessage(orig);
return msg;
}
#endif /* LLVM_VERSION_MAJOR > 11 */

View File

@ -1133,6 +1133,7 @@ LLVMJitHandle
LLVMMemoryBufferRef LLVMMemoryBufferRef
LLVMModuleRef LLVMModuleRef
LLVMOrcJITStackRef LLVMOrcJITStackRef
LLVMOrcLookupStateRef
LLVMOrcModuleHandle LLVMOrcModuleHandle
LLVMOrcTargetAddress LLVMOrcTargetAddress
LLVMPassManagerBuilderRef LLVMPassManagerBuilderRef