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/OrcBindings.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_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 void ResOwnerReleaseJitContext (Datum res)
 
static void ResourceOwnerRememberJIT (ResourceOwner owner, LLVMJitContext *handle)
 
static void ResourceOwnerForgetJIT (ResourceOwner owner, LLVMJitContext *handle)
 
void _PG_jit_provider_init (JitProviderCallbacks *cb)
 
LLVMJitContext * llvm_create_context (int jitFlags)
 
LLVMModuleRef llvm_mutable_module (LLVMJitContext *context)
 
char * llvm_expand_funcname (struct LLVMJitContext *context, const char *basename)
 
void * llvm_get_function (LLVMJitContext *context, const char *funcname)
 
LLVMTypeRef llvm_pg_var_type (const char *varname)
 
LLVMTypeRef llvm_pg_var_func_type (const char *varname)
 
LLVMValueRef llvm_pg_func (LLVMModuleRef mod, const char *funcname)
 
static void llvm_copy_attributes_at_index (LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
 
void llvm_copy_attributes (LLVMValueRef v_from, LLVMValueRef v_to)
 
LLVMValueRef llvm_function_reference (LLVMJitContext *context, LLVMBuilderRef builder, LLVMModuleRef mod, FunctionCallInfo fcinfo)
 
static LLVMTypeRef load_return_type (LLVMModuleRef mod, const char *name)
 
void llvm_split_symbol_name (const char *name, char **modname, char **funcname)
 

Variables

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

Macro Definition Documentation

◆ LLVMJIT_LLVM_CONTEXT_REUSE_MAX

#define LLVMJIT_LLVM_CONTEXT_REUSE_MAX   100

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

164 {
168 }
static void llvm_release_context(JitContext *context)
Definition: llvmjit.c:264
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 737 of file llvmjit.c.

738 {
739  LLVMJitHandle *handle;
740  MemoryContext oldcontext;
741  instr_time starttime;
742  instr_time endtime;
743 #if LLVM_VERSION_MAJOR > 11
744  LLVMOrcLLJITRef compile_orc;
745 #else
746  LLVMOrcJITStackRef compile_orc;
747 #endif
748 
749  if (context->base.flags & PGJIT_OPT3)
750  compile_orc = llvm_opt3_orc;
751  else
752  compile_orc = llvm_opt0_orc;
753 
754  /* perform inlining */
755  if (context->base.flags & PGJIT_INLINE)
756  {
757  INSTR_TIME_SET_CURRENT(starttime);
758  llvm_inline(context->module);
759  INSTR_TIME_SET_CURRENT(endtime);
760  INSTR_TIME_ACCUM_DIFF(context->base.instr.inlining_counter,
761  endtime, starttime);
762  }
763 
764  if (jit_dump_bitcode)
765  {
766  char *filename;
767 
768  filename = psprintf("%d.%zu.bc",
769  MyProcPid,
770  context->module_generation);
771  LLVMWriteBitcodeToFile(context->module, filename);
772  pfree(filename);
773  }
774 
775 
776  /* optimize according to the chosen optimization settings */
777  INSTR_TIME_SET_CURRENT(starttime);
779  INSTR_TIME_SET_CURRENT(endtime);
780  INSTR_TIME_ACCUM_DIFF(context->base.instr.optimization_counter,
781  endtime, starttime);
782 
783  if (jit_dump_bitcode)
784  {
785  char *filename;
786 
787  filename = psprintf("%d.%zu.optimized.bc",
788  MyProcPid,
789  context->module_generation);
790  LLVMWriteBitcodeToFile(context->module, filename);
791  pfree(filename);
792  }
793 
794  handle = (LLVMJitHandle *)
796 
797  /*
798  * Emit the code. Note that this can, depending on the optimization
799  * settings, take noticeable resources as code emission executes low-level
800  * instruction combining/selection passes etc. Without optimization a
801  * faster instruction selection mechanism is used.
802  */
803  INSTR_TIME_SET_CURRENT(starttime);
804 #if LLVM_VERSION_MAJOR > 11
805  {
806  LLVMOrcThreadSafeModuleRef ts_module;
807  LLVMErrorRef error;
808  LLVMOrcJITDylibRef jd = LLVMOrcLLJITGetMainJITDylib(compile_orc);
809 
810  ts_module = LLVMOrcCreateNewThreadSafeModule(context->module, llvm_ts_context);
811 
812  handle->lljit = compile_orc;
813  handle->resource_tracker = LLVMOrcJITDylibCreateResourceTracker(jd);
814 
815  /*
816  * NB: This doesn't actually emit code. That happens lazily the first
817  * time a symbol defined in the module is requested. Due to that
818  * llvm_get_function() also accounts for emission time.
819  */
820 
821  context->module = NULL; /* will be owned by LLJIT */
822  error = LLVMOrcLLJITAddLLVMIRModuleWithRT(compile_orc,
823  handle->resource_tracker,
824  ts_module);
825 
826  if (error)
827  elog(ERROR, "failed to JIT module: %s",
828  llvm_error_message(error));
829 
830  /* LLVMOrcLLJITAddLLVMIRModuleWithRT takes ownership of the module */
831  }
832 #else
833  {
834  handle->stack = compile_orc;
835  if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &handle->orc_handle, context->module,
836  llvm_resolve_symbol, NULL))
837  elog(ERROR, "failed to JIT module");
838 
839  /* LLVMOrcAddEagerlyCompiledIR takes ownership of the module */
840  }
841 #endif
842 
843  INSTR_TIME_SET_CURRENT(endtime);
844  INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
845  endtime, starttime);
846 
847  context->module = NULL;
848  context->compiled = true;
849 
850  /* remember emitted code for cleanup and lookups */
852  context->handles = lappend(context->handles, handle);
853  MemoryContextSwitchTo(oldcontext);
854 
855  ereport(DEBUG1,
856  (errmsg_internal("time to inline: %.3fs, opt: %.3fs, emit: %.3fs",
857  INSTR_TIME_GET_DOUBLE(context->base.instr.inlining_counter),
858  INSTR_TIME_GET_DOUBLE(context->base.instr.optimization_counter),
859  INSTR_TIME_GET_DOUBLE(context->base.instr.emission_counter)),
860  errhidestmt(true),
861  errhidecontext(true)));
862 }
int errmsg_internal(const char *fmt,...)
Definition: elog.c:1157
int errhidestmt(bool hide_stmt)
Definition: elog.c:1411
int errhidecontext(bool hide_ctx)
Definition: elog.c:1430
#define DEBUG1
Definition: elog.h:30
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:224
#define ereport(elevel,...)
Definition: elog.h:149
int MyProcPid
Definition: globals.c:46
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:122
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:188
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
Definition: instr_time.h:184
bool jit_dump_bitcode
Definition: jit.c:35
#define PGJIT_OPT3
Definition: jit.h:21
#define PGJIT_INLINE
Definition: jit.h:22
List * lappend(List *list, void *datum)
Definition: list.c:339
static LLVMOrcJITStackRef llvm_opt3_orc
Definition: llvmjit.c:112
static LLVMOrcJITStackRef llvm_opt0_orc
Definition: llvmjit.c:111
static void llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
Definition: llvmjit.c:635
static uint64_t llvm_resolve_symbol(const char *name, void *ctx)
Definition: llvmjit.c:1183
void llvm_inline(LLVMModuleRef M)
void pfree(void *pointer)
Definition: mcxt.c:1521
MemoryContext TopMemoryContext
Definition: mcxt.c:149
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:1181
static char * filename
Definition: pg_dumpall.c:119
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
tree context
Definition: radixtree.h:1835
MemoryContextSwitchTo(old_ctx)
static void error(void)
Definition: sql-dyntest.c:147
LLVMOrcJITStackRef stack
Definition: llvmjit.c:57
LLVMOrcModuleHandle orc_handle
Definition: llvmjit.c:58

