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 "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_private.h"
Include dependency graph for llvmjit.c:

Go to the source code of this file.

Data Structures

struct  LLVMJitHandle
 

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 uint64_t llvm_resolve_symbol (const char *name, void *ctx)
 
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 StructHeapTupleFieldsField3
 
LLVMTypeRef StructHeapTupleFields
 
LLVMTypeRef StructHeapTupleHeaderData
 
LLVMTypeRef StructHeapTupleDataChoice
 
LLVMTypeRef StructHeapTupleData
 
LLVMTypeRef StructMinimalTupleData
 
LLVMTypeRef StructItemPointerData
 
LLVMTypeRef StructBlockId
 
LLVMTypeRef StructFormPgAttribute
 
LLVMTypeRef StructTupleConstr
 
LLVMTypeRef StructTupleDescData
 
LLVMTypeRef StructTupleTableSlot
 
LLVMTypeRef StructHeapTupleTableSlot
 
LLVMTypeRef StructMinimalTupleTableSlot
 
LLVMTypeRef StructMemoryContextData
 
LLVMTypeRef StructPGFinfoRecord
 
LLVMTypeRef StructFmgrInfo
 
LLVMTypeRef StructFunctionCallInfoData
 
LLVMTypeRef StructExprContext
 
LLVMTypeRef StructExprEvalStep
 
LLVMTypeRef StructExprState
 
LLVMTypeRef StructAggState
 
LLVMTypeRef StructAggStatePerGroupData
 
LLVMTypeRef StructAggStatePerTransData
 
LLVMValueRef AttributeTemplate
 
LLVMModuleRef llvm_types_module = NULL
 
static bool llvm_session_initialized = false
 
static size_t llvm_generation = 0
 
static const char * llvm_triple = NULL
 
static const char * llvm_layout = NULL
 
static LLVMTargetRef llvm_targetref
 
static LLVMOrcJITStackRef llvm_opt0_orc
 
static LLVMOrcJITStackRef llvm_opt3_orc
 
 PG_MODULE_MAGIC
 

Typedef Documentation

◆ LLVMJitHandle

typedef struct LLVMJitHandle LLVMJitHandle

Function Documentation

◆ _PG_jit_provider_init()

void _PG_jit_provider_init ( JitProviderCallbacks cb)

Definition at line 131 of file llvmjit.c.

References JitProviderCallbacks::compile_expr, llvm_compile_expr(), llvm_release_context(), llvm_reset_after_error(), JitProviderCallbacks::release_context, and JitProviderCallbacks::reset_after_error.

132 {
136 }
JitProviderResetAfterErrorCB reset_after_error
Definition: jit.h:75
JitProviderCompileExprCB compile_expr
Definition: jit.h:77
void llvm_reset_after_error(void)
static void llvm_release_context(JitContext *context)
Definition: llvmjit.c:171
bool llvm_compile_expr(ExprState *state)
Definition: llvmjit_expr.c:78
JitProviderReleaseContextCB release_context
Definition: jit.h:76

◆ llvm_compile_module()

static void llvm_compile_module ( LLVMJitContext *  context)
static

Definition at line 630 of file llvmjit.c.

References DEBUG1, elog, ereport, errhidecontext(), errhidestmt(), errmsg_internal(), ERROR, error(), filename, INSTR_TIME_ACCUM_DIFF, INSTR_TIME_GET_DOUBLE, INSTR_TIME_SET_CURRENT, jit_dump_bitcode, lappend(), 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().

