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.

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

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

◆ llvm_compile_module()

static void llvm_compile_module ( LLVMJitContext *  context)
static

Definition at line 630 of file llvmjit.c.

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 }
int errmsg_internal(const char *fmt,...)
Definition: elog.c:993
int errhidestmt(bool hide_stmt)
Definition: elog.c:1247
int errhidecontext(bool hide_ctx)
Definition: elog.c:1266
#define DEBUG1
Definition: elog.h:26
#define ERROR
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:145
int MyProcPid
Definition: globals.c:44
#define INSTR_TIME_SET_CURRENT(t)
Definition: instr_time.h:89
#define INSTR_TIME_GET_DOUBLE(t)
Definition: instr_time.h:132
struct timespec instr_time
Definition: instr_time.h:83
#define INSTR_TIME_ACCUM_DIFF(x, y, z)
Definition: instr_time.h:115
bool jit_dump_bitcode
Definition: jit.c:35
#define PGJIT_OPT3
Definition: jit.h:21
#define PGJIT_INLINE
Definition: jit.h:22
List * lappend(List *list, void *datum)
Definition: list.c:338
static LLVMOrcJITStackRef llvm_opt3_orc
Definition: llvmjit.c:106
static LLVMOrcJITStackRef llvm_opt0_orc
Definition: llvmjit.c:105
static void llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
Definition: llvmjit.c:559
static uint64_t llvm_resolve_symbol(const char *name, void *ctx)
Definition: llvmjit.c:1079
void llvm_inline(LLVMModuleRef M)
void pfree(void *pointer)
Definition: mcxt.c:1306
MemoryContext TopMemoryContext
Definition: mcxt.c:130
void * MemoryContextAlloc(MemoryContext context, Size size)
Definition: mcxt.c:994
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:135
static char * filename
Definition: pg_dumpall.c:119
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
static void error(void)
Definition: sql-dyntest.c:147
LLVMOrcJITStackRef stack
Definition: llvmjit.c:52
LLVMOrcModuleHandle orc_handle
Definition: llvmjit.c:53

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

◆ llvm_copy_attributes()

void llvm_copy_attributes ( LLVMValueRef  v_from,
LLVMValueRef  v_to 
)

Definition at line 475 of file llvmjit.c.

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:442
static void llvm_copy_attributes_at_index(LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
Definition: llvmjit.c:447

References llvm_copy_attributes_at_index().

Referenced by llvm_pg_func(), and slot_compile_deform().

◆ llvm_copy_attributes_at_index()

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

Definition at line 447 of file llvmjit.c.

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 }
unsigned LLVMGetAttributeCountAtIndexPG(LLVMValueRef F, uint32 Idx)
void * palloc(Size size)
Definition: mcxt.c:1199
Definition: type.h:95

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

Referenced by llvm_copy_attributes().

◆ llvm_create_context()

LLVMJitContext* llvm_create_context ( int  jitFlags)

Definition at line 146 of file llvmjit.c.

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 }
static void llvm_session_initialize(void)
Definition: llvmjit.c:783
void llvm_assert_in_fatal_section(void)
void * MemoryContextAllocZero(MemoryContext context, Size size)
Definition: mcxt.c:1037
static Datum PointerGetDatum(const void *X)
Definition: postgres.h:670
void ResourceOwnerEnlargeJIT(ResourceOwner owner)
Definition: resowner.c:1380
ResourceOwner CurrentResourceOwner
Definition: resowner.c:146
void ResourceOwnerRememberJIT(ResourceOwner owner, Datum handle)
Definition: resowner.c:1391

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

Referenced by llvm_compile_expr().

◆ llvm_create_types()

static void llvm_create_types ( void  )
static

Definition at line 989 of file llvmjit.c.

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

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

◆ llvm_expand_funcname()

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

Definition at line 255 of file llvmjit.c.

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 }
Assert(fmt[strlen(fmt) - 1] !='\n')

References Assert(), and psprintf().

Referenced by slot_compile_deform().

◆ llvm_function_reference()

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

Definition at line 496 of file llvmjit.c.

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 = pstrdup(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 }
void fmgr_symbol(Oid functionId, char **mod, char **fn)
Definition: fmgr.c:283
PGFunction fn_addr
Definition: fmgr.h:58
Oid fn_oid
Definition: fmgr.h:59
FmgrInfo * flinfo
Definition: fmgr.h:87

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

Referenced by BuildV1Call().

◆ llvm_get_function()

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