References context, 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(), llvm_inline(), llvm_opt0_orc, llvm_opt3_orc, llvm_optimize_module(), llvm_resolve_symbol(), MemoryContextAlloc(), MemoryContextSwitchTo(), MyProcPid, LLVMJitHandle::orc_handle, pfree(), PGJIT_INLINE, PGJIT_OPT3, psprintf(), LLVMJitHandle::stack, and TopMemoryContext.

Referenced by llvm_get_function().

◆ llvm_copy_attributes()

void llvm_copy_attributes ( LLVMValueRef  v_from,
LLVMValueRef  v_to 
)

Definition at line 548 of file llvmjit.c.

549 {
550  uint32 param_count;
551 
552  /* copy function attributes */
553  llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeFunctionIndex);
554 
555  if (LLVMGetTypeKind(LLVMGetFunctionReturnType(v_to)) != LLVMVoidTypeKind)
556  {
557  /* and the return value attributes */
558  llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeReturnIndex);
559  }
560 
561  /* and each function parameter's attribute */
562  param_count = LLVMCountParams(v_from);
563 
564  for (int paramidx = 1; paramidx <= param_count; paramidx++)
565  llvm_copy_attributes_at_index(v_from, v_to, paramidx);
566 }
unsigned int uint32
Definition: c.h:506
static void llvm_copy_attributes_at_index(LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
Definition: llvmjit.c:524
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 524 of file llvmjit.c.

525 {
526  int num_attributes;
527  LLVMAttributeRef *attrs;
528 
529  num_attributes = LLVMGetAttributeCountAtIndex(v_from, index);
530 
531  if (num_attributes == 0)
532  return;
533 
534  attrs = palloc(sizeof(LLVMAttributeRef) * num_attributes);
535  LLVMGetAttributesAtIndex(v_from, index, attrs);
536 
537  for (int attno = 0; attno < num_attributes; attno++)
538  LLVMAddAttributeAtIndex(v_to, index, attrs[attno]);
539 
540  pfree(attrs);
541 }
void * palloc(Size size)
Definition: mcxt.c:1317
Definition: type.h:95

References palloc(), and pfree().

Referenced by llvm_copy_attributes().

◆ llvm_create_context()

LLVMJitContext* llvm_create_context ( int  jitFlags)

Definition at line 235 of file llvmjit.c.

236 {
237  LLVMJitContext *context;
238 
240 
242 
244 
246 
248  sizeof(LLVMJitContext));
249  context->base.flags = jitFlags;
250 
251  /* ensure cleanup */
252  context->resowner = CurrentResourceOwner;
254 
256 
257  return context;
258 }
static void llvm_recreate_llvm_context(void)
Definition: llvmjit.c:185
static void ResourceOwnerRememberJIT(ResourceOwner owner, LLVMJitContext *handle)
Definition: llvmjit.c:146
static void llvm_session_initialize(void)
Definition: llvmjit.c:868
static size_t llvm_jit_context_in_use_count
Definition: llvmjit.c:96
void llvm_assert_in_fatal_section(void)
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1215
ResourceOwner CurrentResourceOwner
Definition: resowner.c:165
void ResourceOwnerEnlarge(ResourceOwner owner)
Definition: resowner.c:442

References context, 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_types()

static void llvm_create_types ( void  )
static

Definition at line 1095 of file llvmjit.c.