631 {
632  LLVMJitHandle *handle;
633  MemoryContext oldcontext;
634  instr_time starttime;
635  instr_time endtime;
636 #if LLVM_VERSION_MAJOR > 11
637  LLVMOrcLLJITRef compile_orc;
638 #else
639  LLVMOrcJITStackRef compile_orc;
640 #endif
641 
642  if (context->base.flags & PGJIT_OPT3)
643  compile_orc = llvm_opt3_orc;
644  else
645  compile_orc = llvm_opt0_orc;
646 
647  /* perform inlining */
648  if (context->base.flags & PGJIT_INLINE)
649  {
650  INSTR_TIME_SET_CURRENT(starttime);
651  llvm_inline(context->module);
652  INSTR_TIME_SET_CURRENT(endtime);
653  INSTR_TIME_ACCUM_DIFF(context->base.instr.inlining_counter,
654  endtime, starttime);
655  }
656 
657  if (jit_dump_bitcode)
658  {
659  char *filename;
660 
661  filename = psprintf("%u.%zu.bc",
662  MyProcPid,
663  context->module_generation);
664  LLVMWriteBitcodeToFile(context->module, filename);
665  pfree(filename);
666  }
667 
668 
669  /* optimize according to the chosen optimization settings */
670  INSTR_TIME_SET_CURRENT(starttime);
671  llvm_optimize_module(context, context->module);
672  INSTR_TIME_SET_CURRENT(endtime);
673  INSTR_TIME_ACCUM_DIFF(context->base.instr.optimization_counter,
674  endtime, starttime);
675 
676  if (jit_dump_bitcode)
677  {
678  char *filename;
679 
680  filename = psprintf("%u.%zu.optimized.bc",
681  MyProcPid,
682  context->module_generation);
683  LLVMWriteBitcodeToFile(context->module, filename);
684  pfree(filename);
685  }
686 
687  handle = (LLVMJitHandle *)
689 
690  /*
691  * Emit the code. Note that this can, depending on the optimization
692  * settings, take noticeable resources as code emission executes low-level
693  * instruction combining/selection passes etc. Without optimization a
694  * faster instruction selection mechanism is used.
695  */
696  INSTR_TIME_SET_CURRENT(starttime);
697 #if LLVM_VERSION_MAJOR > 11
698  {
699  LLVMOrcThreadSafeModuleRef ts_module;
700  LLVMErrorRef error;
701  LLVMOrcJITDylibRef jd = LLVMOrcLLJITGetMainJITDylib(compile_orc);
702 
703  ts_module = LLVMOrcCreateNewThreadSafeModule(context->module, llvm_ts_context);
704 
705  handle->lljit = compile_orc;
706  handle->resource_tracker = LLVMOrcJITDylibCreateResourceTracker(jd);
707 
708  /*
709  * NB: This doesn't actually emit code. That happens lazily the first
710  * time a symbol defined in the module is requested. Due to that
711  * llvm_get_function() also accounts for emission time.
712  */
713 
714  context->module = NULL; /* will be owned by LLJIT */
715  error = LLVMOrcLLJITAddLLVMIRModuleWithRT(compile_orc,
716  handle->resource_tracker,
717  ts_module);
718 
719  if (error)
720  elog(ERROR, "failed to JIT module: %s",
721  llvm_error_message(error));
722 
723  handle->lljit = compile_orc;
724 
725  /* LLVMOrcLLJITAddLLVMIRModuleWithRT takes ownership of the module */
726  }
727 #elif LLVM_VERSION_MAJOR > 6
728  {
729  handle->stack = compile_orc;
730  if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &handle->orc_handle, context->module,
731  llvm_resolve_symbol, NULL))
732  elog(ERROR, "failed to JIT module");
733 
734  /* LLVMOrcAddEagerlyCompiledIR takes ownership of the module */
735  }
736 #elif LLVM_VERSION_MAJOR > 4
737  {
738  LLVMSharedModuleRef smod;
739 
740  smod = LLVMOrcMakeSharedModule(context->module);
741  handle->stack = compile_orc;
742  if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &handle->orc_handle, smod,
743  llvm_resolve_symbol, NULL))
744  elog(ERROR, "failed to JIT module");
745 
746  LLVMOrcDisposeSharedModuleRef(smod);
747  }
748 #else /* LLVM 4.0 and 3.9 */
749  {
750  handle->stack = compile_orc;
751  handle->orc_handle = LLVMOrcAddEagerlyCompiledIR(compile_orc, context->module,
752  llvm_resolve_symbol, NULL);
753 
754  LLVMDisposeModule(context->module);
755  }
756 #endif
757 
758  INSTR_TIME_SET_CURRENT(endtime);
759  INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
760  endtime, starttime);
761 
762  context->module = NULL;
763  context->compiled = true;
764 
765  /* remember emitted code for cleanup and lookups */
767  context->handles = lappend(context->handles, handle);
768  MemoryContextSwitchTo(oldcontext);
769 
770  ereport(DEBUG1,
771  (errmsg_internal("time to inline: %.3fs, opt: %.3fs, emit: %.3fs",
772  INSTR_TIME_GET_DOUBLE(context->base.instr.inlining_counter),
773  INSTR_TIME_GET_DOUBLE(context->base.instr.optimization_counter),
774  INSTR_TIME_GET_DOUBLE(context->base.instr.emission_counter)),
775  errhidestmt(true),
776  errhidecontext(true)));
777 }
#define DEBUG1
Definition: elog.h:25
int MyProcPid
Definition: globals.c:43
static void error(void)
Definition: sql-dyntest.c:147
LLVMOrcJITStackRef stack
Definition: llvmjit.c:52
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
struct timeval instr_time
Definition: instr_time.h:150
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
int errhidestmt(bool hide_stmt)
Definition: elog.c:1250
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
Definition: instr_time.h:182
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:199
#define PGJIT_OPT3
Definition: jit.h:21
void pfree(void *pointer)
Definition: mcxt.c:1169
#define ERROR
Definition: elog.h:46
static uint64_t llvm_resolve_symbol(const char *name, void *ctx)
Definition: llvmjit.c:1069
LLVMOrcModuleHandle orc_handle
Definition: llvmjit.c:53
MemoryContext TopMemoryContext
Definition: mcxt.c:48
static LLVMOrcJITStackRef llvm_opt3_orc
Definition: llvmjit.c:106
List * lappend(List *list, void *datum)
Definition: list.c:336
#define PGJIT_INLINE
Definition: jit.h:22
#define ereport(elevel,...)
Definition: elog.h:157
int errmsg_internal(const char *fmt,...)
Definition: elog.c:996
bool jit_dump_bitcode
Definition: jit.c:35
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
static char * filename
Definition: pg_dumpall.c:92
void llvm_inline(LLVMModuleRef M)
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:863
#define elog(elevel,...)
Definition: elog.h:232
static LLVMOrcJITStackRef llvm_opt0_orc
Definition: llvmjit.c:105
static void llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
Definition: llvmjit.c:559
int errhidecontext(bool hide_ctx)
Definition: elog.c:1269

◆ llvm_copy_attributes()

void llvm_copy_attributes ( LLVMValueRef  v_from,
LLVMValueRef  v_to 
)

Definition at line 475 of file llvmjit.c.

References llvm_copy_attributes_at_index().

Referenced by llvm_compile_expr(), llvm_pg_func(), and slot_compile_deform().

476 {
477  uint32 param_count;
478 
479  /* copy function attributes */
480  llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeFunctionIndex);
481 
482  /* and the return value attributes */
483  llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeReturnIndex);
484 
485  /* and each function parameter's attribute */
486  param_count = LLVMCountParams(v_from);
487 
488  for (int paramidx = 1; paramidx <= param_count; paramidx++)
489  llvm_copy_attributes_at_index(v_from, v_to, paramidx);
490 }
unsigned int uint32
Definition: c.h:441
static void llvm_copy_attributes_at_index(LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
Definition: llvmjit.c:447

◆ llvm_copy_attributes_at_index()

static void llvm_copy_attributes_at_index ( LLVMValueRef  v_from,
LLVMValueRef  v_to,
uint32  index 
)
static

Definition at line 447 of file llvmjit.c.

References LLVMGetAttributeCountAtIndexPG(), palloc(), and pfree().

Referenced by llvm_copy_attributes().

448 {
449  int num_attributes;
450  LLVMAttributeRef *attrs;
451 
452  num_attributes = LLVMGetAttributeCountAtIndexPG(v_from, index);
453 
454  /*
455  * Not just for efficiency: LLVM <= 3.9 crashes when
456  * LLVMGetAttributesAtIndex() is called for an index with 0 attributes.
457  */
458  if (num_attributes == 0)
459  return;
460 
461  attrs = palloc(sizeof(LLVMAttributeRef) * num_attributes);
462  LLVMGetAttributesAtIndex(v_from, index, attrs);
463 
464  for (int attno = 0; attno < num_attributes; attno++)
465  LLVMAddAttributeAtIndex(v_to, index, attrs[attno]);
466 
467  pfree(attrs);
468 }
Definition: type.h:89
void pfree(void *pointer)
Definition: mcxt.c:1169
unsigned LLVMGetAttributeCountAtIndexPG(LLVMValueRef F, uint32 Idx)
void * palloc(Size size)
Definition: mcxt.c:1062

◆ llvm_create_context()

LLVMJitContext* llvm_create_context ( int  jitFlags)

Definition at line 146 of file llvmjit.c.

References CurrentResourceOwner, llvm_assert_in_fatal_section(), llvm_session_initialize(), MemoryContextAllocZero(), PointerGetDatum, ResourceOwnerEnlargeJIT(), ResourceOwnerRememberJIT(), and TopMemoryContext.

Referenced by llvm_compile_expr().

147 {
148  LLVMJitContext *context;
149 
151 
153 
155 
157  sizeof(LLVMJitContext));
158  context->base.flags = jitFlags;
159 
160  /* ensure cleanup */
161  context->base.resowner = CurrentResourceOwner;
163 
164  return context;
165 }
#define PointerGetDatum(X)
Definition: postgres.h:600
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void llvm_assert_in_fatal_section(void)
MemoryContext TopMemoryContext
Definition: mcxt.c:48
void ResourceOwnerRememberJIT(ResourceOwner owner, Datum handle)
Definition: resowner.c:1387
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:906
static void llvm_session_initialize(void)
Definition: llvmjit.c:783
void ResourceOwnerEnlargeJIT(ResourceOwner owner)
Definition: resowner.c:1376

