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