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)
 
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_type (LLVMModuleRef mod, const char *name)
 
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 589 of file llvmjit.c.

References DEBUG1, elog, ereport, errhidecontext(), errhidestmt(), errmsg(), 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().

590 {
591  LLVMJitHandle *handle;
592  MemoryContext oldcontext;
593  instr_time starttime;
594  instr_time endtime;
595 #if LLVM_VERSION_MAJOR > 11
596  LLVMOrcLLJITRef compile_orc;
597 #else
598  LLVMOrcJITStackRef compile_orc;
599 #endif
600 
601  if (context->base.flags & PGJIT_OPT3)
602  compile_orc = llvm_opt3_orc;
603  else
604  compile_orc = llvm_opt0_orc;
605 
606  /* perform inlining */
607  if (context->base.flags & PGJIT_INLINE)
608  {
609  INSTR_TIME_SET_CURRENT(starttime);
610  llvm_inline(context->module);
611  INSTR_TIME_SET_CURRENT(endtime);
612  INSTR_TIME_ACCUM_DIFF(context->base.instr.inlining_counter,
613  endtime, starttime);
614  }
615 
616  if (jit_dump_bitcode)
617  {
618  char *filename;
619 
620  filename = psprintf("%u.%zu.bc",
621  MyProcPid,
622  context->module_generation);
623  LLVMWriteBitcodeToFile(context->module, filename);
624  pfree(filename);
625  }
626 
627 
628  /* optimize according to the chosen optimization settings */
629  INSTR_TIME_SET_CURRENT(starttime);
630  llvm_optimize_module(context, context->module);
631  INSTR_TIME_SET_CURRENT(endtime);
632  INSTR_TIME_ACCUM_DIFF(context->base.instr.optimization_counter,
633  endtime, starttime);
634 
635  if (jit_dump_bitcode)
636  {
637  char *filename;
638 
639  filename = psprintf("%u.%zu.optimized.bc",
640  MyProcPid,
641  context->module_generation);
642  LLVMWriteBitcodeToFile(context->module, filename);
643  pfree(filename);
644  }
645 
646  handle = (LLVMJitHandle *)
648 
649  /*
650  * Emit the code. Note that this can, depending on the optimization
651  * settings, take noticeable resources as code emission executes low-level
652  * instruction combining/selection passes etc. Without optimization a
653  * faster instruction selection mechanism is used.
654  */
655  INSTR_TIME_SET_CURRENT(starttime);
656 #if LLVM_VERSION_MAJOR > 11
657  {
658  LLVMOrcThreadSafeModuleRef ts_module;
659  LLVMErrorRef error;
660  LLVMOrcJITDylibRef jd = LLVMOrcLLJITGetMainJITDylib(compile_orc);
661 
662  ts_module = LLVMOrcCreateNewThreadSafeModule(context->module, llvm_ts_context);
663 
664  handle->lljit = compile_orc;
665  handle->resource_tracker = LLVMOrcJITDylibCreateResourceTracker(jd);
666 
667  /*
668  * NB: This doesn't actually emit code. That happens lazily the first
669  * time a symbol defined in the module is requested. Due to that
670  * llvm_get_function() also accounts for emission time.
671  */
672 
673  context->module = NULL; /* will be owned by LLJIT */
674  error = LLVMOrcLLJITAddLLVMIRModuleWithRT(compile_orc,
675  handle->resource_tracker,
676  ts_module);
677 
678  if (error)
679  elog(ERROR, "failed to JIT module: %s",
680  llvm_error_message(error));
681 
682  handle->lljit = compile_orc;
683 
684  /* LLVMOrcLLJITAddLLVMIRModuleWithRT takes ownership of the module */
685  }
686 #elif LLVM_VERSION_MAJOR > 6
687  {
688  handle->stack = compile_orc;
689  if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &handle->orc_handle, context->module,
690  llvm_resolve_symbol, NULL))
691  elog(ERROR, "failed to JIT module");
692 
693  /* LLVMOrcAddEagerlyCompiledIR takes ownership of the module */
694  }
695 #elif LLVM_VERSION_MAJOR > 4
696  {
697  LLVMSharedModuleRef smod;
698 
699  smod = LLVMOrcMakeSharedModule(context->module);
700  handle->stack = compile_orc;
701  if (LLVMOrcAddEagerlyCompiledIR(compile_orc, &handle->orc_handle, smod,
702  llvm_resolve_symbol, NULL))
703  elog(ERROR, "failed to JIT module");
704 
705  LLVMOrcDisposeSharedModuleRef(smod);
706  }
707 #else /* LLVM 4.0 and 3.9 */
708  {
709  handle->stack = compile_orc;
710  handle->orc_handle = LLVMOrcAddEagerlyCompiledIR(compile_orc, context->module,
711  llvm_resolve_symbol, NULL);
712 
713  LLVMDisposeModule(context->module);
714  }
715 #endif
716 
717  INSTR_TIME_SET_CURRENT(endtime);
718  INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
719  endtime, starttime);
720 
721  context->module = NULL;
722  context->compiled = true;
723 
724  /* remember emitted code for cleanup and lookups */
726  context->handles = lappend(context->handles, handle);
727  MemoryContextSwitchTo(oldcontext);
728 
729  ereport(DEBUG1,
730  (errmsg("time to inline: %.3fs, opt: %.3fs, emit: %.3fs",
731  INSTR_TIME_GET_DOUBLE(context->base.instr.inlining_counter),
732  INSTR_TIME_GET_DOUBLE(context->base.instr.optimization_counter),
733  INSTR_TIME_GET_DOUBLE(context->base.instr.emission_counter)),
734  errhidestmt(true),
735  errhidecontext(true)));
736 }
#define DEBUG1
Definition: elog.h:25
int MyProcPid
Definition: globals.c:40
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:1220
#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:43
static uint64_t llvm_resolve_symbol(const char *name, void *ctx)
Definition: llvmjit.c:1034
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:321
#define PGJIT_INLINE
Definition: jit.h:22
#define ereport(elevel,...)
Definition: elog.h:155
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)
int errmsg(const char *fmt,...)
Definition: elog.c:902
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:797
#define elog(elevel,...)
Definition: elog.h:228
static LLVMOrcJITStackRef llvm_opt0_orc
Definition: llvmjit.c:105
static void llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
Definition: llvmjit.c:518
int errhidecontext(bool hide_ctx)
Definition: elog.c:1239