◆ llvm_create_types()

static void llvm_create_types ( void  )
static

Definition at line 979 of file llvmjit.c.

References AttributeTemplate, buf, elog, ERROR, llvm_layout, llvm_pg_var_type(), llvm_triple, llvm_types_module, load_return_type(), MAXPGPATH, pkglib_path, pstrdup(), snprintf, StructAggState, StructAggStatePerGroupData, StructAggStatePerTransData, StructExprContext, StructExprEvalStep, StructExprState, StructFunctionCallInfoData, StructHeapTupleData, StructHeapTupleTableSlot, StructMemoryContextData, StructMinimalTupleTableSlot, StructNullableDatum, StructTupleDescData, StructTupleTableSlot, TypeParamBool, TypePGFunction, TypeSizeT, and TypeStorageBool.

Referenced by llvm_session_initialize().

980 {
981  char path[MAXPGPATH];
982  LLVMMemoryBufferRef buf;
983  char *msg;
984 
985  snprintf(path, MAXPGPATH, "%s/%s", pkglib_path, "llvmjit_types.bc");
986 
987  /* open file */
988  if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buf, &msg))
989  {
990  elog(ERROR, "LLVMCreateMemoryBufferWithContentsOfFile(%s) failed: %s",
991  path, msg);
992  }
993 
994  /* eagerly load contents, going to need it all */
995  if (LLVMParseBitcode2(buf, &llvm_types_module))
996  {
997  elog(ERROR, "LLVMParseBitcode2 of %s failed", path);
998  }
999  LLVMDisposeMemoryBuffer(buf);
1000 
1001  /*
1002  * Load triple & layout from clang emitted file so we're guaranteed to be
1003  * compatible.
1004  */
1005  llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
1006  llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
1007 
1008  TypeSizeT = llvm_pg_var_type("TypeSizeT");
1009  TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
1010  TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
1011  TypePGFunction = llvm_pg_var_type("TypePGFunction");
1012  StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
1013  StructExprContext = llvm_pg_var_type("StructExprContext");
1014  StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
1015  StructExprState = llvm_pg_var_type("StructExprState");
1016  StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
1017  StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
1018  StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
1019  StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
1020  StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
1021  StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
1022  StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
1023  StructAggState = llvm_pg_var_type("StructAggState");
1024  StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
1025  StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
1026 
1027  AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
1028 }
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:81
LLVMTypeRef StructExprEvalStep
Definition: llvmjit.c:83
LLVMTypeRef TypeSizeT
Definition: llvmjit.c:59
LLVMTypeRef StructExprState
Definition: llvmjit.c:84
char * pstrdup(const char *in)
Definition: mcxt.c:1299
LLVMTypeRef StructNullableDatum
Definition: llvmjit.c:63
static const char * llvm_layout
Definition: llvmjit.c:96
LLVMTypeRef StructHeapTupleTableSlot
Definition: llvmjit.c:76
LLVMTypeRef StructAggState
Definition: llvmjit.c:85
static LLVMTypeRef load_return_type(LLVMModuleRef mod, const char *name)
Definition: llvmjit.c:949
static const char * llvm_triple
Definition: llvmjit.c:95
LLVMTypeRef llvm_pg_var_type(const char *varname)
Definition: llvmjit.c:375
LLVMTypeRef StructHeapTupleData
Definition: llvmjit.c:68
#define ERROR
Definition: elog.h:46
#define MAXPGPATH
static char * buf
Definition: pg_test_fsync.c:68
LLVMTypeRef TypeStorageBool
Definition: llvmjit.c:61
LLVMTypeRef StructMemoryContextData
Definition: llvmjit.c:78
LLVMTypeRef StructExprContext
Definition: llvmjit.c:82
LLVMTypeRef TypePGFunction
Definition: llvmjit.c:62
LLVMTypeRef StructAggStatePerTransData
Definition: llvmjit.c:87
LLVMTypeRef StructMinimalTupleTableSlot
Definition: llvmjit.c:77
LLVMTypeRef StructTupleTableSlot
Definition: llvmjit.c:75
LLVMTypeRef StructTupleDescData
Definition: llvmjit.c:74
LLVMTypeRef TypeParamBool
Definition: llvmjit.c:60
LLVMModuleRef llvm_types_module
Definition: llvmjit.c:91
#define elog(elevel,...)
Definition: elog.h:232
LLVMValueRef AttributeTemplate
Definition: llvmjit.c:89
#define snprintf
Definition: port.h:217
char pkglib_path[MAXPGPATH]
Definition: globals.c:76
LLVMTypeRef StructAggStatePerGroupData
Definition: llvmjit.c:86

◆ llvm_expand_funcname()

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

Definition at line 255 of file llvmjit.c.

References Assert, and psprintf().

Referenced by llvm_compile_expr(), and slot_compile_deform().

256 {
257  Assert(context->module != NULL);
258 
259  context->base.instr.created_functions++;
260 
261  /*
262  * Previously we used dots to separate, but turns out some tools, e.g.
263  * GDB, don't like that and truncate name.
264  */
265  return psprintf("%s_%zu_%d",
266  basename,
267  context->module_generation,
268  context->counter++);
269 }
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
#define Assert(condition)
Definition: c.h:804

