Thanks to visit codestin.com
Credit goes to doxygen.postgresql.org

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

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

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

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

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: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 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:706
#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 1163 of file llvmjit.c.

1164{
1165 elog(WARNING, "error during JITing: %s",
1167}
#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
678 passes = "default<O0>,mem2reg";
679
680 options = LLVMCreatePassBuilderOptions();
681
682#ifdef LLVM_PASS_DEBUG
683 LLVMPassBuilderOptionsSetDebugLogging(options, 1);
684#endif
685
686 /* In assertion builds, run the LLVM verify pass. */
687#ifdef USE_ASSERT_CHECKING
688 LLVMPassBuilderOptionsSetVerifyEach(options, true);
689#endif
690
691 LLVMPassBuilderOptionsSetInlinerThreshold(options, 512);
692
693 err = LLVMRunPasses(module, passes, NULL, options);
694
695 if (err)
696 elog(ERROR, "failed to JIT module: %s", llvm_error_message(err));
697
698 LLVMDisposePassBuilderOptions(options);
699#endif
700}
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:992
#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:40
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 1081 of file llvmjit.c.

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

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

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

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

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

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

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

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

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

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

954{
955 LLVMValueRef value;
956 LLVMTypeRef typ;
957
958 /* this'll return a *pointer* to the function */
959 value = LLVMGetNamedFunction(mod, name);
960 if (!value)
961 elog(ERROR, "function %s is unknown", name);
962
963 typ = LLVMGetFunctionReturnType(value); /* in llvmjit_wrap.cpp */
964
965 return typ;
966}
static struct @166 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:332
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:322

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