ARM: Start moving runtime libcall configuration out of TargetLowering (#142617)

These Module level triple checks implemented in the Subtarget are kind of
a pain and we should probably get rid of all of them in across all targets,
and stick to a consistent set of names.
This commit is contained in:
Matt Arsenault
2025-06-10 10:00:04 +09:00
committed by GitHub
parent 23fd60d996
commit a082f665f8
4 changed files with 86 additions and 71 deletions

View File

@@ -917,6 +917,34 @@ public:
isOSBinFormatELF();
}
// ARM EABI is the bare-metal EABI described in ARM ABI documents and
// can be accessed via -target arm-none-eabi. This is NOT GNUEABI.
// FIXME: Add a flag for bare-metal for that target and set Triple::EABI
// even for GNUEABI, so we can make a distinction here and still conform to
// the EABI on GNU (and Android) mode. This requires change in Clang, too.
// FIXME: The Darwin exception is temporary, while we move users to
// "*-*-*-macho" triples as quickly as possible.
bool isTargetAEABI() const {
return (getEnvironment() == Triple::EABI ||
getEnvironment() == Triple::EABIHF) &&
!isOSDarwin() && !isOSWindows();
}
bool isTargetGNUAEABI() const {
return (getEnvironment() == Triple::GNUEABI ||
getEnvironment() == Triple::GNUEABIT64 ||
getEnvironment() == Triple::GNUEABIHF ||
getEnvironment() == Triple::GNUEABIHFT64) &&
!isOSDarwin() && !isOSWindows();
}
bool isTargetMuslAEABI() const {
return (getEnvironment() == Triple::MuslEABI ||
getEnvironment() == Triple::MuslEABIHF ||
getEnvironment() == Triple::OpenHOS) &&
!isOSDarwin() && !isOSWindows();
}
/// Tests whether the target is T32.
bool isArmT32() const {
switch (getSubArch()) {

View File

@@ -31,6 +31,56 @@ static void setAArch64LibcallNames(RuntimeLibcallsInfo &Info,
}
}
static void setARMLibcallNames(RuntimeLibcallsInfo &Info, const Triple &TT) {
// Register based DivRem for AEABI (RTABI 4.2)
if (TT.isTargetAEABI() || TT.isAndroid() || TT.isTargetGNUAEABI() ||
TT.isTargetMuslAEABI() || TT.isOSWindows()) {
if (TT.isOSWindows()) {
const struct {
const RTLIB::Libcall Op;
const char *const Name;
const CallingConv::ID CC;
} LibraryCalls[] = {
{RTLIB::SDIVREM_I8, "__rt_sdiv", CallingConv::ARM_AAPCS},
{RTLIB::SDIVREM_I16, "__rt_sdiv", CallingConv::ARM_AAPCS},
{RTLIB::SDIVREM_I32, "__rt_sdiv", CallingConv::ARM_AAPCS},
{RTLIB::SDIVREM_I64, "__rt_sdiv64", CallingConv::ARM_AAPCS},
{RTLIB::UDIVREM_I8, "__rt_udiv", CallingConv::ARM_AAPCS},
{RTLIB::UDIVREM_I16, "__rt_udiv", CallingConv::ARM_AAPCS},
{RTLIB::UDIVREM_I32, "__rt_udiv", CallingConv::ARM_AAPCS},
{RTLIB::UDIVREM_I64, "__rt_udiv64", CallingConv::ARM_AAPCS},
};
for (const auto &LC : LibraryCalls) {
Info.setLibcallName(LC.Op, LC.Name);
Info.setLibcallCallingConv(LC.Op, LC.CC);
}
} else {
const struct {
const RTLIB::Libcall Op;
const char *const Name;
const CallingConv::ID CC;
} LibraryCalls[] = {
{RTLIB::SDIVREM_I8, "__aeabi_idivmod", CallingConv::ARM_AAPCS},
{RTLIB::SDIVREM_I16, "__aeabi_idivmod", CallingConv::ARM_AAPCS},
{RTLIB::SDIVREM_I32, "__aeabi_idivmod", CallingConv::ARM_AAPCS},
{RTLIB::SDIVREM_I64, "__aeabi_ldivmod", CallingConv::ARM_AAPCS},
{RTLIB::UDIVREM_I8, "__aeabi_uidivmod", CallingConv::ARM_AAPCS},
{RTLIB::UDIVREM_I16, "__aeabi_uidivmod", CallingConv::ARM_AAPCS},
{RTLIB::UDIVREM_I32, "__aeabi_uidivmod", CallingConv::ARM_AAPCS},
{RTLIB::UDIVREM_I64, "__aeabi_uldivmod", CallingConv::ARM_AAPCS},
};
for (const auto &LC : LibraryCalls) {
Info.setLibcallName(LC.Op, LC.Name);
Info.setLibcallCallingConv(LC.Op, LC.CC);
}
}
}
}
/// Set default libcall names. If a target wants to opt-out of a libcall it
/// should be placed here.
void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
@@ -298,8 +348,9 @@ void RuntimeLibcallsInfo::initLibcalls(const Triple &TT) {
if (TT.getArch() == Triple::ArchType::aarch64)
setAArch64LibcallNames(*this, TT);
if (TT.getArch() == Triple::ArchType::avr) {
else if (TT.isARM() || TT.isThumb())
setARMLibcallNames(*this, TT);
else if (TT.getArch() == Triple::ArchType::avr) {
// Division rtlib functions (not supported), use divmod functions instead
setLibcallName(RTLIB::SDIV_I8, nullptr);
setLibcallName(RTLIB::SDIV_I16, nullptr);

View File

@@ -1275,50 +1275,6 @@ ARMTargetLowering::ARMTargetLowering(const TargetMachine &TM,
setOperationAction(ISD::UREM, MVT::i64, Custom);
HasStandaloneRem = false;
if (Subtarget->isTargetWindows()) {
const struct {
const RTLIB::Libcall Op;
const char * const Name;
const CallingConv::ID CC;
} LibraryCalls[] = {
{ RTLIB::SDIVREM_I8, "__rt_sdiv", CallingConv::ARM_AAPCS },
{ RTLIB::SDIVREM_I16, "__rt_sdiv", CallingConv::ARM_AAPCS },
{ RTLIB::SDIVREM_I32, "__rt_sdiv", CallingConv::ARM_AAPCS },
{ RTLIB::SDIVREM_I64, "__rt_sdiv64", CallingConv::ARM_AAPCS },
{ RTLIB::UDIVREM_I8, "__rt_udiv", CallingConv::ARM_AAPCS },
{ RTLIB::UDIVREM_I16, "__rt_udiv", CallingConv::ARM_AAPCS },
{ RTLIB::UDIVREM_I32, "__rt_udiv", CallingConv::ARM_AAPCS },
{ RTLIB::UDIVREM_I64, "__rt_udiv64", CallingConv::ARM_AAPCS },
};
for (const auto &LC : LibraryCalls) {
setLibcallName(LC.Op, LC.Name);
setLibcallCallingConv(LC.Op, LC.CC);
}
} else {
const struct {
const RTLIB::Libcall Op;
const char * const Name;
const CallingConv::ID CC;
} LibraryCalls[] = {
{ RTLIB::SDIVREM_I8, "__aeabi_idivmod", CallingConv::ARM_AAPCS },
{ RTLIB::SDIVREM_I16, "__aeabi_idivmod", CallingConv::ARM_AAPCS },
{ RTLIB::SDIVREM_I32, "__aeabi_idivmod", CallingConv::ARM_AAPCS },
{ RTLIB::SDIVREM_I64, "__aeabi_ldivmod", CallingConv::ARM_AAPCS },
{ RTLIB::UDIVREM_I8, "__aeabi_uidivmod", CallingConv::ARM_AAPCS },
{ RTLIB::UDIVREM_I16, "__aeabi_uidivmod", CallingConv::ARM_AAPCS },
{ RTLIB::UDIVREM_I32, "__aeabi_uidivmod", CallingConv::ARM_AAPCS },
{ RTLIB::UDIVREM_I64, "__aeabi_uldivmod", CallingConv::ARM_AAPCS },
};
for (const auto &LC : LibraryCalls) {
setLibcallName(LC.Op, LC.Name);
setLibcallCallingConv(LC.Op, LC.CC);
}
}
setOperationAction(ISD::SDIVREM, MVT::i32, Custom);
setOperationAction(ISD::UDIVREM, MVT::i32, Custom);
setOperationAction(ISD::SDIVREM, MVT::i64, Custom);

View File

@@ -348,31 +348,11 @@ public:
bool isTargetELF() const { return TargetTriple.isOSBinFormatELF(); }
bool isTargetMachO() const { return TargetTriple.isOSBinFormatMachO(); }
// ARM EABI is the bare-metal EABI described in ARM ABI documents and
// can be accessed via -target arm-none-eabi. This is NOT GNUEABI.
// FIXME: Add a flag for bare-metal for that target and set Triple::EABI
// even for GNUEABI, so we can make a distinction here and still conform to
// the EABI on GNU (and Android) mode. This requires change in Clang, too.
// FIXME: The Darwin exception is temporary, while we move users to
// "*-*-*-macho" triples as quickly as possible.
bool isTargetAEABI() const {
return (TargetTriple.getEnvironment() == Triple::EABI ||
TargetTriple.getEnvironment() == Triple::EABIHF) &&
!isTargetDarwin() && !isTargetWindows();
}
bool isTargetGNUAEABI() const {
return (TargetTriple.getEnvironment() == Triple::GNUEABI ||
TargetTriple.getEnvironment() == Triple::GNUEABIT64 ||
TargetTriple.getEnvironment() == Triple::GNUEABIHF ||
TargetTriple.getEnvironment() == Triple::GNUEABIHFT64) &&
!isTargetDarwin() && !isTargetWindows();
}
bool isTargetMuslAEABI() const {
return (TargetTriple.getEnvironment() == Triple::MuslEABI ||
TargetTriple.getEnvironment() == Triple::MuslEABIHF ||
TargetTriple.getEnvironment() == Triple::OpenHOS) &&
!isTargetDarwin() && !isTargetWindows();
}
bool isTargetAEABI() const { return TargetTriple.isTargetAEABI(); }
bool isTargetGNUAEABI() const { return TargetTriple.isTargetGNUAEABI(); }
bool isTargetMuslAEABI() const { return TargetTriple.isTargetMuslAEABI(); }
// ARM Targets that support EHABI exception handling standard
// Darwin uses SjLj. Other targets might need more checks.