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:80
JitProviderResetAfterErrorCB reset_after_error
Definition: jit.h:78
JitProviderReleaseContextCB release_context
Definition: jit.h:79

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

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

1091 {
1092  char path[MAXPGPATH];
1093  LLVMMemoryBufferRef buf;
1094  char *msg;
1095 
1096  snprintf(path, MAXPGPATH, "%s/%s", pkglib_path, "llvmjit_types.bc");
1097 
1098  /* open file */
1099  if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buf, &msg))
1100  {
1101  elog(ERROR, "LLVMCreateMemoryBufferWithContentsOfFile(%s) failed: %s",
1102  path, msg);
1103  }
1104 
1105  /* eagerly load contents, going to need it all */
1106  if (LLVMParseBitcodeInContext2(llvm_context, buf, &llvm_types_module))
1107  {
1108  elog(ERROR, "LLVMParseBitcodeInContext2 of %s failed", path);
1109  }
1110  LLVMDisposeMemoryBuffer(buf);
1111 
1112  TypeSizeT = llvm_pg_var_type("TypeSizeT");
1113  TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
1114  TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
1115  TypePGFunction = llvm_pg_var_type("TypePGFunction");
1116  StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
1117  StructExprContext = llvm_pg_var_type("StructExprContext");
1118  StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
1119  StructExprState = llvm_pg_var_type("StructExprState");
1120  StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
1121  StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
1122  StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
1123  StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
1124  StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
1125  StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
1126  StructHeapTupleHeaderData = llvm_pg_var_type("StructHeapTupleHeaderData");
1127  StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
1128  StructAggState = llvm_pg_var_type("StructAggState");
1129  StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
1130  StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
1131  StructPlanState = llvm_pg_var_type("StructPlanState");
1132  StructMinimalTupleData = llvm_pg_var_type("StructMinimalTupleData");
1133 
1134  AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
1135  ExecEvalSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalSubroutineTemplate");
1136  ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalBoolSubroutineTemplate");
1137 }
char pkglib_path[MAXPGPATH]
Definition: globals.c:79
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:1051
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:1695
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:732
#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  LLVMPassBuilderOptionsSetInlinerThreshold(options, 512);
718 
719  err = LLVMRunPasses(module, passes, NULL, options);
720 
721  if (err)
722  elog(ERROR, "failed to JIT module: %s", llvm_error_message(err));
723 
724  LLVMDisposePassBuilderOptions(options);
725 #endif
726 }
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:1090
#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 (context->resowner)
327  ResourceOwnerForgetJIT(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 1178 of file llvmjit.c.

1179 {
1180  uintptr_t addr;
1181  char *funcname;
1182  char *modname;
1183 
1184  /*
1185  * macOS prefixes all object level symbols with an underscore. But neither
1186  * dlsym() nor PG's inliner expect that. So undo.
1187  */
1188 #if defined(__darwin__)
1189  if (symname[0] != '_')
1190  elog(ERROR, "expected prefixed symbol name, but got \"%s\"", symname);
1191  symname++;
1192 #endif
1193 
1194  llvm_split_symbol_name(symname, &modname, &funcname);
1195 
1196  /* functions that aren't resolved to names shouldn't ever get here */
1197  Assert(funcname);
1198 
1199  if (modname)
1200  addr = (uintptr_t) load_external_function(modname, funcname,
1201  true, NULL);
1202  else
1203  addr = (uintptr_t) LLVMSearchForAddressOfSymbol(symname);
1204 
1205  pfree(funcname);
1206  if (modname)
1207  pfree(modname);
1208 
1209  /* let LLVM will error out - should never happen */
1210  if (!addr)
1211  elog(WARNING, "failed to resolve name %s", symname);
1212 
1213  return (uint64_t) addr;
1214 }
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:1144

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

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

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

1072 {
1073  if (!llvm_types_module)
1074  elog(ERROR, "failed to extract target information, llvmjit_types.c not loaded");
1075 
1076  if (llvm_triple == NULL)
1077  llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
1078 
1079  if (llvm_layout == NULL)
1080  llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
1081 }

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

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

1145 {
1146  *modname = NULL;
1147  *funcname = NULL;
1148 
1149  /*
1150  * Module function names are pgextern.$module.$funcname
1151  */
1152  if (strncmp(name, "pgextern.", strlen("pgextern.")) == 0)
1153  {
1154  /*
1155  * Symbol names cannot contain a ., therefore we can split based on
1156  * first and last occurrence of one.
1157  */
1158  *funcname = rindex(name, '.');
1159  (*funcname)++; /* jump over . */
1160 
1161  *modname = pnstrdup(name + strlen("pgextern."),
1162  *funcname - name - strlen("pgextern.") - 1);
1163  Assert(funcname);
1164 
1165  *funcname = pstrdup(*funcname);
1166  }
1167  else
1168  {
1169  *modname = NULL;
1170  *funcname = pstrdup(name);
1171  }
1172 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1706
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 1051 of file llvmjit.c.

1052 {
1053  LLVMValueRef value;
1054  LLVMTypeRef typ;
1055 
1056  /* this'll return a *pointer* to the function */
1057  value = LLVMGetNamedFunction(mod, name);
1058  if (!value)
1059  elog(ERROR, "function %s is unknown", name);
1060 
1061  typ = LLVMGetFunctionReturnType(value); /* in llvmjit_wrap.cpp */
1062 
1063  return typ;
1064 }
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 1373 of file llvmjit.c.

1374 {
1376 
1377  context->resowner = NULL;
1379 }
void jit_release_context(JitContext *context)
Definition: jit.c:137
static Pointer DatumGetPointer(Datum X)
Definition: postgres.h:312
Definition: jit.h:58

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:1373
#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().