◆ llvm_copy_attributes()

void llvm_copy_attributes ( LLVMValueRef  v_from,
LLVMValueRef  v_to 
)

Definition at line 434 of file llvmjit.c.

References llvm_copy_attributes_at_index().

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

435 {
436  uint32 param_count;
437 
438  /* copy function attributes */
439  llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeFunctionIndex);
440 
441  /* and the return value attributes */
442  llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeReturnIndex);
443 
444  /* and each function parameter's attribute */
445  param_count = LLVMCountParams(v_from);
446 
447  for (int paramidx = 1; paramidx <= param_count; paramidx++)
448  llvm_copy_attributes_at_index(v_from, v_to, paramidx);
449 }
unsigned int uint32
Definition: c.h:429
static void llvm_copy_attributes_at_index(LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
Definition: llvmjit.c:406

◆ llvm_copy_attributes_at_index()

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

Definition at line 406 of file llvmjit.c.

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

Referenced by llvm_copy_attributes().

407 {
408  int num_attributes;
409  LLVMAttributeRef *attrs;
410 
411  num_attributes = LLVMGetAttributeCountAtIndexPG(v_from, index);
412 
413  /*
414  * Not just for efficiency: LLVM <= 3.9 crashes when
415  * LLVMGetAttributesAtIndex() is called for an index with 0 attributes.
416  */
417  if (num_attributes == 0)
418  return;
419 
420  attrs = palloc(sizeof(LLVMAttributeRef) * num_attributes);
421  LLVMGetAttributesAtIndex(v_from, index, attrs);
422 
423  for (int attno = 0; attno < num_attributes; attno++)
424  LLVMAddAttributeAtIndex(v_to, index, attrs[attno]);
425 
426  pfree(attrs);
427 }
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:142
void llvm_assert_in_fatal_section(void)
MemoryContext TopMemoryContext
Definition: mcxt.c:44
void ResourceOwnerRememberJIT(ResourceOwner owner, Datum handle)
Definition: resowner.c:1358
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:840
static void llvm_session_initialize(void)
Definition: llvmjit.c:742
void ResourceOwnerEnlargeJIT(ResourceOwner owner)
Definition: resowner.c:1347

◆ llvm_create_types()

static void llvm_create_types ( void  )
static

Definition at line 944 of file llvmjit.c.

References AttributeTemplate, buf, elog, ERROR, llvm_layout, llvm_triple, llvm_types_module, load_return_type(), load_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().

945 {
946  char path[MAXPGPATH];
947  LLVMMemoryBufferRef buf;
948  char *msg;
949 
950  snprintf(path, MAXPGPATH, "%s/%s", pkglib_path, "llvmjit_types.bc");
951 
952  /* open file */
953  if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buf, &msg))
954  {
955  elog(ERROR, "LLVMCreateMemoryBufferWithContentsOfFile(%s) failed: %s",
956  path, msg);
957  }
958 
959  /* eagerly load contents, going to need it all */
960  if (LLVMParseBitcode2(buf, &llvm_types_module))
961  {
962  elog(ERROR, "LLVMParseBitcode2 of %s failed", path);
963  }
964  LLVMDisposeMemoryBuffer(buf);
965 
966  /*
967  * Load triple & layout from clang emitted file so we're guaranteed to be
968  * compatible.
969  */
970  llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
971  llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
972 
973  TypeSizeT = load_type(llvm_types_module, "TypeSizeT");
974  TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
975  TypeStorageBool = load_type(llvm_types_module, "TypeStorageBool");
976  TypePGFunction = load_type(llvm_types_module, "TypePGFunction");
977  StructNullableDatum = load_type(llvm_types_module, "StructNullableDatum");
978  StructExprContext = load_type(llvm_types_module, "StructExprContext");
979  StructExprEvalStep = load_type(llvm_types_module, "StructExprEvalStep");
980  StructExprState = load_type(llvm_types_module, "StructExprState");
981  StructFunctionCallInfoData = load_type(llvm_types_module, "StructFunctionCallInfoData");
982  StructMemoryContextData = load_type(llvm_types_module, "StructMemoryContextData");
983  StructTupleTableSlot = load_type(llvm_types_module, "StructTupleTableSlot");
984  StructHeapTupleTableSlot = load_type(llvm_types_module, "StructHeapTupleTableSlot");
985  StructMinimalTupleTableSlot = load_type(llvm_types_module, "StructMinimalTupleTableSlot");
986  StructHeapTupleData = load_type(llvm_types_module, "StructHeapTupleData");
987  StructTupleDescData = load_type(llvm_types_module, "StructTupleDescData");
988  StructAggState = load_type(llvm_types_module, "StructAggState");
989  StructAggStatePerGroupData = load_type(llvm_types_module, "StructAggStatePerGroupData");
990  StructAggStatePerTransData = load_type(llvm_types_module, "StructAggStatePerTransData");
991 
992  AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
993 }
LLVMTypeRef StructFunctionCallInfoData
Definition: llvmjit.c:81
static LLVMTypeRef load_type(LLVMModuleRef mod, const char *name)
Definition: llvmjit.c:894
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:914
static const char * llvm_triple
Definition: llvmjit.c:95
LLVMTypeRef StructHeapTupleData
Definition: llvmjit.c:68
#define ERROR
Definition: elog.h:43
#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:228
LLVMValueRef AttributeTemplate
Definition: llvmjit.c:89
#define snprintf
Definition: port.h:215
char pkglib_path[MAXPGPATH]
Definition: globals.c:73
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:800

