From 19ebfa6d0b9bfbb83ca240ad7c7ecc06ade2cf01 Mon Sep 17 00:00:00 2001 From: Matt Arsenault Date: Tue, 19 Aug 2025 10:35:59 +0900 Subject: [PATCH] RuntimeLibcalls: Move exception call config to tablegen (#151948) 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 308be543de2b..cf3e6c7f0b3a 100644 --- a/llvm/include/llvm/IR/RuntimeLibcalls.h +++ b/llvm/include/llvm/IR/RuntimeLibcalls.h @@ -233,8 +233,10 @@ private: } /// 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 dec73760d62e..1f596184f3d6 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 //-------------------------------------------------------------------- @@ -707,10 +715,6 @@ foreach MemSize = [ 1, 2, 4, 8, 16 ] in { !cast("MEMSET_ELEMENT_UNORDERED_ATOMIC_"#MemSize)>; } -// Exception handling -def _Unwind_Resume : RuntimeLibcallImpl; -def __cxa_end_cleanup : RuntimeLibcallImpl; - // Atomic '__sync_*' libcalls. foreach lc = LibCalls__sync in { def __#!tolower(!cast(lc)) : RuntimeLibcallImpl; @@ -1014,9 +1018,20 @@ defm sincos : LibmLongDoubleLibCall; def bzero : RuntimeLibcallImpl; def __bzero : RuntimeLibcallImpl; -def _Unwind_SjLj_Resume : RuntimeLibcallImpl; -def _Unwind_SjLj_Register : RuntimeLibcallImpl; -def _Unwind_SjLj_Unregister : RuntimeLibcallImpl; + +// Exception handling +defset list DefaultExceptionHandlingLibcalls = { + def _Unwind_Resume : RuntimeLibcallImpl; + def __cxa_end_cleanup : RuntimeLibcallImpl; +} + +defset list SjLjExceptionHandlingLibcalls = { + def _Unwind_SjLj_Resume : RuntimeLibcallImpl; + def _Unwind_SjLj_Register : RuntimeLibcallImpl; + def _Unwind_SjLj_Unregister : RuntimeLibcallImpl; +} + +// Only used on wasm? def _Unwind_CallPersonality : RuntimeLibcallImpl; // Used on OpenBSD @@ -1092,6 +1107,13 @@ defset list 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 @@ -1112,19 +1134,25 @@ defvar DefaultRuntimeLibcallImpls_f128 = !filter(entry, AllDefaultRuntimeLibcallImpls, !match(!cast(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>; @@ -1160,7 +1188,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>; @@ -1290,7 +1323,7 @@ def AArch64SystemLibrary : SystemRuntimeLibrary< // Prepend a # to every name defset list WinArm64ECDefaultRuntimeLibcallImpls = { - foreach libcall = WinDefaultLibcallImpls in { + foreach libcall = WinDefaultLibcallImplsBaseList in { def arm64ec_#libcall : DuplicateLibcallImplWithPrefix; } @@ -1301,12 +1334,32 @@ defset list WinArm64ECDefaultRuntimeLibcallImpls = { def arm64ec___stack_chk_fail : DuplicateLibcallImplWithPrefix<__stack_chk_fail, "#">; +defset list WinArm64ECDefaultExceptionHandlingLibcalls = { + foreach libcall = DefaultExceptionHandlingLibcalls in { + def arm64ec_#libcall : DuplicateLibcallImplWithPrefix; + } +} + +defset list WinArm64ECSjLjExceptionHandlingLibcalls = { + foreach libcall = SjLjExceptionHandlingLibcalls in { + def arm64ec_#libcall : DuplicateLibcallImplWithPrefix; + } +} + +defvar ExceptionModelCallsArm64EC = (add + LibcallImpls<(add WinArm64ECDefaultExceptionHandlingLibcalls), + ExceptionModelIsNotNone>, + LibcallImpls<(add WinArm64ECSjLjExceptionHandlingLibcalls), + ExceptionModelIsSjLj> +); + def WindowsARM64ECSystemLibrary : SystemRuntimeLibrary)>; + isWindowsMSVCEnvironment>, + ExceptionModelCallsArm64EC)>; //===----------------------------------------------------------------------===// // AMDGPU Runtime Libcalls @@ -2345,7 +2398,7 @@ defvar X86CommonLibcalls = // hack for one test relying on it. __powitf2_f128, DefaultStackProtector -); + ); defvar Windows32DivRemMulCalls = LibcallsWithCC<(add WindowsDivRemMulLibcalls), X86_STDCALL, @@ -2489,6 +2542,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 09fb78e7a2ac..3c324f2fe0d8 100644 --- a/llvm/lib/IR/RuntimeLibcalls.cpp +++ b/llvm/lib/IR/RuntimeLibcalls.cpp @@ -31,10 +31,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 fcc5f7e0b601..7d1e830c912a 100644 --- a/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td +++ b/llvm/test/TableGen/RuntimeLibcallEmitter-calling-conv.td @@ -41,7 +41,7 @@ def MSP430LibraryWithCondCC : SystemRuntimeLibrary; -// 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 7c62402227f7..dbb5c5e7199d 100644 --- a/llvm/test/TableGen/RuntimeLibcallEmitter.td +++ b/llvm/test/TableGen/RuntimeLibcallEmitter.td @@ -189,7 +189,7 @@ def BlahLibrary : SystemRuntimeLibrary