1096 {
1097  char path[MAXPGPATH];
1098  LLVMMemoryBufferRef buf;
1099  char *msg;
1100 
1101  snprintf(path, MAXPGPATH, "%s/%s", pkglib_path, "llvmjit_types.bc");
1102 
1103  /* open file */
1104  if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buf, &msg))
1105  {
1106  elog(ERROR, "LLVMCreateMemoryBufferWithContentsOfFile(%s) failed: %s",
1107  path, msg);
1108  }
1109 
1110  /* eagerly load contents, going to need it all */
1111  if (LLVMParseBitcodeInContext2(llvm_context, buf, &llvm_types_module))
1112  {
1113  elog(ERROR, "LLVMParseBitcodeInContext2 of %s failed", path);
1114  }
1115  LLVMDisposeMemoryBuffer(buf);
1116 
1117  TypeSizeT = llvm_pg_var_type("TypeSizeT");
1118  TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
1119  TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
1120  TypePGFunction = llvm_pg_var_type("TypePGFunction");
1121  StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
1122  StructExprContext = llvm_pg_var_type("StructExprContext");
1123  StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
1124  StructExprState = llvm_pg_var_type("StructExprState");
1125  StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
1126  StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
1127  StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
1128  StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
1129  StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
1130  StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
1131  StructHeapTupleHeaderData = llvm_pg_var_type("StructHeapTupleHeaderData");
1132  StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
1133  StructAggState = llvm_pg_var_type("StructAggState");
1134  StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
1135  StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
1136  StructPlanState = llvm_pg_var_type("StructPlanState");
1137  StructMinimalTupleData = llvm_pg_var_type("StructMinimalTupleData");
1138 
1139  AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
1140  ExecEvalSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalSubroutineTemplate");
1141  ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalBoolSubroutineTemplate");
1142 }
char pkglib_path[MAXPGPATH]
Definition: globals.c:80
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:77
LLVMTypeRef StructMinimalTupleData
Definition: llvmjit.c:70
LLVMTypeRef StructMinimalTupleTableSlot
Definition: llvmjit.c:75
LLVMTypeRef StructPlanState
Definition: llvmjit.c:84
static LLVMContextRef llvm_context
Definition: llvmjit.c:102
LLVMTypeRef StructExprState
Definition: llvmjit.c:80
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:79
LLVMTypeRef TypeParamBool
Definition: llvmjit.c:65
LLVMTypeRef StructMemoryContextData
Definition: llvmjit.c:76
LLVMTypeRef StructAggStatePerGroupData
Definition: llvmjit.c:82
LLVMTypeRef llvm_pg_var_type(const char *varname)
Definition: llvmjit.c:454
LLVMTypeRef TypeSizeT
Definition: llvmjit.c:64
LLVMTypeRef StructTupleTableSlot
Definition: llvmjit.c:72
LLVMTypeRef TypeStorageBool
Definition: llvmjit.c:66
static LLVMTypeRef load_return_type(LLVMModuleRef mod, const char *name)
Definition: llvmjit.c:1056
LLVMTypeRef StructHeapTupleTableSlot
Definition: llvmjit.c:74
static LLVMModuleRef llvm_types_module
Definition: llvmjit.c:90
LLVMTypeRef StructAggState
Definition: llvmjit.c:81
LLVMTypeRef TypePGFunction
Definition: llvmjit.c:67
LLVMTypeRef StructTupleDescData
Definition: llvmjit.c:71
LLVMValueRef AttributeTemplate
Definition: llvmjit.c:86
LLVMTypeRef StructExprContext
Definition: llvmjit.c:78
LLVMTypeRef StructHeapTupleHeaderData
Definition: llvmjit.c:73
LLVMTypeRef StructHeapTupleData
Definition: llvmjit.c:69
LLVMTypeRef StructNullableDatum
Definition: llvmjit.c:68
LLVMValueRef ExecEvalSubroutineTemplate
Definition: llvmjit.c:87
LLVMValueRef ExecEvalBoolSubroutineTemplate
Definition: llvmjit.c:88
LLVMTypeRef StructAggStatePerTransData
Definition: llvmjit.c:83
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:73
#define snprintf
Definition: port.h:238

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

Referenced by llvm_recreate_llvm_context(), and llvm_session_initialize().

◆ llvm_expand_funcname()

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

Definition at line 359 of file llvmjit.c.

360 {
361  Assert(context->module != NULL);
362 
363  context->base.instr.created_functions++;
364 
365  /*
366  * Previously we used dots to separate, but turns out some tools, e.g.
367  * GDB, don't like that and truncate name.
368  */
369  return psprintf("%s_%zu_%d",
370  basename,
371  context->module_generation,
372  context->counter++);
373 }
#define Assert(condition)
Definition: c.h:858

References Assert, context, 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 572 of file llvmjit.c.

