LCOV - code coverage report
Current view: top level - src/backend/jit/llvm - llvmjit.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 315 390 80.8 %
Date: 2024-10-10 05:14:53 Functions: 27 31 87.1 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * llvmjit.c
       4             :  *    Core part of the LLVM JIT provider.
       5             :  *
       6             :  * Copyright (c) 2016-2024, PostgreSQL Global Development Group
       7             :  *
       8             :  * IDENTIFICATION
       9             :  *    src/backend/jit/llvm/llvmjit.c
      10             :  *
      11             :  *-------------------------------------------------------------------------
      12             :  */
      13             : 
      14             : #include "postgres.h"
      15             : 
      16             : #include <llvm-c/Analysis.h>
      17             : #include <llvm-c/BitReader.h>
      18             : #include <llvm-c/BitWriter.h>
      19             : #include <llvm-c/Core.h>
      20             : #include <llvm-c/ExecutionEngine.h>
      21             : #if LLVM_VERSION_MAJOR > 16
      22             : #include <llvm-c/Transforms/PassBuilder.h>
      23             : #endif
      24             : #include <llvm-c/Orc.h>
      25             : #include <llvm-c/OrcEE.h>
      26             : #include <llvm-c/LLJIT.h>
      27             : #include <llvm-c/Support.h>
      28             : #include <llvm-c/Target.h>
      29             : #if LLVM_VERSION_MAJOR < 17
      30             : #include <llvm-c/Transforms/IPO.h>
      31             : #include <llvm-c/Transforms/PassManagerBuilder.h>
      32             : #include <llvm-c/Transforms/Scalar.h>
      33             : #include <llvm-c/Transforms/Utils.h>
      34             : #endif
      35             : 
      36             : #include "jit/llvmjit.h"
      37             : #include "jit/llvmjit_emit.h"
      38             : #include "miscadmin.h"
      39             : #include "portability/instr_time.h"
      40             : #include "storage/ipc.h"
      41             : #include "utils/memutils.h"
      42             : #include "utils/resowner.h"
      43             : 
      44             : #define LLVMJIT_LLVM_CONTEXT_REUSE_MAX 100
      45             : 
      46             : /* Handle of a module emitted via ORC JIT */
      47             : typedef struct LLVMJitHandle
      48             : {
      49             :     LLVMOrcLLJITRef lljit;
      50             :     LLVMOrcResourceTrackerRef resource_tracker;
      51             : } LLVMJitHandle;
      52             : 
      53             : 
      54             : /* types & functions commonly needed for JITing */
      55             : LLVMTypeRef TypeSizeT;
      56             : LLVMTypeRef TypeParamBool;
      57             : LLVMTypeRef TypeStorageBool;
      58             : LLVMTypeRef TypePGFunction;
      59             : LLVMTypeRef StructNullableDatum;
      60             : LLVMTypeRef StructHeapTupleData;
      61             : LLVMTypeRef StructMinimalTupleData;
      62             : LLVMTypeRef StructTupleDescData;
      63             : LLVMTypeRef StructTupleTableSlot;
      64             : LLVMTypeRef StructHeapTupleHeaderData;
      65             : LLVMTypeRef StructHeapTupleTableSlot;
      66             : LLVMTypeRef StructMinimalTupleTableSlot;
      67             : LLVMTypeRef StructMemoryContextData;
      68             : LLVMTypeRef StructFunctionCallInfoData;
      69             : LLVMTypeRef StructExprContext;
      70             : LLVMTypeRef StructExprEvalStep;
      71             : LLVMTypeRef StructExprState;
      72             : LLVMTypeRef StructAggState;
      73             : LLVMTypeRef StructAggStatePerGroupData;
      74             : LLVMTypeRef StructAggStatePerTransData;
      75             : LLVMTypeRef StructPlanState;
      76             : 
      77             : LLVMValueRef AttributeTemplate;
      78             : LLVMValueRef ExecEvalSubroutineTemplate;
      79             : LLVMValueRef ExecEvalBoolSubroutineTemplate;
      80             : 
      81             : static LLVMModuleRef llvm_types_module = NULL;
      82             : 
      83             : static bool llvm_session_initialized = false;
      84             : static size_t llvm_generation = 0;
      85             : 
      86             : /* number of LLVMJitContexts that currently are in use */
      87             : static size_t llvm_jit_context_in_use_count = 0;
      88             : 
      89             : /* how many times has the current LLVMContextRef been used */
      90             : static size_t llvm_llvm_context_reuse_count = 0;
      91             : static const char *llvm_triple = NULL;
      92             : static const char *llvm_layout = NULL;
      93             : static LLVMContextRef llvm_context;
      94             : 
      95             : 
      96             : static LLVMTargetRef llvm_targetref;
      97             : static LLVMOrcThreadSafeContextRef llvm_ts_context;
      98             : static LLVMOrcLLJITRef llvm_opt0_orc;
      99             : static LLVMOrcLLJITRef llvm_opt3_orc;
     100             : 
     101             : 
     102             : static void llvm_release_context(JitContext *context);
     103             : static void llvm_session_initialize(void);
     104             : static void llvm_shutdown(int code, Datum arg);
     105             : static void llvm_compile_module(LLVMJitContext *context);
     106             : static void llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module);
     107             : 
     108             : static void llvm_create_types(void);
     109             : static void llvm_set_target(void);
     110             : static void llvm_recreate_llvm_context(void);
     111             : static uint64_t llvm_resolve_symbol(const char *name, void *ctx);
     112             : 
     113             : static LLVMOrcLLJITRef llvm_create_jit_instance(LLVMTargetMachineRef tm);
     114             : static char *llvm_error_message(LLVMErrorRef error);
     115             : 
     116             : /* ResourceOwner callbacks to hold JitContexts  */
     117             : static void ResOwnerReleaseJitContext(Datum res);
     118             : 
     119             : static const ResourceOwnerDesc jit_resowner_desc =
     120             : {
     121             :     .name = "LLVM JIT context",
     122             :     .release_phase = RESOURCE_RELEASE_BEFORE_LOCKS,
     123             :     .release_priority = RELEASE_PRIO_JIT_CONTEXTS,
     124             :     .ReleaseResource = ResOwnerReleaseJitContext,
     125             :     .DebugPrint = NULL          /* the default message is fine */
     126             : };
     127             : 
     128             : /* Convenience wrappers over ResourceOwnerRemember/Forget */
     129             : static inline void
     130        1216 : ResourceOwnerRememberJIT(ResourceOwner owner, LLVMJitContext *handle)
     131             : {
     132        1216 :     ResourceOwnerRemember(owner, PointerGetDatum(handle), &jit_resowner_desc);
     133        1216 : }
     134             : static inline void
     135        1200 : ResourceOwnerForgetJIT(ResourceOwner owner, LLVMJitContext *handle)
     136             : {
     137        1200 :     ResourceOwnerForget(owner, PointerGetDatum(handle), &jit_resowner_desc);
     138        1200 : }
     139             : 
     140        1938 : PG_MODULE_MAGIC;
     141             : 
     142             : 
     143             : /*
     144             :  * Initialize LLVM JIT provider.
     145             :  */
     146             : void
     147         470 : _PG_jit_provider_init(JitProviderCallbacks *cb)
     148             : {
     149         470 :     cb->reset_after_error = llvm_reset_after_error;
     150         470 :     cb->release_context = llvm_release_context;
     151         470 :     cb->compile_expr = llvm_compile_expr;
     152         470 : }
     153             : 
     154             : 
     155             : /*
     156             :  * Every now and then create a new LLVMContextRef. Unfortunately, during every
     157             :  * round of inlining, types may "leak" (they can still be found/used via the
     158             :  * context, but new types will be created the next time in inlining is
     159             :  * performed). To prevent that from slowly accumulating problematic amounts of
     160             :  * memory, recreate the LLVMContextRef we use. We don't want to do so too
     161             :  * often, as that implies some overhead (particularly re-loading the module
     162             :  * summaries / modules is fairly expensive). A future TODO would be to make
     163             :  * this more finegrained and only drop/recreate the LLVMContextRef when we know
     164             :  * there has been inlining. If we can get the size of the context from LLVM
     165             :  * then that might be a better way to determine when to drop/recreate rather
     166             :  * then the usagecount heuristic currently employed.
     167             :  */
     168             : static void
     169        1216 : llvm_recreate_llvm_context(void)
     170             : {
     171        1216 :     if (!llvm_context)
     172           0 :         elog(ERROR, "Trying to recreate a non-existing context");
     173             : 
     174             :     /*
     175             :      * We can only safely recreate the LLVM context if no other code is being
     176             :      * JITed, otherwise we'd release the types in use for that.
     177             :      */
     178        1216 :     if (llvm_jit_context_in_use_count > 0)
     179             :     {
     180           0 :         llvm_llvm_context_reuse_count++;
     181           0 :         return;
     182             :     }
     183             : 
     184        1216 :     if (llvm_llvm_context_reuse_count <= LLVMJIT_LLVM_CONTEXT_REUSE_MAX)
     185             :     {
     186        1216 :         llvm_llvm_context_reuse_count++;
     187        1216 :         return;
     188             :     }
     189             : 
     190             :     /*
     191             :      * Need to reset the modules that the inlining code caches before
     192             :      * disposing of the context. LLVM modules exist within a specific LLVM
     193             :      * context, therefore disposing of the context before resetting the cache
     194             :      * would lead to dangling pointers to modules.
     195             :      */
     196           0 :     llvm_inline_reset_caches();
     197             : 
     198           0 :     LLVMContextDispose(llvm_context);
     199           0 :     llvm_context = LLVMContextCreate();
     200           0 :     llvm_llvm_context_reuse_count = 0;
     201             : 
     202             :     /*
     203             :      * Re-build cached type information, so code generation code can rely on
     204             :      * that information to be present (also prevents the variables to be
     205             :      * dangling references).
     206             :      */
     207           0 :     llvm_create_types();
     208             : }
     209             : 
     210             : 
     211             : /*
     212             :  * Create a context for JITing work.
     213             :  *
     214             :  * The context, including subsidiary resources, will be cleaned up either when
     215             :  * the context is explicitly released, or when the lifetime of
     216             :  * CurrentResourceOwner ends (usually the end of the current [sub]xact).
     217             :  */
     218             : LLVMJitContext *
     219        1216 : llvm_create_context(int jitFlags)
     220             : {
     221             :     LLVMJitContext *context;
     222             : 
     223        1216 :     llvm_assert_in_fatal_section();
     224             : 
     225        1216 :     llvm_session_initialize();
     226             : 
     227        1216 :     llvm_recreate_llvm_context();
     228             : 
     229        1216 :     ResourceOwnerEnlarge(CurrentResourceOwner);
     230             : 
     231        1216 :     context = MemoryContextAllocZero(TopMemoryContext,
     232             :                                      sizeof(LLVMJitContext));
     233        1216 :     context->base.flags = jitFlags;
     234             : 
     235             :     /* ensure cleanup */
     236        1216 :     context->resowner = CurrentResourceOwner;
     237        1216 :     ResourceOwnerRememberJIT(CurrentResourceOwner, context);
     238             : 
     239        1216 :     llvm_jit_context_in_use_count++;
     240             : 
     241        1216 :     return context;
     242             : }
     243             : 
     244             : /*
     245             :  * Release resources required by one llvm context.
     246             :  */
     247             : static void
     248        1216 : llvm_release_context(JitContext *context)
     249             : {
     250        1216 :     LLVMJitContext *llvm_jit_context = (LLVMJitContext *) context;
     251             :     ListCell   *lc;
     252             : 
     253             :     /*
     254             :      * Consider as cleaned up even if we skip doing so below, that way we can
     255             :      * verify the tracking is correct (see llvm_shutdown()).
     256             :      */
     257        1216 :     llvm_jit_context_in_use_count--;
     258             : 
     259             :     /*
     260             :      * When this backend is exiting, don't clean up LLVM. As an error might
     261             :      * have occurred from within LLVM, we do not want to risk reentering. All
     262             :      * resource cleanup is going to happen through process exit.
     263             :      */
     264        1216 :     if (proc_exit_inprogress)
     265           0 :         return;
     266             : 
     267        1216 :     llvm_enter_fatal_on_oom();
     268             : 
     269        1216 :     if (llvm_jit_context->module)
     270             :     {
     271         344 :         LLVMDisposeModule(llvm_jit_context->module);
     272         344 :         llvm_jit_context->module = NULL;
     273             :     }
     274             : 
     275        2166 :     foreach(lc, llvm_jit_context->handles)
     276             :     {
     277         950 :         LLVMJitHandle *jit_handle = (LLVMJitHandle *) lfirst(lc);
     278             : 
     279             :         {
     280             :             LLVMOrcExecutionSessionRef ee;
     281             :             LLVMOrcSymbolStringPoolRef sp;
     282             : 
     283         950 :             LLVMOrcResourceTrackerRemove(jit_handle->resource_tracker);
     284         950 :             LLVMOrcReleaseResourceTracker(jit_handle->resource_tracker);
     285             : 
     286             :             /*
     287             :              * Without triggering cleanup of the string pool, we'd leak
     288             :              * memory. It'd be sufficient to do this far less often, but in
     289             :              * experiments the required time was small enough to just always
     290             :              * do it.
     291             :              */
     292         950 :             ee = LLVMOrcLLJITGetExecutionSession(jit_handle->lljit);
     293         950 :             sp = LLVMOrcExecutionSessionGetSymbolStringPool(ee);
     294         950 :             LLVMOrcSymbolStringPoolClearDeadEntries(sp);
     295             :         }
     296             : 
     297         950 :         pfree(jit_handle);
     298             :     }
     299        1216 :     list_free(llvm_jit_context->handles);
     300        1216 :     llvm_jit_context->handles = NIL;
     301             : 
     302        1216 :     llvm_leave_fatal_on_oom();
     303             : 
     304        1216 :     if (llvm_jit_context->resowner)
     305        1200 :         ResourceOwnerForgetJIT(llvm_jit_context->resowner, llvm_jit_context);
     306             : }
     307             : 
     308             : /*
     309             :  * Return module which may be modified, e.g. by creating new functions.
     310             :  */
     311             : LLVMModuleRef
     312       14162 : llvm_mutable_module(LLVMJitContext *context)
     313             : {
     314       14162 :     llvm_assert_in_fatal_section();
     315             : 
     316             :     /*
     317             :      * If there's no in-progress module, create a new one.
     318             :      */
     319       14162 :     if (!context->module)
     320             :     {
     321        1294 :         context->compiled = false;
     322        1294 :         context->module_generation = llvm_generation++;
     323        1294 :         context->module = LLVMModuleCreateWithNameInContext("pg", llvm_context);
     324        1294 :         LLVMSetTarget(context->module, llvm_triple);
     325        1294 :         LLVMSetDataLayout(context->module, llvm_layout);
     326             :     }
     327             : 
     328       14162 :     return context->module;
     329             : }
     330             : 
     331             : /*
     332             :  * Expand function name to be non-conflicting. This should be used by code
     333             :  * generating code, when adding new externally visible function definitions to
     334             :  * a Module.
     335             :  */
     336             : char *
     337       14162 : llvm_expand_funcname(struct LLVMJitContext *context, const char *basename)
     338             : {
     339             :     Assert(context->module != NULL);
     340             : 
     341       14162 :     context->base.instr.created_functions++;
     342             : 
     343             :     /*
     344             :      * Previously we used dots to separate, but turns out some tools, e.g.
     345             :      * GDB, don't like that and truncate name.
     346             :      */
     347       28324 :     return psprintf("%s_%zu_%d",
     348             :                     basename,
     349             :                     context->module_generation,
     350       14162 :                     context->counter++);
     351             : }
     352             : 
     353             : /*
     354             :  * Return pointer to function funcname, which has to exist. If there's pending
     355             :  * code to be optimized and emitted, do so first.
     356             :  */
     357             : void *
     358        5182 : llvm_get_function(LLVMJitContext *context, const char *funcname)
     359             : {
     360             :     ListCell   *lc;
     361             : 
     362        5182 :     llvm_assert_in_fatal_section();
     363             : 
     364             :     /*
     365             :      * If there is a pending / not emitted module, compile and emit now.
     366             :      * Otherwise we might not find the [correct] function.
     367             :      */
     368        5182 :     if (!context->compiled)
     369             :     {
     370         950 :         llvm_compile_module(context);
     371             :     }
     372             : 
     373             :     /*
     374             :      * ORC's symbol table is of *unmangled* symbols. Therefore we don't need
     375             :      * to mangle here.
     376             :      */
     377             : 
     378        5182 :     foreach(lc, context->handles)
     379             :     {
     380        5182 :         LLVMJitHandle *handle = (LLVMJitHandle *) lfirst(lc);
     381             :         instr_time  starttime;
     382             :         instr_time  endtime;
     383             :         LLVMErrorRef error;
     384             :         LLVMOrcJITTargetAddress addr;
     385             : 
     386        5182 :         INSTR_TIME_SET_CURRENT(starttime);
     387             : 
     388        5182 :         addr = 0;
     389        5182 :         error = LLVMOrcLLJITLookup(handle->lljit, &addr, funcname);
     390        5182 :         if (error)
     391           0 :             elog(ERROR, "failed to look up symbol \"%s\": %s",
     392             :                  funcname, llvm_error_message(error));
     393             : 
     394             :         /*
     395             :          * LLJIT only actually emits code the first time a symbol is
     396             :          * referenced. Thus add lookup time to emission time. That's counting
     397             :          * a bit more than with older LLVM versions, but unlikely to ever
     398             :          * matter.
     399             :          */
     400        5182 :         INSTR_TIME_SET_CURRENT(endtime);
     401        5182 :         INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
     402             :                               endtime, starttime);
     403             : 
     404        5182 :         if (addr)
     405        5182 :             return (void *) (uintptr_t) addr;
     406             :     }
     407             : 
     408           0 :     elog(ERROR, "failed to JIT: %s", funcname);
     409             : 
     410             :     return NULL;
     411             : }
     412             : 
     413             : /*
     414             :  * Return type of a variable in llvmjit_types.c. This is useful to keep types
     415             :  * in sync between plain C and JIT related code.
     416             :  */
     417             : LLVMTypeRef
     418        9460 : llvm_pg_var_type(const char *varname)
     419             : {
     420             :     LLVMValueRef v_srcvar;
     421             :     LLVMTypeRef typ;
     422             : 
     423             :     /* this'll return a *pointer* to the global */
     424        9460 :     v_srcvar = LLVMGetNamedGlobal(llvm_types_module, varname);
     425        9460 :     if (!v_srcvar)
     426           0 :         elog(ERROR, "variable %s not in llvmjit_types.c", varname);
     427             : 
     428        9460 :     typ = LLVMGlobalGetValueType(v_srcvar);
     429             : 
     430        9460 :     return typ;
     431             : }
     432             : 
     433             : /*
     434             :  * Return function type of a variable in llvmjit_types.c. This is useful to
     435             :  * keep function types in sync between C and JITed code.
     436             :  */
     437             : LLVMTypeRef
     438       12032 : llvm_pg_var_func_type(const char *varname)
     439             : {
     440             :     LLVMValueRef v_srcvar;
     441             :     LLVMTypeRef typ;
     442             : 
     443       12032 :     v_srcvar = LLVMGetNamedFunction(llvm_types_module, varname);
     444       12032 :     if (!v_srcvar)
     445           0 :         elog(ERROR, "function %s not in llvmjit_types.c", varname);
     446             : 
     447       12032 :     typ = LLVMGetFunctionType(v_srcvar);
     448             : 
     449       12032 :     return typ;
     450             : }
     451             : 
     452             : /*
     453             :  * Return declaration for a function referenced in llvmjit_types.c, adding it
     454             :  * to the module if necessary.
     455             :  *
     456             :  * This is used to make functions discovered via llvm_create_types() known to
     457             :  * the module that's currently being worked on.
     458             :  */
     459             : LLVMValueRef
     460       12126 : llvm_pg_func(LLVMModuleRef mod, const char *funcname)
     461             : {
     462             :     LLVMValueRef v_srcfn;
     463             :     LLVMValueRef v_fn;
     464             : 
     465             :     /* don't repeatedly add function */
     466       12126 :     v_fn = LLVMGetNamedFunction(mod, funcname);
     467       12126 :     if (v_fn)
     468        8950 :         return v_fn;
     469             : 
     470        3176 :     v_srcfn = LLVMGetNamedFunction(llvm_types_module, funcname);
     471             : 
     472        3176 :     if (!v_srcfn)
     473           0 :         elog(ERROR, "function %s not in llvmjit_types.c", funcname);
     474             : 
     475        3176 :     v_fn = LLVMAddFunction(mod,
     476             :                            funcname,
     477             :                            LLVMGetFunctionType(v_srcfn));
     478        3176 :     llvm_copy_attributes(v_srcfn, v_fn);
     479             : 
     480        3176 :     return v_fn;
     481             : }
     482             : 
     483             : /*
     484             :  * Copy attributes from one function to another, for a specific index (an
     485             :  * index can reference return value, function and parameter attributes).
     486             :  */
     487             : static void
     488       48880 : llvm_copy_attributes_at_index(LLVMValueRef v_from, LLVMValueRef v_to, uint32 index)
     489             : {
     490             :     int         num_attributes;
     491             :     LLVMAttributeRef *attrs;
     492             : 
     493       48880 :     num_attributes = LLVMGetAttributeCountAtIndex(v_from, index);
     494             : 
     495       48880 :     if (num_attributes == 0)
     496       17320 :         return;
     497             : 
     498       31560 :     attrs = palloc(sizeof(LLVMAttributeRef) * num_attributes);
     499       31560 :     LLVMGetAttributesAtIndex(v_from, index, attrs);
     500             : 
     501      370310 :     for (int attno = 0; attno < num_attributes; attno++)
     502      338750 :         LLVMAddAttributeAtIndex(v_to, index, attrs[attno]);
     503             : 
     504       31560 :     pfree(attrs);
     505             : }
     506             : 
     507             : /*
     508             :  * Copy all attributes from one function to another. I.e. function, return and
     509             :  * parameters will be copied.
     510             :  */
     511             : void
     512       17338 : llvm_copy_attributes(LLVMValueRef v_from, LLVMValueRef v_to)
     513             : {
     514             :     uint32      param_count;
     515             : 
     516             :     /* copy function attributes */
     517       17338 :     llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeFunctionIndex);
     518             : 
     519       17338 :     if (LLVMGetTypeKind(LLVMGetFunctionReturnType(v_to)) != LLVMVoidTypeKind)
     520             :     {
     521             :         /* and the return value attributes */
     522        9272 :         llvm_copy_attributes_at_index(v_from, v_to, LLVMAttributeReturnIndex);
     523             :     }
     524             : 
     525             :     /* and each function parameter's attribute */
     526       17338 :     param_count = LLVMCountParams(v_from);
     527             : 
     528       39608 :     for (int paramidx = 1; paramidx <= param_count; paramidx++)
     529       22270 :         llvm_copy_attributes_at_index(v_from, v_to, paramidx);
     530       17338 : }
     531             : 
     532             : /*
     533             :  * Return a callable LLVMValueRef for fcinfo.
     534             :  */
     535             : LLVMValueRef
     536        6022 : llvm_function_reference(LLVMJitContext *context,
     537             :                         LLVMBuilderRef builder,
     538             :                         LLVMModuleRef mod,
     539             :                         FunctionCallInfo fcinfo)
     540             : {
     541             :     char       *modname;
     542             :     char       *basename;
     543             :     char       *funcname;
     544             : 
     545             :     LLVMValueRef v_fn;
     546             : 
     547        6022 :     fmgr_symbol(fcinfo->flinfo->fn_oid, &modname, &basename);
     548             : 
     549        6022 :     if (modname != NULL && basename != NULL)
     550             :     {
     551             :         /* external function in loadable library */
     552           0 :         funcname = psprintf("pgextern.%s.%s", modname, basename);
     553             :     }
     554        6022 :     else if (basename != NULL)
     555             :     {
     556             :         /* internal function */
     557        6010 :         funcname = pstrdup(basename);
     558             :     }
     559             :     else
     560             :     {
     561             :         /*
     562             :          * Function we don't know to handle, return pointer. We do so by
     563             :          * creating a global constant containing a pointer to the function.
     564             :          * Makes IR more readable.
     565             :          */
     566             :         LLVMValueRef v_fn_addr;
     567             : 
     568          12 :         funcname = psprintf("pgoidextern.%u",
     569          12 :                             fcinfo->flinfo->fn_oid);
     570          12 :         v_fn = LLVMGetNamedGlobal(mod, funcname);
     571          12 :         if (v_fn != 0)
     572           0 :             return l_load(builder, TypePGFunction, v_fn, "");
     573             : 
     574          12 :         v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction);
     575             : 
     576          12 :         v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname);
     577          12 :         LLVMSetInitializer(v_fn, v_fn_addr);
     578          12 :         LLVMSetGlobalConstant(v_fn, true);
     579          12 :         LLVMSetLinkage(v_fn, LLVMPrivateLinkage);
     580          12 :         LLVMSetUnnamedAddr(v_fn, true);
     581             : 
     582          12 :         return l_load(builder, TypePGFunction, v_fn, "");
     583             :     }
     584             : 
     585             :     /* check if function already has been added */
     586        6010 :     v_fn = LLVMGetNamedFunction(mod, funcname);
     587        6010 :     if (v_fn != 0)
     588        3090 :         return v_fn;
     589             : 
     590        2920 :     v_fn = LLVMAddFunction(mod, funcname, LLVMGetFunctionType(AttributeTemplate));
     591             : 
     592        2920 :     return v_fn;
     593             : }
     594             : 
     595             : /*
     596             :  * Optimize code in module using the flags set in context.
     597             :  */
     598             : static void
     599         950 : llvm_optimize_module(LLVMJitContext *context, LLVMModuleRef module)
     600             : {
     601             : #if LLVM_VERSION_MAJOR < 17
     602             :     LLVMPassManagerBuilderRef llvm_pmb;
     603             :     LLVMPassManagerRef llvm_mpm;
     604             :     LLVMPassManagerRef llvm_fpm;
     605             :     LLVMValueRef func;
     606             :     int         compile_optlevel;
     607             : 
     608         950 :     if (context->base.flags & PGJIT_OPT3)
     609         552 :         compile_optlevel = 3;
     610             :     else
     611         398 :         compile_optlevel = 0;
     612             : 
     613             :     /*
     614             :      * Have to create a new pass manager builder every pass through, as the
     615             :      * inliner has some per-builder state. Otherwise one ends up only inlining
     616             :      * a function the first time though.
     617             :      */
     618         950 :     llvm_pmb = LLVMPassManagerBuilderCreate();
     619         950 :     LLVMPassManagerBuilderSetOptLevel(llvm_pmb, compile_optlevel);
     620         950 :     llvm_fpm = LLVMCreateFunctionPassManagerForModule(module);
     621             : 
     622         950 :     if (context->base.flags & PGJIT_OPT3)
     623             :     {
     624             :         /* TODO: Unscientifically determined threshold */
     625         552 :         LLVMPassManagerBuilderUseInlinerWithThreshold(llvm_pmb, 512);
     626             :     }
     627             :     else
     628             :     {
     629             :         /* we rely on mem2reg heavily, so emit even in the O0 case */
     630         398 :         LLVMAddPromoteMemoryToRegisterPass(llvm_fpm);
     631             :     }
     632             : 
     633         950 :     LLVMPassManagerBuilderPopulateFunctionPassManager(llvm_pmb, llvm_fpm);
     634             : 
     635             :     /*
     636             :      * Do function level optimization. This could be moved to the point where
     637             :      * functions are emitted, to reduce memory usage a bit.
     638             :      */
     639         950 :     LLVMInitializeFunctionPassManager(llvm_fpm);
     640       23482 :     for (func = LLVMGetFirstFunction(context->module);
     641             :          func != NULL;
     642       22532 :          func = LLVMGetNextFunction(func))
     643       22532 :         LLVMRunFunctionPassManager(llvm_fpm, func);
     644         950 :     LLVMFinalizeFunctionPassManager(llvm_fpm);
     645         950 :     LLVMDisposePassManager(llvm_fpm);
     646             : 
     647             :     /*
     648             :      * Perform module level optimization. We do so even in the non-optimized
     649             :      * case, so always-inline functions etc get inlined. It's cheap enough.
     650             :      */
     651         950 :     llvm_mpm = LLVMCreatePassManager();
     652         950 :     LLVMPassManagerBuilderPopulateModulePassManager(llvm_pmb,
     653             :                                                     llvm_mpm);
     654             :     /* always use always-inliner pass */
     655         950 :     if (!(context->base.flags & PGJIT_OPT3))
     656         398 :         LLVMAddAlwaysInlinerPass(llvm_mpm);
     657             :     /* if doing inlining, but no expensive optimization, add inlining pass */
     658         950 :     if (context->base.flags & PGJIT_INLINE
     659         552 :         && !(context->base.flags & PGJIT_OPT3))
     660           0 :         LLVMAddFunctionInliningPass(llvm_mpm);
     661         950 :     LLVMRunPassManager(llvm_mpm, context->module);
     662         950 :     LLVMDisposePassManager(llvm_mpm);
     663             : 
     664         950 :     LLVMPassManagerBuilderDispose(llvm_pmb);
     665             : #else
     666             :     LLVMPassBuilderOptionsRef options;
     667             :     LLVMErrorRef err;
     668             :     const char *passes;
     669             : 
     670             :     if (context->base.flags & PGJIT_OPT3)
     671             :         passes = "default<O3>";
     672             :     else
     673             :         passes = "default<O0>,mem2reg";
     674             : 
     675             :     options = LLVMCreatePassBuilderOptions();
     676             : 
     677             : #ifdef LLVM_PASS_DEBUG
     678             :     LLVMPassBuilderOptionsSetDebugLogging(options, 1);
     679             : #endif
     680             : 
     681             :     /* In assertion builds, run the LLVM verify pass. */
     682             : #ifdef USE_ASSERT_CHECKING
     683             :     LLVMPassBuilderOptionsSetVerifyEach(options, true);
     684             : #endif
     685             : 
     686             :     LLVMPassBuilderOptionsSetInlinerThreshold(options, 512);
     687             : 
     688             :     err = LLVMRunPasses(module, passes, NULL, options);
     689             : 
     690             :     if (err)
     691             :         elog(ERROR, "failed to JIT module: %s", llvm_error_message(err));
     692             : 
     693             :     LLVMDisposePassBuilderOptions(options);
     694             : #endif
     695         950 : }
     696             : 
     697             : /*
     698             :  * Emit code for the currently pending module.
     699             :  */
     700             : static void
     701         950 : llvm_compile_module(LLVMJitContext *context)
     702             : {
     703             :     LLVMJitHandle *handle;
     704             :     MemoryContext oldcontext;
     705             :     instr_time  starttime;
     706             :     instr_time  endtime;
     707             :     LLVMOrcLLJITRef compile_orc;
     708             : 
     709         950 :     if (context->base.flags & PGJIT_OPT3)
     710         552 :         compile_orc = llvm_opt3_orc;
     711             :     else
     712         398 :         compile_orc = llvm_opt0_orc;
     713             : 
     714             :     /* perform inlining */
     715         950 :     if (context->base.flags & PGJIT_INLINE)
     716             :     {
     717         552 :         INSTR_TIME_SET_CURRENT(starttime);
     718         552 :         llvm_inline(context->module);
     719         552 :         INSTR_TIME_SET_CURRENT(endtime);
     720         552 :         INSTR_TIME_ACCUM_DIFF(context->base.instr.inlining_counter,
     721             :                               endtime, starttime);
     722             :     }
     723             : 
     724         950 :     if (jit_dump_bitcode)
     725             :     {
     726             :         char       *filename;
     727             : 
     728           0 :         filename = psprintf("%d.%zu.bc",
     729             :                             MyProcPid,
     730             :                             context->module_generation);
     731           0 :         LLVMWriteBitcodeToFile(context->module, filename);
     732           0 :         pfree(filename);
     733             :     }
     734             : 
     735             : 
     736             :     /* optimize according to the chosen optimization settings */
     737         950 :     INSTR_TIME_SET_CURRENT(starttime);
     738         950 :     llvm_optimize_module(context, context->module);
     739         950 :     INSTR_TIME_SET_CURRENT(endtime);
     740         950 :     INSTR_TIME_ACCUM_DIFF(context->base.instr.optimization_counter,
     741             :                           endtime, starttime);
     742             : 
     743         950 :     if (jit_dump_bitcode)
     744             :     {
     745             :         char       *filename;
     746             : 
     747           0 :         filename = psprintf("%d.%zu.optimized.bc",
     748             :                             MyProcPid,
     749             :                             context->module_generation);
     750           0 :         LLVMWriteBitcodeToFile(context->module, filename);
     751           0 :         pfree(filename);
     752             :     }
     753             : 
     754             :     handle = (LLVMJitHandle *)
     755         950 :         MemoryContextAlloc(TopMemoryContext, sizeof(LLVMJitHandle));
     756             : 
     757             :     /*
     758             :      * Emit the code. Note that this can, depending on the optimization
     759             :      * settings, take noticeable resources as code emission executes low-level
     760             :      * instruction combining/selection passes etc. Without optimization a
     761             :      * faster instruction selection mechanism is used.
     762             :      */
     763         950 :     INSTR_TIME_SET_CURRENT(starttime);
     764             :     {
     765             :         LLVMOrcThreadSafeModuleRef ts_module;
     766             :         LLVMErrorRef error;
     767         950 :         LLVMOrcJITDylibRef jd = LLVMOrcLLJITGetMainJITDylib(compile_orc);
     768             : 
     769         950 :         ts_module = LLVMOrcCreateNewThreadSafeModule(context->module, llvm_ts_context);
     770             : 
     771         950 :         handle->lljit = compile_orc;
     772         950 :         handle->resource_tracker = LLVMOrcJITDylibCreateResourceTracker(jd);
     773             : 
     774             :         /*
     775             :          * NB: This doesn't actually emit code. That happens lazily the first
     776             :          * time a symbol defined in the module is requested. Due to that
     777             :          * llvm_get_function() also accounts for emission time.
     778             :          */
     779             : 
     780         950 :         context->module = NULL; /* will be owned by LLJIT */
     781         950 :         error = LLVMOrcLLJITAddLLVMIRModuleWithRT(compile_orc,
     782             :                                                   handle->resource_tracker,
     783             :                                                   ts_module);
     784             : 
     785         950 :         if (error)
     786           0 :             elog(ERROR, "failed to JIT module: %s",
     787             :                  llvm_error_message(error));
     788             : 
     789             :         /* LLVMOrcLLJITAddLLVMIRModuleWithRT takes ownership of the module */
     790             :     }
     791             : 
     792         950 :     INSTR_TIME_SET_CURRENT(endtime);
     793         950 :     INSTR_TIME_ACCUM_DIFF(context->base.instr.emission_counter,
     794             :                           endtime, starttime);
     795             : 
     796         950 :     context->module = NULL;
     797         950 :     context->compiled = true;
     798             : 
     799             :     /* remember emitted code for cleanup and lookups */
     800         950 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
     801         950 :     context->handles = lappend(context->handles, handle);
     802         950 :     MemoryContextSwitchTo(oldcontext);
     803             : 
     804         950 :     ereport(DEBUG1,
     805             :             (errmsg_internal("time to inline: %.3fs, opt: %.3fs, emit: %.3fs",
     806             :                              INSTR_TIME_GET_DOUBLE(context->base.instr.inlining_counter),
     807             :                              INSTR_TIME_GET_DOUBLE(context->base.instr.optimization_counter),
     808             :                              INSTR_TIME_GET_DOUBLE(context->base.instr.emission_counter)),
     809             :              errhidestmt(true),
     810             :              errhidecontext(true)));
     811         950 : }
     812             : 
     813             : /*
     814             :  * Per session initialization.
     815             :  */
     816             : static void
     817        1216 : llvm_session_initialize(void)
     818             : {
     819             :     MemoryContext oldcontext;
     820        1216 :     char       *error = NULL;
     821        1216 :     char       *cpu = NULL;
     822        1216 :     char       *features = NULL;
     823             :     LLVMTargetMachineRef opt0_tm;
     824             :     LLVMTargetMachineRef opt3_tm;
     825             : 
     826        1216 :     if (llvm_session_initialized)
     827         746 :         return;
     828             : 
     829         470 :     oldcontext = MemoryContextSwitchTo(TopMemoryContext);
     830             : 
     831         470 :     LLVMInitializeNativeTarget();
     832         470 :     LLVMInitializeNativeAsmPrinter();
     833         470 :     LLVMInitializeNativeAsmParser();
     834             : 
     835         470 :     if (llvm_context == NULL)
     836             :     {
     837         470 :         llvm_context = LLVMContextCreate();
     838             : 
     839         470 :         llvm_jit_context_in_use_count = 0;
     840         470 :         llvm_llvm_context_reuse_count = 0;
     841             :     }
     842             : 
     843             :     /*
     844             :      * Synchronize types early, as that also includes inferring the target
     845             :      * triple.
     846             :      */
     847         470 :     llvm_create_types();
     848             : 
     849             :     /*
     850             :      * Extract target information from loaded module.
     851             :      */
     852         470 :     llvm_set_target();
     853             : 
     854         470 :     if (LLVMGetTargetFromTriple(llvm_triple, &llvm_targetref, &error) != 0)
     855             :     {
     856           0 :         elog(FATAL, "failed to query triple %s", error);
     857             :     }
     858             : 
     859             :     /*
     860             :      * We want the generated code to use all available features. Therefore
     861             :      * grab the host CPU string and detect features of the current CPU. The
     862             :      * latter is needed because some CPU architectures default to enabling
     863             :      * features not all CPUs have (weird, huh).
     864             :      */
     865         470 :     cpu = LLVMGetHostCPUName();
     866         470 :     features = LLVMGetHostCPUFeatures();
     867         470 :     elog(DEBUG2, "LLVMJIT detected CPU \"%s\", with features \"%s\"",
     868             :          cpu, features);
     869             : 
     870             :     opt0_tm =
     871         470 :         LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
     872             :                                 LLVMCodeGenLevelNone,
     873             :                                 LLVMRelocDefault,
     874             :                                 LLVMCodeModelJITDefault);
     875             :     opt3_tm =
     876         470 :         LLVMCreateTargetMachine(llvm_targetref, llvm_triple, cpu, features,
     877             :                                 LLVMCodeGenLevelAggressive,
     878             :                                 LLVMRelocDefault,
     879             :                                 LLVMCodeModelJITDefault);
     880             : 
     881         470 :     LLVMDisposeMessage(cpu);
     882         470 :     cpu = NULL;
     883         470 :     LLVMDisposeMessage(features);
     884         470 :     features = NULL;
     885             : 
     886             :     /* force symbols in main binary to be loaded */
     887         470 :     LLVMLoadLibraryPermanently(NULL);
     888             : 
     889             :     {
     890         470 :         llvm_ts_context = LLVMOrcCreateNewThreadSafeContext();
     891             : 
     892         470 :         llvm_opt0_orc = llvm_create_jit_instance(opt0_tm);
     893         470 :         opt0_tm = 0;
     894             : 
     895         470 :         llvm_opt3_orc = llvm_create_jit_instance(opt3_tm);
     896         470 :         opt3_tm = 0;
     897             :     }
     898             : 
     899         470 :     on_proc_exit(llvm_shutdown, 0);
     900             : 
     901         470 :     llvm_session_initialized = true;
     902             : 
     903         470 :     MemoryContextSwitchTo(oldcontext);
     904             : }
     905             : 
     906             : static void
     907         470 : llvm_shutdown(int code, Datum arg)
     908             : {
     909             :     /*
     910             :      * If llvm_shutdown() is reached while in a fatal-on-oom section an error
     911             :      * has occurred in the middle of LLVM code. It is not safe to call back
     912             :      * into LLVM (which is why a FATAL error was thrown).
     913             :      *
     914             :      * We do need to shutdown LLVM in other shutdown cases, otherwise e.g.
     915             :      * profiling data won't be written out.
     916             :      */
     917         470 :     if (llvm_in_fatal_on_oom())
     918             :     {
     919             :         Assert(proc_exit_inprogress);
     920           0 :         return;
     921             :     }
     922             : 
     923         470 :     if (llvm_jit_context_in_use_count != 0)
     924           0 :         elog(PANIC, "LLVMJitContext in use count not 0 at exit (is %zu)",
     925             :              llvm_jit_context_in_use_count);
     926             : 
     927             :     {
     928         470 :         if (llvm_opt3_orc)
     929             :         {
     930         470 :             LLVMOrcDisposeLLJIT(llvm_opt3_orc);
     931         470 :             llvm_opt3_orc = NULL;
     932             :         }
     933         470 :         if (llvm_opt0_orc)
     934             :         {
     935         470 :             LLVMOrcDisposeLLJIT(llvm_opt0_orc);
     936         470 :             llvm_opt0_orc = NULL;
     937             :         }
     938         470 :         if (llvm_ts_context)
     939             :         {
     940         470 :             LLVMOrcDisposeThreadSafeContext(llvm_ts_context);
     941         470 :             llvm_ts_context = NULL;
     942             :         }
     943             :     }
     944             : }
     945             : 
     946             : /* helper for llvm_create_types, returning a function's return type */
     947             : static LLVMTypeRef
     948         470 : load_return_type(LLVMModuleRef mod, const char *name)
     949             : {
     950             :     LLVMValueRef value;
     951             :     LLVMTypeRef typ;
     952             : 
     953             :     /* this'll return a *pointer* to the function */
     954         470 :     value = LLVMGetNamedFunction(mod, name);
     955         470 :     if (!value)
     956           0 :         elog(ERROR, "function %s is unknown", name);
     957             : 
     958         470 :     typ = LLVMGetFunctionReturnType(value); /* in llvmjit_wrap.cpp */
     959             : 
     960         470 :     return typ;
     961             : }
     962             : 
     963             : /*
     964             :  * Load triple & layout from clang emitted file so we're guaranteed to be
     965             :  * compatible.
     966             :  */
     967             : static void
     968         470 : llvm_set_target(void)
     969             : {
     970         470 :     if (!llvm_types_module)
     971           0 :         elog(ERROR, "failed to extract target information, llvmjit_types.c not loaded");
     972             : 
     973         470 :     if (llvm_triple == NULL)
     974         470 :         llvm_triple = pstrdup(LLVMGetTarget(llvm_types_module));
     975             : 
     976         470 :     if (llvm_layout == NULL)
     977         470 :         llvm_layout = pstrdup(LLVMGetDataLayoutStr(llvm_types_module));
     978         470 : }
     979             : 
     980             : /*
     981             :  * Load required information, types, function signatures from llvmjit_types.c
     982             :  * and make them available in global variables.
     983             :  *
     984             :  * Those global variables are then used while emitting code.
     985             :  */
     986             : static void
     987         470 : llvm_create_types(void)
     988             : {
     989             :     char        path[MAXPGPATH];
     990             :     LLVMMemoryBufferRef buf;
     991             :     char       *msg;
     992             : 
     993         470 :     snprintf(path, MAXPGPATH, "%s/%s", pkglib_path, "llvmjit_types.bc");
     994             : 
     995             :     /* open file */
     996         470 :     if (LLVMCreateMemoryBufferWithContentsOfFile(path, &buf, &msg))
     997             :     {
     998           0 :         elog(ERROR, "LLVMCreateMemoryBufferWithContentsOfFile(%s) failed: %s",
     999             :              path, msg);
    1000             :     }
    1001             : 
    1002             :     /* eagerly load contents, going to need it all */
    1003         470 :     if (LLVMParseBitcodeInContext2(llvm_context, buf, &llvm_types_module))
    1004             :     {
    1005           0 :         elog(ERROR, "LLVMParseBitcodeInContext2 of %s failed", path);
    1006             :     }
    1007         470 :     LLVMDisposeMemoryBuffer(buf);
    1008             : 
    1009         470 :     TypeSizeT = llvm_pg_var_type("TypeSizeT");
    1010         470 :     TypeParamBool = load_return_type(llvm_types_module, "FunctionReturningBool");
    1011         470 :     TypeStorageBool = llvm_pg_var_type("TypeStorageBool");
    1012         470 :     TypePGFunction = llvm_pg_var_type("TypePGFunction");
    1013         470 :     StructNullableDatum = llvm_pg_var_type("StructNullableDatum");
    1014         470 :     StructExprContext = llvm_pg_var_type("StructExprContext");
    1015         470 :     StructExprEvalStep = llvm_pg_var_type("StructExprEvalStep");
    1016         470 :     StructExprState = llvm_pg_var_type("StructExprState");
    1017         470 :     StructFunctionCallInfoData = llvm_pg_var_type("StructFunctionCallInfoData");
    1018         470 :     StructMemoryContextData = llvm_pg_var_type("StructMemoryContextData");
    1019         470 :     StructTupleTableSlot = llvm_pg_var_type("StructTupleTableSlot");
    1020         470 :     StructHeapTupleTableSlot = llvm_pg_var_type("StructHeapTupleTableSlot");
    1021         470 :     StructMinimalTupleTableSlot = llvm_pg_var_type("StructMinimalTupleTableSlot");
    1022         470 :     StructHeapTupleData = llvm_pg_var_type("StructHeapTupleData");
    1023         470 :     StructHeapTupleHeaderData = llvm_pg_var_type("StructHeapTupleHeaderData");
    1024         470 :     StructTupleDescData = llvm_pg_var_type("StructTupleDescData");
    1025         470 :     StructAggState = llvm_pg_var_type("StructAggState");
    1026         470 :     StructAggStatePerGroupData = llvm_pg_var_type("StructAggStatePerGroupData");
    1027         470 :     StructAggStatePerTransData = llvm_pg_var_type("StructAggStatePerTransData");
    1028         470 :     StructPlanState = llvm_pg_var_type("StructPlanState");
    1029         470 :     StructMinimalTupleData = llvm_pg_var_type("StructMinimalTupleData");
    1030             : 
    1031         470 :     AttributeTemplate = LLVMGetNamedFunction(llvm_types_module, "AttributeTemplate");
    1032         470 :     ExecEvalSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalSubroutineTemplate");
    1033         470 :     ExecEvalBoolSubroutineTemplate = LLVMGetNamedFunction(llvm_types_module, "ExecEvalBoolSubroutineTemplate");
    1034         470 : }
    1035             : 
    1036             : /*
    1037             :  * Split a symbol into module / function parts.  If the function is in the
    1038             :  * main binary (or an external library) *modname will be NULL.
    1039             :  */
    1040             : void
    1041       17938 : llvm_split_symbol_name(const char *name, char **modname, char **funcname)
    1042             : {
    1043       17938 :     *modname = NULL;
    1044       17938 :     *funcname = NULL;
    1045             : 
    1046             :     /*
    1047             :      * Module function names are pgextern.$module.$funcname
    1048             :      */
    1049       17938 :     if (strncmp(name, "pgextern.", strlen("pgextern.")) == 0)
    1050             :     {
    1051             :         /*
    1052             :          * Symbol names cannot contain a ., therefore we can split based on
    1053             :          * first and last occurrence of one.
    1054             :          */
    1055           0 :         *funcname = rindex(name, '.');
    1056           0 :         (*funcname)++;          /* jump over . */
    1057             : 
    1058           0 :         *modname = pnstrdup(name + strlen("pgextern."),
    1059           0 :                             *funcname - name - strlen("pgextern.") - 1);
    1060             :         Assert(funcname);
    1061             : 
    1062           0 :         *funcname = pstrdup(*funcname);
    1063             :     }
    1064             :     else
    1065             :     {
    1066       17938 :         *modname = NULL;
    1067       17938 :         *funcname = pstrdup(name);
    1068             :     }
    1069       17938 : }
    1070             : 
    1071             : /*
    1072             :  * Attempt to resolve symbol, so LLVM can emit a reference to it.
    1073             :  */
    1074             : static uint64_t
    1075           0 : llvm_resolve_symbol(const char *symname, void *ctx)
    1076             : {
    1077             :     uintptr_t   addr;
    1078             :     char       *funcname;
    1079             :     char       *modname;
    1080             : 
    1081             :     /*
    1082             :      * macOS prefixes all object level symbols with an underscore. But neither
    1083             :      * dlsym() nor PG's inliner expect that. So undo.
    1084             :      */
    1085             : #if defined(__darwin__)
    1086             :     if (symname[0] != '_')
    1087             :         elog(ERROR, "expected prefixed symbol name, but got \"%s\"", symname);
    1088             :     symname++;
    1089             : #endif
    1090             : 
    1091           0 :     llvm_split_symbol_name(symname, &modname, &funcname);
    1092             : 
    1093             :     /* functions that aren't resolved to names shouldn't ever get here */
    1094             :     Assert(funcname);
    1095             : 
    1096           0 :     if (modname)
    1097           0 :         addr = (uintptr_t) load_external_function(modname, funcname,
    1098             :                                                   true, NULL);
    1099             :     else
    1100           0 :         addr = (uintptr_t) LLVMSearchForAddressOfSymbol(symname);
    1101             : 
    1102           0 :     pfree(funcname);
    1103           0 :     if (modname)
    1104           0 :         pfree(modname);
    1105             : 
    1106             :     /* let LLVM will error out - should never happen */
    1107           0 :     if (!addr)
    1108           0 :         elog(WARNING, "failed to resolve name %s", symname);
    1109             : 
    1110           0 :     return (uint64_t) addr;
    1111             : }
    1112             : 
    1113             : static LLVMErrorRef
    1114           0 : llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx,
    1115             :                      LLVMOrcLookupStateRef *LookupState, LLVMOrcLookupKind Kind,
    1116             :                      LLVMOrcJITDylibRef JD, LLVMOrcJITDylibLookupFlags JDLookupFlags,
    1117             :                      LLVMOrcCLookupSet LookupSet, size_t LookupSetSize)
    1118             : {
    1119             : #if LLVM_VERSION_MAJOR > 14
    1120           0 :     LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMOrcCSymbolMapPair) * LookupSetSize);
    1121             : #else
    1122             :     LLVMOrcCSymbolMapPairs symbols = palloc0(sizeof(LLVMJITCSymbolMapPair) * LookupSetSize);
    1123             : #endif
    1124             :     LLVMErrorRef error;
    1125             :     LLVMOrcMaterializationUnitRef mu;
    1126             : 
    1127           0 :     for (int i = 0; i < LookupSetSize; i++)
    1128             :     {
    1129           0 :         const char *name = LLVMOrcSymbolStringPoolEntryStr(LookupSet[i].Name);
    1130             : 
    1131           0 :         LLVMOrcRetainSymbolStringPoolEntry(LookupSet[i].Name);
    1132           0 :         symbols[i].Name = LookupSet[i].Name;
    1133           0 :         symbols[i].Sym.Address = llvm_resolve_symbol(name, NULL);
    1134           0 :         symbols[i].Sym.Flags.GenericFlags = LLVMJITSymbolGenericFlagsExported;
    1135             :     }
    1136             : 
    1137           0 :     mu = LLVMOrcAbsoluteSymbols(symbols, LookupSetSize);
    1138           0 :     error = LLVMOrcJITDylibDefine(JD, mu);
    1139           0 :     if (error != LLVMErrorSuccess)
    1140           0 :         LLVMOrcDisposeMaterializationUnit(mu);
    1141             : 
    1142           0 :     pfree(symbols);
    1143             : 
    1144           0 :     return error;
    1145             : }
    1146             : 
    1147             : /*
    1148             :  * We cannot throw errors through LLVM (without causing a FATAL at least), so
    1149             :  * just use WARNING here. That's OK anyway, as the error is also reported at
    1150             :  * the top level action (with less detail) and there might be multiple
    1151             :  * invocations of errors with details.
    1152             :  *
    1153             :  * This doesn't really happen during normal operation, but in cases like
    1154             :  * symbol resolution breakage. So just using elog(WARNING) is fine.
    1155             :  */
    1156             : static void
    1157           0 : llvm_log_jit_error(void *ctx, LLVMErrorRef error)
    1158             : {
    1159           0 :     elog(WARNING, "error during JITing: %s",
    1160             :          llvm_error_message(error));
    1161           0 : }
    1162             : 
    1163             : /*
    1164             :  * Create our own object layer, so we can add event listeners.
    1165             :  */
    1166             : static LLVMOrcObjectLayerRef
    1167         940 : llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
    1168             : {
    1169             :     LLVMOrcObjectLayerRef objlayer =
    1170         940 :         LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
    1171             : 
    1172             : #if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
    1173         940 :     if (jit_debugging_support)
    1174             :     {
    1175           0 :         LLVMJITEventListenerRef l = LLVMCreateGDBRegistrationListener();
    1176             : 
    1177           0 :         LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
    1178             :     }
    1179             : #endif
    1180             : 
    1181             : #if defined(HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER) && HAVE_DECL_LLVMCREATEPERFJITEVENTLISTENER
    1182         940 :     if (jit_profiling_support)
    1183             :     {
    1184           0 :         LLVMJITEventListenerRef l = LLVMCreatePerfJITEventListener();
    1185             : 
    1186           0 :         LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
    1187             :     }
    1188             : #endif
    1189             : 
    1190         940 :     return objlayer;
    1191             : }
    1192             : 
    1193             : /*
    1194             :  * Create LLJIT instance, using the passed in target machine. Note that the
    1195             :  * target machine afterwards is owned by the LLJIT instance.
    1196             :  */
    1197             : static LLVMOrcLLJITRef
    1198         940 : llvm_create_jit_instance(LLVMTargetMachineRef tm)
    1199             : {
    1200             :     LLVMOrcLLJITRef lljit;
    1201             :     LLVMOrcJITTargetMachineBuilderRef tm_builder;
    1202             :     LLVMOrcLLJITBuilderRef lljit_builder;
    1203             :     LLVMErrorRef error;
    1204             :     LLVMOrcDefinitionGeneratorRef main_gen;
    1205             :     LLVMOrcDefinitionGeneratorRef ref_gen;
    1206             : 
    1207         940 :     lljit_builder = LLVMOrcCreateLLJITBuilder();
    1208         940 :     tm_builder = LLVMOrcJITTargetMachineBuilderCreateFromTargetMachine(tm);
    1209         940 :     LLVMOrcLLJITBuilderSetJITTargetMachineBuilder(lljit_builder, tm_builder);
    1210             : 
    1211         940 :     LLVMOrcLLJITBuilderSetObjectLinkingLayerCreator(lljit_builder,
    1212             :                                                     llvm_create_object_layer,
    1213             :                                                     NULL);
    1214             : 
    1215         940 :     error = LLVMOrcCreateLLJIT(&lljit, lljit_builder);
    1216         940 :     if (error)
    1217           0 :         elog(ERROR, "failed to create lljit instance: %s",
    1218             :              llvm_error_message(error));
    1219             : 
    1220         940 :     LLVMOrcExecutionSessionSetErrorReporter(LLVMOrcLLJITGetExecutionSession(lljit),
    1221             :                                             llvm_log_jit_error, NULL);
    1222             : 
    1223             :     /*
    1224             :      * Symbol resolution support for symbols in the postgres binary /
    1225             :      * libraries already loaded.
    1226             :      */
    1227         940 :     error = LLVMOrcCreateDynamicLibrarySearchGeneratorForProcess(&main_gen,
    1228         940 :                                                                  LLVMOrcLLJITGetGlobalPrefix(lljit),
    1229             :                                                                  0, NULL);
    1230         940 :     if (error)
    1231           0 :         elog(ERROR, "failed to create generator: %s",
    1232             :              llvm_error_message(error));
    1233         940 :     LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), main_gen);
    1234             : 
    1235             :     /*
    1236             :      * Symbol resolution support for "special" functions, e.g. a call into an
    1237             :      * SQL callable function.
    1238             :      */
    1239             : #if LLVM_VERSION_MAJOR > 14
    1240         940 :     ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL, NULL);
    1241             : #else
    1242             :     ref_gen = LLVMOrcCreateCustomCAPIDefinitionGenerator(llvm_resolve_symbols, NULL);
    1243             : #endif
    1244         940 :     LLVMOrcJITDylibAddGenerator(LLVMOrcLLJITGetMainJITDylib(lljit), ref_gen);
    1245             : 
    1246         940 :     return lljit;
    1247             : }
    1248             : 
    1249             : static char *
    1250           0 : llvm_error_message(LLVMErrorRef error)
    1251             : {
    1252           0 :     char       *orig = LLVMGetErrorMessage(error);
    1253           0 :     char       *msg = pstrdup(orig);
    1254             : 
    1255           0 :     LLVMDisposeErrorMessage(orig);
    1256             : 
    1257           0 :     return msg;
    1258             : }
    1259             : 
    1260             : /*
    1261             :  * ResourceOwner callbacks
    1262             :  */
    1263             : static void
    1264          16 : ResOwnerReleaseJitContext(Datum res)
    1265             : {
    1266          16 :     LLVMJitContext *context = (LLVMJitContext *) DatumGetPointer(res);
    1267             : 
    1268          16 :     context->resowner = NULL;
    1269          16 :     jit_release_context(&context->base);
    1270          16 : }

Generated by: LCOV version 1.14