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