PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
llvmjit.c File Reference
#include "postgres.h"
#include <llvm-c/Analysis.h>
#include <llvm-c/BitReader.h>
#include <llvm-c/BitWriter.h>
#include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Orc.h>
#include <llvm-c/OrcEE.h>
#include <llvm-c/LLJIT.h>
#include <llvm-c/Support.h>
#include <llvm-c/Target.h>
#include <llvm-c/Transforms/IPO.h>
#include <llvm-c/Transforms/PassManagerBuilder.h>
#include <llvm-c/Transforms/Scalar.h>
#include <llvm-c/Transforms/Utils.h>
#include "jit/llvmjit.h"
#include "jit/llvmjit_backport.h"
#include "jit/llvmjit_emit.h"
#include "miscadmin.h"
#include "portability/instr_time.h"
#include "storage/ipc.h"
#include "utils/memutils.h"
#include "utils/resowner.h"
Include dependency graph for llvmjit.c:

Go to the source code of this file.

Data Structures

struct  LLVMJitHandle
 

Macros

#define LLVMJIT_LLVM_CONTEXT_REUSE_MAX   100
 

Typedefs

typedef struct LLVMJitHandle LLVMJitHandle
 

Functions

static void llvm_release_context (JitContext *context)
 
static void llvm_session_initialize (void)
 
static void llvm_shutdown (int code, Datum arg)
 
static void llvm_compile_module (LLVMJitContext *context)
 
static void llvm_optimize_module (LLVMJitContext *context, LLVMModuleRef module)
 
static void llvm_create_types (void)
 
static void llvm_set_target (void)
 
static void llvm_recreate_llvm_context (void)
 
static uint64_t llvm_resolve_symbol (const char *name, void *ctx)
 
static LLVMOrcLLJITRef llvm_create_jit_instance (LLVMTargetMachineRef tm)
 
static char * llvm_error_message (LLVMErrorRef error)
 
static void ResOwnerReleaseJitContext (Datum res)
 
static void ResourceOwnerRememberJIT (ResourceOwner owner, LLVMJitContext *handle)
 
static void ResourceOwnerForgetJIT (ResourceOwner owner, LLVMJitContext *handle)
 
 PG_MODULE_MAGIC_EXT (.name="llvmjit",.version=PG_VERSION)
 
void _PG_jit_provider_init (JitProviderCallbacks *cb)
 
LLVMJitContext * llvm_create_context (int jitFlags)
 
LLVMModuleRef llvm_mutable_module (LLVMJitContext *context)
 
char * llvm_expand_funcname (struct LLVMJitContext *context, const char *basename)
 
void * llvm_get_function (LLVMJitContext *context, const char *funcname)
 
LLVMTypeRef llvm_pg_var_type (const char *varname)
 
LLVMTypeRef llvm_pg_var_func_type (const char *varname)
 
LLVMValueRef llvm_pg_func (LLVMModuleRef mod, const char *funcname)
 