◆ llvm_function_reference()

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

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

459 {
460  char *modname;
461  char *basename;
462  char *funcname;
463 
464  LLVMValueRef v_fn;
465 
466  fmgr_symbol(fcinfo->flinfo->fn_oid, &modname, &basename);
467 
468  if (modname != NULL && basename != NULL)
469  {
470  /* external function in loadable library */
471  funcname = psprintf("pgextern.%s.%s", modname, basename);
472  }
473  else if (basename != NULL)
474  {
475  /* internal function */
476  funcname = psprintf("%s", basename);
477  }
478  else
479  {
480  /*
481  * Function we don't know to handle, return pointer. We do so by
482  * creating a global constant containing a pointer to the function.
483  * Makes IR more readable.
484  */
485  LLVMValueRef v_fn_addr;
486 
487  funcname = psprintf("pgoidextern.%u",
488  fcinfo->flinfo->fn_oid);
489  v_fn = LLVMGetNamedGlobal(mod, funcname);
490  if (v_fn != 0)
491  return LLVMBuildLoad(builder, v_fn, "");
492 
493  v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction);
494 
495  v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname);
496  LLVMSetInitializer(v_fn, v_fn_addr);
497  LLVMSetGlobalConstant(v_fn, true);
498  LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
499  LLVMSetUnnamedAddr(v_fn, true);
500 
501  return LLVMBuildLoad(builder, v_fn, "");
502  }
503 
504  /* check if function already has been added */
505  v_fn = LLVMGetNamedFunction(mod, funcname);
506  if (v_fn != 0)
507  return v_fn;
508 
509  v_fn = LLVMAddFunction(mod, funcname, LLVMGetElementType(TypePGFunction));
510 
511  return v_fn;
512 }
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:589
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:43
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:228
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 518 of file llvmjit.c.