576 {
577  char *modname;
578  char *basename;
579  char *funcname;
580 
581  LLVMValueRef v_fn;
582 
583  fmgr_symbol(fcinfo->flinfo->fn_oid, &modname, &basename);
584 
585  if (modname != NULL && basename != NULL)
586  {
587  /* external function in loadable library */
588  funcname = psprintf("pgextern.%s.%s", modname, basename);
589  }
590  else if (basename != NULL)
591  {
592  /* internal function */
593  funcname = pstrdup(basename);
594  }
595  else
596  {
597  /*
598  * Function we don't know to handle, return pointer. We do so by
599  * creating a global constant containing a pointer to the function.
600  * Makes IR more readable.
601  */
602  LLVMValueRef v_fn_addr;
603 
604  funcname = psprintf("pgoidextern.%u",
605  fcinfo->flinfo->fn_oid);
606  v_fn = LLVMGetNamedGlobal(mod, funcname);
607  if (v_fn != 0)
608  return l_load(builder, TypePGFunction, v_fn, "");
609 
610  v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction);
611 
612  v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname);
613  LLVMSetInitializer(v_fn, v_fn_addr);
614  LLVMSetGlobalConstant(v_fn, true);
615  LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
616  LLVMSetUnnamedAddr(v_fn, true);
617 
618  return l_load(builder, TypePGFunction, v_fn, "");
619  }
620 
621  /* check if function already has been added */
622  v_fn = LLVMGetNamedFunction(mod, funcname);
623  if (v_fn != 0)
624  return v_fn;
625 
626  v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(AttributeTemplate));
627 
628  return v_fn;
629 }
void fmgr_symbol(Oid functionId, char **mod, char **fn)
Definition: fmgr.c:281
#define funcname
Definition: indent_codes.h:69
LLVMTypeRef LLVMGetFunctionType(LLVMValueRef r)
char * pstrdup(const char *in)
Definition: mcxt.c:1696
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 380 of file llvmjit.c.

381 {
382  ListCell *lc;
383 
385 
386  /*
387  * If there is a pending / not emitted module, compile and emit now.
388  * Otherwise we might not find the [correct] function.
389  */
390  if (!context->compiled)
391  {
393  }
394 
395  /*
396  * ORC's symbol table is of *unmangled* symbols. Therefore we don't need
397  * to mangle here.
398  */
399 
400 #if LLVM_VERSION_MAJOR > 11
401  foreach(lc, context->handles)
402  {
403  LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc);
404  instr_time starttime;
405  instr_time endtime;
406  LLVMErrorRef error;
407  LLVMOrcJITTargetAddress addr;
408 
409  INSTR_TIME_SET_CURRENT(starttime);
410 
411  addr = 0;
412  error = LLVMOrcLLJITLookup(handle->lljit, &addr, funcname);
413  if (error)
414  elog(ERROR, "failed to look up symbol \"%s\": %s",
415  funcname, llvm_error_message(error));
416 
417  /*
418  * LLJIT only actually emits code the first time a symbol is
419  * referenced. Thus add lookup time to emission time. That's counting
420  * a bit more than with older LLVM versions, but unlikely to ever
421  * matter.
422  */
423  INSTR_TIME_SET_CURRENT(endtime);
424  INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
425  endtime, starttime);
426 
427  if (addr)
428  return (void *) (uintptr_t) addr;
429  }
430 #else
431  foreach(lc, context->handles)
432  {
433  LLVMOrcTargetAddress addr;
434  LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc);
435 
436  addr = 0;
437  if (LLVMOrcGetSymbolAddressIn(handle->stack, &addr, handle->orc_handle, funcname))
438  elog(ERROR, "failed to look up symbol \"%s\"", funcname);
439  if (addr)
440  return (void *) (uintptr_t) addr;
441  }
442 #endif
443 
444  elog(ERROR, "failed to JIT: %s", funcname);
445 
446  return NULL;
447 }
static void llvm_compile_module(LLVMJitContext *context)
Definition: llvmjit.c:737
#define lfirst(lc)
Definition: pg_list.h:172

References context, elog, ERROR, error(), funcname, INSTR_TIME_ACCUM_DIFF, INSTR_TIME_SET_CURRENT, lfirst, llvm_assert_in_fatal_section(), llvm_compile_module(), LLVMJitHandle::orc_handle, and LLVMJitHandle::stack.

Referenced by ExecRunCompiledExpr().

◆ llvm_mutable_module()

LLVMModuleRef llvm_mutable_module ( LLVMJitContext *  context)

Definition at line 334 of file llvmjit.c.

335 {
337 
338  /*
339  * If there's no in-progress module, create a new one.
340  */
341  if (!context->module)
342  {
343  context->compiled = false;
344  context->module_generation = llvm_generation++;
345  context->module = LLVMModuleCreateWithNameInContext("pg", llvm_context);
346  LLVMSetTarget(context->module, llvm_triple);
347  LLVMSetDataLayout(context->module, llvm_layout);
348  }
349 
350  return context->module;
351 }
static const char * llvm_triple
Definition: llvmjit.c:100
static const char * llvm_layout
Definition: llvmjit.c:101
static size_t llvm_generation
Definition: llvmjit.c:93

References context, 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 635 of file llvmjit.c.

