PostgreSQL Source Code  git master
llvmjit.c File Reference
#include "postgres.h"
#include <llvm-c/Analysis.h>
#include <llvm-c/BitReader.h>
#include <llvm-c/BitWriter.h>
#include <llvm-c/Core.h>
#include <llvm-c/ExecutionEngine.h>
#include <llvm-c/Orc.h>
#include <llvm-c/OrcEE.h>
#include <llvm-c/LLJIT.h>
#include <llvm-c/Support.h>
#include <llvm-c/Target.h>
#include <llvm-c/Transforms/IPO.h>
#include <llvm-c/Transforms/PassManagerBuilder.h>
#include <llvm-c/Transforms/Scalar.h>
#include <llvm-c/Transforms/Utils.h>
#include "jit/llvmjit.h"
#include "jit/llvmjit_emit.h"
#include "miscadmin.h"
#include "portability/instr_time.h"
#include "storage/ipc.h"
#include "utils/memutils.h"
#include "utils/resowner.h"
Include dependency graph for llvmjit.c:

Go to the source code of this file.

Data Structures

struct  LLVMJitHandle
 

Macros

#define LLVMJIT_LLVM_CONTEXT_REUSE_MAX   100
 

Typedefs

typedef struct LLVMJitHandle LLVMJitHandle
 

Functions

static void llvm_release_context (JitContext *context)
 
static void llvm_session_initialize (void)
 
static void llvm_shutdown (int code, Datum arg)
 
static void llvm_compile_module (LLVMJitContext *context)
 
static void llvm_optimize_module (LLVMJitContext *context, LLVMModuleRef module)
 
static void llvm_create_types (void)
 
static void llvm_set_target (void)
 
static void llvm_recreate_llvm_context (void)
 
static uint64_t llvm_resolve_symbol (const char *name, void *ctx)
 
static LLVMOrcLLJITRef llvm_create_jit_instance (LLVMTargetMachineRef tm)
 
static char * llvm_error_message (LLVMErrorRef error)
 
static void ResOwnerReleaseJitContext (Datum res)
 
static void ResourceOwnerRememberJIT (ResourceOwner owner, LLVMJitContext *handle)
 
static void ResourceOwnerForgetJIT (ResourceOwner owner, LLVMJitContext *handle)
 
void _PG_jit_provider_init (JitProviderCallbacks *cb)
 
LLVMJitContext * llvm_create_context (int jitFlags)
 
LLVMModuleRef llvm_mutable_module (LLVMJitContext *context)
 
char * llvm_expand_funcname (struct LLVMJitContext *context, const char *basename)
 
void * llvm_get_function (LLVMJitContext *context, const char *funcname)
 
LLVMTypeRef llvm_pg_var_type (const char *varname)
 
LLVMTypeRef llvm_pg_var_func_type (const char *varname)
 
LLVMValueRef llvm_pg_func (LLVMModuleRef mod, const char *funcname)
 