static void llvm_copy_attributes_at_index (LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
 
void llvm_copy_attributes (LLVMValueRef v_from, LLVMValueRef v_to)
 
LLVMValueRef llvm_function_reference (LLVMJitContext *context, LLVMBuilderRef builder, LLVMModuleRef mod, FunctionCallInfo fcinfo)
 
static LLVMTypeRef load_return_type (LLVMModuleRef mod, const char *name)
 
void llvm_split_symbol_name (const char *name, char **modname, char **funcname)
 
static LLVMErrorRef llvm_resolve_symbols (LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx, LLVMOrcLookupStateRef *LookupState, LLVMOrcLookupKind Kind, LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags JDLookupFlags, LLVMOrcCLookupSet LookupSet, size_t LookupSetSize)
 
static void llvm_log_jit_error (void *ctx, LLVMErrorRef error)
 
static LLVMOrcObjectLayerRef llvm_create_object_layer (void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
 

Variables

LLVMTypeRef TypeSizeT
 
LLVMTypeRef TypeParamBool
 
LLVMTypeRef TypeStorageBool
 
LLVMTypeRef TypePGFunction
 
LLVMTypeRef StructNullableDatum
 
LLVMTypeRef StructHeapTupleData
 
LLVMTypeRef StructMinimalTupleData
 
LLVMTypeRef StructTupleDescData
 
LLVMTypeRef StructTupleTableSlot
 
LLVMTypeRef StructHeapTupleHeaderData
 
LLVMTypeRef StructHeapTupleTableSlot
 
LLVMTypeRef StructMinimalTupleTableSlot
 
LLVMTypeRef StructMemoryContextData
 
LLVMTypeRef StructFunctionCallInfoData
 
LLVMTypeRef StructExprContext
 
LLVMTypeRef StructExprEvalStep
 
LLVMTypeRef StructExprState
 
LLVMTypeRef StructAggState
 
LLVMTypeRef StructAggStatePerGroupData
 
LLVMTypeRef StructAggStatePerTransData
 
LLVMTypeRef StructPlanState
 
LLVMValueRef AttributeTemplate
 
LLVMValueRef ExecEvalSubroutineTemplate
 
LLVMValueRef ExecEvalBoolSubroutineTemplate
 
static LLVMModuleRef llvm_types_module = NULL
 
static bool llvm_session_initialized = false
 
static size_t llvm_generation = 0
 
static size_t llvm_jit_context_in_use_count = 0
 
static size_t llvm_llvm_context_reuse_count = 0
 
static const char * llvm_triple = NULL
 
static const char * llvm_layout = NULL
 
static LLVMContextRef llvm_context
 
static LLVMTargetRef llvm_targetref
 
static LLVMOrcThreadSafeContextRef llvm_ts_context
 
static LLVMOrcLLJITRef llvm_opt0_orc
 
static LLVMOrcLLJITRef llvm_opt3_orc
 
static const ResourceOwnerDesc jit_resowner_desc
 

Macro Definition Documentation

◆ LLVMJIT_LLVM_CONTEXT_REUSE_MAX

#define LLVMJIT_LLVM_CONTEXT_REUSE_MAX   100

Definition at line 45 of file llvmjit.c.

Typedef Documentation

◆ LLVMJitHandle

typedef struct LLVMJitHandle LLVMJitHandle

Function Documentation

◆ _PG_jit_provider_init()

void _PG_jit_provider_init ( JitProviderCallbacks cb)

Definition at line 151 of file llvmjit.c.

152{
156}
static void llvm_release_context(JitContext *context)
Definition: llvmjit.c:252
void llvm_reset_after_error(void)
bool llvm_compile_expr(ExprState *state)
Definition: llvmjit_expr.c:78
JitProviderCompileExprCB compile_expr
Definition: jit.h:78
JitProviderResetAfterErrorCB reset_after_error
Definition: jit.h:76
JitProviderReleaseContextCB release_context
Definition: jit.h:77

References JitProviderCallbacks::compile_expr, llvm_compile_expr(), llvm_release_context(), llvm_reset_after_error(), JitProviderCallbacks::release_context, and JitProviderCallbacks::reset_after_error.

◆ llvm_compile_module()

static void llvm_compile_module ( LLVMJitContext *  context)
static

Definition at line 705 of file llvmjit.c.

706{
707 LLVMJitHandle *handle;
708 MemoryContext oldcontext;
709 instr_time starttime;
710 instr_time endtime;
711 LLVMOrcLLJITRef compile_orc;
712
713 if (context->base.flags & PGJIT_OPT3)
714 compile_orc = llvm_opt3_orc;
715 else
716 compile_orc = llvm_opt0_orc;
717
718 /* perform inlining */
719 if (context->base.flags & PGJIT_INLINE)
720 {
721 INSTR_TIME_SET_CURRENT(starttime);
722 llvm_inline(context->module);
723 INSTR_TIME_SET_CURRENT(endtime);
724 INSTR_TIME_ACCUM_DIFF(context->base.instr.inlining_counter,
725 endtime, starttime);
726 }
727
729 {
730 char *filename;
731
732 filename = psprintf("%d.%zu.bc",
733 MyProcPid,
734 context->module_generation);
735 LLVMWriteBitcodeToFile(context->module, filename);
737 }
738
739
740 /* optimize according to the chosen optimization settings */
741 INSTR_TIME_SET_CURRENT(starttime);
742 llvm_optimize_module(context, context->module);
743 INSTR_TIME_SET_CURRENT(endtime);
744 INSTR_TIME_ACCUM_DIFF(context->base.instr.optimization_counter,
745 endtime, starttime);
746
748 {
749 char *filename;
750
751 filename = psprintf("%d.%zu.optimized.bc",
752 MyProcPid,
753 context->module_generation);
754 LLVMWriteBitcodeToFile(context->module, filename);
756 }
757
758 handle = (LLVMJitHandle *)
760
761 /*
762 * Emit the code. Note that this can, depending on the optimization
763 * settings, take noticeable resources as code emission executes low-level
764 * instruction combining/selection passes etc. Without optimization a
765 * faster instruction selection mechanism is used.
766 */
767 INSTR_TIME_SET_CURRENT(starttime);
768 {
769 LLVMOrcThreadSafeModuleRef ts_module;
770 LLVMErrorRef error;
771 LLVMOrcJITDylibRef jd = LLVMOrcLLJITGetMainJITDylib(compile_orc);
772
773 ts_module = LLVMOrcCreateNewThreadSafeModule(context->module, llvm_ts_context);
774
775 handle->lljit = compile_orc;
776 handle->resource_tracker = LLVMOrcJITDylibCreateResourceTracker(jd);
777
778 /*
779 * NB: This doesn't actually emit code. That happens lazily the first
780 * time a symbol defined in the module is requested. Due to that
781 * llvm_get_function() also accounts for emission time.
782 */
783
784 context->module = NULL; /* will be owned by LLJIT */
785 error = LLVMOrcLLJITAddLLVMIRModuleWithRT(compile_orc,
786 handle->resource_tracker,
787 ts_module);
788
789 if (error)
790 elog(ERROR, "failed to JIT module: %s",
792
793 /* LLVMOrcLLJITAddLLVMIRModuleWithRT takes ownership of the module */
794 }
795
796 INSTR_TIME_SET_CURRENT(endtime);
797 INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
798 endtime, starttime);
799
800 context->module = NULL;
801 context->compiled = true;
802
803 /* remember emitted code for cleanup and lookups */
805 context->handles = lappend(context->handles, handle);
806 MemoryContextSwitchTo(oldcontext);
807
809 (errmsg_internal("time to inline: %.3fs, opt: %.3fs, emit: %.3fs",
810 INSTR_TIME_GET_DOUBLE(context->base.instr.inlining_counter),
811 INSTR_TIME_GET_DOUBLE(context->base.instr.optimization_counter),
812 INSTR_TIME_GET_DOUBLE(context->base.instr.emission_counter)),
813 errhidestmt(true),
814 errhidecontext(true)));
815}
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1158
int errhidestmt(bool hide_stmt)
Definition: elog.c:1433
int errhidecontext(bool hide_ctx)
Definition: elog.c:1452
#define DEBUG1
Definition: elog.h:30
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:225
#define ereport(elevel,...)
Definition: elog.h:149
int MyProcPid
Definition: globals.c:48
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:122
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:188
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
Definition: instr_time.h:184
bool jit_dump_bitcode
Definition: jit.c:35
#define PGJIT_OPT3
Definition: jit.h:21
#define PGJIT_INLINE
Definition: jit.h:22
List * lappend(List *list, void *datum)
Definition: list.c:339
static LLVMOrcLLJITRef llvm_opt3_orc
Definition: llvmjit.c:100
static LLVMOrcLLJITRef llvm_opt0_orc
Definition: llvmjit.c:99
static char * llvm_error_message(LLVMErrorRef error)
Definition: llvmjit.c:1260
static LLVMOrcThreadSafeContextRef llvm_ts_context
Definition: llvmjit.c:98
static void llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
Definition: llvmjit.c:603
void llvm_inline(LLVMModuleRef M)
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1260
void pfree(void *pointer)
Definition: mcxt.c:2152
MemoryContext TopMemoryContext
Definition: mcxt.c:165
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static char * filename
Definition: pg_dumpall.c:124
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
static void error(void)
Definition: sql-dyntest.c:147
LLVMOrcLLJITRef lljit
Definition: llvmjit.c:50
LLVMOrcResourceTrackerRef resource_tracker
Definition: llvmjit.c:51

References DEBUG1, elog, ereport, errhidecontext(), errhidestmt(), errmsg_internal(), ERROR, error(), filename, INSTR_TIME_ACCUM_DIFF, INSTR_TIME_GET_DOUBLE, INSTR_TIME_SET_CURRENT, jit_dump_bitcode, lappend(), LLVMJitHandle::lljit, llvm_error_message(), llvm_inline(), llvm_opt0_orc, llvm_opt3_orc, llvm_optimize_module(), llvm_ts_context, MemoryContextAlloc(), MemoryContextSwitchTo(), MyProcPid, pfree(), PGJIT_INLINE, PGJIT_OPT3, psprintf(), LLVMJitHandle::resource_tracker, and TopMemoryContext.

Referenced by llvm_get_function().

◆ llvm_copy_attributes()

void llvm_copy_attributes ( LLVMValueRef  v_from,
LLVMValueRef  v_to 
)

Definition at line 516 of file llvmjit.c.

517{
518 uint32 param_count;
519
520 /* copy function attributes */
521 llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeFunctionIndex);
522
523 if (LLVMGetTypeKind(LLVMGetFunctionReturnType(v_to)) != LLVMVoidTypeKind)
524 {
525 /* and the return value attributes */
526 llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeReturnIndex);
527 }
528
529 /* and each function parameter's attribute */
530 param_count = LLVMCountParams(v_from);
531
532 for (int paramidx = 1; paramidx <= param_count; paramidx++)
533 llvm_copy_attributes_at_index(v_from, v_to, paramidx);
534}
uint32_t uint32
Definition: c.h:502
static void llvm_copy_attributes_at_index(LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
Definition: llvmjit.c:492
LLVMTypeRef LLVMGetFunctionReturnType(LLVMValueRef r)

References llvm_copy_attributes_at_index(), and LLVMGetFunctionReturnType().

Referenced by llvm_pg_func(), and slot_compile_deform().

◆ llvm_copy_attributes_at_index()

static void llvm_copy_attributes_at_index ( LLVMValueRef  v_from,
LLVMValueRef  v_to,
uint32  index 
)
static

Definition at line 492 of file llvmjit.c.

493{
494 int num_attributes;
495 LLVMAttributeRef *attrs;
496
497 num_attributes = LLVMGetAttributeCountAtIndex(v_from, index);
498
499 if (num_attributes == 0)
500 return;
501
502 attrs = palloc(sizeof(LLVMAttributeRef) * num_attributes);
503 LLVMGetAttributesAtIndex(v_from, index, attrs);
504
505 for (int attno = 0; attno < num_attributes; attno++)
506 LLVMAddAttributeAtIndex(v_to, index, attrs[attno]);
507
508 pfree(attrs);
509}
void * palloc(Size size)
Definition: mcxt.c:1945
Definition: type.h:96

References palloc(), and pfree().

Referenced by llvm_copy_attributes().

◆ llvm_create_context()

LLVMJitContext * llvm_create_context ( int  jitFlags)

Definition at line 223 of file llvmjit.c.

224{
225 LLVMJitContext *context;
226
228
230
232
234
236 sizeof(LLVMJitContext));
237 context->base.flags = jitFlags;
238
239 /* ensure cleanup */
240 context->resowner = CurrentResourceOwner;
242
244
245 return context;
246}
static void llvm_recreate_llvm_context(void)
Definition: llvmjit.c:173
static void ResourceOwnerRememberJIT(ResourceOwner owner, LLVMJitContext *handle)
Definition: llvmjit.c:131
static void llvm_session_initialize(void)
Definition: llvmjit.c:821
static size_t llvm_jit_context_in_use_count
Definition: llvmjit.c:88
void llvm_assert_in_fatal_section(void)
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1294
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:452

