LLVM JITLink attempt II (WIP)
Hi,
Here's a short unfinished but semi-working patch to try out JITLink
instead of RuntimeDyld, since Greg expressed an interest in it. I'm
not actively working on this myself right now, but in case it helps, I
think the main things to do next are probably: try out the recently
added debugger and perf plugins (I hope these are the equivalents of
the JITEventListener stuff we use), figure out how and when we can
actually cut over, tidy/refactor and possibly consider upstreaming
some C wrappers if we want to minimise the C++ glue we carry. See
patch for a few more details.
While rebasing, I made it use JITLink for LLVM >= 19, but that's
arbitrary. Tested on FreeBSD/amd64 + LLVM 19, 20, 21. I haven't
tried other architectures or 32 bit, and support is clearly moving at
very different speeds with 32 bit support far behind. There is a
published table[1]https://llvm.org/docs/JITLink.html (bottom of page), but it may already be out of date and doesn't talk
about releases. Ideally I guess we'd put this change off as long as
possible and then cut over everywhere with a simple version threshold
just as RuntimeDyld is finally removed (which hopefully requires full
feature parity to happen first!), but the reality might be messier:
RISC-V doesn't work with RuntimeDyld[2]/messages/by-id/20220829074622.2474104-1-alex.fan.q@gmail.com and it's reasonable to want
that to work sooner, and it might also be nice to drop the ugly ARM
workaround from commit 9044fc1d as soon as LLVM < 15 falls off our
radar.
With LLVM 22 (bleeding edge main branch) it builds and runs simple
things, but I get a SIGBUS crash in the regression tests even on
unpatched master, something to look into separately...
[1]: https://llvm.org/docs/JITLink.html (bottom of page)
[2]: /messages/by-id/20220829074622.2474104-1-alex.fan.q@gmail.com
Attachments:
v1-0001-jit-Add-optional-LLVM-JITLink-support.patchapplication/octet-stream; name=v1-0001-jit-Add-optional-LLVM-JITLink-support.patchDownload
From 24d375900604935867b0e538a48299dedaace92a Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 10 Oct 2024 13:31:56 +1300
Subject: [PATCH v1] jit: Add optional LLVM JITLink support.
LLVM's JITLink API is replacing RuntimeDyld, and the latter will
eventually be deprecated and disappear. Support currently varies by
architecture/platform and LLVM version. In the case of RISC-V, only
JITLink works, while in some other cases especially in older LLVM
versions, only RuntimeDyld seems to be mature enough.
XXX WIP -- see comments
---
src/backend/jit/llvm/llvmjit.c | 25 ++++++++++++++++-----
src/backend/jit/llvm/llvmjit_wrap.cpp | 31 +++++++++++++++++++++++++--
src/include/jit/llvmjit.h | 5 ++++-
src/include/jit/llvmjit_backport.h | 10 +++++++++
4 files changed, 63 insertions(+), 8 deletions(-)
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index e978b996bae..d87e16f9a0c 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -1172,15 +1172,29 @@ llvm_log_jit_error(void *ctx, LLVMErrorRef error)
static LLVMOrcObjectLayerRef
llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
{
-#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
- LLVMOrcObjectLayerRef objlayer =
- LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
+ LLVMOrcObjectLayerRef objlayer;
+
+#if defined(USE_LLVM_JITLINK)
+ objlayer = LLVMOrcCreateJITLinkObjectLinkingLayer(ES);
+#elif defined(USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER)
+ objlayer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
#else
- LLVMOrcObjectLayerRef objlayer =
- LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
+ objlayer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
#endif
+ /*
+ * XXX The JITLink equivalents of the following seem to be:
+ *
+ * llvm::orc::PerfSupportPlugin
+ * llvm::orc::DebuggerSupportPlugin
+ *
+ * At least the first arrived in LLVM 18? Need to decide how to access
+ * those, either from C like below, or just shove it inot the C++ wrapper
+ * function, and check if they are feature-equivalent and
+ * portability-equivalent.
+ */
+#if !defined(USE_LLVM_JITLINK)
#if defined(HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER) && HAVE_DECL_LLVMCREATEGDBREGISTRATIONLISTENER
if (jit_debugging_support)
{
@@ -1197,6 +1211,7 @@ llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *T
LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
}
+#endif
#endif
return objlayer;
diff --git a/src/backend/jit/llvm/llvmjit_wrap.cpp b/src/backend/jit/llvm/llvmjit_wrap.cpp
index da850d67ab6..ecb97a14944 100644
--- a/src/backend/jit/llvm/llvmjit_wrap.cpp
+++ b/src/backend/jit/llvm/llvmjit_wrap.cpp
@@ -22,6 +22,10 @@ extern "C"
#include "jit/llvmjit.h"
#include "jit/llvmjit_backport.h"
+#ifdef USE_LLVM_JITLINK
+#include <llvm/ExecutionEngine/Orc/ObjectLinkingLayer.h>
+#endif
+
#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
#include <llvm/ExecutionEngine/SectionMemoryManager.h>
@@ -46,14 +50,37 @@ LLVMGetFunctionType(LLVMValueRef r)
return llvm::wrap(llvm::unwrap<llvm::Function>(r)->getFunctionType());
}
-#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
+#if defined(USE_LLVM_JITLINK) || defined(USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER)
DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::orc::ExecutionSession, LLVMOrcExecutionSessionRef)
-DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::orc::ObjectLayer, LLVMOrcObjectLayerRef);
+DEFINE_SIMPLE_CONVERSION_FUNCTIONS(llvm::orc::ObjectLayer, LLVMOrcObjectLayerRef)
+#endif
+
+#if defined(USE_LLVM_JITLINK)
+LLVMOrcObjectLayerRef
+LLVMOrcCreateJITLinkObjectLinkingLayer(LLVMOrcExecutionSessionRef ES)
+{
+ auto expected_mm = llvm::jitlink::InProcessMemoryManager::Create();
+
+ /* XXX how should this error be reported? */
+ if (!expected_mm)
+ elog(ERROR,
+ "could not create JITLink memory manager: %s",
+ llvm::toString(expected_mm.takeError()).c_str());
+
+ return wrap(new llvm::orc::ObjectLinkingLayer(*unwrap(ES), std::move(*expected_mm)));
+}
+
+#elif defined(USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER)
+
+/*
+ * Using the older RuntimeDyld API, but with our backported memory manager.
+ */
LLVMOrcObjectLayerRef
LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(LLVMOrcExecutionSessionRef ES)
{
return wrap(new llvm::orc::RTDyldObjectLinkingLayer(
*unwrap(ES), [] { return std::make_unique<llvm::backport::SectionMemoryManager>(nullptr, true); }));
}
+
#endif
diff --git a/src/include/jit/llvmjit.h b/src/include/jit/llvmjit.h
index b3c75022f55..95004cf12f0 100644
--- a/src/include/jit/llvmjit.h
+++ b/src/include/jit/llvmjit.h
@@ -20,7 +20,7 @@
#include "jit/llvmjit_backport.h"
#include <llvm-c/Types.h>
-#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
+#if defined(USE_LLVM_JITLINK) || defined(USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER)
#include <llvm-c/OrcEE.h>
#endif
@@ -141,6 +141,9 @@ extern LLVMValueRef slot_compile_deform(struct LLVMJitContext *context, TupleDes
*/
extern LLVMTypeRef LLVMGetFunctionReturnType(LLVMValueRef r);
extern LLVMTypeRef LLVMGetFunctionType(LLVMValueRef r);
+#ifdef USE_LLVM_JITLINK
+extern LLVMOrcObjectLayerRef LLVMOrcCreateJITLinkObjectLinkingLayer(LLVMOrcExecutionSessionRef ES);
+#endif
#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
extern LLVMOrcObjectLayerRef LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(LLVMOrcExecutionSessionRef ES);
#endif
diff --git a/src/include/jit/llvmjit_backport.h b/src/include/jit/llvmjit_backport.h
index cba8eafc4f3..ed2245d7011 100644
--- a/src/include/jit/llvmjit_backport.h
+++ b/src/include/jit/llvmjit_backport.h
@@ -7,6 +7,15 @@
#include <llvm/Config/llvm-config.h>
+/*
+ * On newer LLVM versions, prefer JITLink over RuntimeDyld for linking.
+ * Earlier versions may also work on some platforms.
+ *
+ * XXX What should the conditions be for this?
+ */
+#if LLVM_VERSION_MAJOR >= 19
+#define USE_LLVM_JITLINK
+#else
/*
* LLVM's RuntimeDyld can produce code that crashes on larger memory ARM
* systems, because llvm::SectionMemoryManager allocates multiple pieces of
@@ -18,5 +27,6 @@
#if defined(__aarch64__)
#define USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
#endif
+#endif
#endif
--
2.39.5 (Apple Git-154)
On Thu, Sep 18, 2025 at 5:05 PM Thomas Munro <thomas.munro@gmail.com> wrote:
Here's a short unfinished but semi-working patch to try out JITLink
instead of RuntimeDyld, since Greg expressed an interest in it. I'm
not actively working on this myself right now, but in case it helps, I
think the main things to do next are probably: try out the recently
added debugger and perf plugins (I hope these are the equivalents of
the JITEventListener stuff we use), figure out how and when we can
actually cut over, tidy/refactor and possibly consider upstreaming
some C wrappers if we want to minimise the C++ glue we carry. See
patch for a few more details.
LLVMOrcCreateObjectLinkingLayerWithInProcessMemoryManager() has been
upstreamed into LLVM 22[1]https://github.com/llvm/llvm-project/commit/2222cfe7e11ff3e0434bc696856629199ef0da7c, so this patch became shorter.
We could optionally photocopy that function into our llvm_wrap.cpp
file if we have a need to use JITLink with older LLVM versions. The
motivations for that might be that it is needed for RISC-V and we want
that to work on current Debian et al without waiting ages, or that we
want to kill off our llvm::backport::SectionMemoryManager sooner
without having to wait for LLVM 22 (which has finally fixed the
underlying problem[2]/messages/by-id/CA+hUKGJTumad75o8Zao-LFseEbt=enbUFCM7LZVV=c8yg2i7dg@mail.gmail.com) to be our minimum version. Someone said this
is also needed for Windows, and I read somewhere that Visual Studio
ships a copy of LLVM these days and it could be a few releases behind,
so that might also provide a motivation, IDK.
I still don't know how to enable GDB and Perf support with JITLink...
With LLVM 22 (bleeding edge main branch) it builds and runs simple
things, but I get a SIGBUS crash in the regression tests even on
unpatched master, something to look into separately...
That turned out to be not our bug, and has been fixed.
[1]: https://github.com/llvm/llvm-project/commit/2222cfe7e11ff3e0434bc696856629199ef0da7c
[2]: /messages/by-id/CA+hUKGJTumad75o8Zao-LFseEbt=enbUFCM7LZVV=c8yg2i7dg@mail.gmail.com
Attachments:
v2-0001-jit-Use-JITLink-for-LLVM-22.patchtext/x-patch; charset=US-ASCII; name=v2-0001-jit-Use-JITLink-for-LLVM-22.patchDownload
From cac92d0786db7686cf449ff1535d8da558eec206 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 10 Oct 2024 13:31:56 +1300
Subject: [PATCH v2] jit: Use JITLink for LLVM 22.
The RuntimeDyld ObjectLinkingLayer is semi-deprecated, unsupported and
likely to be removed. Unfortunately we couldn't use the recommended
JITLink replacement earlier due to incompleteness. Now we can. This
avoids the need to use the back-patched SectionMemoryManager from commit
9044fc1d.
XXX TODO: figure out how to turn on GDB and Perf support...
---
src/backend/jit/llvm/llvmjit.c | 27 +++++++++++++++++++++++----
src/backend/jit/llvm/llvmjit_wrap.cpp | 2 ++
2 files changed, 25 insertions(+), 4 deletions(-)
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 6a0db9de7c6..e1c04834d46 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -34,7 +34,9 @@
#endif
#include "jit/llvmjit.h"
+#if LLVM_VERSION_MAJOR < 22
#include "jit/llvmjit_backport.h"
+#endif
#include "jit/llvmjit_emit.h"
#include "miscadmin.h"
#include "portability/instr_time.h"
@@ -1172,12 +1174,27 @@ llvm_log_jit_error(void *ctx, LLVMErrorRef error)
static LLVMOrcObjectLayerRef
llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
{
+ LLVMOrcObjectLayerRef objlayer;
+
+#if LLVM_VERSION_MAJOR >= 22
+ LLVMErrorRef error =
+ LLVMOrcCreateObjectLinkingLayerWithInProcessMemoryManager(&objlayer, ES);
+
+ if (error)
+ elog(FATAL, "could not create LLVM ObjectLinkingLayer: %s",
+ llvm_error_message(error));
+
+ /*
+ * TODO: llvm::orc::PerfSupportPlugin
+ *
+ * TODO: llvm::orc::DebuggerSupportPlugin
+ */
+#else
+
#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
- LLVMOrcObjectLayerRef objlayer =
- LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
+ objlayer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
#else
- LLVMOrcObjectLayerRef objlayer =
- LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
+ objlayer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
#endif
if (jit_debugging_support)
@@ -1195,6 +1212,8 @@ llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *T
LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
}
+#endif
+
return objlayer;
}
diff --git a/src/backend/jit/llvm/llvmjit_wrap.cpp b/src/backend/jit/llvm/llvmjit_wrap.cpp
index 0dd311c59df..15ba65c3bd3 100644
--- a/src/backend/jit/llvm/llvmjit_wrap.cpp
+++ b/src/backend/jit/llvm/llvmjit_wrap.cpp
@@ -20,7 +20,9 @@ extern "C"
#include <llvm/IR/Function.h>
#include "jit/llvmjit.h"
+#if LLVM_VERSION_MAJOR < 22
#include "jit/llvmjit_backport.h"
+#endif
#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
--
2.52.0
On Sat, Jan 3, 2026 at 4:09 PM Thomas Munro <thomas.munro@gmail.com> wrote:
I still don't know how to enable GDB and Perf support with JITLink...
jit_debugging_support may just be just a matter of calling
LLVMOrcLLJITEnableDebugSupport()[1]https://github.com/llvm/llvm-project/issues/174305#issuecomment-3709546309, though it looks like it might
only work for ELF (the other interesting object format at this stage
being macOS's MachO, and in the past/possible future AIX's COFF/XCOFF
and eventually Windows COFF/PE), but I'm not sure. You can tell if
it's working by making it crash/abort in JITed code and seeing if the
stack is decodable by GDB I had been thinking we were going to have
to write that function because I'd missed its arrival in LLVM 18[2]https://github.com/llvm/llvm-project/commit/54397f9ac128568838f2ac7bfc8e1f94b3eb264d,
d'uh. It sounds like we might need to wait for or write a similar
function for perf support. Sorry for drip-feeding incomplete work,
but since others expressed an interest in helping :-)
[1]: https://github.com/llvm/llvm-project/issues/174305#issuecomment-3709546309
[2]: https://github.com/llvm/llvm-project/commit/54397f9ac128568838f2ac7bfc8e1f94b3eb264d
Hi,
On Tue, Jan 6, 2026 at 1:09 AM Thomas Munro <thomas.munro@gmail.com> wrote:
jit_debugging_support may just be just a matter of calling
LLVMOrcLLJITEnableDebugSupport()[1], though it looks like it might
only work for ELF (the other interesting object format at this stage
being macOS's MachO, and in the past/possible future AIX's COFF/XCOFF
and eventually Windows COFF/PE), but I'm not sure. You can tell if
it's working by making it crash/abort in JITed code and seeing if the
stack is decodable by GDB I had been thinking we were going to have
to write that function because I'd missed its arrival in LLVM 18[2],
d'uh.
I've tested the patch while adding the call to
'LLVMOrcLLJITEnableDebugSupport(lljit);', and it works. I have full
backtraces with JIT function names:
* frame #0: 0x0000f4196f94a254 JIT(0xf4196f956000)`deform_1_2 + 28
frame #1: 0x0000f4196f94a14c JIT(0xf4196f956000)`evalexpr_1_1 + 172
frame #2: 0x0000bb2f132f3098
postgres`ExecEvalExprNoReturn(econtext=<unavailable>,
state=<unavailable>) at executor.h:423:13
frame #3: 0x0000bb2f132f3094
postgres`ExecEvalExprNoReturnSwitchContext(econtext=<unavailable>,
state=<unavailable>) at executor.h:464:2
It sounds like we might need to wait for or write a similar
function for perf support.
Yeah, there's no C api provided by LLVM yet. I've just opened a
tentative PR[1]https://github.com/llvm/llvm-project/pull/174973 to add it. With the modified LLVM and postgres calling
LLVMOrcLLJITEnablePerfSupport, I see the generated perf dumps in
~/.debug/jit/llvm-IR-jit-20260108-61640f/jit-38489.dump.
Though if I try to perf inject the dumps, I have the following errors
jitdump file contains invalid or unsupported flags 0xf5880666c26c
0x2b750 [0xa8]: failed to process type: 10 [Operation not permitted]
But that might be an issue with my setup, I would need to test it
further to understand the issue...
Attachments:
v3-0001-jit-Use-JITLink-for-LLVM-22.patchapplication/octet-stream; name=v3-0001-jit-Use-JITLink-for-LLVM-22.patchDownload
From 93bd96a1afb37c0f68f42bef0e1a3d85a60c8da3 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 10 Oct 2024 13:31:56 +1300
Subject: jit: Use JITLink for LLVM 22.
The RuntimeDyld ObjectLinkingLayer is semi-deprecated, unsupported and
likely to be removed. Unfortunately we couldn't use the recommended
JITLink replacement earlier due to incompleteness. Now we can. This
avoids the need to use the back-patched SectionMemoryManager from commit
9044fc1d.
---
src/backend/jit/llvm/llvmjit.c | 39 ++++++++++++++++++++++++---
src/backend/jit/llvm/llvmjit_wrap.cpp | 2 ++
2 files changed, 37 insertions(+), 4 deletions(-)
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 8d009dd5cf7..044ae50078c 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -24,6 +24,9 @@
#include <llvm-c/Orc.h>
#include <llvm-c/OrcEE.h>
#include <llvm-c/LLJIT.h>
+#if LLVM_VERSION_MAJOR >= 22
+#include <llvm-c/LLJITUtils.h>
+#endif
#include <llvm-c/Support.h>
#include <llvm-c/Target.h>
#if LLVM_VERSION_MAJOR < 17
@@ -34,7 +37,9 @@
#endif
#include "jit/llvmjit.h"
+#if LLVM_VERSION_MAJOR < 22
#include "jit/llvmjit_backport.h"
+#endif
#include "jit/llvmjit_emit.h"
#include "miscadmin.h"
#include "portability/instr_time.h"
@@ -1136,6 +1141,7 @@ llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx,
LLVMOrcRetainSymbolStringPoolEntry(LookupSet[i].Name);
symbols[i].Name = LookupSet[i].Name;
+
symbols[i].Sym.Address = llvm_resolve_symbol(name, NULL);
symbols[i].Sym.Flags.GenericFlags = LLVMJITSymbolGenericFlagsExported;
}
@@ -1172,12 +1178,22 @@ llvm_log_jit_error(void *ctx, LLVMErrorRef error)
static LLVMOrcObjectLayerRef
llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
{
+ LLVMOrcObjectLayerRef objlayer;
+
+#if LLVM_VERSION_MAJOR >= 22
+ LLVMErrorRef error =
+ LLVMOrcCreateObjectLinkingLayerWithInProcessMemoryManager(&objlayer, ES);
+
+ if (error)
+ elog(FATAL, "could not create LLVM ObjectLinkingLayer: %s",
+ llvm_error_message(error));
+
+#else
+
#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
- LLVMOrcObjectLayerRef objlayer =
- LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
+ objlayer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
#else
- LLVMOrcObjectLayerRef objlayer =
- LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
+ objlayer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
#endif
if (jit_debugging_support)
@@ -1195,6 +1211,8 @@ llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *T
LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
}
+#endif
+
return objlayer;
}
@@ -1225,6 +1243,19 @@ llvm_create_jit_instance(LLVMTargetMachineRef tm)
elog(ERROR, "failed to create lljit instance: %s",
llvm_error_message(error));
+#if LLVM_VERSION_MAJOR >= 22
+ if (jit_debugging_support)
+ {
+ LLVMOrcLLJITEnableDebugSupport(lljit);
+ }
+
+ if (jit_profiling_support)
+ {
+ // This requires llvm with https://github.com/bonnefoa/llvm-project/tree/jitlink-perf
+ LLVMOrcLLJITEnablePerfSupport(lljit);
+ }
+#endif
+
LLVMOrcExecutionSessionSetErrorReporter(LLVMOrcLLJITGetExecutionSession(lljit),
llvm_log_jit_error, NULL);
diff --git a/src/backend/jit/llvm/llvmjit_wrap.cpp b/src/backend/jit/llvm/llvmjit_wrap.cpp
index 9cba4b96e45..6a7d63444f8 100644
--- a/src/backend/jit/llvm/llvmjit_wrap.cpp
+++ b/src/backend/jit/llvm/llvmjit_wrap.cpp
@@ -20,7 +20,9 @@ extern "C"
#include <llvm/IR/Function.h>
#include "jit/llvmjit.h"
+#if LLVM_VERSION_MAJOR < 22
#include "jit/llvmjit_backport.h"
+#endif
#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
--
2.51.0
Though if I try to perf inject the dumps, I have the following errors
jitdump file contains invalid or unsupported flags 0xf5880666c26c
0x2b750 [0xa8]: failed to process type: 10 [Operation not permitted]
But that might be an issue with my setup, I would need to test it
further to understand the issue...
After some additional investigation, I think that's a LLVM issue: The
Flags field is never initialised so the JIT perf plugin was writing
random data in the JIT dump header.
I've opened a PR[0]https://github.com/llvm/llvm-project/pull/175204 to fix this.
On Fri, Jan 9, 2026 at 2:33 AM Anthonin Bonnefoy
<anthonin.bonnefoy@datadoghq.com> wrote:
On Tue, Jan 6, 2026 at 1:09 AM Thomas Munro <thomas.munro@gmail.com> wrote:
It sounds like we might need to wait for or write a similar
function for perf support.Yeah, there's no C api provided by LLVM yet. I've just opened a
tentative PR[1] to add it.
Thanks Anthonin! The configure script needs the library for the
"orcdebugging" component (Meson must be adding all components
automatically), and we should check the return value. I also figured
we should set the error report handler as soon as possible, just in
case it wants to tell us something. v4 attached.
jit_profiling_support=1 doesn't fail nicely on a system without perf,
but I don't think it's the fault of your patch. I posted some details
to your PR. Let's see if it can land in time... I think there are
just a couple of days left, so it might just be too late for 22.
I suppose we should only use this for ELF systems initially, given
that debugging support is missing for Macs.
Attachments:
v4-0001-jit-Use-JITLink-for-LLVM-22.patchtext/x-patch; charset=US-ASCII; name=v4-0001-jit-Use-JITLink-for-LLVM-22.patchDownload
From 74b49aced5230932c5232614a30ad6eb81f07661 Mon Sep 17 00:00:00 2001
From: Thomas Munro <thomas.munro@gmail.com>
Date: Thu, 10 Oct 2024 13:31:56 +1300
Subject: [PATCH v4 1/3] jit: Use JITLink for LLVM 22.
The RuntimeDyld ObjectLinkingLayer is semi-deprecated, unsupported and
likely to be removed. Unfortunately we couldn't use the recommended
JITLink replacement earlier due to incompleteness. Now we can. This
avoids the need to use the back-patched SectionMemoryManager from commit
9044fc1d.
XXX If Anthonin's patch for LLVMOrcLLJITEnablePerfSupport() is committed
in time for LLVM 22 we'll have to decide how to gate the use of JITLink
Co-authored-by: Thomas Munro <thomas.munro@gmail.com>
Co-authored-by: Anthonin Bonnefoy <anthonin.bonnefoy@datadoghq.com>
Discussion: https://postgr.es/m/CA%2BhUKGJBJx4fDGLv8zUtmsmg16Swry7DJbMr2_GNZcd6sgE0rg%40mail.gmail.com
---
config/llvm.m4 | 1 +
configure | 1 +
src/backend/jit/llvm/llvmjit.c | 45 ++++++++++++++++++++++++---
src/backend/jit/llvm/llvmjit_wrap.cpp | 2 ++
4 files changed, 45 insertions(+), 4 deletions(-)
diff --git a/config/llvm.m4 b/config/llvm.m4
index 5d4f14cb900..b1ef4e90bdb 100644
--- a/config/llvm.m4
+++ b/config/llvm.m4
@@ -75,6 +75,7 @@ AC_DEFUN([PGAC_LLVM_SUPPORT],
case $pgac_component in
engine) pgac_components="$pgac_components $pgac_component";;
debuginfodwarf) pgac_components="$pgac_components $pgac_component";;
+ orcdebugging) pgac_components="$pgac_components $pgac_component";;
orcjit) pgac_components="$pgac_components $pgac_component";;
passes) pgac_components="$pgac_components $pgac_component";;
native) pgac_components="$pgac_components $pgac_component";;
diff --git a/configure b/configure
index 02e4ec7890f..cba5a9061ff 100755
--- a/configure
+++ b/configure
@@ -5041,6 +5041,7 @@ fi
case $pgac_component in
engine) pgac_components="$pgac_components $pgac_component";;
debuginfodwarf) pgac_components="$pgac_components $pgac_component";;
+ orcdebugging) pgac_components="$pgac_components $pgac_component";;
orcjit) pgac_components="$pgac_components $pgac_component";;
passes) pgac_components="$pgac_components $pgac_component";;
native) pgac_components="$pgac_components $pgac_component";;
diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c
index 49e76153f9a..ffd04bbc988 100644
--- a/src/backend/jit/llvm/llvmjit.c
+++ b/src/backend/jit/llvm/llvmjit.c
@@ -24,6 +24,9 @@
#include <llvm-c/Orc.h>
#include <llvm-c/OrcEE.h>
#include <llvm-c/LLJIT.h>
+#if LLVM_VERSION_MAJOR >= 22
+#include <llvm-c/LLJITUtils.h>
+#endif
#include <llvm-c/Support.h>
#include <llvm-c/Target.h>
#if LLVM_VERSION_MAJOR < 17
@@ -34,7 +37,9 @@
#endif
#include "jit/llvmjit.h"
+#if LLVM_VERSION_MAJOR < 22
#include "jit/llvmjit_backport.h"
+#endif
#include "jit/llvmjit_emit.h"
#include "miscadmin.h"
#include "portability/instr_time.h"
@@ -1136,6 +1141,7 @@ llvm_resolve_symbols(LLVMOrcDefinitionGeneratorRef GeneratorObj, void *Ctx,
LLVMOrcRetainSymbolStringPoolEntry(LookupSet[i].Name);
symbols[i].Name = LookupSet[i].Name;
+
symbols[i].Sym.Address = llvm_resolve_symbol(name, NULL);
symbols[i].Sym.Flags.GenericFlags = LLVMJITSymbolGenericFlagsExported;
}
@@ -1172,12 +1178,22 @@ llvm_log_jit_error(void *ctx, LLVMErrorRef error)
static LLVMOrcObjectLayerRef
llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *Triple)
{
+ LLVMOrcObjectLayerRef objlayer;
+
+#if LLVM_VERSION_MAJOR >= 22
+ LLVMErrorRef error =
+ LLVMOrcCreateObjectLinkingLayerWithInProcessMemoryManager(&objlayer, ES);
+
+ if (error)
+ elog(FATAL, "could not create LLVM ObjectLinkingLayer: %s",
+ llvm_error_message(error));
+
+#else
+
#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
- LLVMOrcObjectLayerRef objlayer =
- LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
+ objlayer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSafeSectionMemoryManager(ES);
#else
- LLVMOrcObjectLayerRef objlayer =
- LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
+ objlayer = LLVMOrcCreateRTDyldObjectLinkingLayerWithSectionMemoryManager(ES);
#endif
if (jit_debugging_support)
@@ -1195,6 +1211,8 @@ llvm_create_object_layer(void *Ctx, LLVMOrcExecutionSessionRef ES, const char *T
LLVMOrcRTDyldObjectLinkingLayerRegisterJITEventListener(objlayer, l);
}
+#endif
+
return objlayer;
}
@@ -1228,6 +1246,25 @@ llvm_create_jit_instance(LLVMTargetMachineRef tm)
LLVMOrcExecutionSessionSetErrorReporter(LLVMOrcLLJITGetExecutionSession(lljit),
llvm_log_jit_error, NULL);
+#if LLVM_VERSION_MAJOR >= 22
+ if (jit_debugging_support)
+ {
+ error = LLVMOrcLLJITEnableDebugSupport(lljit);
+ if (error)
+ elog(ERROR, "failed to enable JIT debugging support: %s",
+ llvm_error_message(error));
+ }
+
+ if (jit_profiling_support)
+ {
+ // This requires llvm with https://github.com/bonnefoa/llvm-project/tree/jitlink-perf
+ error = LLVMOrcLLJITEnablePerfSupport(lljit);
+ if (error)
+ elog(ERROR, "failed to enable JIT perf support: %s",
+ llvm_error_message(error));
+ }
+#endif
+
/*
* Symbol resolution support for symbols in the postgres binary /
* libraries already loaded.
diff --git a/src/backend/jit/llvm/llvmjit_wrap.cpp b/src/backend/jit/llvm/llvmjit_wrap.cpp
index 9cba4b96e45..6a7d63444f8 100644
--- a/src/backend/jit/llvm/llvmjit_wrap.cpp
+++ b/src/backend/jit/llvm/llvmjit_wrap.cpp
@@ -20,7 +20,9 @@ extern "C"
#include <llvm/IR/Function.h>
#include "jit/llvmjit.h"
+#if LLVM_VERSION_MAJOR < 22
#include "jit/llvmjit_backport.h"
+#endif
#ifdef USE_LLVM_BACKPORT_SECTION_MEMORY_MANAGER
#include <llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h>
--
2.51.0