◆ llvm_function_reference()

LLVMValueRef llvm_function_reference ( LLVMJitContext *  context,
LLVMBuilderRef  builder,
LLVMModuleRef  mod,
FunctionCallInfo  fcinfo 
)

Definition at line 496 of file llvmjit.c.

References FunctionCallInfoBaseData::flinfo, fmgr_symbol(), FmgrInfo::fn_addr, FmgrInfo::fn_oid, psprintf(), and TypePGFunction.

Referenced by BuildV1Call(), and llvm_compile_expr().

500 {
501  char *modname;
502  char *basename;
503  char *funcname;
504 
505  LLVMValueRef v_fn;
506 
507  fmgr_symbol(fcinfo->flinfo->fn_oid, &modname, &basename);
508 
509  if (modname != NULL && basename != NULL)
510  {
511  /* external function in loadable library */
512  funcname = psprintf("pgextern.%s.%s", modname, basename);
513  }
514  else if (basename != NULL)
515  {
516  /* internal function */
517  funcname = psprintf("%s", basename);
518  }
519  else
520  {
521  /*
522  * Function we don't know to handle, return pointer. We do so by
523  * creating a global constant containing a pointer to the function.
524  * Makes IR more readable.
525  */
526  LLVMValueRef v_fn_addr;
527 
528  funcname = psprintf("pgoidextern.%u",
529  fcinfo->flinfo->fn_oid);
530  v_fn = LLVMGetNamedGlobal(mod, funcname);
531  if (v_fn != 0)
532  return LLVMBuildLoad(builder, v_fn, "");
533 
534  v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction);
535 
536  v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname);
537  LLVMSetInitializer(v_fn, v_fn_addr);
538  LLVMSetGlobalConstant(v_fn, true);
539  LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
540  LLVMSetUnnamedAddr(v_fn, true);
541 
542  return LLVMBuildLoad(builder, v_fn, "");
543  }
544 
545  /* check if function already has been added */
546  v_fn = LLVMGetNamedFunction(mod, funcname);
547  if (v_fn != 0)
548  return v_fn;
549 
550  v_fn = LLVMAddFunction(mod, funcname, LLVMGetElementType(TypePGFunction));
551 
552  return v_fn;
553 }
PGFunction fn_addr
Definition: fmgr.h:58
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
void fmgr_symbol(Oid functionId, char **mod, char **fn)
Definition: fmgr.c:283
LLVMTypeRef TypePGFunction
Definition: llvmjit.c:62
FmgrInfo * flinfo
Definition: fmgr.h:87
Oid fn_oid
Definition: fmgr.h:59

◆ llvm_get_function()

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

Definition at line 276 of file llvmjit.c.

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

Referenced by ExecRunCompiledExpr().

277 {
278 #if LLVM_VERSION_MAJOR > 11 || \
279  defined(HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN) && HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN
280  ListCell *lc;
281 #endif
282 
284 
285  /*
286  * If there is a pending / not emitted module, compile and emit now.
287  * Otherwise we might not find the [correct] function.
288  */
289  if (!context->compiled)
290  {
291  llvm_compile_module(context);
292  }
293 
294  /*
295  * ORC's symbol table is of *unmangled* symbols. Therefore we don't need
296  * to mangle here.
297  */
298 
299 #if LLVM_VERSION_MAJOR > 11
300  foreach(lc, context->handles)
301  {
302  LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc);
303  instr_time starttime;
304  instr_time endtime;
305  LLVMErrorRef error;
306  LLVMOrcJITTargetAddress addr;
307 
308  INSTR_TIME_SET_CURRENT(starttime);
309 
310  addr = 0;
311  error = LLVMOrcLLJITLookup(handle->lljit, &addr, funcname);
312  if (error)
313  elog(ERROR, "failed to look up symbol \"%s\": %s",
314  funcname, llvm_error_message(error));
315 
316  /*
317  * LLJIT only actually emits code the first time a symbol is
318  * referenced. Thus add lookup time to emission time. That's counting
319  * a bit more than with older LLVM versions, but unlikely to ever
320  * matter.
321  */
322  INSTR_TIME_SET_CURRENT(endtime);
323  INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
324  endtime, starttime);
325 
326  if (addr)
327  return (void *) (uintptr_t) addr;
328  }
329 #elif defined(HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN) && HAVE_DECL_LLVMORCGETSYMBOLADDRESSIN
330  foreach(lc, context->handles)
331  {
332  LLVMOrcTargetAddress addr;
333  LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc);
334 
335  addr = 0;
336  if (LLVMOrcGetSymbolAddressIn(handle->stack, &addr, handle->orc_handle, funcname))
337  elog(ERROR, "failed to look up symbol \"%s\"", funcname);
338  if (addr)
339  return (void *) (uintptr_t) addr;
340  }
341 #elif LLVM_VERSION_MAJOR < 5
342  {
343  LLVMOrcTargetAddress addr;
344 
345  if ((addr = LLVMOrcGetSymbolAddress(llvm_opt0_orc, funcname)))
346  return (void *) (uintptr_t) addr;
347  if ((addr = LLVMOrcGetSymbolAddress(llvm_opt3_orc, funcname)))
348  return (void *) (uintptr_t) addr;
349  }
350 #else
351  {
352  LLVMOrcTargetAddress addr;
353 
354  if (LLVMOrcGetSymbolAddress(llvm_opt0_orc, &addr, funcname))
355  elog(ERROR, "failed to look up symbol \"%s\"", funcname);
356  if (addr)
357  return (void *) (uintptr_t) addr;
358  if (LLVMOrcGetSymbolAddress(llvm_opt3_orc, &addr, funcname))
359  elog(ERROR, "failed to look up symbol \"%s\"", funcname);
360  if (addr)
361  return (void *) (uintptr_t) addr;
362  }
363 #endif
364 
365  elog(ERROR, "failed to JIT: %s", funcname);
366 
367  return NULL;
368 }
static void llvm_compile_module(LLVMJitContext *context)
Definition: llvmjit.c:630
static void error(void)
Definition: sql-dyntest.c:147
LLVMOrcJITStackRef stack
Definition: llvmjit.c:52
struct timeval instr_time
Definition: instr_time.h:150
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
Definition: instr_time.h:182
#define ERROR
Definition: elog.h:46
LLVMOrcModuleHandle orc_handle
Definition: llvmjit.c:53
void llvm_assert_in_fatal_section(void)
static LLVMOrcJITStackRef llvm_opt3_orc
Definition: llvmjit.c:106
#define lfirst(lc)
Definition: pg_list.h:169
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:156
#define elog(elevel,...)
Definition: elog.h:232
static LLVMOrcJITStackRef llvm_opt0_orc
Definition: llvmjit.c:105