References CurrentResourceOwner, llvm_assert_in_fatal_section(), llvm_jit_context_in_use_count, llvm_recreate_llvm_context(), llvm_session_initialize(), MemoryContextAllocZero(), ResourceOwnerEnlarge(), ResourceOwnerRememberJIT(), and TopMemoryContext.

Referenced by llvm_compile_expr().

◆ llvm_create_jit_instance()

static LLVMOrcLLJITRef llvm_create_jit_instance ( LLVMTargetMachineRef  tm)
static

Definition at line 1208 of file llvmjit.c.

1209{
1210 LLVMOrcLLJITRef lljit;
1211 LLVMOrcJITTargetMachineBuilderRef tm_builder;
1212 LLVMOrcLLJITBuilderRef lljit_builder;
1213 LLVMErrorRef error;
1214 LLVMOrcDefinitionGeneratorRef main_gen;
1215 LLVMOrcDefinitionGeneratorRef ref_gen;
1216
1217 lljit_builder = LLVMOrcCreateLLJITBuilder();
1218 tm_builder = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm);
1219 LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(lljit_builder, tm_builder);
1220
1221 LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(lljit_builder,
1223 NULL);
1224
1225 error = LLVMOrcCreateLLJIT(&lljit, lljit_builder);
1226 if (error)
1227 elog(ERROR, "failed to create lljit instance: %s",
1229
1230 LLVMOrcExecutionSessionSetErrorReporter(LLVMOrcLLJITGetExecutionSession(lljit),
1231 llvm_log_jit_error, NULL);
1232
1233 /*
1234 * Symbol resolution support for symbols in the postgres binary /
1235 * libraries already loaded.
1236 */
1237 error = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(&main_gen,
1238 LLVMOrcLLJITGetGlobalPrefix(lljit),
1239 0, NULL);
1240 if (error)
1241 elog(ERROR, "failed to create generator: %s",
1243 LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), main_gen);
1244
1245 /*
1246 * Symbol resolution support for "special" functions, e.g. a call into an
1247 * SQL callable function.
1248 */
1249#if LLVM_VERSION_MAJOR > 14
1250 ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL, NULL);
1251#else
1252 ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL);
1253#endif
1254 LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), ref_gen);
1255
1256 return lljit;
1257}
static LLVMOrcObjectLayerRef llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
Definition: llvmjit.c:1171
static LLVMErrorRef llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx, LLVMOrcLookupStateRef *LookupState, LLVMOrcLookupKind Kind, LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags JDLookupFlags, LLVMOrcCLookupSet LookupSet, size_t LookupSetSize)
Definition: llvmjit.c:1118
static void llvm_log_jit_error(void *ctx, LLVMErrorRef error)
Definition: llvmjit.c:1161
static struct pg_tm tm
Definition: localtime.c:104

References elog, ERROR, error(), llvm_create_object_layer(), llvm_error_message(), llvm_log_jit_error(), llvm_resolve_symbols(), and tm.

Referenced by llvm_session_initialize().

◆ llvm_create_object_layer()

static LLVMOrcObjectLayerRef llvm_create_object_layer ( void *  Ctx,
LLVMOrcExecutionSessionRef  ES,
const char *  Triple 
)
static

Definition at line 1171 of file llvmjit.c.

1172{
1173#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
1174 LLVMOrcObjectLayerRef objlayer =
1175 LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
1176#else
1177 LLVMOrcObjectLayerRef objlayer =
1178 LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
1179#endif
1180
1181
1182#if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
1184 {
1185 LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
1186
1187 LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
1188 }
1189#endif
1190
1191#if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
1193 {
1194 LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
1195
1196 LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
1197 }
1198#endif
1199
1200 return objlayer;
1201}
bool jit_profiling_support
Definition: jit.c:37
bool jit_debugging_support
Definition: jit.c:34

References jit_debugging_support, and jit_profiling_support.

Referenced by llvm_create_jit_instance().

◆ llvm_create_types()

static void llvm_create_types ( void  )
static

Definition at line 991 of file llvmjit.c.

992{
993 char path[MAXPGPATH];
994 LLVMMemoryBufferRef buf;
995 char *msg;
996
997 snprintf(path, MAXPGPATH, "%s/%s", pkglib_path, "llvmjit_types.bc");
998
999 /* open file */
1000 if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buf, &msg))
1001 {
1002 elog(ERROR, "LLVMCreateMemoryBufferWithContentsOfFile(%s) failed: %s",
1003 path, msg);
1004 }
1005
1006 /* eagerly load contents, going to need it all */
1007 if (LLVMParseBitcodeInContext2(llvm_context, buf, &llvm_types_module))
1008 {
1009 elog(ERROR, "LLVMParseBitcodeInContext2 of %s failed", path);
1010 }
1011 LLVMDisposeMemoryBuffer(buf);
1012
1013 TypeSizeT = llvm_pg_var_type("TypeSizeT");
1014 TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
1015 TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
1016 TypePGFunction = llvm_pg_var_type("TypePGFunction");
1017 StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
1018 StructExprContext = llvm_pg_var_type("StructExprContext");
1019 StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
1020 StructExprState = llvm_pg_var_type("StructExprState");
1021 StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
1022 StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
1023 StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
1024 StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
1025 StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
1026 StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
1027 StructHeapTupleHeaderData = llvm_pg_var_type("StructHeapTupleHeaderData");
1028 StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
1029 StructAggState = llvm_pg_var_type("StructAggState");
1030 StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
1031 StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
1032 StructPlanState = llvm_pg_var_type("StructPlanState");
1033 StructMinimalTupleData = llvm_pg_var_type("StructMinimalTupleData");
1034
1035 AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
1036 ExecEvalSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalSubroutineTemplate");
1037 ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalBoolSubroutineTemplate");
1038}
char pkglib_path[MAXPGPATH]
Definition: globals.c:83
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:69
LLVMTypeRef StructMinimalTupleData
Definition: llvmjit.c:62
LLVMTypeRef StructMinimalTupleTableSlot
Definition: llvmjit.c:67
LLVMTypeRef StructPlanState
Definition: llvmjit.c:76
static LLVMContextRef llvm_context
Definition: llvmjit.c:94
LLVMTypeRef StructExprState
Definition: llvmjit.c:72
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:71
LLVMTypeRef TypeParamBool
Definition: llvmjit.c:57
LLVMTypeRef StructMemoryContextData
Definition: llvmjit.c:68
LLVMTypeRef StructAggStatePerGroupData
Definition: llvmjit.c:74
LLVMTypeRef llvm_pg_var_type(const char *varname)
Definition: llvmjit.c:422
LLVMTypeRef TypeSizeT
Definition: llvmjit.c:56
LLVMTypeRef StructTupleTableSlot
Definition: llvmjit.c:64
LLVMTypeRef TypeStorageBool
Definition: llvmjit.c:58
static LLVMTypeRef load_return_type(LLVMModuleRef mod, const char *name)
Definition: llvmjit.c:952
LLVMTypeRef StructHeapTupleTableSlot
Definition: llvmjit.c:66
static LLVMModuleRef llvm_types_module
Definition: llvmjit.c:82
LLVMTypeRef StructAggState
Definition: llvmjit.c:73
LLVMTypeRef TypePGFunction
Definition: llvmjit.c:59
LLVMTypeRef StructTupleDescData
Definition: llvmjit.c:63
LLVMValueRef AttributeTemplate
Definition: llvmjit.c:78
LLVMTypeRef StructExprContext
Definition: llvmjit.c:70
LLVMTypeRef StructHeapTupleHeaderData
Definition: llvmjit.c:65
LLVMTypeRef StructHeapTupleData
Definition: llvmjit.c:61
LLVMTypeRef StructNullableDatum
Definition: llvmjit.c:60
LLVMValueRef ExecEvalSubroutineTemplate
Definition: llvmjit.c:79
LLVMValueRef ExecEvalBoolSubroutineTemplate
Definition: llvmjit.c:80
LLVMTypeRef StructAggStatePerTransData
Definition: llvmjit.c:75
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:72
#define snprintf
Definition: port.h:239

