PostgreSQL Source Code git master
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)
 
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
 
 PG_MODULE_MAGIC
 

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 148 of file llvmjit.c.

149{
153}
static void llvm_release_context(JitContext *context)
Definition: llvmjit.c:249
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 702 of file llvmjit.c.

703{
704 LLVMJitHandle *handle;
705 MemoryContext oldcontext;
706 instr_time starttime;
707 instr_time endtime;
708 LLVMOrcLLJITRef compile_orc;
709
710 if (context->base.flags & PGJIT_OPT3)
711 compile_orc = llvm_opt3_orc;
712 else
713 compile_orc = llvm_opt0_orc;
714
715 /* perform inlining */
716 if (context->base.flags & PGJIT_INLINE)
717 {
718 INSTR_TIME_SET_CURRENT(starttime);
719 llvm_inline(context->module);
720 INSTR_TIME_SET_CURRENT(endtime);
721 INSTR_TIME_ACCUM_DIFF(context->base.instr.inlining_counter,
722 endtime, starttime);
723 }
724
726 {
727 char *filename;
728
729 filename = psprintf("%d.%zu.bc",
730 MyProcPid,
731 context->module_generation);
732 LLVMWriteBitcodeToFile(context->module, filename);
734 }
735
736
737 /* optimize according to the chosen optimization settings */
738 INSTR_TIME_SET_CURRENT(starttime);
739 llvm_optimize_module(context, context->module);
740 INSTR_TIME_SET_CURRENT(endtime);
741 INSTR_TIME_ACCUM_DIFF(context->base.instr.optimization_counter,
742 endtime, starttime);
743
745 {
746 char *filename;
747
748 filename = psprintf("%d.%zu.optimized.bc",
749 MyProcPid,
750 context->module_generation);
751 LLVMWriteBitcodeToFile(context->module, filename);
753 }
754
755 handle = (LLVMJitHandle *)
757
758 /*
759 * Emit the code. Note that this can, depending on the optimization
760 * settings, take noticeable resources as code emission executes low-level
761 * instruction combining/selection passes etc. Without optimization a
762 * faster instruction selection mechanism is used.
763 */
764 INSTR_TIME_SET_CURRENT(starttime);
765 {
766 LLVMOrcThreadSafeModuleRef ts_module;
767 LLVMErrorRef error;
768 LLVMOrcJITDylibRef jd = LLVMOrcLLJITGetMainJITDylib(compile_orc);
769
770 ts_module = LLVMOrcCreateNewThreadSafeModule(context->module, llvm_ts_context);
771
772 handle->lljit = compile_orc;
773 handle->resource_tracker = LLVMOrcJITDylibCreateResourceTracker(jd);
774
775 /*
776 * NB: This doesn't actually emit code. That happens lazily the first
777 * time a symbol defined in the module is requested. Due to that
778 * llvm_get_function() also accounts for emission time.
779 */
780
781 context->module = NULL; /* will be owned by LLJIT */
782 error = LLVMOrcLLJITAddLLVMIRModuleWithRT(compile_orc,
783 handle->resource_tracker,
784 ts_module);
785
786 if (error)
787 elog(ERROR, "failed to JIT module: %s",
789
790 /* LLVMOrcLLJITAddLLVMIRModuleWithRT takes ownership of the module */
791 }
792
793 INSTR_TIME_SET_CURRENT(endtime);
794 INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
795 endtime, starttime);
796
797 context->module = NULL;
798 context->compiled = true;
799
800 /* remember emitted code for cleanup and lookups */
802 context->handles = lappend(context->handles, handle);
803 MemoryContextSwitchTo(oldcontext);
804
806 (errmsg_internal("time to inline: %.3fs, opt: %.3fs, emit: %.3fs",
807 INSTR_TIME_GET_DOUBLE(context->base.instr.inlining_counter),
808 INSTR_TIME_GET_DOUBLE(context->base.instr.optimization_counter),
809 INSTR_TIME_GET_DOUBLE(context->base.instr.emission_counter)),
810 errhidestmt(true),
811 errhidecontext(true)));
812}
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errhidestmt(bool hide_stmt)
Definition: elog.c:1411
int errhidecontext(bool hide_ctx)
Definition: elog.c:1430
#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:46
#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:1257
static LLVMOrcThreadSafeContextRef llvm_ts_context
Definition: llvmjit.c:98
static void llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
Definition: llvmjit.c:600
void llvm_inline(LLVMModuleRef M)
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
void pfree(void *pointer)
Definition: mcxt.c:1521
MemoryContext TopMemoryContext
Definition: mcxt.c:149
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
static char * filename
Definition: pg_dumpall.c:119
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 513 of file llvmjit.c.