636 {
637 #if LLVM_VERSION_MAJOR < 17
638  LLVMPassManagerBuilderRef llvm_pmb;
639  LLVMPassManagerRef llvm_mpm;
640  LLVMPassManagerRef llvm_fpm;
641  LLVMValueRef func;
642  int compile_optlevel;
643 
644  if (context->base.flags & PGJIT_OPT3)
645  compile_optlevel = 3;
646  else
647  compile_optlevel = 0;
648 
649  /*
650  * Have to create a new pass manager builder every pass through, as the
651  * inliner has some per-builder state. Otherwise one ends up only inlining
652  * a function the first time though.
653  */
654  llvm_pmb = LLVMPassManagerBuilderCreate();
655  LLVMPassManagerBuilderSetOptLevel(llvm_pmb, compile_optlevel);
656  llvm_fpm = LLVMCreateFunctionPassManagerForModule(module);
657 
658  if (context->base.flags & PGJIT_OPT3)
659  {
660  /* TODO: Unscientifically determined threshold */
661  LLVMPassManagerBuilderUseInlinerWithThreshold(llvm_pmb, 512);
662  }
663  else
664  {
665  /* we rely on mem2reg heavily, so emit even in the O0 case */
666  LLVMAddPromoteMemoryToRegisterPass(llvm_fpm);
667  }
668 
669  LLVMPassManagerBuilderPopulateFunctionPassManager(llvm_pmb, llvm_fpm);
670 
671  /*
672  * Do function level optimization. This could be moved to the point where
673  * functions are emitted, to reduce memory usage a bit.
674  */
675  LLVMInitializeFunctionPassManager(llvm_fpm);
676  for (func = LLVMGetFirstFunction(context->module);
677  func != NULL;
678  func = LLVMGetNextFunction(func))
679  LLVMRunFunctionPassManager(llvm_fpm, func);
680  LLVMFinalizeFunctionPassManager(llvm_fpm);
681  LLVMDisposePassManager(llvm_fpm);
682 
683  /*
684  * Perform module level optimization. We do so even in the non-optimized
685  * case, so always-inline functions etc get inlined. It's cheap enough.
686  */
687  llvm_mpm = LLVMCreatePassManager();
688  LLVMPassManagerBuilderPopulateModulePassManager(llvm_pmb,
689  llvm_mpm);
690  /* always use always-inliner pass */
691  if (!(context->base.flags & PGJIT_OPT3))
692  LLVMAddAlwaysInlinerPass(llvm_mpm);
693  /* if doing inlining, but no expensive optimization, add inlining pass */
694  if (context->base.flags & PGJIT_INLINE
695  && !(context->base.flags & PGJIT_OPT3))
696  LLVMAddFunctionInliningPass(llvm_mpm);
697  LLVMRunPassManager(llvm_mpm, context->module);
698  LLVMDisposePassManager(llvm_mpm);
699 
700  LLVMPassManagerBuilderDispose(llvm_pmb);
701 #else
702  LLVMPassBuilderOptionsRef options;
703  LLVMErrorRef err;
704  const char *passes;
705 
706  if (context->base.flags & PGJIT_OPT3)
707  passes = "default<O3>";
708  else
709  passes = "default<O0>,mem2reg";
710 
711  options = LLVMCreatePassBuilderOptions();
712 
713 #ifdef LLVM_PASS_DEBUG
714  LLVMPassBuilderOptionsSetDebugLogging(options, 1);
715 #endif
716 
717  /* In assertion builds, run the LLVM verify pass. */
718 #ifdef USE_ASSERT_CHECKING
719  LLVMPassBuilderOptionsSetVerifyEach(options, true);
720 #endif
721 
722  LLVMPassBuilderOptionsSetInlinerThreshold(options, 512);
723 
724  err = LLVMRunPasses(module, passes, NULL, options);
725 
726  if (err)
727  elog(ERROR, "failed to JIT module: %s", llvm_error_message(err));
728 
729  LLVMDisposePassBuilderOptions(options);
730 #endif
731 }
void err(int eval, const char *fmt,...)
Definition: err.c:43
static char ** options

References context, elog, err(), ERROR, 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 496 of file llvmjit.c.

497 {
498  LLVMValueRef v_srcfn;
499  LLVMValueRef v_fn;
500 
501  /* don't repeatedly add function */
502  v_fn = LLVMGetNamedFunction(mod, funcname);
503  if (v_fn)
504  return v_fn;
505 
506  v_srcfn = LLVMGetNamedFunction(llvm_types_module, funcname);
507 
508  if (!v_srcfn)
509  elog(ERROR, "function %s not in llvmjit_types.c", funcname);
510 
511  v_fn = LLVMAddFunction(mod,
512  funcname,
513  LLVMGetFunctionType(v_srcfn));
514  llvm_copy_attributes(v_srcfn, v_fn);
515 
516  return v_fn;
517 }
void llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
Definition: llvmjit.c:548

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

475 {
476  LLVMValueRef v_srcvar;
477  LLVMTypeRef typ;
478 
479  v_srcvar = LLVMGetNamedFunction(llvm_types_module, varname);
480  if (!v_srcvar)
481  elog(ERROR, "function %s not in llvmjit_types.c", varname);
482 
483  typ = LLVMGetFunctionType(v_srcvar);
484 
485  return typ;
486 }

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

455 {
456  LLVMValueRef v_srcvar;
457  LLVMTypeRef typ;
458 
459  /* this'll return a *pointer* to the global */
460  v_srcvar = LLVMGetNamedGlobal(llvm_types_module, varname);
461  if (!v_srcvar)
462  elog(ERROR, "variable %s not in llvmjit_types.c", varname);
463 
464  typ = LLVMGlobalGetValueType(v_srcvar);
465 
466  return typ;
467 }

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

186 {
187  if (!llvm_context)
188  elog(ERROR, "Trying to recreate a non-existing context");
189 
190  /*
191  * We can only safely recreate the LLVM context if no other code is being
192  * JITed, otherwise we'd release the types in use for that.
193  */
195  {
197  return;
198  }
199 
201  {
203  return;
204  }
205 
206  /*
207  * Need to reset the modules that the inlining code caches before
208  * disposing of the context. LLVM modules exist within a specific LLVM
209  * context, therefore disposing of the context before resetting the cache
210  * would lead to dangling pointers to modules.
211  */
213 
214  LLVMContextDispose(llvm_context);
215  llvm_context = LLVMContextCreate();
217 
218  /*
219  * Re-build cached type information, so code generation code can rely on
220  * that information to be present (also prevents the variables to be
221  * dangling references).
222  */
224 }
static void llvm_create_types(void)
Definition: llvmjit.c:1095
#define LLVMJIT_LLVM_CONTEXT_REUSE_MAX
Definition: llvmjit.c:48
static size_t llvm_llvm_context_reuse_count
Definition: llvmjit.c:99
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 264 of file llvmjit.c.