Definition at line 276 of file llvmjit.c.

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
#define lfirst(lc)
Definition: pg_list.h:170

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

◆ llvm_mutable_module()

LLVMModuleRef llvm_mutable_module ( LLVMJitContext *  context)

Definition at line 230 of file llvmjit.c.

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 size_t llvm_generation
Definition: llvmjit.c:94

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

Referenced by slot_compile_deform().

◆ llvm_optimize_module()

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

Definition at line 559 of file llvmjit.c.

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 }

References PGJIT_INLINE, and PGJIT_OPT3.

Referenced by llvm_compile_module().

◆ llvm_pg_func()

LLVMValueRef llvm_pg_func ( LLVMModuleRef  mod,
const char *  funcname 
)

Definition at line 419 of file llvmjit.c.

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 }
void llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
Definition: llvmjit.c:475

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

Referenced by build_EvalXFuncInt(), and slot_compile_deform().

◆ llvm_pg_var_func_type()

LLVMTypeRef llvm_pg_var_func_type ( const char *  varname)

Definition at line 399 of file llvmjit.c.

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 }

References Assert(), and llvm_pg_var_type().

◆ llvm_pg_var_type()

LLVMTypeRef llvm_pg_var_type ( const char *  varname)

Definition at line 375 of file llvmjit.c.

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 }

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

Referenced by llvm_create_types(), and llvm_pg_var_func_type().

◆ llvm_release_context()

static void llvm_release_context ( JitContext context)
static

Definition at line 171 of file llvmjit.c.

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

References lfirst, list_free(), llvm_enter_fatal_on_oom(), NIL, LLVMJitHandle::orc_handle, pfree(), proc_exit_inprogress, and LLVMJitHandle::stack.

Referenced by _PG_jit_provider_init().

◆ llvm_resolve_symbol()

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

Definition at line 1079 of file llvmjit.c.

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

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

Referenced by llvm_compile_module().

◆ llvm_session_initialize()

static void llvm_session_initialize ( void  )
static

Definition at line 783 of file llvmjit.c.

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  * When targeting an LLVM version with opaque pointers enabled by
803  * default, turn them off for the context we build our code in. We don't
804  * need to do so for other contexts (e.g. llvm_ts_context). Once the IR is
805  * generated, it carries the necessary information.
806  */
807 #if LLVM_VERSION_MAJOR > 14
808  LLVMContextSetOpaquePointers(LLVMGetGlobalContext(), false);
809 #endif
810 
811  /*
812  * Synchronize types early, as that also includes inferring the target
813  * triple.
814  */
816 
817  if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &error) != 0)
818  {
819  elog(FATAL, "failed to query triple %s\n", error);
820  }
821 
822  /*
823  * We want the generated code to use all available features. Therefore
824  * grab the host CPU string and detect features of the current CPU. The
825  * latter is needed because some CPU architectures default to enabling
826  * features not all CPUs have (weird, huh).
827  */
828  cpu = LLVMGetHostCPUName();
829  features = LLVMGetHostCPUFeatures();
830  elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"",
831  cpu, features);
832 
833  opt0_tm =
834  LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
835  LLVMCodeGenLevelNone,
836  LLVMRelocDefault,
837  LLVMCodeModelJITDefault);
838  opt3_tm =
839  LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
840  LLVMCodeGenLevelAggressive,
841  LLVMRelocDefault,
842  LLVMCodeModelJITDefault);
843 
844  LLVMDisposeMessage(cpu);
845  cpu = NULL;
846  LLVMDisposeMessage(features);
847  features = NULL;
848 
849  /* force symbols in main binary to be loaded */
850  LLVMLoadLibraryPermanently(NULL);
851 
852 #if LLVM_VERSION_MAJOR > 11
853  {
854  llvm_ts_context = LLVMOrcCreateNewThreadSafeContext();
855 
856  llvm_opt0_orc = llvm_create_jit_instance(opt0_tm);
857  opt0_tm = 0;
858 
859  llvm_opt3_orc = llvm_create_jit_instance(opt3_tm);
860  opt3_tm = 0;
861  }
862 #else /* LLVM_VERSION_MAJOR > 11 */
863  {
864  llvm_opt0_orc = LLVMOrcCreateInstance(opt0_tm);
865  llvm_opt3_orc = LLVMOrcCreateInstance(opt3_tm);
866 
867 #if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
869  {
870  LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
871 
872  LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l);
873  LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l);
874  }
875 #endif
876 #if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
878  {
879  LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
880 
881  LLVMOrcRegisterJITEventListener(llvm_opt0_orc, l);
882  LLVMOrcRegisterJITEventListener(llvm_opt3_orc, l);
883  }
884 #endif
885  }
886 #endif /* LLVM_VERSION_MAJOR > 11 */
887 
889 
891 
892  MemoryContextSwitchTo(oldcontext);
893 }
#define FATAL
Definition: elog.h:37
#define DEBUG2
Definition: elog.h:25
void on_proc_exit(pg_on_exit_callback function, Datum arg)
Definition: ipc.c:305
bool jit_profiling_support
Definition: jit.c:37
bool jit_debugging_support
Definition: jit.c:34
static LLVMTargetRef llvm_targetref
Definition: llvmjit.c:99
static bool llvm_session_initialized
Definition: llvmjit.c:93
static void llvm_create_types(void)
Definition: llvmjit.c:989
static void llvm_shutdown(int code, Datum arg)
Definition: llvmjit.c:896

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