◆ llvm_mutable_module()

LLVMModuleRef llvm_mutable_module ( LLVMJitContext *  context)

Definition at line 230 of file llvmjit.c.

References llvm_assert_in_fatal_section(), llvm_generation, llvm_layout, and llvm_triple.

Referenced by llvm_compile_expr(), and slot_compile_deform().

231 {
233 
234  /*
235  * If there's no in-progress module, create a new one.
236  */
237  if (!context->module)
238  {
239  context->compiled = false;
240  context->module_generation = llvm_generation++;
241  context->module = LLVMModuleCreateWithName("pg");
242  LLVMSetTarget(context->module, llvm_triple);
243  LLVMSetDataLayout(context->module, llvm_layout);
244  }
245 
246  return context->module;
247 }
static const char * llvm_layout
Definition: llvmjit.c:96
static const char * llvm_triple
Definition: llvmjit.c:95
void llvm_assert_in_fatal_section(void)
static size_t llvm_generation
Definition: llvmjit.c:94

◆ llvm_optimize_module()

static void llvm_optimize_module ( LLVMJitContext *  context,
LLVMModuleRef  module 
)
static

Definition at line 559 of file llvmjit.c.

References PGJIT_INLINE, and PGJIT_OPT3.

Referenced by llvm_compile_module().

560 {
561  LLVMPassManagerBuilderRef llvm_pmb;
562  LLVMPassManagerRef llvm_mpm;
563  LLVMPassManagerRef llvm_fpm;
564  LLVMValueRef func;
565  int compile_optlevel;
566 
567  if (context->base.flags & PGJIT_OPT3)
568  compile_optlevel = 3;
569  else
570  compile_optlevel = 0;
571 
572  /*
573  * Have to create a new pass manager builder every pass through, as the
574  * inliner has some per-builder state. Otherwise one ends up only inlining
575  * a function the first time though.
576  */
577  llvm_pmb = LLVMPassManagerBuilderCreate();
578  LLVMPassManagerBuilderSetOptLevel(llvm_pmb, compile_optlevel);
579  llvm_fpm = LLVMCreateFunctionPassManagerForModule(module);
580 
581  if (context->base.flags & PGJIT_OPT3)
582  {
583  /* TODO: Unscientifically determined threshold */
584  LLVMPassManagerBuilderUseInlinerWithThreshold(llvm_pmb, 512);
585  }
586  else
587  {
588  /* we rely on mem2reg heavily, so emit even in the O0 case */
589  LLVMAddPromoteMemoryToRegisterPass(llvm_fpm);
590  }
591 
592  LLVMPassManagerBuilderPopulateFunctionPassManager(llvm_pmb, llvm_fpm);
593 
594  /*
595  * Do function level optimization. This could be moved to the point where
596  * functions are emitted, to reduce memory usage a bit.
597  */
598  LLVMInitializeFunctionPassManager(llvm_fpm);
599  for (func = LLVMGetFirstFunction(context->module);
600  func != NULL;
601  func = LLVMGetNextFunction(func))
602  LLVMRunFunctionPassManager(llvm_fpm, func);
603  LLVMFinalizeFunctionPassManager(llvm_fpm);
604  LLVMDisposePassManager(llvm_fpm);
605 
606  /*
607  * Perform module level optimization. We do so even in the non-optimized
608  * case, so always-inline functions etc get inlined. It's cheap enough.
609  */
610  llvm_mpm = LLVMCreatePassManager();
611  LLVMPassManagerBuilderPopulateModulePassManager(llvm_pmb,
612  llvm_mpm);
613  /* always use always-inliner pass */
614  if (!(context->base.flags & PGJIT_OPT3))
615  LLVMAddAlwaysInlinerPass(llvm_mpm);
616  /* if doing inlining, but no expensive optimization, add inlining pass */
617  if (context->base.flags & PGJIT_INLINE
618  && !(context->base.flags & PGJIT_OPT3))
619  LLVMAddFunctionInliningPass(llvm_mpm);
620  LLVMRunPassManager(llvm_mpm, context->module);
621  LLVMDisposePassManager(llvm_mpm);
622 
623  LLVMPassManagerBuilderDispose(llvm_pmb);
624 }
#define PGJIT_OPT3
Definition: jit.h:21
#define PGJIT_INLINE
Definition: jit.h:22

◆ llvm_pg_func()

LLVMValueRef llvm_pg_func ( LLVMModuleRef  mod,
const char *  funcname 
)

Definition at line 419 of file llvmjit.c.

References elog, ERROR, llvm_copy_attributes(), and llvm_types_module.

Referenced by build_EvalXFuncInt(), llvm_compile_expr(), and slot_compile_deform().

420 {
421  LLVMValueRef v_srcfn;
422  LLVMValueRef v_fn;
423 
424  /* don't repeatedly add function */
425  v_fn = LLVMGetNamedFunction(mod, funcname);
426  if (v_fn)
427  return v_fn;
428 
429  v_srcfn = LLVMGetNamedFunction(llvm_types_module, funcname);
430 
431  if (!v_srcfn)
432  elog(ERROR, "function %s not in llvmjit_types.c", funcname);
433 
434  v_fn = LLVMAddFunction(mod,
435  funcname,
436  LLVMGetElementType(LLVMTypeOf(v_srcfn)));
437  llvm_copy_attributes(v_srcfn, v_fn);
438 
439  return v_fn;
440 }
#define ERROR
Definition: elog.h:46
LLVMModuleRef llvm_types_module
Definition: llvmjit.c:91
#define elog(elevel,...)
Definition: elog.h:232
void llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
Definition: llvmjit.c:475

◆ llvm_pg_var_func_type()

LLVMTypeRef llvm_pg_var_func_type ( const char *  varname)

Definition at line 399 of file llvmjit.c.

References Assert, and llvm_pg_var_type().

Referenced by llvm_compile_expr().