static void llvm_copy_attributes_at_index (LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
 
void llvm_copy_attributes (LLVMValueRef v_from, LLVMValueRef v_to)
 
LLVMValueRef llvm_function_reference (LLVMJitContext *context, LLVMBuilderRef builder, LLVMModuleRef mod, FunctionCallInfo fcinfo)
 
static LLVMTypeRef load_return_type (LLVMModuleRef mod, const char *name)
 
void llvm_split_symbol_name (const char *name, char **modname, char **funcname)
 
static LLVMErrorRef llvm_resolve_symbols (LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx, LLVMOrcLookupStateRef *LookupState, LLVMOrcLookupKind Kind, LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags JDLookupFlags, LLVMOrcCLookupSet LookupSet, size_t LookupSetSize)
 
static void llvm_log_jit_error (void *ctx, LLVMErrorRef error)
 
static LLVMOrcObjectLayerRef llvm_create_object_layer (void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
 

Variables

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

Macro Definition Documentation

◆ LLVMJIT_LLVM_CONTEXT_REUSE_MAX

#define LLVMJIT_LLVM_CONTEXT_REUSE_MAX   100

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

148 {
152 }
static void llvm_release_context(JitContext *context)
Definition: llvmjit.c:248
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 701 of file llvmjit.c.

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

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(), LLVMJitHandle::lljit, llvm_error_message(), llvm_inline(), llvm_opt0_orc, llvm_opt3_orc, llvm_optimize_module(), llvm_ts_context, MemoryContextAlloc(), MemoryContextSwitchTo(), MyProcPid, pfree(), PGJIT_INLINE, PGJIT_OPT3, psprintf(), LLVMJitHandle::resource_tracker, and TopMemoryContext.

Referenced by llvm_get_function().

◆ llvm_copy_attributes()

void llvm_copy_attributes ( LLVMValueRef  v_from,
LLVMValueRef  v_to 
)

Definition at line 512 of file llvmjit.c.

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

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

220 {
221  LLVMJitContext *context;
222 
224 
226 
228 
230 
232  sizeof(LLVMJitContext));
233  context->base.flags = jitFlags;
234 
235  /* ensure cleanup */
236  context->resowner = CurrentResourceOwner;
238 
240 
241  return context;
242 }
static void llvm_recreate_llvm_context(void)
Definition: llvmjit.c:169
static void ResourceOwnerRememberJIT(ResourceOwner owner, LLVMJitContext *handle)
Definition: llvmjit.c:130
static void llvm_session_initialize(void)
Definition: llvmjit.c:817
static size_t llvm_jit_context_in_use_count
Definition: llvmjit.c:87
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_jit_instance()

static LLVMOrcLLJITRef llvm_create_jit_instance ( LLVMTargetMachineRef  tm)
static

Definition at line 1198 of file llvmjit.c.

1199 {
1200  LLVMOrcLLJITRef lljit;
1201  LLVMOrcJITTargetMachineBuilderRef tm_builder;
1202  LLVMOrcLLJITBuilderRef lljit_builder;
1203  LLVMErrorRef error;
1204  LLVMOrcDefinitionGeneratorRef main_gen;
1205  LLVMOrcDefinitionGeneratorRef ref_gen;
1206 
1207  lljit_builder = LLVMOrcCreateLLJITBuilder();
1208  tm_builder = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm);
1209  LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(lljit_builder, tm_builder);
1210 
1211  LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(lljit_builder,
1213  NULL);
1214 
1215  error = LLVMOrcCreateLLJIT(&lljit, lljit_builder);
1216  if (error)
1217  elog(ERROR, "failed to create lljit instance: %s",
1219 
1220  LLVMOrcExecutionSessionSetErrorReporter(LLVMOrcLLJITGetExecutionSession(lljit),
1221  llvm_log_jit_error, NULL);
1222 
1223  /*
1224  * Symbol resolution support for symbols in the postgres binary /
1225  * libraries already loaded.
1226  */
1227  error = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(&main_gen,
1228  LLVMOrcLLJITGetGlobalPrefix(lljit),
1229  0, NULL);
1230  if (error)
1231  elog(ERROR, "failed to create generator: %s",
1233  LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), main_gen);
1234 
1235  /*
1236  * Symbol resolution support for "special" functions, e.g. a call into an
1237  * SQL callable function.
1238  */
1239 #if LLVM_VERSION_MAJOR > 14
1240  ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL, NULL);
1241 #else
1242  ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL);
1243 #endif
1244  LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), ref_gen);
1245 
1246  return lljit;
1247 }
static LLVMOrcObjectLayerRef llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
Definition: llvmjit.c:1167
static LLVMErrorRef llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx, LLVMOrcLookupStateRef *LookupState, LLVMOrcLookupKind Kind, LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags JDLookupFlags, LLVMOrcCLookupSet LookupSet, size_t LookupSetSize)
Definition: llvmjit.c:1114
static void llvm_log_jit_error(void *ctx, LLVMErrorRef error)
Definition: llvmjit.c:1157
static struct pg_tm tm
Definition: localtime.c:104

References elog, ERROR, error(), llvm_create_object_layer(), llvm_error_message(), llvm_log_jit_error(), llvm_resolve_symbols(), and tm.

Referenced by llvm_session_initialize().

◆ llvm_create_object_layer()

static LLVMOrcObjectLayerRef llvm_create_object_layer ( void *  Ctx,
LLVMOrcExecutionSessionRef  ES,
const char *  Triple 
)
static

Definition at line 1167 of file llvmjit.c.

1168 {
1169  LLVMOrcObjectLayerRef objlayer =
1170  LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
1171 
1172 #if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
1174  {
1175  LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
1176 
1177  LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
1178  }
1179 #endif
1180 
1181 #if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
1183  {
1184  LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
1185 
1186  LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
1187  }
1188 #endif
1189 
1190  return objlayer;
1191 }
bool jit_profiling_support
Definition: jit.c:37
bool jit_debugging_support
Definition: jit.c:34