References AttributeTemplate, buf, elog, ERROR, ExecEvalBoolSubroutineTemplate, ExecEvalSubroutineTemplate, llvm_context, llvm_pg_var_type(), llvm_types_module, load_return_type(), MAXPGPATH, pkglib_path, snprintf, StructAggState, StructAggStatePerGroupData, StructAggStatePerTransData, StructExprContext, StructExprEvalStep, StructExprState, StructFunctionCallInfoData, StructHeapTupleData, StructHeapTupleHeaderData, StructHeapTupleTableSlot, StructMemoryContextData, StructMinimalTupleData, StructMinimalTupleTableSlot, StructNullableDatum, StructPlanState, StructTupleDescData, StructTupleTableSlot, TypeParamBool, TypePGFunction, TypeSizeT, and TypeStorageBool.

Referenced by llvm_recreate_llvm_context(), and llvm_session_initialize().

◆ llvm_error_message()

static char * llvm_error_message ( LLVMErrorRef  error)
static

Definition at line 1260 of file llvmjit.c.

1261{
1262 char *orig = LLVMGetErrorMessage(error);
1263 char *msg = pstrdup(orig);
1264
1265 LLVMDisposeErrorMessage(orig);
1266
1267 return msg;
1268}
char * pstrdup(const char *in)
Definition: mcxt.c:2327

References error(), and pstrdup().

Referenced by llvm_compile_module(), llvm_create_jit_instance(), llvm_get_function(), llvm_log_jit_error(), and llvm_optimize_module().

◆ llvm_expand_funcname()

char * llvm_expand_funcname ( struct LLVMJitContext *  context,
const char *  basename 
)

Definition at line 341 of file llvmjit.c.

342{
343 Assert(context->module != NULL);
344
345 context->base.instr.created_functions++;
346
347 /*
348 * Previously we used dots to separate, but turns out some tools, e.g.
349 * GDB, don't like that and truncate name.
350 */
351 return psprintf("%s_%zu_%d",
352 basename,
353 context->module_generation,
354 context->counter++);
355}
Assert(PointerIsAligned(start, uint64))

References Assert(), and psprintf().

Referenced by slot_compile_deform().

◆ llvm_function_reference()

LLVMValueRef llvm_function_reference ( LLVMJitContext *  context,
LLVMBuilderRef  builder,
LLVMModuleRef  mod,
FunctionCallInfo  fcinfo 
)

Definition at line 540 of file llvmjit.c.

544{
545 char *modname;
546 char *basename;
547 char *funcname;
548
549 LLVMValueRef v_fn;
550
551 fmgr_symbol(fcinfo->flinfo->fn_oid, &modname, &basename);
552
553 if (modname != NULL && basename != NULL)
554 {
555 /* external function in loadable library */
556 funcname = psprintf("pgextern.%s.%s", modname, basename);
557 }
558 else if (basename != NULL)
559 {
560 /* internal function */
561 funcname = pstrdup(basename);
562 }
563 else
564 {
565 /*
566 * Function we don't know to handle, return pointer. We do so by
567 * creating a global constant containing a pointer to the function.
568 * Makes IR more readable.
569 */
570 LLVMValueRef v_fn_addr;
571
572 funcname = psprintf("pgoidextern.%u",
573 fcinfo->flinfo->fn_oid);
574 v_fn = LLVMGetNamedGlobal(mod, funcname);
575 if (v_fn != 0)
576 return l_load(builder, TypePGFunction, v_fn, "");
577
578 v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction);
579
580 v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname);
581 LLVMSetInitializer(v_fn, v_fn_addr);
582 LLVMSetGlobalConstant(v_fn, true);
583 LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
584 LLVMSetUnnamedAddr(v_fn, true);
585
586 return l_load(builder, TypePGFunction, v_fn, "");
587 }
588
589 /* check if function already has been added */
590 v_fn = LLVMGetNamedFunction(mod, funcname);
591 if (v_fn != 0)
592 return v_fn;
593
594 v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(AttributeTemplate));
595
596 return v_fn;
597}
void fmgr_symbol(Oid functionId, char **mod, char **fn)
Definition: fmgr.c:281
#define funcname
Definition: indent_codes.h:69
LLVMTypeRef LLVMGetFunctionType(LLVMValueRef r)
PGFunction fn_addr
Definition: fmgr.h:58
Oid fn_oid
Definition: fmgr.h:59
FmgrInfo * flinfo
Definition: fmgr.h:87

References AttributeTemplate, FunctionCallInfoBaseData::flinfo, fmgr_symbol(), FmgrInfo::fn_addr, FmgrInfo::fn_oid, funcname, LLVMGetFunctionType(), psprintf(), pstrdup(), and TypePGFunction.

Referenced by BuildV1Call().

◆ llvm_get_function()

void * llvm_get_function ( LLVMJitContext *  context,
const char *  funcname 
)

Definition at line 362 of file llvmjit.c.

363{
364 ListCell *lc;
365
367
368 /*
369 * If there is a pending / not emitted module, compile and emit now.
370 * Otherwise we might not find the [correct] function.
371 */
372 if (!context->compiled)
373 {
374 llvm_compile_module(context);
375 }
376
377 /*
378 * ORC's symbol table is of *unmangled* symbols. Therefore we don't need
379 * to mangle here.
380 */
381
382 foreach(lc, context->handles)
383 {
384 LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc);
385 instr_time starttime;
386 instr_time endtime;
387 LLVMErrorRef error;
388 LLVMOrcJITTargetAddress addr;
389
390 INSTR_TIME_SET_CURRENT(starttime);
391
392 addr = 0;
393 error = LLVMOrcLLJITLookup(handle->lljit, &addr, funcname);
394 if (error)
395 elog(ERROR, "failed to look up symbol \"%s\": %s",
397
398 /*
399 * LLJIT only actually emits code the first time a symbol is
400 * referenced. Thus add lookup time to emission time. That's counting
401 * a bit more than with older LLVM versions, but unlikely to ever
402 * matter.
403 */
404 INSTR_TIME_SET_CURRENT(endtime);
405 INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
406 endtime, starttime);
407
408 if (addr)
409 return (void *) (uintptr_t) addr;
410 }
411
412 elog(ERROR, "failed to JIT: %s", funcname);
413
414 return NULL;
415}
static void llvm_compile_module(LLVMJitContext *context)
Definition: llvmjit.c:705
#define lfirst(lc)
Definition: pg_list.h:172