514{
515 uint32 param_count;
516
517 /* copy function attributes */
518 llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeFunctionIndex);
519
520 if (LLVMGetTypeKind(LLVMGetFunctionReturnType(v_to)) != LLVMVoidTypeKind)
521 {
522 /* and the return value attributes */
523 llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeReturnIndex);
524 }
525
526 /* and each function parameter's attribute */
527 param_count = LLVMCountParams(v_from);
528
529 for (int paramidx = 1; paramidx <= param_count; paramidx++)
530 llvm_copy_attributes_at_index(v_from, v_to, paramidx);
531}
uint32_t uint32
Definition: c.h:488
static void llvm_copy_attributes_at_index(LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
Definition: llvmjit.c:489
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 489 of file llvmjit.c.

490{
491 int num_attributes;
492 LLVMAttributeRef *attrs;
493
494 num_attributes = LLVMGetAttributeCountAtIndex(v_from, index);
495
496 if (num_attributes == 0)
497 return;
498
499 attrs = palloc(sizeof(LLVMAttributeRef) * num_attributes);
500 LLVMGetAttributesAtIndex(v_from, index, attrs);
501
502 for (int attno = 0; attno < num_attributes; attno++)
503 LLVMAddAttributeAtIndex(v_to, index, attrs[attno]);
504
505 pfree(attrs);
506}
void * palloc(Size size)
Definition: mcxt.c:1317
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 220 of file llvmjit.c.

221{
222 LLVMJitContext *context;
223
225
227
229
231
233 sizeof(LLVMJitContext));
234 context->base.flags = jitFlags;
235
236 /* ensure cleanup */
237 context->resowner = CurrentResourceOwner;
239
241
242 return context;
243}
static void llvm_recreate_llvm_context(void)
Definition: llvmjit.c:170
static void ResourceOwnerRememberJIT(ResourceOwner owner, LLVMJitContext *handle)
Definition: llvmjit.c:131
static void llvm_session_initialize(void)
Definition: llvmjit.c:818
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:1215
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:442

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 1205 of file llvmjit.c.

1206{
1207 LLVMOrcLLJITRef lljit;
1208 LLVMOrcJITTargetMachineBuilderRef tm_builder;
1209 LLVMOrcLLJITBuilderRef lljit_builder;
1210 LLVMErrorRef error;
1211 LLVMOrcDefinitionGeneratorRef main_gen;
1212 LLVMOrcDefinitionGeneratorRef ref_gen;
1213
1214 lljit_builder = LLVMOrcCreateLLJITBuilder();
1215 tm_builder = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm);
1216 LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(lljit_builder, tm_builder);
1217
1218 LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(lljit_builder,
1220 NULL);
1221
1222 error = LLVMOrcCreateLLJIT(&lljit, lljit_builder);
1223 if (error)
1224 elog(ERROR, "failed to create lljit instance: %s",
1226
1227 LLVMOrcExecutionSessionSetErrorReporter(LLVMOrcLLJITGetExecutionSession(lljit),
1228 llvm_log_jit_error, NULL);
1229
1230 /*
1231 * Symbol resolution support for symbols in the postgres binary /
1232 * libraries already loaded.
1233 */
1234 error = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(&main_gen,
1235 LLVMOrcLLJITGetGlobalPrefix(lljit),
1236 0, NULL);
1237 if (error)
1238 elog(ERROR, "failed to create generator: %s",
1240 LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), main_gen);
1241
1242 /*
1243 * Symbol resolution support for "special" functions, e.g. a call into an
1244 * SQL callable function.
1245 */
1246#if LLVM_VERSION_MAJOR > 14
1247 ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL, NULL);
1248#else
1249 ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL);
1250#endif
1251 LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), ref_gen);
1252
1253 return lljit;
1254}
static LLVMOrcObjectLayerRef llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
Definition: llvmjit.c:1168
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:1115
static void llvm_log_jit_error(void *ctx, LLVMErrorRef error)
Definition: llvmjit.c:1158
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 1168 of file llvmjit.c.

1169{
1170#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
1171 LLVMOrcObjectLayerRef objlayer =
1172 LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
1173#else
1174 LLVMOrcObjectLayerRef objlayer =
1175 LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
1176#endif
1177
1178
1179#if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
1181 {
1182 LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
1183
1184 LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
1185 }
1186#endif
1187
1188#if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
1190 {
1191 LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
1192
1193 LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
1194 }
1195#endif
1196
1197 return objlayer;
1198}
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 988 of file llvmjit.c.