400 {
401  LLVMTypeRef typ = llvm_pg_var_type(varname);
402 
403  /* look at the contained type */
404  Assert(LLVMGetTypeKind(typ) == LLVMPointerTypeKind);
405  typ = LLVMGetElementType(typ);
406  Assert(typ != NULL && LLVMGetTypeKind(typ) == LLVMFunctionTypeKind);
407 
408  return typ;
409 }
LLVMTypeRef llvm_pg_var_type(const char *varname)
Definition: llvmjit.c:375
#define Assert(condition)
Definition: c.h:804

◆ llvm_pg_var_type()

LLVMTypeRef llvm_pg_var_type ( const char *  varname)

Definition at line 375 of file llvmjit.c.

References Assert, elog, ERROR, and llvm_types_module.

Referenced by llvm_create_types(), and llvm_pg_var_func_type().

376 {
377  LLVMValueRef v_srcvar;
378  LLVMTypeRef typ;
379 
380  /* this'll return a *pointer* to the global */
381  v_srcvar = LLVMGetNamedGlobal(llvm_types_module, varname);
382  if (!v_srcvar)
383  elog(ERROR, "variable %s not in llvmjit_types.c", varname);
384 
385  /* look at the contained type */
386  typ = LLVMTypeOf(v_srcvar);
387  Assert(typ != NULL && LLVMGetTypeKind(typ) == LLVMPointerTypeKind);
388  typ = LLVMGetElementType(typ);
389  Assert(typ != NULL);
390 
391  return typ;
392 }
#define ERROR
Definition: elog.h:46
#define Assert(condition)
Definition: c.h:804
LLVMModuleRef llvm_types_module
Definition: llvmjit.c:91
#define elog(elevel,...)
Definition: elog.h:232

◆ llvm_release_context()

static void llvm_release_context ( JitContext context)
static

Definition at line 171 of file llvmjit.c.

References linitial, list_delete_first(), llvm_enter_fatal_on_oom(), NIL, LLVMJitHandle::orc_handle, pfree(), proc_exit_inprogress, and LLVMJitHandle::stack.

Referenced by _PG_jit_provider_init().

172 {
173  LLVMJitContext *llvm_context = (LLVMJitContext *) context;
174 
175  /*
176  * When this backend is exiting, don't clean up LLVM. As an error might
177  * have occurred from within LLVM, we do not want to risk reentering. All
178  * resource cleanup is going to happen through process exit.
179  */
181  return;
182 
184 
185  if (llvm_context->module)
186  {
187  LLVMDisposeModule(llvm_context->module);
188  llvm_context->module = NULL;
189  }
190 
191  while (llvm_context->handles != NIL)
192  {
193  LLVMJitHandle *jit_handle;
194 
195  jit_handle = (LLVMJitHandle *) linitial(llvm_context->handles);
196  llvm_context->handles = list_delete_first(llvm_context->handles);
197 
198 #if LLVM_VERSION_MAJOR > 11
199  {
200  LLVMOrcExecutionSessionRef ee;
201  LLVMOrcSymbolStringPoolRef sp;
202 
203  LLVMOrcResourceTrackerRemove(jit_handle->resource_tracker);
204  LLVMOrcReleaseResourceTracker(jit_handle->resource_tracker);
205 
206  /*
207  * Without triggering cleanup of the string pool, we'd leak
208  * memory. It'd be sufficient to do this far less often, but in
209  * experiments the required time was small enough to just always
210  * do it.
211  */
212  ee = LLVMOrcLLJITGetExecutionSession(jit_handle->lljit);
213  sp = LLVMOrcExecutionSessionGetSymbolStringPool(ee);
214  LLVMOrcSymbolStringPoolClearDeadEntries(sp);
215  }
216 #else /* LLVM_VERSION_MAJOR > 11 */
217  {
218  LLVMOrcRemoveModule(jit_handle->stack, jit_handle->orc_handle);
219  }
220 #endif /* LLVM_VERSION_MAJOR > 11 */
221 
222  pfree(jit_handle);
223  }
224 }
#define NIL
Definition: pg_list.h:65
LLVMOrcJITStackRef stack
Definition: llvmjit.c:52
void pfree(void *pointer)
Definition: mcxt.c:1169
#define linitial(l)
Definition: pg_list.h:174
LLVMOrcModuleHandle orc_handle
Definition: llvmjit.c:53
bool proc_exit_inprogress
Definition: ipc.c:40
void llvm_enter_fatal_on_oom(void)
List * list_delete_first(List *list)
Definition: list.c:875

◆ llvm_resolve_symbol()

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

Definition at line 1069 of file llvmjit.c.

References Assert, elog, ERROR, error(), i, jit_debugging_support, jit_profiling_support, llvm_split_symbol_name(), load_external_function(), name, palloc0(), pfree(), pstrdup(), tm, and WARNING.

Referenced by llvm_compile_module().

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

◆ llvm_session_initialize()

static void llvm_session_initialize ( void  )
static

Definition at line 783 of file llvmjit.c.

References DEBUG2, elog, error(), FATAL, jit_debugging_support, jit_profiling_support, llvm_create_types(), llvm_opt0_orc, llvm_opt3_orc, llvm_session_initialized, llvm_shutdown(), llvm_targetref, llvm_triple, MemoryContextSwitchTo(), on_proc_exit(), and TopMemoryContext.

Referenced by llvm_create_context().

