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.
This commit is contained in:
Matt Arsenault 2025-08-19 10:35:59 +09:00 committed by GitHub
parent fe67267d19
commit 19ebfa6d0b
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 79 additions and 24 deletions

View File

@ -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.

View File

@ -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<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>;
@ -1014,9 +1018,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
@ -1092,6 +1107,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
@ -1112,19 +1134,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>;
@ -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<RuntimeLibcallImpl> WinArm64ECDefaultRuntimeLibcallImpls = {
foreach libcall = WinDefaultLibcallImpls in {
foreach libcall = WinDefaultLibcallImplsBaseList in {
def arm64ec_#libcall : DuplicateLibcallImplWithPrefix<libcall, "#">;
}
@ -1301,12 +1334,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
@ -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)>;

View File

@ -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

View File

@ -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) {

View File

@ -189,7 +189,7 @@ def BlahLibrary : SystemRuntimeLibrary<isBlahArch, (add calloc, LibraryWithCondi
// CHECK: return enum_seq(RTLIB::Unsupported, RTLIB::Unsupported);
// 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;

View File

@ -550,7 +550,8 @@ const uint8_t RTLIB::RuntimeLibcallsInfo::RuntimeLibcallNameSizeTable[] = {
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"