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:41
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:1223
#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:1057
#define ERROR
Definition: elog.h:45
static uint64_t llvm_resolve_symbol(const char *name, void *ctx)
Definition: llvmjit.c:1055
LLVMOrcModuleHandle orc_handle
Definition: llvmjit.c:53
MemoryContext TopMemoryContext
Definition: mcxt.c:44
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:155
int errmsg_internal(const char *fmt,...)
Definition: elog.c:992
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:91
void llvm_inline(LLVMModuleRef M)
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
#define elog(elevel,...)
Definition: elog.h:227
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:1242

◆ 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:1057
unsigned LLVMGetAttributeCountAtIndexPG(LLVMValueRef F, uint32 Idx)
void * palloc(Size size)
Definition: mcxt.c:950

◆ 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:556
ResourceOwner CurrentResourceOwner
Definition: resowner.c:144
void llvm_assert_in_fatal_section(void)
MemoryContext TopMemoryContext
Definition: mcxt.c:44
void ResourceOwnerRememberJIT(ResourceOwner owner, Datum handle)
Definition: resowner.c:1371
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
static void llvm_session_initialize(void)
Definition: llvmjit.c:783
void ResourceOwnerEnlargeJIT(ResourceOwner owner)
Definition: resowner.c:1360

◆ llvm_create_types()

static void llvm_create_types ( void  )
static

Definition at line 965 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().

966 {
967  char path[MAXPGPATH];
968  LLVMMemoryBufferRef buf;
969  char *msg;
970 
971  snprintf(path, MAXPGPATH, "%s/%s", pkglib_path, "llvmjit_types.bc");
972 
973  /* open file */
974  if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buf, &msg))
975  {
976  elog(ERROR, "LLVMCreateMemoryBufferWithContentsOfFile(%s) failed: %s",
977  path, msg);
978  }
979 
980  /* eagerly load contents, going to need it all */
981  if (LLVMParseBitcode2(buf, &llvm_types_module))
982  {
983  elog(ERROR, "LLVMParseBitcode2 of %s failed", path);
984  }
985  LLVMDisposeMemoryBuffer(buf);
986 
987  /*
988  * Load triple & layout from clang emitted file so we're guaranteed to be
989  * compatible.
990  */
991  llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
992  llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
993 
994  TypeSizeT = llvm_pg_var_type("TypeSizeT");
995  TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
996  TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
997  TypePGFunction = llvm_pg_var_type("TypePGFunction");
998  StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
999  StructExprContext = llvm_pg_var_type("StructExprContext");
1000  StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
1001  StructExprState = llvm_pg_var_type("StructExprState");
1002  StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
1003  StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
1004  StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
1005  StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
1006  StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
1007  StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
1008  StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
1009  StructAggState = llvm_pg_var_type("StructAggState");
1010  StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
1011  StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
1012 
1013  AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
1014 }
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:1187
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:935
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:45
#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:227
LLVMValueRef AttributeTemplate
Definition: llvmjit.c:89
#define snprintf
Definition: port.h:216
char pkglib_path[MAXPGPATH]
Definition: globals.c:74
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:45
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:227
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:45
LLVMModuleRef llvm_types_module
Definition: llvmjit.c:91
#define elog(elevel,...)
Definition: elog.h:227
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:45
#define Assert(condition)
Definition: c.h:804
LLVMModuleRef llvm_types_module
Definition: llvmjit.c:91
#define elog(elevel,...)
Definition: elog.h:227

◆ 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 
176 
177  /*
178  * When this backend is exiting, don't clean up LLVM. As an error might
179  * have occurred from within LLVM, we do not want to risk reentering. All
180  * resource cleanup is going to happen through process exit.
181  */
183  return;
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:1057
#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 1055 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().

1056 {
1057  uintptr_t addr;
1058  char *funcname;
1059  char *modname;
1060 
1061  /*
1062  * macOS prefixes all object level symbols with an underscore. But neither
1063  * dlsym() nor PG's inliner expect that. So undo.
1064  */
1065 #if defined(__darwin__)
1066  if (symname[0] != '_')
1067  elog(ERROR, "expected prefixed symbol name, but got \"%s\"", symname);
1068  symname++;
1069 #endif
1070 
1071  llvm_split_symbol_name(symname, &modname, &funcname);
1072 
1073  /* functions that aren't resolved to names shouldn't ever get here */
1074  Assert(funcname);
1075 
1076  if (modname)
1077  addr = (uintptr_t) load_external_function(modname, funcname,
1078  true, NULL);
1079  else
1080  addr = (uintptr_t) LLVMSearchForAddressOfSymbol(symname);
1081 
1082  pfree(funcname);
1083  if (modname)
1084  pfree(modname);
1085 
1086  /* let LLVM will error out - should never happen */
1087  if (!addr)
1088  elog(WARNING, "failed to resolve name %s", symname);
1089 
1090  return (uint64_t) addr;
1091 }
void llvm_split_symbol_name(const char *name, char **modname, char **funcname)
Definition: llvmjit.c:1021
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:45
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:227