784 {
785  MemoryContext oldcontext;
786  char *error = NULL;
787  char *cpu = NULL;
788  char *features = NULL;
789  LLVMTargetMachineRef opt0_tm;
790  LLVMTargetMachineRef opt3_tm;
791 
793  return;
794 
796 
797  LLVMInitializeNativeTarget();
798  LLVMInitializeNativeAsmPrinter();
799  LLVMInitializeNativeAsmParser();
800 
801  /*
802  * Synchronize types early, as that also includes inferring the target
803  * triple.
804  */
806 
807  if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &error) != 0)
808  {
809  elog(FATAL, "failed to query triple %s\n", error);
810  }
811 
812  /*
813  * We want the generated code to use all available features. Therefore
814  * grab the host CPU string and detect features of the current CPU. The
815  * latter is needed because some CPU architectures default to enabling
816  * features not all CPUs have (weird, huh).
817  */
818  cpu = LLVMGetHostCPUName();
819  features = LLVMGetHostCPUFeatures();
820  elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"",
821  cpu, features);
822 
823  opt0_tm =
824  LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
825  LLVMCodeGenLevelNone,
826  LLVMRelocDefault,
827  LLVMCodeModelJITDefault);
828  opt3_tm =
829  LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
830  LLVMCodeGenLevelAggressive,
831  LLVMRelocDefault,
832  LLVMCodeModelJITDefault);
833 
834  LLVMDisposeMessage(cpu);
835  cpu = NULL;
836  LLVMDisposeMessage(features);
837  features = NULL;
838 
839  /* force symbols in main binary to be loaded */
840  LLVMLoadLibraryPermanently(NULL);
841 
842 #if LLVM_VERSION_MAJOR > 11
843  {
844  llvm_ts_context = LLVMOrcCreateNewThreadSafeContext();
845 
846  llvm_opt0_orc = llvm_create_jit_instance(opt0_tm);
847  opt0_tm = 0;
848 
849  llvm_opt3_orc = llvm_create_jit_instance(opt3_tm);
850  opt3_tm = 0;
851  }
852 #else /* LLVM_VERSION_MAJOR > 11 */
853  {
854  llvm_opt0_orc = LLVMOrcCreateInstance(opt0_tm);
855  llvm_opt3_orc = LLVMOrcCreateInstance(opt3_tm);
856 
857 #if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
859  {
860  LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
861 
862  LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l);
863  LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l);
864  }
865 #endif
866 #if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
868  {
869  LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
870 
871  LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l);
872  LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l);
873  }
874 #endif
875  }
876 #endif /* LLVM_VERSION_MAJOR > 11 */
877 
879 
881 
882  MemoryContextSwitchTo(oldcontext);
883 }
static void error(void)
Definition: sql-dyntest.c:147
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:305
bool jit_debugging_support
Definition: jit.c:34
static void llvm_shutdown(int code, Datum arg)
Definition: llvmjit.c:886
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static const char * llvm_triple
Definition: llvmjit.c:95
#define FATAL
Definition: elog.h:49
#define DEBUG2
Definition: elog.h:24
MemoryContext TopMemoryContext
Definition: mcxt.c:48
static LLVMOrcJITStackRef llvm_opt3_orc
Definition: llvmjit.c:106
static bool llvm_session_initialized
Definition: llvmjit.c:93
static LLVMTargetRef llvm_targetref
Definition: llvmjit.c:99
bool jit_profiling_support
Definition: jit.c:37
static void llvm_create_types(void)
Definition: llvmjit.c:979
#define elog(elevel,...)
Definition: elog.h:232
static LLVMOrcJITStackRef llvm_opt0_orc
Definition: llvmjit.c:105

◆ llvm_shutdown()

static void llvm_shutdown ( int  code,
Datum  arg 
)
static

Definition at line 886 of file llvmjit.c.

References Assert, jit_profiling_support, llvm_in_fatal_on_oom(), llvm_opt0_orc, llvm_opt3_orc, and proc_exit_inprogress.

Referenced by llvm_session_initialize().

887 {
888  /*
889  * If llvm_shutdown() is reached while in a fatal-on-oom section an error
890  * has occurred in the middle of LLVM code. It is not safe to call back
891  * into LLVM (which is why a FATAL error was thrown).
892  *
893  * We do need to shutdown LLVM in other shutdown cases, otherwise
894  * e.g. profiling data won't be written out.
895  */
896  if (llvm_in_fatal_on_oom())
897  {
899  return;
900  }
901 
902 #if LLVM_VERSION_MAJOR > 11
903  {
904  if (llvm_opt3_orc)
905  {
906  LLVMOrcDisposeLLJIT(llvm_opt3_orc);
907  llvm_opt3_orc = NULL;
908  }
909  if (llvm_opt0_orc)
910  {
911  LLVMOrcDisposeLLJIT(llvm_opt0_orc);
912  llvm_opt0_orc = NULL;
913  }
914  if (llvm_ts_context)
915  {
916  LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
917  llvm_ts_context = NULL;
918  }
919  }
920 #else /* LLVM_VERSION_MAJOR > 11 */
921  {
922  /* unregister profiling support, needs to be flushed to be useful */
923 
924  if (llvm_opt3_orc)
925  {
926 #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF
928  LLVMOrcUnregisterPerf(llvm_opt3_orc);
929 #endif
930  LLVMOrcDisposeInstance(llvm_opt3_orc);
931  llvm_opt3_orc = NULL;
932  }
933 
934  if (llvm_opt0_orc)
935  {
936 #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF
938  LLVMOrcUnregisterPerf(llvm_opt0_orc);
939 #endif
940  LLVMOrcDisposeInstance(llvm_opt0_orc);
941  llvm_opt0_orc = NULL;
942  }
943  }
944 #endif /* LLVM_VERSION_MAJOR > 11 */
945 }
bool llvm_in_fatal_on_oom(void)
static LLVMOrcJITStackRef llvm_opt3_orc
Definition: llvmjit.c:106
#define Assert(condition)
Definition: c.h:804
bool proc_exit_inprogress
Definition: ipc.c:40
bool jit_profiling_support
Definition: jit.c:37
static LLVMOrcJITStackRef llvm_opt0_orc
Definition: llvmjit.c:105

◆ llvm_split_symbol_name()

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

Definition at line 1035 of file llvmjit.c.

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

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

