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)
 
 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 TypeDatum
 
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 152 of file llvmjit.c.

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

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

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

494{
495 int num_attributes;
496 LLVMAttributeRef *attrs;
497
498 num_attributes = LLVMGetAttributeCountAtIndex(v_from, index);
499
500 if (num_attributes == 0)
501 return;
502
503 attrs = palloc_array(LLVMAttributeRef, num_attributes);
504 LLVMGetAttributesAtIndex(v_from, index, attrs);
505
506 for (int attno = 0; attno < num_attributes; attno++)
507 LLVMAddAttributeAtIndex(v_to, index, attrs[attno]);
508
509 pfree(attrs);
510}
#define palloc_array(type, count)
Definition: fe_memutils.h:76
Definition: type.h:96

References palloc_array, and pfree().

Referenced by llvm_copy_attributes().

◆ llvm_create_context()

LLVMJitContext * llvm_create_context ( int  jitFlags)

Definition at line 224 of file llvmjit.c.

225{
226 LLVMJitContext *context;
227
229
231
233
235
237 sizeof(LLVMJitContext));
238 context->base.flags = jitFlags;
239
240 /* ensure cleanup */
241 context->resowner = CurrentResourceOwner;
243
245
246 return context;
247}
static void llvm_recreate_llvm_context(void)
Definition: llvmjit.c:174
static void ResourceOwnerRememberJIT(ResourceOwner owner, LLVMJitContext *handle)
Definition: llvmjit.c:132
static void llvm_session_initialize(void)
Definition: llvmjit.c:826
static size_t llvm_jit_context_in_use_count
Definition: llvmjit.c:89
void llvm_assert_in_fatal_section(void)
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1266
ResourceOwner CurrentResourceOwner
Definition: resowner.c:173
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:449

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

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

1178{
1179#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
1180 LLVMOrcObjectLayerRef objlayer =
1181 LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
1182#else
1183 LLVMOrcObjectLayerRef objlayer =
1184 LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
1185#endif
1186
1188 {
1189 LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
1190
1191 LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
1192 }
1193
1195 {
1196 LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
1197
1198 if (l)
1199 LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
1200 }
1201
1202 return objlayer;
1203}
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 996 of file llvmjit.c.

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

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, TypeDatum, 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 1262 of file llvmjit.c.

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

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

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

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

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