989{
990 char path[MAXPGPATH];
991 LLVMMemoryBufferRef buf;
992 char *msg;
993
994 snprintf(path, MAXPGPATH, "%s/%s", pkglib_path, "llvmjit_types.bc");
995
996 /* open file */
997 if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buf, &msg))
998 {
999 elog(ERROR, "LLVMCreateMemoryBufferWithContentsOfFile(%s) failed: %s",
1000 path, msg);
1001 }
1002
1003 /* eagerly load contents, going to need it all */
1004 if (LLVMParseBitcodeInContext2(llvm_context, buf, &llvm_types_module))
1005 {
1006 elog(ERROR, "LLVMParseBitcodeInContext2 of %s failed", path);
1007 }
1008 LLVMDisposeMemoryBuffer(buf);
1009
1010 TypeSizeT = llvm_pg_var_type("TypeSizeT");
1011 TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
1012 TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
1013 TypePGFunction = llvm_pg_var_type("TypePGFunction");
1014 StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
1015 StructExprContext = llvm_pg_var_type("StructExprContext");
1016 StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
1017 StructExprState = llvm_pg_var_type("StructExprState");
1018 StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
1019 StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
1020 StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
1021 StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
1022 StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
1023 StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
1024 StructHeapTupleHeaderData = llvm_pg_var_type("StructHeapTupleHeaderData");
1025 StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
1026 StructAggState = llvm_pg_var_type("StructAggState");
1027 StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
1028 StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
1029 StructPlanState = llvm_pg_var_type("StructPlanState");
1030 StructMinimalTupleData = llvm_pg_var_type("StructMinimalTupleData");
1031
1032 AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
1033 ExecEvalSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalSubroutineTemplate");
1034 ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalBoolSubroutineTemplate");
1035}
char pkglib_path[MAXPGPATH]
Definition: globals.c:81
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:419
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:949
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 1257 of file llvmjit.c.

1258{
1259 char *orig = LLVMGetErrorMessage(error);
1260 char *msg = pstrdup(orig);
1261
1262 LLVMDisposeErrorMessage(orig);
1263
1264 return msg;
1265}
char * pstrdup(const char *in)
Definition: mcxt.c:1696

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 338 of file llvmjit.c.

339{
340 Assert(context->module != NULL);
341
342 context->base.instr.created_functions++;
343
344 /*
345 * Previously we used dots to separate, but turns out some tools, e.g.
346 * GDB, don't like that and truncate name.
347 */
348 return psprintf("%s_%zu_%d",
349 basename,
350 context->module_generation,
351 context->counter++);
352}
#define Assert(condition)
Definition: c.h:815

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 537 of file llvmjit.c.

541{
542 char *modname;
543 char *basename;
544 char *funcname;
545
546 LLVMValueRef v_fn;
547
548 fmgr_symbol(fcinfo->flinfo->fn_oid, &modname, &basename);
549
550 if (modname != NULL && basename != NULL)
551 {
552 /* external function in loadable library */
553 funcname = psprintf("pgextern.%s.%s", modname, basename);
554 }
555 else if (basename != NULL)
556 {
557 /* internal function */
558 funcname = pstrdup(basename);
559 }
560 else
561 {
562 /*
563 * Function we don't know to handle, return pointer. We do so by
564 * creating a global constant containing a pointer to the function.
565 * Makes IR more readable.
566 */
567 LLVMValueRef v_fn_addr;
568
569 funcname = psprintf("pgoidextern.%u",
570 fcinfo->flinfo->fn_oid);
571 v_fn = LLVMGetNamedGlobal(mod, funcname);
572 if (v_fn != 0)
573 return l_load(builder, TypePGFunction, v_fn, "");
574
575 v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction);
576
577 v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname);
578 LLVMSetInitializer(v_fn, v_fn_addr);
579 LLVMSetGlobalConstant(v_fn, true);
580 LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
581 LLVMSetUnnamedAddr(v_fn, true);
582
583 return l_load(builder, TypePGFunction, v_fn, "");
584 }
585
586 /* check if function already has been added */
587 v_fn = LLVMGetNamedFunction(mod, funcname);
588 if (v_fn != 0)
589 return v_fn;
590
591 v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(AttributeTemplate));
592
593 return v_fn;
594}
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 359 of file llvmjit.c.

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

