[llvm] RuntimeLibcalls: Move exception call config to tablegen (PR #151948)
Matt Arsenault via llvm-commits
llvm-commits at lists.llvm.org
Thu Aug 14 07:43:45 PDT 2025
https://github.com/arsenm updated https://github.com/llvm/llvm-project/pull/151948
>From 6e2d6f7c3ad7db8a160187ca9be8b178ad4dbc88 Mon Sep 17 00:00:00 2001
From: Matt Arsenault <Matthew.Arsenault at amd.com>
Date: Mon, 4 Aug 2025 11:57:41 +0900
Subject: [PATCH] RuntimeLibcalls: Move exception call config to tablegen
Also starts pruning out these calls if the exception model is
forced to none.
I worked backwards from the logic in addPassesToHandleExceptions
and the pass content. There appears to be some tolerance
for mixing and matching exception modes inside of a single module.
As far as I can tell _Unwind_CallPersonality is only relevant for
wasm, so just add it there.
As usual, the arm64ec case makes things difficult and is
missing test coverage. The set of calls in list form is necessary
to use foreach for the duplication, but in every other context a
dag is more convenient. You cannot use foreach over a dag, and I
haven't found a way to flatten a dag into a list.
This removes the last manual setLibcallImpl call in generic code.
---
llvm/include/llvm/IR/RuntimeLibcalls.h | 6 +-
llvm/include/llvm/IR/RuntimeLibcalls.td | 84 +++++++++++++++----
llvm/lib/IR/RuntimeLibcalls.cpp | 6 +-
.../RuntimeLibcallEmitter-calling-conv.td | 2 +-
llvm/test/TableGen/RuntimeLibcallEmitter.td | 2 +-
.../TableGen/Basic/RuntimeLibcallsEmitter.cpp | 3 +-
6 files changed, 79 insertions(+), 24 deletions(-)
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.h b/llvm/include/llvm/IR/RuntimeLibcalls.h
index 2d1d07c5fd81b..66198fd19b314 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.h
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.h
@@ -203,8 +203,10 @@ struct RuntimeLibcallsInfo {
}
/// Generated by tablegen.
- void setTargetRuntimeLibcallSets(const Triple &TT, FloatABI::ABIType FloatABI,
- EABI ABIType, StringRef ABIName);
+ void setTargetRuntimeLibcallSets(const Triple &TT,
+ ExceptionHandling ExceptionModel,
+ FloatABI::ABIType FloatABI, EABI ABIType,
+ StringRef ABIName);
/// Set default libcall names. If a target wants to opt-out of a libcall it
/// should be placed here.
diff --git a/llvm/include/llvm/IR/RuntimeLibcalls.td b/llvm/include/llvm/IR/RuntimeLibcalls.td
index 9072a0aa1531f..3d99553e8a3c3 100644
--- a/llvm/include/llvm/IR/RuntimeLibcalls.td
+++ b/llvm/include/llvm/IR/RuntimeLibcalls.td
@@ -39,6 +39,14 @@ def hasSinCos : RuntimeLibcallPredicate<"hasSinCos(TT)">;
// FIXME: Way to combine predicates
def hasSinCos_f32_f64 : RuntimeLibcallPredicate<"hasSinCos_f32_f64(TT)">;
+def ExceptionModelIsNotNone : RuntimeLibcallPredicate<
+ [{ExceptionModel != ExceptionHandling::None}]
+>;
+
+def ExceptionModelIsSjLj : RuntimeLibcallPredicate<
+ [{ExceptionModel == ExceptionHandling::SjLj}]
+>;
+
//--------------------------------------------------------------------
// Declare all kinds of used libcalls
//--------------------------------------------------------------------
@@ -696,10 +704,6 @@ foreach MemSize = [ 1, 2, 4, 8, 16 ] in {
!cast<RuntimeLibcall>("MEMSET_ELEMENT_UNORDERED_ATOMIC_"#MemSize)>;
}
-// Exception handling
-def _Unwind_Resume : RuntimeLibcallImpl<UNWIND_RESUME>;
-def __cxa_end_cleanup : RuntimeLibcallImpl<CXA_END_CLEANUP>;
-
// Atomic '__sync_*' libcalls.
foreach lc = LibCalls__sync in {
def __#!tolower(!cast<string>(lc)) : RuntimeLibcallImpl<lc>;
@@ -1003,9 +1007,20 @@ defm sincos : LibmLongDoubleLibCall;
def bzero : RuntimeLibcallImpl<BZERO>;
def __bzero : RuntimeLibcallImpl<BZERO>;
-def _Unwind_SjLj_Resume : RuntimeLibcallImpl<UNWIND_RESUME>;
-def _Unwind_SjLj_Register : RuntimeLibcallImpl<UNWIND_REGISTER>;
-def _Unwind_SjLj_Unregister : RuntimeLibcallImpl<UNWIND_UNREGISTER>;
+
+// Exception handling
+defset list<RuntimeLibcallImpl> DefaultExceptionHandlingLibcalls = {
+ def _Unwind_Resume : RuntimeLibcallImpl<UNWIND_RESUME>;
+ def __cxa_end_cleanup : RuntimeLibcallImpl<CXA_END_CLEANUP>;
+}
+
+defset list<RuntimeLibcallImpl> SjLjExceptionHandlingLibcalls = {
+ def _Unwind_SjLj_Resume : RuntimeLibcallImpl<UNWIND_RESUME>;
+ def _Unwind_SjLj_Register : RuntimeLibcallImpl<UNWIND_REGISTER>;
+ def _Unwind_SjLj_Unregister : RuntimeLibcallImpl<UNWIND_UNREGISTER>;
+}
+
+// Only used on wasm?
def _Unwind_CallPersonality : RuntimeLibcallImpl<UNWIND_CALL_PERSONALITY>;
// Used on OpenBSD
@@ -1081,6 +1096,13 @@ defset list<RuntimeLibcallImpl> LibmF128FiniteLibcalls = {
// Common Libcall Sets
//===----------------------------------------------------------------------===//
+defvar ExceptionModelCalls = (add
+ LibcallImpls<(add DefaultExceptionHandlingLibcalls),
+ ExceptionModelIsNotNone>,
+ LibcallImpls<(add SjLjExceptionHandlingLibcalls),
+ ExceptionModelIsSjLj>
+);
+
// FIXME: Should move to explicit opt-in to different sets of libcalls
// instead of trying to remove from a default set. We have
// unreasonable defaults like reporting f80 calls on most targets when
@@ -1101,19 +1123,25 @@ defvar DefaultRuntimeLibcallImpls_f128 =
!filter(entry, AllDefaultRuntimeLibcallImpls,
!match(!cast<string>(entry.Provides), "_F128"));
-defvar DefaultRuntimeLibcallImpls =
+// FIXME: Ideally we would just use dags everywhere, but for the
+// arm64ec case we need iterable lists so we can add the # prefix
+defvar DefaultRuntimeLibcallImplsBaseList =
!listremove(
!listremove(
!listremove(AllDefaultRuntimeLibcallImpls, Int128RTLibcalls),
DefaultRuntimeLibcallImpls_f80),
DefaultRuntimeLibcallImpls_ppcf128);
+defvar DefaultRuntimeLibcallImpls =
+ (add DefaultRuntimeLibcallImplsBaseList,
+ ExceptionModelCalls);
+
/// Default set of libcall impls for 32-bit architectures.
-defvar DefaultLibcallImpls32 = DefaultRuntimeLibcallImpls;
+defvar DefaultLibcallImpls32 = (add DefaultRuntimeLibcallImpls);
/// Default set of libcall impls for 64-bit architectures.
-defvar DefaultLibcallImpls64 = !listconcat(DefaultRuntimeLibcallImpls,
- Int128RTLibcalls);
+defvar DefaultLibcallImpls64 = (add DefaultRuntimeLibcallImpls,
+ Int128RTLibcalls);
defvar DarwinSinCosStret = LibcallImpls<(add __sincosf_stret, __sincos_stret),
darwinHasSinCosStret>;
@@ -1149,7 +1177,12 @@ defvar WindowsExclusions = !listconcat(WindowsMathRemovals, MostPowI);
// Targets which support windows should start with these as a base and
// add in calls for other OSes
-defvar WinDefaultLibcallImpls = !listremove(DefaultRuntimeLibcallImpls, WindowsExclusions);
+defvar WinDefaultLibcallImplsBaseList =
+ !listremove(DefaultRuntimeLibcallImplsBaseList,
+ WindowsExclusions);
+
+defvar WinDefaultLibcallImpls = (add WinDefaultLibcallImplsBaseList,
+ ExceptionModelCalls);
defvar LibmHasFrexpF32 = LibcallImpls<(add frexpf), isNotOSWindowsOrIsCygwinMinGW>;
defvar LibmHasLdexpF32 = LibcallImpls<(add ldexpf), isNotOSWindowsOrIsCygwinMinGW>;
@@ -1249,7 +1282,7 @@ def AArch64SystemLibrary : SystemRuntimeLibrary<
// Prepend a # to every name
defset list<RuntimeLibcallImpl> WinArm64ECDefaultRuntimeLibcallImpls = {
- foreach libcall = WinDefaultLibcallImpls in {
+ foreach libcall = WinDefaultLibcallImplsBaseList in {
def arm64ec_#libcall : DuplicateLibcallImplWithPrefix<libcall, "#">;
}
@@ -1260,12 +1293,32 @@ defset list<RuntimeLibcallImpl> WinArm64ECDefaultRuntimeLibcallImpls = {
def arm64ec___stack_chk_fail : DuplicateLibcallImplWithPrefix<__stack_chk_fail, "#">;
+defset list<RuntimeLibcallImpl> WinArm64ECDefaultExceptionHandlingLibcalls = {
+ foreach libcall = DefaultExceptionHandlingLibcalls in {
+ def arm64ec_#libcall : DuplicateLibcallImplWithPrefix<libcall, "#">;
+ }
+}
+
+defset list<RuntimeLibcallImpl> WinArm64ECSjLjExceptionHandlingLibcalls = {
+ foreach libcall = SjLjExceptionHandlingLibcalls in {
+ def arm64ec_#libcall : DuplicateLibcallImplWithPrefix<libcall, "#">;
+ }
+}
+
+defvar ExceptionModelCallsArm64EC = (add
+ LibcallImpls<(add WinArm64ECDefaultExceptionHandlingLibcalls),
+ ExceptionModelIsNotNone>,
+ LibcallImpls<(add WinArm64ECSjLjExceptionHandlingLibcalls),
+ ExceptionModelIsSjLj>
+);
+
def WindowsARM64ECSystemLibrary
: SystemRuntimeLibrary<isWindowsArm64EC,
(add WinArm64ECDefaultRuntimeLibcallImpls,
arm64ec___stack_chk_fail,
LibcallImpls<(add __security_check_cookie_arm64ec),
- isWindowsMSVCEnvironment>)>;
+ isWindowsMSVCEnvironment>,
+ ExceptionModelCallsArm64EC)>;
//===----------------------------------------------------------------------===//
// AMDGPU Runtime Libcalls
@@ -2301,7 +2354,7 @@ defvar X86CommonLibcalls =
// hack for one test relying on it.
__powitf2_f128,
DefaultStackProtector
-);
+ );
defvar Windows32DivRemMulCalls =
LibcallsWithCC<(add WindowsDivRemMulLibcalls), X86_STDCALL,
@@ -2445,6 +2498,7 @@ def WasmSystemLibrary
(add DefaultRuntimeLibcallImpls, Int128RTLibcalls,
CompilerRTOnlyInt64Libcalls, CompilerRTOnlyInt128Libcalls,
exp10f, exp10,
+ _Unwind_CallPersonality,
emscripten_return_address,
__stack_chk_fail)>;
diff --git a/llvm/lib/IR/RuntimeLibcalls.cpp b/llvm/lib/IR/RuntimeLibcalls.cpp
index ac845c4998783..3b67dc138cbab 100644
--- a/llvm/lib/IR/RuntimeLibcalls.cpp
+++ b/llvm/lib/IR/RuntimeLibcalls.cpp
@@ -28,10 +28,8 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT,
ExceptionHandling ExceptionModel,
FloatABI::ABIType FloatABI,
EABI EABIVersion, StringRef ABIName) {
- setTargetRuntimeLibcallSets(TT, FloatABI, EABIVersion, ABIName);
-
- if (ExceptionModel == ExceptionHandling::SjLj)
- setLibcallImpl(RTLIB::UNWIND_RESUME, RTLIB::_Unwind_SjLj_Resume);
+ setTargetRuntimeLibcallSets(TT, ExceptionModel, FloatABI, EABIVersion,
+ ABIName);
if (TT.isARM() || TT.isThumb()) {
// The half <-> float conversion functions are always soft-float on
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td
index fcc5f7e0b6012..7d1e830c912a5 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td
@@ -41,7 +41,7 @@ def MSP430LibraryWithCondCC : SystemRuntimeLibrary<isMSP430,
>;
-// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(const llvm::Triple &TT, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName) {
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName) {
// CHECK: if (TT.getArch() == Triple::avr && TT.isOSHurd()) {
// CHECK-NEXT: const CallingConv::ID DefaultCC = isFoo() ? CallingConv::Fast : CallingConv::GHC;
// CHECK-NEXT: for (CallingConv::ID &Entry : LibcallImplCallingConvs) {
diff --git a/llvm/test/TableGen/RuntimeLibcallEmitter.td b/llvm/test/TableGen/RuntimeLibcallEmitter.td
index a2d946f3aa84f..b63076056c306 100644
--- a/llvm/test/TableGen/RuntimeLibcallEmitter.td
+++ b/llvm/test/TableGen/RuntimeLibcallEmitter.td
@@ -150,7 +150,7 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
// CHECK-NEXT: };
-// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(const llvm::Triple &TT, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName) {
+// CHECK: void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets(const llvm::Triple &TT, ExceptionHandling ExceptionModel, FloatABI::ABIType FloatABI, EABI EABIVersion, StringRef ABIName) {
// CHECK-NEXT: struct LibcallImplPair {
// CHECK-NEXT: RTLIB::Libcall Func;
// CHECK-NEXT: RTLIB::LibcallImpl Impl;
diff --git a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
index 0fc230c4714f0..4e9ff6c933352 100644
--- a/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
+++ b/llvm/utils/TableGen/Basic/RuntimeLibcallsEmitter.cpp
@@ -356,7 +356,8 @@ const uint16_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameOffsetTable[] = {
void RuntimeLibcallEmitter::emitSystemRuntimeLibrarySetCalls(
raw_ostream &OS) const {
OS << "void llvm::RTLIB::RuntimeLibcallsInfo::setTargetRuntimeLibcallSets("
- "const llvm::Triple &TT, FloatABI::ABIType FloatABI, EABI EABIVersion, "
+ "const llvm::Triple &TT, ExceptionHandling ExceptionModel, "
+ "FloatABI::ABIType FloatABI, EABI EABIVersion, "
"StringRef ABIName) {\n"
" struct LibcallImplPair {\n"
" RTLIB::Libcall Func;\n"
More information about the llvm-commits
mailing list