1036 {
1037  *modname = NULL;
1038  *funcname = NULL;
1039 
1040  /*
1041  * Module function names are pgextern.$module.$funcname
1042  */
1043  if (strncmp(name, "pgextern.", strlen("pgextern.")) == 0)
1044  {
1045  /*
1046  * Symbol names cannot contain a ., therefore we can split based on
1047  * first and last occurrence of one.
1048  */
1049  *funcname = rindex(name, '.');
1050  (*funcname)++; /* jump over . */
1051 
1052  *modname = pnstrdup(name + strlen("pgextern."),
1053  *funcname - name - strlen("pgextern.") - 1);
1054  Assert(funcname);
1055 
1056  *funcname = pstrdup(*funcname);
1057  }
1058  else
1059  {
1060  *modname = NULL;
1061  *funcname = pstrdup(name);
1062  }
1063 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1310
char * pstrdup(const char *in)
Definition: mcxt.c:1299
#define Assert(condition)
Definition: c.h:804
const char * name
Definition: encode.c:561

◆ load_return_type()

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

Definition at line 949 of file llvmjit.c.

References Assert, elog, ERROR, and value.

Referenced by llvm_create_types().

950 {
951  LLVMValueRef value;
952  LLVMTypeRef typ;
953 
954  /* this'll return a *pointer* to the function */
955  value = LLVMGetNamedFunction(mod, name);
956  if (!value)
957  elog(ERROR, "function %s is unknown", name);
958 
959  /* get type of function pointer */
960  typ = LLVMTypeOf(value);
961  Assert(typ != NULL);
962  /* dereference pointer */
963  typ = LLVMGetElementType(typ);
964  Assert(typ != NULL);
965  /* and look at return type */
966  typ = LLVMGetReturnType(typ);
967  Assert(typ != NULL);
968 
969  return typ;
970 }
#define ERROR
Definition: elog.h:46
static struct @143 value
#define Assert(condition)
Definition: c.h:804
const char * name
Definition: encode.c:561
#define elog(elevel,...)
Definition: elog.h:232

Variable Documentation

◆ AttributeTemplate

Datum AttributeTemplate

Definition at line 89 of file llvmjit.c.

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

◆ llvm_generation

size_t llvm_generation = 0
static

Definition at line 94 of file llvmjit.c.

Referenced by llvm_mutable_module().

◆ llvm_layout

const char* llvm_layout = NULL
static

Definition at line 96 of file llvmjit.c.

Referenced by llvm_create_types(), and llvm_mutable_module().

◆ llvm_opt0_orc

LLVMOrcJITStackRef llvm_opt0_orc
static

◆ llvm_opt3_orc

LLVMOrcJITStackRef llvm_opt3_orc
static

◆ llvm_session_initialized

bool llvm_session_initialized = false
static

Definition at line 93 of file llvmjit.c.

Referenced by llvm_session_initialize().

◆ llvm_targetref

LLVMTargetRef llvm_targetref
static

Definition at line 99 of file llvmjit.c.

Referenced by llvm_session_initialize().

◆ llvm_triple

const char* llvm_triple = NULL
static

Definition at line 95 of file llvmjit.c.

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

◆ llvm_types_module

LLVMModuleRef llvm_types_module = NULL

Definition at line 91 of file llvmjit.c.

Referenced by llvm_create_types(), llvm_pg_func(), and llvm_pg_var_type().

◆ PG_MODULE_MAGIC

PG_MODULE_MAGIC

Definition at line 124 of file llvmjit.c.

◆ StructAggState

LLVMTypeRef StructAggState

Definition at line 85 of file llvmjit.c.

Referenced by llvm_compile_expr(), and llvm_create_types().

◆ StructAggStatePerGroupData

LLVMTypeRef StructAggStatePerGroupData

Definition at line 86 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructAggStatePerTransData

LLVMTypeRef StructAggStatePerTransData

Definition at line 87 of file llvmjit.c.

Referenced by llvm_compile_expr(), and llvm_create_types().

◆ StructBlockId

LLVMTypeRef StructBlockId

Definition at line 71 of file llvmjit.c.

◆ StructExprContext

LLVMTypeRef StructExprContext

Definition at line 82 of file llvmjit.c.

Referenced by llvm_compile_expr(), and llvm_create_types().

◆ StructExprEvalStep

LLVMTypeRef StructExprEvalStep

Definition at line 83 of file llvmjit.c.

Referenced by build_EvalXFuncInt(), llvm_compile_expr(), and llvm_create_types().

◆ StructExprState

LLVMTypeRef StructExprState

Definition at line 84 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructFmgrInfo

LLVMTypeRef StructFmgrInfo

Definition at line 80 of file llvmjit.c.

◆ StructFormPgAttribute

LLVMTypeRef StructFormPgAttribute

Definition at line 72 of file llvmjit.c.

◆ StructFunctionCallInfoData

LLVMTypeRef StructFunctionCallInfoData

Definition at line 81 of file llvmjit.c.

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

◆ StructHeapTupleData

LLVMTypeRef StructHeapTupleData

Definition at line 68 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructHeapTupleDataChoice

LLVMTypeRef StructHeapTupleDataChoice

Definition at line 67 of file llvmjit.c.

◆ StructHeapTupleFields

LLVMTypeRef StructHeapTupleFields

Definition at line 65 of file llvmjit.c.

◆ StructHeapTupleFieldsField3

LLVMTypeRef StructHeapTupleFieldsField3

Definition at line 64 of file llvmjit.c.

◆ StructHeapTupleHeaderData

LLVMTypeRef StructHeapTupleHeaderData

Definition at line 66 of file llvmjit.c.

◆ StructHeapTupleTableSlot

LLVMTypeRef StructHeapTupleTableSlot

Definition at line 76 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructItemPointerData

LLVMTypeRef StructItemPointerData

Definition at line 70 of file llvmjit.c.

◆ StructMemoryContextData

LLVMTypeRef StructMemoryContextData

Definition at line 78 of file llvmjit.c.

Referenced by llvm_compile_expr(), and llvm_create_types().

◆ StructMinimalTupleData

LLVMTypeRef StructMinimalTupleData

Definition at line 69 of file llvmjit.c.

◆ StructMinimalTupleTableSlot

LLVMTypeRef StructMinimalTupleTableSlot

Definition at line 77 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ StructNullableDatum

LLVMTypeRef StructNullableDatum

Definition at line 63 of file llvmjit.c.

Referenced by llvm_compile_expr(), and llvm_create_types().

◆ StructPGFinfoRecord

LLVMTypeRef StructPGFinfoRecord

Definition at line 79 of file llvmjit.c.

◆ StructTupleConstr

LLVMTypeRef StructTupleConstr

Definition at line 73 of file llvmjit.c.

◆ StructTupleDescData

LLVMTypeRef StructTupleDescData

Definition at line 74 of file llvmjit.c.

Referenced by llvm_create_types().

◆ StructTupleTableSlot

LLVMTypeRef StructTupleTableSlot

Definition at line 75 of file llvmjit.c.

Referenced by llvm_create_types(), and slot_compile_deform().

◆ TypeParamBool

LLVMTypeRef TypeParamBool

Definition at line 60 of file llvmjit.c.

Referenced by llvm_compile_expr(), and llvm_create_types().

◆ TypePGFunction

LLVMTypeRef TypePGFunction

Definition at line 62 of file llvmjit.c.

Referenced by llvm_create_types(), and llvm_function_reference().

◆ TypeSizeT

LLVMTypeRef TypeSizeT

Definition at line 59 of file llvmjit.c.

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

◆ TypeStorageBool

LLVMTypeRef TypeStorageBool

Definition at line 61 of file llvmjit.c.

Referenced by llvm_compile_expr(), and llvm_create_types().