mirror of
https://github.com/postgres/postgres.git
synced 2025-05-03 22:24:49 +03:00
backpatch "jit: Add support for LLVM 12."
As there haven't been problem on the buildfarm due to this change, backpatch 6c57f2ed16e 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:
parent
10d9c9d03c
commit
90eb343ef3
@ -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 */
|
||||||
|
@ -1133,6 +1133,7 @@ LLVMJitHandle
|
|||||||
LLVMMemoryBufferRef
|
LLVMMemoryBufferRef
|
||||||
LLVMModuleRef
|
LLVMModuleRef
|
||||||
LLVMOrcJITStackRef
|
LLVMOrcJITStackRef
|
||||||
|
LLVMOrcLookupStateRef
|
||||||
LLVMOrcModuleHandle
|
LLVMOrcModuleHandle
|
||||||
LLVMOrcTargetAddress
|
LLVMOrcTargetAddress
|
||||||
LLVMPassManagerBuilderRef
|
LLVMPassManagerBuilderRef
|
||||||
|
Loading…
x
Reference in New Issue
Block a user