265 {
266  LLVMJitContext *llvm_jit_context = (LLVMJitContext *) context;
267  ListCell *lc;
268 
269  /*
270  * Consider as cleaned up even if we skip doing so below, that way we can
271  * verify the tracking is correct (see llvm_shutdown()).
272  */
274 
275  /*
276  * When this backend is exiting, don't clean up LLVM. As an error might
277  * have occurred from within LLVM, we do not want to risk reentering. All
278  * resource cleanup is going to happen through process exit.
279  */
281  return;
282 
284 
285  if (llvm_jit_context->module)
286  {
287  LLVMDisposeModule(llvm_jit_context->module);
288  llvm_jit_context->module = NULL;
289  }
290 
291  foreach(lc, llvm_jit_context->handles)
292  {
293  LLVMJitHandle *jit_handle = (LLVMJitHandle *) lfirst(lc);
294 
295 #if LLVM_VERSION_MAJOR > 11
296  {
297  LLVMOrcExecutionSessionRef ee;
298  LLVMOrcSymbolStringPoolRef sp;
299 
300  LLVMOrcResourceTrackerRemove(jit_handle->resource_tracker);
301  LLVMOrcReleaseResourceTracker(jit_handle->resource_tracker);
302 
303  /*
304  * Without triggering cleanup of the string pool, we'd leak
305  * memory. It'd be sufficient to do this far less often, but in
306  * experiments the required time was small enough to just always
307  * do it.
308  */
309  ee = LLVMOrcLLJITGetExecutionSession(jit_handle->lljit);
310  sp = LLVMOrcExecutionSessionGetSymbolStringPool(ee);
311  LLVMOrcSymbolStringPoolClearDeadEntries(sp);
312  }
313 #else /* LLVM_VERSION_MAJOR > 11 */
314  {
315  LLVMOrcRemoveModule(jit_handle->stack, jit_handle->orc_handle);
316  }
317 #endif /* LLVM_VERSION_MAJOR > 11 */
318 
319  pfree(jit_handle);
320  }
321  list_free(llvm_jit_context->handles);
322  llvm_jit_context->handles = NIL;
323 
325 
326  if (llvm_jit_context->resowner)
327  ResourceOwnerForgetJIT(llvm_jit_context->resowner, llvm_jit_context);
328 }
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:151
void llvm_enter_fatal_on_oom(void)
void llvm_leave_fatal_on_oom(void)
#define NIL
Definition: pg_list.h:68

References context, lfirst, list_free(), llvm_enter_fatal_on_oom(), llvm_jit_context_in_use_count, llvm_leave_fatal_on_oom(), NIL, LLVMJitHandle::orc_handle, pfree(), proc_exit_inprogress, ResourceOwnerForgetJIT(), and LLVMJitHandle::stack.

Referenced by _PG_jit_provider_init().

◆ llvm_resolve_symbol()

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

Definition at line 1183 of file llvmjit.c.

1184 {
1185  uintptr_t addr;
1186  char *funcname;
1187  char *modname;
1188 
1189  /*
1190  * macOS prefixes all object level symbols with an underscore. But neither
1191  * dlsym() nor PG's inliner expect that. So undo.
1192  */
1193 #if defined(__darwin__)
1194  if (symname[0] != '_')
1195  elog(ERROR, "expected prefixed symbol name, but got \"%s\"", symname);
1196  symname++;
1197 #endif
1198 
1199  llvm_split_symbol_name(symname, &modname, &funcname);
1200 
1201  /* functions that aren't resolved to names shouldn't ever get here */
1202  Assert(funcname);
1203 
1204  if (modname)
1205  addr = (uintptr_t) load_external_function(modname, funcname,
1206  true, NULL);
1207  else
1208  addr = (uintptr_t) LLVMSearchForAddressOfSymbol(symname);
1209 
1210  pfree(funcname);
1211  if (modname)
1212  pfree(modname);
1213 
1214  /* let LLVM will error out - should never happen */
1215  if (!addr)
1216  elog(WARNING, "failed to resolve name %s", symname);
1217 
1218  return (uint64_t) addr;
1219 }
void * load_external_function(const char *filename, const char *funcname, bool signalNotFound, void **filehandle)
Definition: dfmgr.c:105
#define WARNING
Definition: elog.h:36
void llvm_split_symbol_name(const char *name, char **modname, char **funcname)
Definition: llvmjit.c:1149

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

Referenced by llvm_compile_module().

◆ llvm_session_initialize()

static void llvm_session_initialize ( void  )
static

Definition at line 868 of file llvmjit.c.