References PGJIT_INLINE, and PGJIT_OPT3.

Referenced by llvm_compile_module().

519 {
520  LLVMPassManagerBuilderRef llvm_pmb;
521  LLVMPassManagerRef llvm_mpm;
522  LLVMPassManagerRef llvm_fpm;
523  LLVMValueRef func;
524  int compile_optlevel;
525 
526  if (context->base.flags & PGJIT_OPT3)
527  compile_optlevel = 3;
528  else
529  compile_optlevel = 0;
530 
531  /*
532  * Have to create a new pass manager builder every pass through, as the
533  * inliner has some per-builder state. Otherwise one ends up only inlining
534  * a function the first time though.
535  */
536  llvm_pmb = LLVMPassManagerBuilderCreate();
537  LLVMPassManagerBuilderSetOptLevel(llvm_pmb, compile_optlevel);
538  llvm_fpm = LLVMCreateFunctionPassManagerForModule(module);
539 
540  if (context->base.flags & PGJIT_OPT3)
541  {
542  /* TODO: Unscientifically determined threshold */
543  LLVMPassManagerBuilderUseInlinerWithThreshold(llvm_pmb, 512);
544  }
545  else
546  {
547  /* we rely on mem2reg heavily, so emit even in the O0 case */
548  LLVMAddPromoteMemoryToRegisterPass(llvm_fpm);
549  }
550 
551  LLVMPassManagerBuilderPopulateFunctionPassManager(llvm_pmb, llvm_fpm);
552 
553  /*
554  * Do function level optimization. This could be moved to the point where
555  * functions are emitted, to reduce memory usage a bit.
556  */
557  LLVMInitializeFunctionPassManager(llvm_fpm);
558  for (func = LLVMGetFirstFunction(context->module);
559  func != NULL;
560  func = LLVMGetNextFunction(func))
561  LLVMRunFunctionPassManager(llvm_fpm, func);
562  LLVMFinalizeFunctionPassManager(llvm_fpm);
563  LLVMDisposePassManager(llvm_fpm);
564 
565  /*
566  * Perform module level optimization. We do so even in the non-optimized
567  * case, so always-inline functions etc get inlined. It's cheap enough.
568  */
569  llvm_mpm = LLVMCreatePassManager();
570  LLVMPassManagerBuilderPopulateModulePassManager(llvm_pmb,
571  llvm_mpm);
572  /* always use always-inliner pass */
573  if (!(context->base.flags & PGJIT_OPT3))
574  LLVMAddAlwaysInlinerPass(llvm_mpm);
575  /* if doing inlining, but no expensive optimization, add inlining pass */
576  if (context->base.flags & PGJIT_INLINE
577  && !(context->base.flags & PGJIT_OPT3))
578  LLVMAddFunctionInliningPass(llvm_mpm);
579  LLVMRunPassManager(llvm_mpm, context->module);
580  LLVMDisposePassManager(llvm_mpm);
581 
582  LLVMPassManagerBuilderDispose(llvm_pmb);
583 }
#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 378 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().