1159{
1160 elog(WARNING, "error during JITing: %s",
1162}
#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 313 of file llvmjit.c.

314{
316
317 /*
318 * If there's no in-progress module, create a new one.
319 */
320 if (!context->module)
321 {
322 context->compiled = false;
323 context->module_generation = llvm_generation++;
324 context->module = LLVMModuleCreateWithNameInContext("pg", llvm_context);
325 LLVMSetTarget(context->module, llvm_triple);
326 LLVMSetDataLayout(context->module, llvm_layout);
327 }
328
329 return context->module;
330}
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 600 of file llvmjit.c.

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

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

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 439 of file llvmjit.c.

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

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 419 of file llvmjit.c.

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

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 170 of file llvmjit.c.

171{
172 if (!llvm_context)
173 elog(ERROR, "Trying to recreate a non-existing context");
174
175 /*
176 * We can only safely recreate the LLVM context if no other code is being
177 * JITed, otherwise we'd release the types in use for that.
178 */
180 {
182 return;
183 }
184
186 {
188 return;
189 }
190
191 /*
192 * Need to reset the modules that the inlining code caches before
193 * disposing of the context. LLVM modules exist within a specific LLVM
194 * context, therefore disposing of the context before resetting the cache
195 * would lead to dangling pointers to modules.
196 */
198
199 LLVMContextDispose(llvm_context);
200 llvm_context = LLVMContextCreate();
202
203 /*
204 * Re-build cached type information, so code generation code can rely on
205 * that information to be present (also prevents the variables to be
206 * dangling references).
207 */
209}
static void llvm_create_types(void)
Definition: llvmjit.c:988
#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 249 of file llvmjit.c.

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

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

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 1115 of file llvmjit.c.

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

819{
820 MemoryContext oldcontext;
821 char *error = NULL;
822 char *cpu = NULL;
823 char *features = NULL;
824 LLVMTargetMachineRef opt0_tm;
825 LLVMTargetMachineRef opt3_tm;
826
828 return;
829
831
832 LLVMInitializeNativeTarget();
833 LLVMInitializeNativeAsmPrinter();
834 LLVMInitializeNativeAsmParser();
835
836 if (llvm_context == NULL)
837 {
838 llvm_context = LLVMContextCreate();
839
842 }
843
844 /*
845 * Synchronize types early, as that also includes inferring the target
846 * triple.
847 */
849
850 /*
851 * Extract target information from loaded module.
852 */
854
855 if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &error) != 0)
856 {
857 elog(FATAL, "failed to query triple %s", error);
858 }
859
860 /*
861 * We want the generated code to use all available features. Therefore
862 * grab the host CPU string and detect features of the current CPU. The
863 * latter is needed because some CPU architectures default to enabling
864 * features not all CPUs have (weird, huh).
865 */
866 cpu = LLVMGetHostCPUName();
867 features = LLVMGetHostCPUFeatures();
868 elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"",
869 cpu, features);
870
871 opt0_tm =
872 LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
873 LLVMCodeGenLevelNone,
874 LLVMRelocDefault,
875 LLVMCodeModelJITDefault);
876 opt3_tm =
877 LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
878 LLVMCodeGenLevelAggressive,
879 LLVMRelocDefault,
880 LLVMCodeModelJITDefault);
881
882 LLVMDisposeMessage(cpu);
883 cpu = NULL;
884 LLVMDisposeMessage(features);
885 features = NULL;
886
887 /* force symbols in main binary to be loaded */
888 LLVMLoadLibraryPermanently(NULL);
889
890 {
891 llvm_ts_context = LLVMOrcCreateNewThreadSafeContext();
892
894 opt0_tm = 0;
895
897 opt3_tm = 0;
898 }
899
901
903
904 MemoryContextSwitchTo(oldcontext);
905}
#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:969
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:1205
static void llvm_shutdown(int code, Datum arg)
Definition: llvmjit.c:908

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 969 of file llvmjit.c.

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

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 908 of file llvmjit.c.

909{
910 /*
911 * If llvm_shutdown() is reached while in a fatal-on-oom section an error
912 * has occurred in the middle of LLVM code. It is not safe to call back
913 * into LLVM (which is why a FATAL error was thrown).
914 *
915 * We do need to shutdown LLVM in other shutdown cases, otherwise e.g.
916 * profiling data won't be written out.
917 */
919 {
921 return;
922 }
923
925 elog(PANIC, "LLVMJitContext in use count not 0 at exit (is %zu)",
927
928 {
929 if (llvm_opt3_orc)
930 {
931 LLVMOrcDisposeLLJIT(llvm_opt3_orc);
932 llvm_opt3_orc = NULL;
933 }
934 if (llvm_opt0_orc)
935 {
936 LLVMOrcDisposeLLJIT(llvm_opt0_orc);
937 llvm_opt0_orc = NULL;
938 }
939 if (llvm_ts_context)
940 {
941 LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
942 llvm_ts_context = NULL;
943 }
944 }
945}
#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 1042 of file llvmjit.c.

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

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 949 of file llvmjit.c.

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

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

Referenced by llvm_create_types().

◆ 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:554

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:514

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

Referenced by llvm_create_context().

◆ ResOwnerReleaseJitContext()

static void ResOwnerReleaseJitContext ( Datum  res)
static

Definition at line 1271 of file llvmjit.c.

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

References DatumGetPointer(), jit_release_context(), and res.

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:1271
#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

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 141 of file llvmjit.c.

◆ 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().