869 {
870  MemoryContext oldcontext;
871  char *error = NULL;
872  char *cpu = NULL;
873  char *features = NULL;
874  LLVMTargetMachineRef opt0_tm;
875  LLVMTargetMachineRef opt3_tm;
876 
878  return;
879 
881 
882  LLVMInitializeNativeTarget();
883  LLVMInitializeNativeAsmPrinter();
884  LLVMInitializeNativeAsmParser();
885 
886  if (llvm_context == NULL)
887  {
888  llvm_context = LLVMContextCreate();
889 
892  }
893 
894  /*
895  * When targeting LLVM 15, turn off opaque pointers for the context we
896  * build our code in. We don't need to do so for other contexts (e.g.
897  * llvm_ts_context). Once the IR is generated, it carries the necessary
898  * information.
899  *
900  * For 16 and above, opaque pointers must be used, and we have special
901  * code for that.
902  */
903 #if LLVM_VERSION_MAJOR == 15
904  LLVMContextSetOpaquePointers(LLVMGetGlobalContext(), false);
905 #endif
906 
907  /*
908  * Synchronize types early, as that also includes inferring the target
909  * triple.
910  */
912 
913  /*
914  * Extract target information from loaded module.
915  */
916  llvm_set_target();
917 
918  if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &error) != 0)
919  {
920  elog(FATAL, "failed to query triple %s", error);
921  }
922 
923  /*
924  * We want the generated code to use all available features. Therefore
925  * grab the host CPU string and detect features of the current CPU. The
926  * latter is needed because some CPU architectures default to enabling
927  * features not all CPUs have (weird, huh).
928  */
929  cpu = LLVMGetHostCPUName();
930  features = LLVMGetHostCPUFeatures();
931  elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"",
932  cpu, features);
933 
934  opt0_tm =
935  LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
936  LLVMCodeGenLevelNone,
937  LLVMRelocDefault,
938  LLVMCodeModelJITDefault);
939  opt3_tm =
940  LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
941  LLVMCodeGenLevelAggressive,
942  LLVMRelocDefault,
943  LLVMCodeModelJITDefault);
944 
945  LLVMDisposeMessage(cpu);
946  cpu = NULL;
947  LLVMDisposeMessage(features);
948  features = NULL;
949 
950  /* force symbols in main binary to be loaded */
951  LLVMLoadLibraryPermanently(NULL);
952 
953 #if LLVM_VERSION_MAJOR > 11
954  {
955  llvm_ts_context = LLVMOrcCreateNewThreadSafeContext();
956 
957  llvm_opt0_orc = llvm_create_jit_instance(opt0_tm);
958  opt0_tm = 0;
959 
960  llvm_opt3_orc = llvm_create_jit_instance(opt3_tm);
961  opt3_tm = 0;
962  }
963 #else /* LLVM_VERSION_MAJOR > 11 */
964  {
965  llvm_opt0_orc = LLVMOrcCreateInstance(opt0_tm);
966  llvm_opt3_orc = LLVMOrcCreateInstance(opt3_tm);
967 
968 #if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
970  {
971  LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
972 
973  LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l);
974  LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l);
975  }
976 #endif
977 #if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
979  {
980  LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
981 
982  LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l);
983  LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l);
984  }
985 #endif
986  }
987 #endif /* LLVM_VERSION_MAJOR > 11 */
988 
990 
992 
993  MemoryContextSwitchTo(oldcontext);
994 }
#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
bool jit_profiling_support
Definition: jit.c:37
bool jit_debugging_support
Definition: jit.c:34
static void llvm_set_target(void)
Definition: llvmjit.c:1076
static LLVMTargetRef llvm_targetref
Definition: llvmjit.c:105
static bool llvm_session_initialized
Definition: llvmjit.c:92
static void llvm_shutdown(int code, Datum arg)
Definition: llvmjit.c:997

References DEBUG2, elog, error(), FATAL, jit_debugging_support, jit_profiling_support, llvm_context, 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, MemoryContextSwitchTo(), on_proc_exit(), and TopMemoryContext.

Referenced by llvm_create_context().

◆ llvm_set_target()

static void llvm_set_target ( void  )
static

Definition at line 1076 of file llvmjit.c.

1077 {
1078  if (!llvm_types_module)
1079  elog(ERROR, "failed to extract target information, llvmjit_types.c not loaded");
1080 
1081  if (llvm_triple == NULL)
1082  llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
1083 
1084  if (llvm_layout == NULL)
1085  llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
1086 }

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