References jit_debugging_support, and jit_profiling_support.

Referenced by llvm_create_jit_instance().

◆ llvm_create_types()

static void llvm_create_types ( void  )
static

Definition at line 987 of file llvmjit.c.

988 {
989  char path[MAXPGPATH];
990  LLVMMemoryBufferRef buf;
991  char *msg;
992 
993  snprintf(path, MAXPGPATH, "%s/%s", pkglib_path, "llvmjit_types.bc");
994 
995  /* open file */
996  if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buf, &msg))
997  {
998  elog(ERROR, "LLVMCreateMemoryBufferWithContentsOfFile(%s) failed: %s",
999  path, msg);
1000  }
1001 
1002  /* eagerly load contents, going to need it all */
1003  if (LLVMParseBitcodeInContext2(llvm_context, buf, &llvm_types_module))
1004  {
1005  elog(ERROR, "LLVMParseBitcodeInContext2 of %s failed", path);
1006  }
1007  LLVMDisposeMemoryBuffer(buf);
1008 
1009  TypeSizeT = llvm_pg_var_type("TypeSizeT");
1010  TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
1011  TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
1012  TypePGFunction = llvm_pg_var_type("TypePGFunction");
1013  StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
1014  StructExprContext = llvm_pg_var_type("StructExprContext");
1015  StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
1016  StructExprState = llvm_pg_var_type("StructExprState");
1017  StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
1018  StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
1019  StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
1020  StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
1021  StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
1022  StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
1023  StructHeapTupleHeaderData = llvm_pg_var_type("StructHeapTupleHeaderData");
1024  StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
1025  StructAggState = llvm_pg_var_type("StructAggState");
1026  StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
1027  StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
1028  StructPlanState = llvm_pg_var_type("StructPlanState");
1029  StructMinimalTupleData = llvm_pg_var_type("StructMinimalTupleData");
1030 
1031  AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
1032  ExecEvalSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalSubroutineTemplate");
1033  ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalBoolSubroutineTemplate");
1034 }
char pkglib_path[MAXPGPATH]
Definition: globals.c:81
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:68
LLVMTypeRef StructMinimalTupleData
Definition: llvmjit.c:61
LLVMTypeRef StructMinimalTupleTableSlot
Definition: llvmjit.c:66
LLVMTypeRef StructPlanState
Definition: llvmjit.c:75
static LLVMContextRef llvm_context
Definition: llvmjit.c:93
LLVMTypeRef StructExprState
Definition: llvmjit.c:71
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:70
LLVMTypeRef TypeParamBool
Definition: llvmjit.c:56
LLVMTypeRef StructMemoryContextData
Definition: llvmjit.c:67
LLVMTypeRef StructAggStatePerGroupData
Definition: llvmjit.c:73
LLVMTypeRef llvm_pg_var_type(const char *varname)
Definition: llvmjit.c:418
LLVMTypeRef TypeSizeT
Definition: llvmjit.c:55
LLVMTypeRef StructTupleTableSlot
Definition: llvmjit.c:63
LLVMTypeRef TypeStorageBool
Definition: llvmjit.c:57
static LLVMTypeRef load_return_type(LLVMModuleRef mod, const char *name)
Definition: llvmjit.c:948
LLVMTypeRef StructHeapTupleTableSlot
Definition: llvmjit.c:65
static LLVMModuleRef llvm_types_module
Definition: llvmjit.c:81
LLVMTypeRef StructAggState
Definition: llvmjit.c:72
LLVMTypeRef TypePGFunction
Definition: llvmjit.c:58
LLVMTypeRef StructTupleDescData
Definition: llvmjit.c:62
LLVMValueRef AttributeTemplate
Definition: llvmjit.c:77
LLVMTypeRef StructExprContext
Definition: llvmjit.c:69
LLVMTypeRef StructHeapTupleHeaderData
Definition: llvmjit.c:64
LLVMTypeRef StructHeapTupleData
Definition: llvmjit.c:60
LLVMTypeRef StructNullableDatum
Definition: llvmjit.c:59
LLVMValueRef ExecEvalSubroutineTemplate
Definition: llvmjit.c:78
LLVMValueRef ExecEvalBoolSubroutineTemplate
Definition: llvmjit.c:79
LLVMTypeRef StructAggStatePerTransData
Definition: llvmjit.c:74
#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_error_message()

static char * llvm_error_message ( LLVMErrorRef  error)
static

Definition at line 1250 of file llvmjit.c.