379 {
380  LLVMValueRef v_srcfn;
381  LLVMValueRef v_fn;
382 
383  /* don't repeatedly add function */
384  v_fn = LLVMGetNamedFunction(mod, funcname);
385  if (v_fn)
386  return v_fn;
387 
388  v_srcfn = LLVMGetNamedFunction(llvm_types_module, funcname);
389 
390  if (!v_srcfn)
391  elog(ERROR, "function %s not in llvmjit_types.c", funcname);
392 
393  v_fn = LLVMAddFunction(mod,
394  funcname,
395  LLVMGetElementType(LLVMTypeOf(v_srcfn)));
396  llvm_copy_attributes(v_srcfn, v_fn);
397 
398  return v_fn;
399 }
#define ERROR
Definition: elog.h:43
LLVMModuleRef llvm_types_module
Definition: llvmjit.c:91
#define elog(elevel,...)
Definition: elog.h:228
void llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
Definition: llvmjit.c:434

◆ 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:860

◆ llvm_resolve_symbol()

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

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

1035 {
1036  uintptr_t addr;
1037  char *funcname;
1038  char *modname;
1039 
1040  /*
1041  * macOS prefixes all object level symbols with an underscore. But neither
1042  * dlsym() nor PG's inliner expect that. So undo.
1043  */
1044 #if defined(__darwin__)
1045  if (symname[0] != '_')
1046  elog(ERROR, "expected prefixed symbol name, but got \"%s\"", symname);
1047  symname++;
1048 #endif
1049 
1050  llvm_split_symbol_name(symname, &modname, &funcname);
1051 
1052  /* functions that aren't resolved to names shouldn't ever get here */
1053  Assert(funcname);
1054 
1055  if (modname)
1056  addr = (uintptr_t) load_external_function(modname, funcname,
1057  true, NULL);
1058  else
1059  addr = (uintptr_t) LLVMSearchForAddressOfSymbol(symname);
1060 
1061  pfree(funcname);
1062  if (modname)
1063  pfree(modname);
1064 
1065  /* let LLVM will error out - should never happen */
1066  if (!addr)
1067  elog(WARNING, "failed to resolve name %s", symname);
1068 
1069  return (uint64_t) addr;
1070 }
void llvm_split_symbol_name(const char *name, char **modname, char **funcname)
Definition: llvmjit.c:1000
void pfree(void *pointer)
Definition: mcxt.c:1057
#define ERROR
Definition: elog.h:43
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:800
#define elog(elevel,...)
Definition: elog.h:228

◆ llvm_session_initialize()

static void llvm_session_initialize ( void  )
static

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