References elog, ERROR, error(), funcname, INSTR_TIME_ACCUM_DIFF, INSTR_TIME_SET_CURRENT, lfirst, LLVMJitHandle::lljit, llvm_assert_in_fatal_section(), llvm_compile_module(), and llvm_error_message().

Referenced by ExecRunCompiledExpr().

◆ llvm_log_jit_error()

static void llvm_log_jit_error ( void *  ctx,
LLVMErrorRef  error 
)
static

Definition at line 1161 of file llvmjit.c.

1162{
1163 elog(WARNING, "error during JITing: %s",
1165}
#define WARNING
Definition: elog.h:36

References elog, error(), llvm_error_message(), and WARNING.

Referenced by llvm_create_jit_instance().

◆ llvm_mutable_module()

LLVMModuleRef llvm_mutable_module ( LLVMJitContext *  context)

Definition at line 316 of file llvmjit.c.

317{
319
320 /*
321 * If there's no in-progress module, create a new one.
322 */
323 if (!context->module)
324 {
325 context->compiled = false;
326 context->module_generation = llvm_generation++;
327 context->module = LLVMModuleCreateWithNameInContext("pg", llvm_context);
328 LLVMSetTarget(context->module, llvm_triple);
329 LLVMSetDataLayout(context->module, llvm_layout);
330 }
331
332 return context->module;
333}
static const char * llvm_triple
Definition: llvmjit.c:92
static const char * llvm_layout
Definition: llvmjit.c:93
static size_t llvm_generation
Definition: llvmjit.c:85

References llvm_assert_in_fatal_section(), llvm_context, llvm_generation, llvm_layout, and llvm_triple.

Referenced by slot_compile_deform().

◆ llvm_optimize_module()

static void llvm_optimize_module ( LLVMJitContext *  context,
LLVMModuleRef  module 
)
static

Definition at line 603 of file llvmjit.c.

604{
605#if LLVM_VERSION_MAJOR < 17
606 LLVMPassManagerBuilderRef llvm_pmb;
607 LLVMPassManagerRef llvm_mpm;
608 LLVMPassManagerRef llvm_fpm;
609 LLVMValueRef func;
610 int compile_optlevel;
611
612 if (context->base.flags & PGJIT_OPT3)
613 compile_optlevel = 3;
614 else
615 compile_optlevel = 0;
616
617 /*
618 * Have to create a new pass manager builder every pass through, as the
619 * inliner has some per-builder state. Otherwise one ends up only inlining
620 * a function the first time though.
621 */
622 llvm_pmb = LLVMPassManagerBuilderCreate();
623 LLVMPassManagerBuilderSetOptLevel(llvm_pmb, compile_optlevel);
624 llvm_fpm = LLVMCreateFunctionPassManagerForModule(module);
625
626 if (context->base.flags & PGJIT_OPT3)
627 {
628 /* TODO: Unscientifically determined threshold */
629 LLVMPassManagerBuilderUseInlinerWithThreshold(llvm_pmb, 512);
630 }
631 else
632 {
633 /* we rely on mem2reg heavily, so emit even in the O0 case */
634 LLVMAddPromoteMemoryToRegisterPass(llvm_fpm);
635 }
636
637 LLVMPassManagerBuilderPopulateFunctionPassManager(llvm_pmb, llvm_fpm);
638
639 /*
640 * Do function level optimization. This could be moved to the point where
641 * functions are emitted, to reduce memory usage a bit.
642 */
643 LLVMInitializeFunctionPassManager(llvm_fpm);
644 for (func = LLVMGetFirstFunction(context->module);
645 func != NULL;
646 func = LLVMGetNextFunction(func))
647 LLVMRunFunctionPassManager(llvm_fpm, func);
648 LLVMFinalizeFunctionPassManager(llvm_fpm);
649 LLVMDisposePassManager(llvm_fpm);
650
651 /*
652 * Perform module level optimization. We do so even in the non-optimized
653 * case, so always-inline functions etc get inlined. It's cheap enough.
654 */
655 llvm_mpm = LLVMCreatePassManager();
656 LLVMPassManagerBuilderPopulateModulePassManager(llvm_pmb,
657 llvm_mpm);
658 /* always use always-inliner pass */
659 if (!(context->base.flags & PGJIT_OPT3))
660 LLVMAddAlwaysInlinerPass(llvm_mpm);
661 /* if doing inlining, but no expensive optimization, add inlining pass */
662 if (context->base.flags & PGJIT_INLINE
663 && !(context->base.flags & PGJIT_OPT3))
664 LLVMAddFunctionInliningPass(llvm_mpm);
665 LLVMRunPassManager(llvm_mpm, context->module);
666 LLVMDisposePassManager(llvm_mpm);
667
668 LLVMPassManagerBuilderDispose(llvm_pmb);
669#else
670 LLVMPassBuilderOptionsRef options;
671 LLVMErrorRef err;
672 const char *passes;
673
674 if (context->base.flags & PGJIT_OPT3)
675 passes = "default<O3>";
676 else
677 passes = "default<O0>,mem2reg";
678
679 options = LLVMCreatePassBuilderOptions();
680
681#ifdef LLVM_PASS_DEBUG
682 LLVMPassBuilderOptionsSetDebugLogging(options, 1);
683#endif
684
685 /* In assertion builds, run the LLVM verify pass. */
686#ifdef USE_ASSERT_CHECKING
687 LLVMPassBuilderOptionsSetVerifyEach(options, true);
688#endif
689
690 LLVMPassBuilderOptionsSetInlinerThreshold(options, 512);
691
692 err = LLVMRunPasses(module, passes, NULL, options);
693
694 if (err)
695 elog(ERROR, "failed to JIT module: %s", llvm_error_message(err));
696
697 LLVMDisposePassBuilderOptions(options);
698#endif
699}
void err(int eval, const char *fmt,...)
Definition: err.c:43
static char ** options

References elog, err(), ERROR, llvm_error_message(), options, PGJIT_INLINE, and PGJIT_OPT3.

Referenced by llvm_compile_module().

◆ llvm_pg_func()

LLVMValueRef llvm_pg_func ( LLVMModuleRef  mod,
const char *  funcname 
)

Definition at line 464 of file llvmjit.c.

465{
466 LLVMValueRef v_srcfn;
467 LLVMValueRef v_fn;
468
469 /* don't repeatedly add function */
470 v_fn = LLVMGetNamedFunction(mod, funcname);
471 if (v_fn)
472 return v_fn;
473
474 v_srcfn = LLVMGetNamedFunction(llvm_types_module, funcname);
475
476 if (!v_srcfn)
477 elog(ERROR, "function %s not in llvmjit_types.c", funcname);
478
479 v_fn = LLVMAddFunction(mod,
480 funcname,
481 LLVMGetFunctionType(v_srcfn));
482 llvm_copy_attributes(v_srcfn, v_fn);
483
484 return v_fn;
485}
void llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
Definition: llvmjit.c:516

References elog, ERROR, funcname, llvm_copy_attributes(), llvm_types_module, and LLVMGetFunctionType().

Referenced by build_EvalXFuncInt(), and slot_compile_deform().

◆ llvm_pg_var_func_type()

LLVMTypeRef llvm_pg_var_func_type ( const char *  varname)

Definition at line 442 of file llvmjit.c.

443{
444 LLVMValueRef v_srcvar;
445 LLVMTypeRef typ;
446
447 v_srcvar = LLVMGetNamedFunction(llvm_types_module, varname);
448 if (!v_srcvar)
449 elog(ERROR, "function %s not in llvmjit_types.c", varname);
450
451 typ = LLVMGetFunctionType(v_srcvar);
452
453 return typ;
454}

References elog, ERROR, llvm_types_module, and LLVMGetFunctionType().

Referenced by slot_compile_deform().

◆ llvm_pg_var_type()

LLVMTypeRef llvm_pg_var_type ( const char *  varname)

Definition at line 422 of file llvmjit.c.

423{
424 LLVMValueRef v_srcvar;
425 LLVMTypeRef typ;
426
427 /* this'll return a *pointer* to the global */
428 v_srcvar = LLVMGetNamedGlobal(llvm_types_module, varname);
429 if (!v_srcvar)
430 elog(ERROR, "variable %s not in llvmjit_types.c", varname);
431
432 typ = LLVMGlobalGetValueType(v_srcvar);
433
434 return typ;
435}

References elog, ERROR, and llvm_types_module.

Referenced by llvm_create_types().

◆ llvm_recreate_llvm_context()

static void llvm_recreate_llvm_context ( void  )
static

Definition at line 173 of file llvmjit.c.

174{
175 if (!llvm_context)
176 elog(ERROR, "Trying to recreate a non-existing context");
177
178 /*
179 * We can only safely recreate the LLVM context if no other code is being
180 * JITed, otherwise we'd release the types in use for that.
181 */
183 {
185 return;
186 }
187
189 {
191 return;
192 }
193
194 /*
195 * Need to reset the modules that the inlining code caches before
196 * disposing of the context. LLVM modules exist within a specific LLVM
197 * context, therefore disposing of the context before resetting the cache
198 * would lead to dangling pointers to modules.
199 */
201
202 LLVMContextDispose(llvm_context);
203 llvm_context = LLVMContextCreate();
205
206 /*
207 * Re-build cached type information, so code generation code can rely on
208 * that information to be present (also prevents the variables to be
209 * dangling references).
210 */
212}
static void llvm_create_types(void)
Definition: llvmjit.c:991
#define LLVMJIT_LLVM_CONTEXT_REUSE_MAX
Definition: llvmjit.c:45
static size_t llvm_llvm_context_reuse_count
Definition: llvmjit.c:91
void llvm_inline_reset_caches(void)

References elog, ERROR, llvm_context, llvm_create_types(), llvm_inline_reset_caches(), llvm_jit_context_in_use_count, llvm_llvm_context_reuse_count, and LLVMJIT_LLVM_CONTEXT_REUSE_MAX.

Referenced by llvm_create_context().

◆ llvm_release_context()

static void llvm_release_context ( JitContext context)
static

Definition at line 252 of file llvmjit.c.

253{
254 LLVMJitContext *llvm_jit_context = (LLVMJitContext *) context;
255 ListCell *lc;
256
257 /*
258 * Consider as cleaned up even if we skip doing so below, that way we can
259 * verify the tracking is correct (see llvm_shutdown()).
260 */
262
263 /*
264 * When this backend is exiting, don't clean up LLVM. As an error might
265 * have occurred from within LLVM, we do not want to risk reentering. All
266 * resource cleanup is going to happen through process exit.
267 */
269 return;
270
272
273 if (llvm_jit_context->module)
274 {
275 LLVMDisposeModule(llvm_jit_context->module);
276 llvm_jit_context->module = NULL;
277 }
278
279 foreach(lc, llvm_jit_context->handles)
280 {
281 LLVMJitHandle *jit_handle = (LLVMJitHandle *) lfirst(lc);
282
283 {
284 LLVMOrcExecutionSessionRef ee;
285 LLVMOrcSymbolStringPoolRef sp;
286
287 LLVMOrcResourceTrackerRemove(jit_handle->resource_tracker);
288 LLVMOrcReleaseResourceTracker(jit_handle->resource_tracker);
289
290 /*
291 * Without triggering cleanup of the string pool, we'd leak
292 * memory. It'd be sufficient to do this far less often, but in
293 * experiments the required time was small enough to just always
294 * do it.
295 */
296 ee = LLVMOrcLLJITGetExecutionSession(jit_handle->lljit);
297 sp = LLVMOrcExecutionSessionGetSymbolStringPool(ee);
298 LLVMOrcSymbolStringPoolClearDeadEntries(sp);
299 }
300
301 pfree(jit_handle);
302 }
303 list_free(llvm_jit_context->handles);
304 llvm_jit_context->handles = NIL;
305
307
308 if (llvm_jit_context->resowner)
309 ResourceOwnerForgetJIT(llvm_jit_context->resowner, llvm_jit_context);
310}
bool proc_exit_inprogress
Definition: ipc.c:40
void list_free(List *list)
Definition: list.c:1546
static void ResourceOwnerForgetJIT(ResourceOwner owner, LLVMJitContext *handle)
Definition: llvmjit.c:136
void llvm_enter_fatal_on_oom(void)
void llvm_leave_fatal_on_oom(void)
#define NIL
Definition: pg_list.h:68

References lfirst, list_free(), LLVMJitHandle::lljit, llvm_enter_fatal_on_oom(), llvm_jit_context_in_use_count, llvm_leave_fatal_on_oom(), NIL, pfree(), proc_exit_inprogress, LLVMJitHandle::resource_tracker, and ResourceOwnerForgetJIT().

Referenced by _PG_jit_provider_init().

◆ llvm_resolve_symbol()

static uint64_t llvm_resolve_symbol ( const char *  name,
void *  ctx 
)
static

Definition at line 1079 of file llvmjit.c.

1080{
1081 uintptr_t addr;
1082 char *funcname;
1083 char *modname;
1084
1085 /*
1086 * macOS prefixes all object level symbols with an underscore. But neither
1087 * dlsym() nor PG's inliner expect that. So undo.
1088 */
1089#if defined(__darwin__)
1090 if (symname[0] != '_')
1091 elog(ERROR, "expected prefixed symbol name, but got \"%s\"", symname);
1092 symname++;
1093#endif
1094
1095 llvm_split_symbol_name(symname, &modname, &funcname);
1096
1097 /* functions that aren't resolved to names shouldn't ever get here */
1099
1100 if (modname)
1101 addr = (uintptr_t) load_external_function(modname, funcname,
1102 true, NULL);
1103 else
1104 addr = (uintptr_t) LLVMSearchForAddressOfSymbol(symname);
1105
1106 pfree(funcname);
1107 if (modname)
1108 pfree(modname);
1109
1110 /* let LLVM will error out - should never happen */
1111 if (!addr)
1112 elog(WARNING, "failed to resolve name %s", symname);
1113
1114 return (uint64_t) addr;
1115}
void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
Definition: dfmgr.c:95
void llvm_split_symbol_name(const char *name, char **modname, char **funcname)
Definition: llvmjit.c:1045

References Assert(), elog, ERROR, funcname, llvm_split_symbol_name(), load_external_function(), pfree(), and WARNING.

Referenced by llvm_resolve_symbols().

◆ llvm_resolve_symbols()

static LLVMErrorRef llvm_resolve_symbols ( LLVMOrcDefinitionGeneratorRef  GeneratorObj,
void *  Ctx,
LLVMOrcLookupStateRef *  LookupState,
LLVMOrcLookupKind  Kind,
LLVMOrcJITDylibRef  JD,
LLVMOrcJITDylibLookupFlags  JDLookupFlags,
LLVMOrcCLookupSet  LookupSet,
size_t  LookupSetSize 
)
static

Definition at line 1118 of file llvmjit.c.

1122{
1123#if LLVM_VERSION_MAJOR > 14
1124 LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMOrcCSymbolMapPair) * LookupSetSize);
1125#else
1126 LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMJITCSymbolMapPair) * LookupSetSize);
1127#endif
1128 LLVMErrorRef error;
1129 LLVMOrcMaterializationUnitRef mu;
1130
1131 for (int i = 0; i < LookupSetSize; i++)
1132 {
1133 const char *name = LLVMOrcSymbolStringPoolEntryStr(LookupSet[i].Name);
1134
1135 LLVMOrcRetainSymbolStringPoolEntry(LookupSet[i].Name);
1136 symbols[i].Name = LookupSet[i].Name;
1137 symbols[i].Sym.Address = llvm_resolve_symbol(name, NULL);
1138 symbols[i].Sym.Flags.GenericFlags = LLVMJITSymbolGenericFlagsExported;
1139 }
1140
1141 mu = LLVMOrcAbsoluteSymbols(symbols, LookupSetSize);
1142 error = LLVMOrcJITDylibDefine(JD, mu);
1143 if (error != LLVMErrorSuccess)
1144 LLVMOrcDisposeMaterializationUnit(mu);
1145
1146 pfree(symbols);
1147
1148 return error;
1149}
int i
Definition: isn.c:77
static uint64_t llvm_resolve_symbol(const char *name, void *ctx)
Definition: llvmjit.c:1079
void * palloc0(Size size)
Definition: mcxt.c:1975
Definition: c.h:712
const char * name