1251 {
1252  char *orig = LLVMGetErrorMessage(error);
1253  char *msg = pstrdup(orig);
1254 
1255  LLVMDisposeErrorMessage(orig);
1256 
1257  return msg;
1258 }
char * pstrdup(const char *in)
Definition: mcxt.c:1696

References error(), and pstrdup().

Referenced by llvm_compile_module(), llvm_create_jit_instance(), llvm_get_function(), llvm_log_jit_error(), and llvm_optimize_module().

◆ llvm_expand_funcname()

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

Definition at line 337 of file llvmjit.c.

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

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

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

References AttributeTemplate, FunctionCallInfoBaseData::flinfo, fmgr_symbol(), FmgrInfo::fn_addr, FmgrInfo::fn_oid, funcname, LLVMGetFunctionType(), psprintf(), pstrdup(), and TypePGFunction.

Referenced by BuildV1Call().

◆ llvm_get_function()

void* llvm_get_function ( LLVMJitContext *  context,
const char *  funcname 
)

Definition at line 358 of file llvmjit.c.

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

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

Referenced by ExecRunCompiledExpr().

◆ llvm_log_jit_error()

static void llvm_log_jit_error ( void *  ctx,
LLVMErrorRef  error 
)
static

Definition at line 1157 of file llvmjit.c.

1158 {
1159  elog(WARNING, "error during JITing: %s",
1161 }
#define WARNING
Definition: elog.h:36

References elog, error(), llvm_error_message(), and WARNING.

Referenced by llvm_create_jit_instance().

◆ llvm_mutable_module()

LLVMModuleRef llvm_mutable_module ( LLVMJitContext *  context)

Definition at line 312 of file llvmjit.c.

313 {
315 
316  /*
317  * If there's no in-progress module, create a new one.
318  */
319  if (!context->module)
320  {
321  context->compiled = false;
322  context->module_generation = llvm_generation++;
323  context->module = LLVMModuleCreateWithNameInContext("pg", llvm_context);
324  LLVMSetTarget(context->module, llvm_triple);
325  LLVMSetDataLayout(context->module, llvm_layout);
326  }
327 
328  return context->module;
329 }
static const char * llvm_triple
Definition: llvmjit.c:91
static const char * llvm_layout
Definition: llvmjit.c:92
static size_t llvm_generation
Definition: llvmjit.c:84

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

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

References context, elog, err(), ERROR, llvm_error_message(), options, PGJIT_INLINE, and PGJIT_OPT3.

Referenced by llvm_compile_module().

◆ llvm_pg_func()

LLVMValueRef llvm_pg_func ( LLVMModuleRef  mod,
const char *  funcname 
)

Definition at line 460 of file llvmjit.c.

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

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

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

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

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

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

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

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

Referenced by _PG_jit_provider_init().

◆ llvm_resolve_symbol()

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

Definition at line 1075 of file llvmjit.c.

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

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

Referenced by llvm_resolve_symbols().

◆ llvm_resolve_symbols()

static LLVMErrorRef llvm_resolve_symbols ( LLVMOrcDefinitionGeneratorRef  GeneratorObj,
void *  Ctx,
LLVMOrcLookupStateRef *  LookupState,
LLVMOrcLookupKind  Kind,
LLVMOrcJITDylibRef  JD,
LLVMOrcJITDylibLookupFlags  JDLookupFlags,
LLVMOrcCLookupSet  LookupSet,
size_t  LookupSetSize 
)
static

Definition at line 1114 of file llvmjit.c.

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

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

Referenced by llvm_create_jit_instance().

◆ llvm_session_initialize()

static void llvm_session_initialize ( void  )
static

Definition at line 817 of file llvmjit.c.

818 {
819  MemoryContext oldcontext;
820  char *error = NULL;
821  char *cpu = NULL;
822  char *features = NULL;
823  LLVMTargetMachineRef opt0_tm;
824  LLVMTargetMachineRef opt3_tm;
825 
827  return;
828 
830 
831  LLVMInitializeNativeTarget();
832  LLVMInitializeNativeAsmPrinter();
833  LLVMInitializeNativeAsmParser();
834 
835  if (llvm_context == NULL)
836  {
837  llvm_context = LLVMContextCreate();
838 
841  }
842 
843  /*
844  * Synchronize types early, as that also includes inferring the target
845  * triple.
846  */
848 
849  /*
850  * Extract target information from loaded module.
851  */
852  llvm_set_target();
853 
854  if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &error) != 0)
855  {
856  elog(FATAL, "failed to query triple %s", error);
857  }
858 
859  /*
860  * We want the generated code to use all available features. Therefore
861  * grab the host CPU string and detect features of the current CPU. The
862  * latter is needed because some CPU architectures default to enabling
863  * features not all CPUs have (weird, huh).
864  */
865  cpu = LLVMGetHostCPUName();
866  features = LLVMGetHostCPUFeatures();
867  elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"",
868  cpu, features);
869 
870  opt0_tm =
871  LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
872  LLVMCodeGenLevelNone,
873  LLVMRelocDefault,
874  LLVMCodeModelJITDefault);
875  opt3_tm =
876  LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
877  LLVMCodeGenLevelAggressive,
878  LLVMRelocDefault,
879  LLVMCodeModelJITDefault);
880 
881  LLVMDisposeMessage(cpu);
882  cpu = NULL;
883  LLVMDisposeMessage(features);
884  features = NULL;
885 
886  /* force symbols in main binary to be loaded */
887  LLVMLoadLibraryPermanently(NULL);
888 
889  {
890  llvm_ts_context = LLVMOrcCreateNewThreadSafeContext();
891 
893  opt0_tm = 0;
894 
896  opt3_tm = 0;
897  }
898 
900 
902 
903  MemoryContextSwitchTo(oldcontext);
904 }
#define FATAL
Definition: elog.h:41
#define DEBUG2
Definition: elog.h:29
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:309
static void llvm_set_target(void)
Definition: llvmjit.c:968
static LLVMTargetRef llvm_targetref
Definition: llvmjit.c:96
static bool llvm_session_initialized
Definition: llvmjit.c:83
static LLVMOrcLLJITRef llvm_create_jit_instance(LLVMTargetMachineRef tm)
Definition: llvmjit.c:1198
static void llvm_shutdown(int code, Datum arg)
Definition: llvmjit.c:907