743 {
744  MemoryContext oldcontext;
745  char *error = NULL;
746  char *cpu = NULL;
747  char *features = NULL;
748  LLVMTargetMachineRef opt0_tm;
749  LLVMTargetMachineRef opt3_tm;
750 
752  return;
753 
755 
756  LLVMInitializeNativeTarget();
757  LLVMInitializeNativeAsmPrinter();
758  LLVMInitializeNativeAsmParser();
759 
760  /*
761  * Synchronize types early, as that also includes inferring the target
762  * triple.
763  */
765 
766  if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &error) != 0)
767  {
768  elog(FATAL, "failed to query triple %s\n", error);
769  }
770 
771  /*
772  * We want the generated code to use all available features. Therefore
773  * grab the host CPU string and detect features of the current CPU. The
774  * latter is needed because some CPU architectures default to enabling
775  * features not all CPUs have (weird, huh).
776  */
777  cpu = LLVMGetHostCPUName();
778  features = LLVMGetHostCPUFeatures();
779  elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"",
780  cpu, features);
781 
782  opt0_tm =
783  LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
784  LLVMCodeGenLevelNone,
785  LLVMRelocDefault,
786  LLVMCodeModelJITDefault);
787  opt3_tm =
788  LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
789  LLVMCodeGenLevelAggressive,
790  LLVMRelocDefault,
791  LLVMCodeModelJITDefault);
792 
793  LLVMDisposeMessage(cpu);
794  cpu = NULL;
795  LLVMDisposeMessage(features);
796  features = NULL;
797 
798  /* force symbols in main binary to be loaded */
799  LLVMLoadLibraryPermanently(NULL);
800 
801 #if LLVM_VERSION_MAJOR > 11
802  {
803  llvm_ts_context = LLVMOrcCreateNewThreadSafeContext();
804 
805  llvm_opt0_orc = llvm_create_jit_instance(opt0_tm);
806  opt0_tm = 0;
807 
808  llvm_opt3_orc = llvm_create_jit_instance(opt3_tm);
809  opt3_tm = 0;
810  }
811 #else /* LLVM_VERSION_MAJOR > 11 */
812  {
813  llvm_opt0_orc = LLVMOrcCreateInstance(opt0_tm);
814  llvm_opt3_orc = LLVMOrcCreateInstance(opt3_tm);
815 
816 #if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
818  {
819  LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
820 
821  LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l);
822  LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l);
823  }
824 #endif
825 #if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
827  {
828  LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
829 
830  LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l);
831  LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l);
832  }
833 #endif
834  }
835 #endif /* LLVM_VERSION_MAJOR > 11 */
836 
838 
840 
841  MemoryContextSwitchTo(oldcontext);
842 }
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:845
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:109
static const char * llvm_triple
Definition: llvmjit.c:95
#define FATAL
Definition: elog.h:52
#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:944
#define elog(elevel,...)
Definition: elog.h:228
static LLVMOrcJITStackRef llvm_opt0_orc
Definition: llvmjit.c:105

◆ llvm_shutdown()

static void llvm_shutdown ( int  code,
Datum  arg 
)
static

Definition at line 845 of file llvmjit.c.

References jit_profiling_support, llvm_opt0_orc, and llvm_opt3_orc.

Referenced by llvm_session_initialize().