998 {
999  /*
1000  * If llvm_shutdown() is reached while in a fatal-on-oom section an error
1001  * has occurred in the middle of LLVM code. It is not safe to call back
1002  * into LLVM (which is why a FATAL error was thrown).
1003  *
1004  * We do need to shutdown LLVM in other shutdown cases, otherwise e.g.
1005  * profiling data won't be written out.
1006  */
1007  if (llvm_in_fatal_on_oom())
1008  {
1010  return;
1011  }
1012 
1014  elog(PANIC, "LLVMJitContext in use count not 0 at exit (is %zu)",
1016 
1017 #if LLVM_VERSION_MAJOR > 11
1018  {
1019  if (llvm_opt3_orc)
1020  {
1021  LLVMOrcDisposeLLJIT(llvm_opt3_orc);
1022  llvm_opt3_orc = NULL;
1023  }
1024  if (llvm_opt0_orc)
1025  {
1026  LLVMOrcDisposeLLJIT(llvm_opt0_orc);
1027  llvm_opt0_orc = NULL;
1028  }
1029  if (llvm_ts_context)
1030  {
1031  LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
1032  llvm_ts_context = NULL;
1033  }
1034  }
1035 #else /* LLVM_VERSION_MAJOR > 11 */
1036  {
1037  /* unregister profiling support, needs to be flushed to be useful */
1038 
1039  if (llvm_opt3_orc)
1040  {
1041  LLVMOrcDisposeInstance(llvm_opt3_orc);
1042  llvm_opt3_orc = NULL;
1043  }
1044 
1045  if (llvm_opt0_orc)
1046  {
1047  LLVMOrcDisposeInstance(llvm_opt0_orc);
1048  llvm_opt0_orc = NULL;
1049  }
1050  }
1051 #endif /* LLVM_VERSION_MAJOR > 11 */
1052 }
#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, 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 1149 of file llvmjit.c.

1150 {
1151  *modname = NULL;
1152  *funcname = NULL;
1153 
1154  /*
1155  * Module function names are pgextern.$module.$funcname
1156  */
1157  if (strncmp(name, "pgextern.", strlen("pgextern.")) == 0)
1158  {
1159  /*
1160  * Symbol names cannot contain a ., therefore we can split based on
1161  * first and last occurrence of one.
1162  */
1163  *funcname = rindex(name, '.');
1164  (*funcname)++; /* jump over . */
1165 
1166  *modname = pnstrdup(name + strlen("pgextern."),
1167  *funcname - name - strlen("pgextern.") - 1);
1168  Assert(funcname);
1169 
1170  *funcname = pstrdup(*funcname);
1171  }
1172  else
1173  {
1174  *modname = NULL;
1175  *funcname = pstrdup(name);
1176  }
1177 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1707
const char * name

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

1057 {
1058  LLVMValueRef value;
1059  LLVMTypeRef typ;
1060 
1061  /* this'll return a *pointer* to the function */
1062  value = LLVMGetNamedFunction(mod, name);
1063  if (!value)
1064  elog(ERROR, "function %s is unknown", name);
1065 
1066  typ = LLVMGetFunctionReturnType(value); /* in llvmjit_wrap.cpp */
1067 
1068  return typ;
1069 }
static struct @155 value

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

Referenced by llvm_create_types().

◆ ResourceOwnerForgetJIT()

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

Definition at line 151 of file llvmjit.c.

152 {
154 }
static const ResourceOwnerDesc jit_resowner_desc
Definition: llvmjit.c:135
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:322
void ResourceOwnerForget(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:554

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

Referenced by llvm_release_context().

◆ ResourceOwnerRememberJIT()

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

Definition at line 146 of file llvmjit.c.

147 {
149 }
void ResourceOwnerRemember(ResourceOwner owner, Datum value, const ResourceOwnerDesc *kind)
Definition: resowner.c:514

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

Referenced by llvm_create_context().

◆ ResOwnerReleaseJitContext()

static void ResOwnerReleaseJitContext ( Datum  res)
static

Definition at line 1378 of file llvmjit.c.

1379 {
1380  LLVMJitContext *context = (LLVMJitContext *) DatumGetPointer(res);
1381 
1382  context->resowner = NULL;
1383  jit_release_context(&context->base);
1384 }
void jit_release_context(JitContext *context)
Definition: jit.c:137
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312

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

Variable Documentation

◆ AttributeTemplate

Datum AttributeTemplate

◆ ExecEvalBoolSubroutineTemplate

bool ExecEvalBoolSubroutineTemplate

Definition at line 88 of file llvmjit.c.

Referenced by llvm_create_types().

◆ ExecEvalSubroutineTemplate

void ExecEvalSubroutineTemplate

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

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

Referenced by llvm_recreate_llvm_context(), and llvm_session_initialize().

◆ llvm_opt0_orc

LLVMOrcJITStackRef llvm_opt0_orc
static

Definition at line 111 of file llvmjit.c.

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

◆ llvm_opt3_orc

LLVMOrcJITStackRef llvm_opt3_orc
static

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

Referenced by llvm_session_initialize().

◆ llvm_targetref

LLVMTargetRef llvm_targetref
static

Definition at line 105 of file llvmjit.c.

Referenced by llvm_session_initialize().

◆ llvm_triple

const char* llvm_triple = NULL
static

Definition at line 100 of file llvmjit.c.

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

◆ llvm_types_module

LLVMModuleRef llvm_types_module = NULL
static

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 156 of file llvmjit.c.

◆ StructAggState

LLVMTypeRef StructAggState

Definition at line 81 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructAggStatePerGroupData

LLVMTypeRef StructAggStatePerGroupData

Definition at line 82 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructAggStatePerTransData

LLVMTypeRef StructAggStatePerTransData

Definition at line 83 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructExprContext

LLVMTypeRef StructExprContext

Definition at line 78 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructExprEvalStep

LLVMTypeRef StructExprEvalStep

Definition at line 79 of file llvmjit.c.

Referenced by build_EvalXFuncInt(), and llvm_create_types().

◆ StructExprState

LLVMTypeRef StructExprState

Definition at line 80 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructFunctionCallInfoData

LLVMTypeRef StructFunctionCallInfoData

Definition at line 77 of file llvmjit.c.

Referenced by BuildV1Call(), and llvm_create_types().

◆ StructHeapTupleData

LLVMTypeRef StructHeapTupleData

Definition at line 69 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructHeapTupleHeaderData

LLVMTypeRef StructHeapTupleHeaderData

Definition at line 73 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructHeapTupleTableSlot

LLVMTypeRef StructHeapTupleTableSlot

Definition at line 74 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructMemoryContextData

LLVMTypeRef StructMemoryContextData

Definition at line 76 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructMinimalTupleData

LLVMTypeRef StructMinimalTupleData

Definition at line 70 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructMinimalTupleTableSlot

LLVMTypeRef StructMinimalTupleTableSlot

Definition at line 75 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructNullableDatum

LLVMTypeRef StructNullableDatum

Definition at line 68 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructPlanState

LLVMTypeRef StructPlanState

Definition at line 84 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructTupleDescData

LLVMTypeRef StructTupleDescData

Definition at line 71 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructTupleTableSlot

LLVMTypeRef StructTupleTableSlot

Definition at line 72 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ TypeParamBool

LLVMTypeRef TypeParamBool

Definition at line 65 of file llvmjit.c.

Referenced by llvm_create_types().

◆ TypePGFunction

LLVMTypeRef TypePGFunction

Definition at line 67 of file llvmjit.c.

Referenced by llvm_create_types(), and llvm_function_reference().

◆ TypeSizeT

LLVMTypeRef TypeSizeT

Definition at line 64 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ TypeStorageBool

LLVMTypeRef TypeStorageBool

Definition at line 66 of file llvmjit.c.

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