References DEBUG2, elog, error(), FATAL, llvm_context, llvm_create_jit_instance(), llvm_create_types(), llvm_jit_context_in_use_count, llvm_llvm_context_reuse_count, llvm_opt0_orc, llvm_opt3_orc, llvm_session_initialized, llvm_set_target(), llvm_shutdown(), llvm_targetref, llvm_triple, llvm_ts_context, MemoryContextSwitchTo(), on_proc_exit(), and TopMemoryContext.

Referenced by llvm_create_context().

◆ llvm_set_target()

static void llvm_set_target ( void  )
static

Definition at line 968 of file llvmjit.c.

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

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

908 {
909  /*
910  * If llvm_shutdown() is reached while in a fatal-on-oom section an error
911  * has occurred in the middle of LLVM code. It is not safe to call back
912  * into LLVM (which is why a FATAL error was thrown).
913  *
914  * We do need to shutdown LLVM in other shutdown cases, otherwise e.g.
915  * profiling data won't be written out.
916  */
917  if (llvm_in_fatal_on_oom())
918  {
920  return;
921  }
922 
924  elog(PANIC, "LLVMJitContext in use count not 0 at exit (is %zu)",
926 
927  {
928  if (llvm_opt3_orc)
929  {
930  LLVMOrcDisposeLLJIT(llvm_opt3_orc);
931  llvm_opt3_orc = NULL;
932  }
933  if (llvm_opt0_orc)
934  {
935  LLVMOrcDisposeLLJIT(llvm_opt0_orc);
936  llvm_opt0_orc = NULL;
937  }
938  if (llvm_ts_context)
939  {
940  LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
941  llvm_ts_context = NULL;
942  }
943  }
944 }
#define PANIC
Definition: elog.h:42
bool llvm_in_fatal_on_oom(void)

References Assert, elog, llvm_in_fatal_on_oom(), llvm_jit_context_in_use_count, llvm_opt0_orc, llvm_opt3_orc, llvm_ts_context, PANIC, and proc_exit_inprogress.

Referenced by llvm_session_initialize().

◆ llvm_split_symbol_name()

void llvm_split_symbol_name ( const char *  name,
char **  modname,
char **  funcname 
)

Definition at line 1041 of file llvmjit.c.

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

References Assert, funcname, name, pnstrdup(), and pstrdup().

Referenced by llvm_build_inline_plan(), llvm_execute_inline_plan(), and llvm_resolve_symbol().

◆ load_return_type()

static LLVMTypeRef load_return_type ( LLVMModuleRef  mod,
const char *  name 
)
static

Definition at line 948 of file llvmjit.c.

949 {
950  LLVMValueRef value;
951  LLVMTypeRef typ;
952 
953  /* this'll return a *pointer* to the function */
954  value = LLVMGetNamedFunction(mod, name);
955  if (!value)
956  elog(ERROR, "function %s is unknown", name);
957 
958  typ = LLVMGetFunctionReturnType(value); /* in llvmjit_wrap.cpp */
959 
960  return typ;
961 }
static struct @157 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 135 of file llvmjit.c.

136 {
138 }
static const ResourceOwnerDesc jit_resowner_desc
Definition: llvmjit.c:119
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 130 of file llvmjit.c.

131 {
133 }
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 1264 of file llvmjit.c.

1265 {
1266  LLVMJitContext *context = (LLVMJitContext *) DatumGetPointer(res);
1267 
1268  context->resowner = NULL;
1269  jit_release_context(&context->base);
1270 }
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 79 of file llvmjit.c.

Referenced by llvm_create_types().

◆ ExecEvalSubroutineTemplate

void ExecEvalSubroutineTemplate

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

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

Referenced by llvm_recreate_llvm_context(), and llvm_session_initialize().

◆ llvm_opt0_orc

LLVMOrcLLJITRef llvm_opt0_orc
static

Definition at line 98 of file llvmjit.c.

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

◆ llvm_opt3_orc

LLVMOrcLLJITRef llvm_opt3_orc
static

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

Referenced by llvm_session_initialize().

◆ llvm_targetref

LLVMTargetRef llvm_targetref
static

Definition at line 96 of file llvmjit.c.

Referenced by llvm_session_initialize().

◆ llvm_triple

const char* llvm_triple = NULL
static

Definition at line 91 of file llvmjit.c.

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

◆ llvm_ts_context

LLVMOrcThreadSafeContextRef llvm_ts_context
static

Definition at line 97 of file llvmjit.c.

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

◆ llvm_types_module

LLVMModuleRef llvm_types_module = NULL
static

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 140 of file llvmjit.c.

◆ StructAggState

LLVMTypeRef StructAggState

Definition at line 72 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructAggStatePerGroupData

LLVMTypeRef StructAggStatePerGroupData

Definition at line 73 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructAggStatePerTransData

LLVMTypeRef StructAggStatePerTransData

Definition at line 74 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructExprContext

LLVMTypeRef StructExprContext

Definition at line 69 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructExprEvalStep

LLVMTypeRef StructExprEvalStep

Definition at line 70 of file llvmjit.c.

Referenced by build_EvalXFuncInt(), and llvm_create_types().

◆ StructExprState

LLVMTypeRef StructExprState

Definition at line 71 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructFunctionCallInfoData

LLVMTypeRef StructFunctionCallInfoData

Definition at line 68 of file llvmjit.c.

Referenced by BuildV1Call(), and llvm_create_types().

◆ StructHeapTupleData

LLVMTypeRef StructHeapTupleData

Definition at line 60 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructHeapTupleHeaderData

LLVMTypeRef StructHeapTupleHeaderData

Definition at line 64 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructHeapTupleTableSlot

LLVMTypeRef StructHeapTupleTableSlot

Definition at line 65 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructMemoryContextData

LLVMTypeRef StructMemoryContextData

Definition at line 67 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructMinimalTupleData

LLVMTypeRef StructMinimalTupleData

Definition at line 61 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructMinimalTupleTableSlot

LLVMTypeRef StructMinimalTupleTableSlot

Definition at line 66 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructNullableDatum

LLVMTypeRef StructNullableDatum

Definition at line 59 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructPlanState

LLVMTypeRef StructPlanState

Definition at line 75 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructTupleDescData

LLVMTypeRef StructTupleDescData

Definition at line 62 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructTupleTableSlot

LLVMTypeRef StructTupleTableSlot

Definition at line 63 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ TypeParamBool

LLVMTypeRef TypeParamBool

Definition at line 56 of file llvmjit.c.

Referenced by llvm_create_types().

◆ TypePGFunction

LLVMTypeRef TypePGFunction

Definition at line 58 of file llvmjit.c.

Referenced by llvm_create_types(), and llvm_function_reference().

◆ TypeSizeT

LLVMTypeRef TypeSizeT

Definition at line 55 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ TypeStorageBool

LLVMTypeRef TypeStorageBool

Definition at line 57 of file llvmjit.c.

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