846 {
847 #if LLVM_VERSION_MAJOR > 11
848  {
849  if (llvm_opt3_orc)
850  {
851  LLVMOrcDisposeLLJIT(llvm_opt3_orc);
852  llvm_opt3_orc = NULL;
853  }
854  if (llvm_opt0_orc)
855  {
856  LLVMOrcDisposeLLJIT(llvm_opt0_orc);
857  llvm_opt0_orc = NULL;
858  }
859  if (llvm_ts_context)
860  {
861  LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
862  llvm_ts_context = NULL;
863  }
864  }
865 #else /* LLVM_VERSION_MAJOR > 11 */
866  {
867  /* unregister profiling support, needs to be flushed to be useful */
868 
869  if (llvm_opt3_orc)
870  {
871 #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF
873  LLVMOrcUnregisterPerf(llvm_opt3_orc);
874 #endif
875  LLVMOrcDisposeInstance(llvm_opt3_orc);
876  llvm_opt3_orc = NULL;
877  }
878 
879  if (llvm_opt0_orc)
880  {
881 #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF
883  LLVMOrcUnregisterPerf(llvm_opt0_orc);
884 #endif
885  LLVMOrcDisposeInstance(llvm_opt0_orc);
886  llvm_opt0_orc = NULL;
887  }
888  }
889 #endif /* LLVM_VERSION_MAJOR > 11 */
890 }
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 1000 of file llvmjit.c.

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

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

1001 {
1002  *modname = NULL;
1003  *funcname = NULL;
1004 
1005  /*
1006  * Module function names are pgextern.$module.$funcname
1007  */
1008  if (strncmp(name, "pgextern.", strlen("pgextern.")) == 0)
1009  {
1010  /*
1011  * Symbol names cannot contain a ., therefore we can split based on
1012  * first and last occurrence of one.
1013  */
1014  *funcname = rindex(name, '.');
1015  (*funcname)++; /* jump over . */
1016 
1017  *modname = pnstrdup(name + strlen("pgextern."),
1018  *funcname - name - strlen("pgextern.") - 1);
1019  Assert(funcname);
1020 
1021  *funcname = pstrdup(*funcname);
1022  }
1023  else
1024  {
1025  *modname = NULL;
1026  *funcname = pstrdup(name);
1027  }
1028 }
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:800
const char * name
Definition: encode.c:561

◆ load_return_type()

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

Definition at line 914 of file llvmjit.c.

References Assert, elog, ERROR, and value.

Referenced by llvm_create_types().

915 {
916  LLVMValueRef value;
917  LLVMTypeRef typ;
918 
919  /* this'll return a *pointer* to the function */
920  value = LLVMGetNamedFunction(mod, name);
921  if (!value)
922  elog(ERROR, "function %s is unknown", name);
923 
924  /* get type of function pointer */
925  typ = LLVMTypeOf(value);
926  Assert(typ != NULL);
927  /* dereference pointer */
928  typ = LLVMGetElementType(typ);
929  Assert(typ != NULL);
930  /* and look at return type */
931  typ = LLVMGetReturnType(typ);
932  Assert(typ != NULL);
933 
934  return typ;
935 }
#define ERROR
Definition: elog.h:43
static struct @143 value
#define Assert(condition)
Definition: c.h:800
const char * name
Definition: encode.c:561
#define elog(elevel,...)
Definition: elog.h:228

◆ load_type()

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

Definition at line 894 of file llvmjit.c.

References Assert, elog, ERROR, and value.

Referenced by llvm_create_types().

895 {
896  LLVMValueRef value;
897  LLVMTypeRef typ;
898 
899  /* this'll return a *pointer* to the global */
900  value = LLVMGetNamedGlobal(mod, name);
901  if (!value)
902  elog(ERROR, "type %s is unknown", name);
903 
904  /* therefore look at the contained type and return that */
905  typ = LLVMTypeOf(value);
906  Assert(typ != NULL);
907  typ = LLVMGetElementType(typ);
908  Assert(typ != NULL);
909  return typ;
910 }
#define ERROR
Definition: elog.h:43
static struct @143 value
#define Assert(condition)
Definition: c.h:800
const char * name
Definition: encode.c:561
#define elog(elevel,...)
Definition: elog.h:228

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(), and llvm_pg_func().

◆ 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(), and llvm_create_types().

◆ StructExprState

LLVMTypeRef StructExprState

Definition at line 84 of file llvmjit.c.

Referenced by llvm_compile_expr(), and 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().