◆ llvm_shutdown()

static void llvm_shutdown ( int  code,
Datum  arg 
)
static

Definition at line 896 of file llvmjit.c.

897 {
898  /*
899  * If llvm_shutdown() is reached while in a fatal-on-oom section an error
900  * has occurred in the middle of LLVM code. It is not safe to call back
901  * into LLVM (which is why a FATAL error was thrown).
902  *
903  * We do need to shutdown LLVM in other shutdown cases, otherwise e.g.
904  * profiling data won't be written out.
905  */
906  if (llvm_in_fatal_on_oom())
907  {
909  return;
910  }
911 
912 #if LLVM_VERSION_MAJOR > 11
913  {
914  if (llvm_opt3_orc)
915  {
916  LLVMOrcDisposeLLJIT(llvm_opt3_orc);
917  llvm_opt3_orc = NULL;
918  }
919  if (llvm_opt0_orc)
920  {
921  LLVMOrcDisposeLLJIT(llvm_opt0_orc);
922  llvm_opt0_orc = NULL;
923  }
924  if (llvm_ts_context)
925  {
926  LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
927  llvm_ts_context = NULL;
928  }
929  }
930 #else /* LLVM_VERSION_MAJOR > 11 */
931  {
932  /* unregister profiling support, needs to be flushed to be useful */
933 
934  if (llvm_opt3_orc)
935  {
936 #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF
938  LLVMOrcUnregisterPerf(llvm_opt3_orc);
939 #endif
940  LLVMOrcDisposeInstance(llvm_opt3_orc);
941  llvm_opt3_orc = NULL;
942  }
943 
944  if (llvm_opt0_orc)
945  {
946 #if defined(HAVE_DECL_LLVMORCREGISTERPERF) && HAVE_DECL_LLVMORCREGISTERPERF
948  LLVMOrcUnregisterPerf(llvm_opt0_orc);
949 #endif
950  LLVMOrcDisposeInstance(llvm_opt0_orc);
951  llvm_opt0_orc = NULL;
952  }
953  }
954 #endif /* LLVM_VERSION_MAJOR > 11 */
955 }
bool llvm_in_fatal_on_oom(void)

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

Referenced by llvm_session_initialize().

◆ llvm_split_symbol_name()

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

Definition at line 1045 of file llvmjit.c.

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

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

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

◆ load_return_type()

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

Definition at line 959 of file llvmjit.c.

960 {
961  LLVMValueRef value;
962  LLVMTypeRef typ;
963 
964  /* this'll return a *pointer* to the function */
965  value = LLVMGetNamedFunction(mod, name);
966  if (!value)
967  elog(ERROR, "function %s is unknown", name);
968 
969  /* get type of function pointer */
970  typ = LLVMTypeOf(value);
971  Assert(typ != NULL);
972  /* dereference pointer */
973  typ = LLVMGetElementType(typ);
974  Assert(typ != NULL);
975  /* and look at return type */
976  typ = LLVMGetReturnType(typ);
977  Assert(typ != NULL);
978 
979  return typ;
980 }
static struct @143 value

References Assert(), elog(), ERROR, name, and value.

Referenced by llvm_create_types().

Variable Documentation

◆ AttributeTemplate

Datum AttributeTemplate

Definition at line 89 of file llvmjit.c.

Referenced by 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_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_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_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_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(), 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_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_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_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_create_types(), and slot_compile_deform().

◆ TypeStorageBool

LLVMTypeRef TypeStorageBool

Definition at line 61 of file llvmjit.c.

Referenced by llvm_create_types().