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