◆ 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:54
#define DEBUG2
Definition: elog.h:24
MemoryContext TopMemoryContext
Definition: mcxt.c:44
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:965
#define elog(elevel,...)
Definition: elog.h:227
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 jit_profiling_support, llvm_opt0_orc, and llvm_opt3_orc.

Referenced by llvm_session_initialize().

887 {
888 #if LLVM_VERSION_MAJOR > 11
889  {
890  if (llvm_opt3_orc)
891  {
892  LLVMOrcDisposeLLJIT(llvm_opt3_orc);
893  llvm_opt3_orc = NULL;
894  }
895  if (llvm_opt0_orc)
896  {
897  LLVMOrcDisposeLLJIT(llvm_opt0_orc);
898  llvm_opt0_orc = NULL;
899  }
900  if (llvm_ts_context)
901  {
902  LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
903  llvm_ts_context = NULL;
904  }
905  }
906 #else /* LLVM_VERSION_MAJOR > 11 */
907  {
908  /* unregister profiling support, needs to be flushed to be useful */
909 
910  if (llvm_opt3_orc)
911  {
912 #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF
914  LLVMOrcUnregisterPerf(llvm_opt3_orc);
915 #endif
916  LLVMOrcDisposeInstance(llvm_opt3_orc);
917  llvm_opt3_orc = NULL;
918  }
919 
920  if (llvm_opt0_orc)
921  {
922 #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF
924  LLVMOrcUnregisterPerf(llvm_opt0_orc);
925 #endif
926  LLVMOrcDisposeInstance(llvm_opt0_orc);
927  llvm_opt0_orc = NULL;
928  }
929  }
930 #endif /* LLVM_VERSION_MAJOR > 11 */
931 }
static LLVMOrcJITStackRef llvm_opt3_orc
Definition: llvmjit.c:106
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 1021 of file llvmjit.c.

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

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

1022 {
1023  *modname = NULL;
1024  *funcname = NULL;
1025 
1026  /*
1027  * Module function names are pgextern.$module.$funcname
1028  */
1029  if (strncmp(name, "pgextern.", strlen("pgextern.")) == 0)
1030  {
1031  /*
1032  * Symbol names cannot contain a ., therefore we can split based on
1033  * first and last occurrence of one.
1034  */
1035  *funcname = rindex(name, '.');
1036  (*funcname)++; /* jump over . */
1037 
1038  *modname = pnstrdup(name + strlen("pgextern."),
1039  *funcname - name - strlen("pgextern.") - 1);
1040  Assert(funcname);
1041 
1042  *funcname = pstrdup(*funcname);
1043  }
1044  else
1045  {
1046  *modname = NULL;
1047  *funcname = pstrdup(name);
1048  }
1049 }
char * pnstrdup(const char *in, Size len)
Definition: mcxt.c:1198
char * pstrdup(const char *in)
Definition: mcxt.c:1187
#define Assert(condition)
Definition: c.h:804
const char * name
Definition: encode.c:515

◆ load_return_type()

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

Definition at line 935 of file llvmjit.c.

References Assert, elog, ERROR, and value.

Referenced by llvm_create_types().

936 {
937  LLVMValueRef value;
938  LLVMTypeRef typ;
939 
940  /* this'll return a *pointer* to the function */
941  value = LLVMGetNamedFunction(mod, name);
942  if (!value)
943  elog(ERROR, "function %s is unknown", name);
944 
945  /* get type of function pointer */
946  typ = LLVMTypeOf(value);
947  Assert(typ != NULL);
948  /* dereference pointer */
949  typ = LLVMGetElementType(typ);
950  Assert(typ != NULL);
951  /* and look at return type */
952  typ = LLVMGetReturnType(typ);
953  Assert(typ != NULL);
954 
955  return typ;
956 }
static struct @141 value
#define ERROR
Definition: elog.h:45
#define Assert(condition)
Definition: c.h:804
const char * name
Definition: encode.c:515
#define elog(elevel,...)
Definition: elog.h:227

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