References error(), i, llvm_resolve_symbol(), name, palloc0(), and pfree().

Referenced by llvm_create_jit_instance().

◆ llvm_session_initialize()

static void llvm_session_initialize ( void  )
static

Definition at line 821 of file llvmjit.c.

822{
823 MemoryContext oldcontext;
824 char *error = NULL;
825 char *cpu = NULL;
826 char *features = NULL;
827 LLVMTargetMachineRef opt0_tm;
828 LLVMTargetMachineRef opt3_tm;
829
831 return;
832
834
835 LLVMInitializeNativeTarget();
836 LLVMInitializeNativeAsmPrinter();
837 LLVMInitializeNativeAsmParser();
838
839 if (llvm_context == NULL)
840 {
841 llvm_context = LLVMContextCreate();
842
845 }
846
847 /*
848 * Synchronize types early, as that also includes inferring the target
849 * triple.
850 */
852
853 /*
854 * Extract target information from loaded module.
855 */
857
858 if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &error) != 0)
859 {
860 elog(FATAL, "failed to query triple %s", error);
861 }
862
863 /*
864 * We want the generated code to use all available features. Therefore
865 * grab the host CPU string and detect features of the current CPU. The
866 * latter is needed because some CPU architectures default to enabling
867 * features not all CPUs have (weird, huh).
868 */
869 cpu = LLVMGetHostCPUName();
870 features = LLVMGetHostCPUFeatures();
871 elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"",
872 cpu, features);
873
874 opt0_tm =
875 LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
876 LLVMCodeGenLevelNone,
877 LLVMRelocDefault,
878 LLVMCodeModelJITDefault);
879 opt3_tm =
880 LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
881 LLVMCodeGenLevelAggressive,
882 LLVMRelocDefault,
883 LLVMCodeModelJITDefault);
884
885 LLVMDisposeMessage(cpu);
886 cpu = NULL;
887 LLVMDisposeMessage(features);
888 features = NULL;
889
890 /* force symbols in main binary to be loaded */
891 LLVMLoadLibraryPermanently(NULL);
892
893 {
894 llvm_ts_context = LLVMOrcCreateNewThreadSafeContext();
895
897 opt0_tm = 0;
898
900 opt3_tm = 0;
901 }
902
904
906
907 MemoryContextSwitchTo(oldcontext);
908}
#define FATAL
Definition: elog.h:41
#define DEBUG2
Definition: elog.h:29
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:309
static void llvm_set_target(void)
Definition: llvmjit.c:972
static LLVMTargetRef llvm_targetref
Definition: llvmjit.c:97
static bool llvm_session_initialized
Definition: llvmjit.c:84
static LLVMOrcLLJITRef llvm_create_jit_instance(LLVMTargetMachineRef tm)
Definition: llvmjit.c:1208
static void llvm_shutdown(int code, Datum arg)
Definition: llvmjit.c:911