1168{
1169 elog(WARNING, "error during JITing: %s",
1171}
#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 317 of file llvmjit.c.

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

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

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

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

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

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

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

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

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

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

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

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

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

1128{
1129#if LLVM_VERSION_MAJOR > 14
1130 LLVMOrcCSymbolMapPairs symbols = palloc0_array(LLVMOrcCSymbolMapPair, LookupSetSize);
1131#else
1132 LLVMOrcCSymbolMapPairs symbols = palloc0_array(LLVMJITCSymbolMapPair, LookupSetSize);
1133#endif
1134 LLVMErrorRef error;
1135 LLVMOrcMaterializationUnitRef mu;
1136
1137 for (int i = 0; i < LookupSetSize; i++)
1138 {
1139 const char *name = LLVMOrcSymbolStringPoolEntryStr(LookupSet[i].Name);
1140
1141 LLVMOrcRetainSymbolStringPoolEntry(LookupSet[i].Name);
1142 symbols[i].Name = LookupSet[i].Name;
1143 symbols[i].Sym.Address = llvm_resolve_symbol(name, NULL);
1144 symbols[i].Sym.Flags.GenericFlags = LLVMJITSymbolGenericFlagsExported;
1145 }
1146
1147 mu = LLVMOrcAbsoluteSymbols(symbols, LookupSetSize);
1148 error = LLVMOrcJITDylibDefine(JD, mu);
1149 if (error != LLVMErrorSuccess)
1150 LLVMOrcDisposeMaterializationUnit(mu);
1151
1152 pfree(symbols);
1153
1154 return error;
1155}
#define palloc0_array(type, count)
Definition: fe_memutils.h:77
int i
Definition: isn.c:77
static uint64_t llvm_resolve_symbol(const char *name, void *ctx)
Definition: llvmjit.c:1085
Definition: c.h:760
const char * name

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

Referenced by llvm_create_jit_instance().

◆ llvm_session_initialize()

static void llvm_session_initialize ( void  )
static

Definition at line 826 of file llvmjit.c.

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

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

978{
980 elog(ERROR, "failed to extract target information, llvmjit_types.c not loaded");
981
982 if (llvm_triple == NULL)
983 llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
984
985 if (llvm_layout == NULL)
986 llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
987}

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

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

1052{
1053 *modname = NULL;
1054 *funcname = NULL;
1055
1056 /*
1057 * Module function names are pgextern.$module.$funcname
1058 */
1059 if (strncmp(name, "pgextern.", strlen("pgextern.")) == 0)
1060 {
1061 /*
1062 * Symbol names cannot contain a ., therefore we can split based on
1063 * first and last occurrence of one.
1064 */
1065 *funcname = strrchr(name, '.');
1066 (*funcname)++; /* jump over . */
1067
1068 *modname = pnstrdup(name + strlen("pgextern."),
1069 *funcname - name - strlen("pgextern.") - 1);
1071
1073 }
1074 else
1075 {
1076 *modname = NULL;
1077 *funcname = pstrdup(name);
1078 }
1079}
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1792

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

958{
959 LLVMValueRef value;
960 LLVMTypeRef typ;
961
962 /* this'll return a *pointer* to the function */
963 value = LLVMGetNamedFunction(mod, name);
964 if (!value)
965 elog(ERROR, "function %s is unknown", name);
966
967 typ = LLVMGetFunctionReturnType(value); /* in llvmjit_wrap.cpp */
968
969 return typ;
970}
static struct @171 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 137 of file llvmjit.c.

138{
140}
static const ResourceOwnerDesc jit_resowner_desc
Definition: llvmjit.c:121
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:352
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:561

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

Referenced by llvm_release_context().

◆ ResourceOwnerRememberJIT()

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

Definition at line 132 of file llvmjit.c.

133{
135}
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:521

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

Referenced by llvm_create_context().

◆ ResOwnerReleaseJitContext()

static void ResOwnerReleaseJitContext ( Datum  res)
static

Definition at line 1276 of file llvmjit.c.

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

References DatumGetPointer(), and jit_release_context().

Variable Documentation

◆ AttributeTemplate

Datum AttributeTemplate

◆ ExecEvalBoolSubroutineTemplate

bool ExecEvalBoolSubroutineTemplate

Definition at line 81 of file llvmjit.c.

Referenced by llvm_create_types().

◆ ExecEvalSubroutineTemplate

void ExecEvalSubroutineTemplate

Definition at line 80 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:1276
#define RELEASE_PRIO_JIT_CONTEXTS
Definition: resowner.h:66
@ RESOURCE_RELEASE_BEFORE_LOCKS
Definition: resowner.h:54

Definition at line 121 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 86 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 94 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 92 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 100 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 101 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 85 of file llvmjit.c.

Referenced by llvm_session_initialize().

◆ llvm_targetref

LLVMTargetRef llvm_targetref
static

Definition at line 98 of file llvmjit.c.

Referenced by llvm_session_initialize().

◆ llvm_triple

const char* llvm_triple = NULL
static

Definition at line 93 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 99 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 74 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructAggStatePerGroupData

LLVMTypeRef StructAggStatePerGroupData

Definition at line 75 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructAggStatePerTransData

LLVMTypeRef StructAggStatePerTransData

Definition at line 76 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructExprContext

LLVMTypeRef StructExprContext

Definition at line 71 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructExprEvalStep

LLVMTypeRef StructExprEvalStep

Definition at line 72 of file llvmjit.c.

Referenced by build_EvalXFuncInt(), and llvm_create_types().

◆ StructExprState

LLVMTypeRef StructExprState

Definition at line 73 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructFunctionCallInfoData

LLVMTypeRef StructFunctionCallInfoData

Definition at line 70 of file llvmjit.c.

Referenced by BuildV1Call(), and llvm_create_types().

◆ StructHeapTupleData

LLVMTypeRef StructHeapTupleData

Definition at line 62 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructHeapTupleHeaderData

LLVMTypeRef StructHeapTupleHeaderData

Definition at line 66 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructHeapTupleTableSlot

LLVMTypeRef StructHeapTupleTableSlot

Definition at line 67 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructMemoryContextData

LLVMTypeRef StructMemoryContextData

Definition at line 69 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructMinimalTupleData

LLVMTypeRef StructMinimalTupleData

Definition at line 63 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructMinimalTupleTableSlot

LLVMTypeRef StructMinimalTupleTableSlot

Definition at line 68 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructNullableDatum

LLVMTypeRef StructNullableDatum

Definition at line 61 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructPlanState

LLVMTypeRef StructPlanState

Definition at line 77 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructTupleDescData

LLVMTypeRef StructTupleDescData

Definition at line 64 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructTupleTableSlot

LLVMTypeRef StructTupleTableSlot

Definition at line 65 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ TypeDatum

LLVMTypeRef TypeDatum

Definition at line 57 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ TypeParamBool

LLVMTypeRef TypeParamBool

Definition at line 58 of file llvmjit.c.

Referenced by llvm_create_types().

◆ TypePGFunction

LLVMTypeRef TypePGFunction

Definition at line 60 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 59 of file llvmjit.c.

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