References DEBUG2, elog, error(), FATAL, llvm_context, llvm_create_jit_instance(), llvm_create_types(), llvm_jit_context_in_use_count, llvm_llvm_context_reuse_count, llvm_opt0_orc, llvm_opt3_orc, llvm_session_initialized, llvm_set_target(), llvm_shutdown(), llvm_targetref, llvm_triple, llvm_ts_context, MemoryContextSwitchTo(), on_proc_exit(), and TopMemoryContext.

Referenced by llvm_create_context().

◆ llvm_set_target()

static void llvm_set_target ( void  )
static

Definition at line 972 of file llvmjit.c.

973{
975 elog(ERROR, "failed to extract target information, llvmjit_types.c not loaded");
976
977 if (llvm_triple == NULL)
978 llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
979
980 if (llvm_layout == NULL)
981 llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
982}

References elog, ERROR, llvm_layout, llvm_triple, llvm_types_module, and pstrdup().

Referenced by llvm_session_initialize().

◆ llvm_shutdown()

static void llvm_shutdown ( int  code,
Datum  arg 
)
static

Definition at line 911 of file llvmjit.c.

912{
913 /*
914 * If llvm_shutdown() is reached while in a fatal-on-oom section an error
915 * has occurred in the middle of LLVM code. It is not safe to call back
916 * into LLVM (which is why a FATAL error was thrown).
917 *
918 * We do need to shutdown LLVM in other shutdown cases, otherwise e.g.
919 * profiling data won't be written out.
920 */
922 {
924 return;
925 }
926
928 elog(PANIC, "LLVMJitContext in use count not 0 at exit (is %zu)",
930
931 {
932 if (llvm_opt3_orc)
933 {
934 LLVMOrcDisposeLLJIT(llvm_opt3_orc);
935 llvm_opt3_orc = NULL;
936 }
937 if (llvm_opt0_orc)
938 {
939 LLVMOrcDisposeLLJIT(llvm_opt0_orc);
940 llvm_opt0_orc = NULL;
941 }
942 if (llvm_ts_context)
943 {
944 LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
945 llvm_ts_context = NULL;
946 }
947 }
948}
#define PANIC
Definition: elog.h:42
bool llvm_in_fatal_on_oom(void)

References Assert(), elog, llvm_in_fatal_on_oom(), llvm_jit_context_in_use_count, llvm_opt0_orc, llvm_opt3_orc, llvm_ts_context, PANIC, and proc_exit_inprogress.

Referenced by llvm_session_initialize().

◆ llvm_split_symbol_name()

void llvm_split_symbol_name ( const char *  name,
char **  modname,
char **  funcname 
)

Definition at line 1045 of file llvmjit.c.

1046{
1047 *modname = NULL;
1048 *funcname = NULL;
1049
1050 /*
1051 * Module function names are pgextern.$module.$funcname
1052 */
1053 if (strncmp(name, "pgextern.", strlen("pgextern.")) == 0)
1054 {
1055 /*
1056 * Symbol names cannot contain a ., therefore we can split based on
1057 * first and last occurrence of one.
1058 */
1059 *funcname = rindex(name, '.');
1060 (*funcname)++; /* jump over . */
1061
1062 *modname = pnstrdup(name + strlen("pgextern."),
1063 *funcname - name - strlen("pgextern.") - 1);
1065
1067 }
1068 else
1069 {
1070 *modname = NULL;
1071 *funcname = pstrdup(name);
1072 }
1073}
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:2338

References Assert(), funcname, name, pnstrdup(), and pstrdup().

Referenced by llvm_build_inline_plan(), llvm_execute_inline_plan(), and llvm_resolve_symbol().

◆ load_return_type()

static LLVMTypeRef load_return_type ( LLVMModuleRef  mod,
const char *  name 
)
static

Definition at line 952 of file llvmjit.c.

953{
954 LLVMValueRef value;
955 LLVMTypeRef typ;
956
957 /* this'll return a *pointer* to the function */
958 value = LLVMGetNamedFunction(mod, name);
959 if (!value)
960 elog(ERROR, "function %s is unknown", name);
961
962 typ = LLVMGetFunctionReturnType(value); /* in llvmjit_wrap.cpp */
963
964 return typ;
965}
static struct @165 value

References elog, ERROR, LLVMGetFunctionReturnType(), name, and value.

Referenced by llvm_create_types().

◆ PG_MODULE_MAGIC_EXT()

PG_MODULE_MAGIC_EXT ( name = "llvmjit",
version = PG_VERSION 
)

◆ ResourceOwnerForgetJIT()

static void ResourceOwnerForgetJIT ( ResourceOwner  owner,
LLVMJitContext *  handle 
)
inlinestatic

Definition at line 136 of file llvmjit.c.

137{
139}
static const ResourceOwnerDesc jit_resowner_desc
Definition: llvmjit.c:120
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:327
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:564

References jit_resowner_desc, PointerGetDatum(), and ResourceOwnerForget().

Referenced by llvm_release_context().

◆ ResourceOwnerRememberJIT()

static void ResourceOwnerRememberJIT ( ResourceOwner  owner,
LLVMJitContext *  handle 
)
inlinestatic

Definition at line 131 of file llvmjit.c.

132{
134}
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:524

References jit_resowner_desc, PointerGetDatum(), and ResourceOwnerRemember().

Referenced by llvm_create_context().

◆ ResOwnerReleaseJitContext()

static void ResOwnerReleaseJitContext ( Datum  res)
static

Definition at line 1274 of file llvmjit.c.

1275{
1276 LLVMJitContext *context = (LLVMJitContext *) DatumGetPointer(res);
1277
1278 context->resowner = NULL;
1279 jit_release_context(&context->base);
1280}
void jit_release_context(JitContext *context)
Definition: jit.c:137
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:317

References DatumGetPointer(), and jit_release_context().

Variable Documentation

◆ AttributeTemplate

Datum AttributeTemplate

◆ ExecEvalBoolSubroutineTemplate

bool ExecEvalBoolSubroutineTemplate

Definition at line 80 of file llvmjit.c.

Referenced by llvm_create_types().

◆ ExecEvalSubroutineTemplate

void ExecEvalSubroutineTemplate

Definition at line 79 of file llvmjit.c.

Referenced by llvm_create_types().

◆ jit_resowner_desc

const ResourceOwnerDesc jit_resowner_desc
static
Initial value:
=
{
.name = "LLVM JIT context",
.release_priority = RELEASE_PRIO_JIT_CONTEXTS,
.ReleaseResource = ResOwnerReleaseJitContext,
.DebugPrint = NULL
}
static void ResOwnerReleaseJitContext(Datum res)
Definition: llvmjit.c:1274
#define RELEASE_PRIO_JIT_CONTEXTS
Definition: resowner.h:66
@ RESOURCE_RELEASE_BEFORE_LOCKS
Definition: resowner.h:54

Definition at line 120 of file llvmjit.c.

Referenced by ResourceOwnerForgetJIT(), and ResourceOwnerRememberJIT().

◆ llvm_context

LLVMContextRef llvm_context
static

◆ llvm_generation

size_t llvm_generation = 0
static

Definition at line 85 of file llvmjit.c.

Referenced by llvm_mutable_module().

◆ llvm_jit_context_in_use_count

size_t llvm_jit_context_in_use_count = 0
static

◆ llvm_layout

const char* llvm_layout = NULL
static

Definition at line 93 of file llvmjit.c.

Referenced by llvm_mutable_module(), and llvm_set_target().

◆ llvm_llvm_context_reuse_count

size_t llvm_llvm_context_reuse_count = 0
static

Definition at line 91 of file llvmjit.c.

Referenced by llvm_recreate_llvm_context(), and llvm_session_initialize().

◆ llvm_opt0_orc

LLVMOrcLLJITRef llvm_opt0_orc
static

Definition at line 99 of file llvmjit.c.

Referenced by llvm_compile_module(), llvm_session_initialize(), and llvm_shutdown().

◆ llvm_opt3_orc

LLVMOrcLLJITRef llvm_opt3_orc
static

Definition at line 100 of file llvmjit.c.

Referenced by llvm_compile_module(), llvm_session_initialize(), and llvm_shutdown().

◆ llvm_session_initialized

bool llvm_session_initialized = false
static

Definition at line 84 of file llvmjit.c.

Referenced by llvm_session_initialize().

◆ llvm_targetref

LLVMTargetRef llvm_targetref
static

Definition at line 97 of file llvmjit.c.

Referenced by llvm_session_initialize().

◆ llvm_triple

const char* llvm_triple = NULL
static

Definition at line 92 of file llvmjit.c.

Referenced by llvm_mutable_module(), llvm_session_initialize(), and llvm_set_target().

◆ llvm_ts_context

LLVMOrcThreadSafeContextRef llvm_ts_context
static

Definition at line 98 of file llvmjit.c.

Referenced by llvm_compile_module(), llvm_session_initialize(), and llvm_shutdown().

◆ llvm_types_module

LLVMModuleRef llvm_types_module = NULL
static

◆ StructAggState

LLVMTypeRef StructAggState

Definition at line 73 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructAggStatePerGroupData

LLVMTypeRef StructAggStatePerGroupData

Definition at line 74 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructAggStatePerTransData

LLVMTypeRef StructAggStatePerTransData

Definition at line 75 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructExprContext

LLVMTypeRef StructExprContext

Definition at line 70 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructExprEvalStep

LLVMTypeRef StructExprEvalStep

Definition at line 71 of file llvmjit.c.

Referenced by build_EvalXFuncInt(), and llvm_create_types().

◆ StructExprState

LLVMTypeRef StructExprState

Definition at line 72 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructFunctionCallInfoData

LLVMTypeRef StructFunctionCallInfoData

Definition at line 69 of file llvmjit.c.

Referenced by BuildV1Call(), and llvm_create_types().

◆ StructHeapTupleData

LLVMTypeRef StructHeapTupleData

Definition at line 61 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructHeapTupleHeaderData

LLVMTypeRef StructHeapTupleHeaderData

Definition at line 65 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructHeapTupleTableSlot

LLVMTypeRef StructHeapTupleTableSlot

Definition at line 66 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructMemoryContextData

LLVMTypeRef StructMemoryContextData

Definition at line 68 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructMinimalTupleData

LLVMTypeRef StructMinimalTupleData

Definition at line 62 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructMinimalTupleTableSlot

LLVMTypeRef StructMinimalTupleTableSlot

Definition at line 67 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructNullableDatum

LLVMTypeRef StructNullableDatum

Definition at line 60 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructPlanState

LLVMTypeRef StructPlanState

Definition at line 76 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructTupleDescData

LLVMTypeRef StructTupleDescData

Definition at line 63 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructTupleTableSlot

LLVMTypeRef StructTupleTableSlot

Definition at line 64 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ TypeParamBool

LLVMTypeRef TypeParamBool

Definition at line 57 of file llvmjit.c.

Referenced by llvm_create_types().

◆ TypePGFunction

LLVMTypeRef TypePGFunction

Definition at line 59 of file llvmjit.c.

Referenced by llvm_create_types(), and llvm_function_reference().

◆ TypeSizeT

LLVMTypeRef TypeSizeT

Definition at line 56 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ TypeStorageBool

LLVMTypeRef TypeStorageBool

Definition at line 58 of file llvmjit.c.

Referenced by BuildV1Call(), llvm_create_types(), and slot_compile_deform().