Skip to content

Commit

Permalink
[LLVM] [Clang] Support for Gentoo *t64 triples (64-bit time_t ABIs) (
Browse files Browse the repository at this point in the history
…llvm#111302)

Gentoo is planning to introduce a `*t64` suffix for triples that will be
used by 32-bit platforms that use 64-bit `time_t`. Add support for
parsing and accepting these triples, and while at it make clang
automatically enable the necessary glibc feature macros when this suffix
is used.

An open question is whether we can backport this to LLVM 19.x. After
all, adding new triplets to Triple sounds like an ABI change — though I
suppose we can minimize the risk of breaking something if we move new
enum values to the very end.
  • Loading branch information
mgorny authored Oct 14, 2024
1 parent f778861 commit 387b37a
Show file tree
Hide file tree
Showing 16 changed files with 136 additions and 11 deletions.
2 changes: 2 additions & 0 deletions clang/lib/Basic/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -313,7 +313,9 @@ ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
switch (Triple.getEnvironment()) {
case llvm::Triple::Android:
case llvm::Triple::GNUEABI:
case llvm::Triple::GNUEABIT64:
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABIHFT64:
case llvm::Triple::MuslEABI:
case llvm::Triple::MuslEABIHF:
case llvm::Triple::OpenHOS:
Expand Down
4 changes: 4 additions & 0 deletions clang/lib/Basic/Targets/OSTargets.h
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,10 @@ class LLVM_LIBRARY_VISIBILITY LinuxTargetInfo : public OSTargetInfo<Target> {
Builder.defineMacro("_GNU_SOURCE");
if (this->HasFloat128)
Builder.defineMacro("__FLOAT128__");
if (Triple.isTime64ABI()) {
Builder.defineMacro("_FILE_OFFSET_BITS", "64");
Builder.defineMacro("_TIME_BITS", "64");
}
}

public:
Expand Down
5 changes: 1 addition & 4 deletions clang/lib/CodeGen/CodeGenModule.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -175,10 +175,7 @@ createTargetCodeGenInfo(CodeGenModule &CGM) {
else if (ABIStr == "aapcs16")
Kind = ARMABIKind::AAPCS16_VFP;
else if (CodeGenOpts.FloatABI == "hard" ||
(CodeGenOpts.FloatABI != "soft" &&
(Triple.getEnvironment() == llvm::Triple::GNUEABIHF ||
Triple.getEnvironment() == llvm::Triple::MuslEABIHF ||
Triple.getEnvironment() == llvm::Triple::EABIHF)))
(CodeGenOpts.FloatABI != "soft" && Triple.isHardFloatABI()))
Kind = ARMABIKind::AAPCS_VFP;

return createARMTargetCodeGenInfo(CGM, Kind);
Expand Down
3 changes: 3 additions & 0 deletions clang/lib/CodeGen/Targets/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,9 @@ class ARMABIInfo : public ABIInfo {
case llvm::Triple::EABI:
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABI:
case llvm::Triple::GNUEABIT64:
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABIHFT64:
case llvm::Triple::MuslEABI:
case llvm::Triple::MuslEABIHF:
return true;
Expand All @@ -48,6 +50,7 @@ class ARMABIInfo : public ABIInfo {
switch (getTarget().getTriple().getEnvironment()) {
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABIHFT64:
case llvm::Triple::MuslEABIHF:
return true;
default:
Expand Down
5 changes: 4 additions & 1 deletion clang/lib/Driver/Driver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -610,7 +610,8 @@ static llvm::Triple computeTargetTriple(const Driver &D,
if (A->getOption().matches(options::OPT_m64) ||
A->getOption().matches(options::OPT_maix64)) {
AT = Target.get64BitArchVariant().getArch();
if (Target.getEnvironment() == llvm::Triple::GNUX32)
if (Target.getEnvironment() == llvm::Triple::GNUX32 ||
Target.getEnvironment() == llvm::Triple::GNUT64)
Target.setEnvironment(llvm::Triple::GNU);
else if (Target.getEnvironment() == llvm::Triple::MuslX32)
Target.setEnvironment(llvm::Triple::Musl);
Expand Down Expand Up @@ -673,6 +674,7 @@ static llvm::Triple computeTargetTriple(const Driver &D,
} else if (ABIName == "n32") {
Target = Target.get64BitArchVariant();
if (Target.getEnvironment() == llvm::Triple::GNU ||
Target.getEnvironment() == llvm::Triple::GNUT64 ||
Target.getEnvironment() == llvm::Triple::GNUABI64)
Target.setEnvironment(llvm::Triple::GNUABIN32);
else if (Target.getEnvironment() == llvm::Triple::Musl ||
Expand All @@ -681,6 +683,7 @@ static llvm::Triple computeTargetTriple(const Driver &D,
} else if (ABIName == "64") {
Target = Target.get64BitArchVariant();
if (Target.getEnvironment() == llvm::Triple::GNU ||
Target.getEnvironment() == llvm::Triple::GNUT64 ||
Target.getEnvironment() == llvm::Triple::GNUABIN32)
Target.setEnvironment(llvm::Triple::GNUABI64);
else if (Target.getEnvironment() == llvm::Triple::Musl ||
Expand Down
7 changes: 7 additions & 0 deletions clang/lib/Driver/ToolChains/Arch/ARM.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -327,6 +327,11 @@ void arm::setFloatABIInTriple(const Driver &D, const ArgList &Args,
Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHF
: llvm::Triple::GNUEABI);
break;
case llvm::Triple::GNUEABIT64:
case llvm::Triple::GNUEABIHFT64:
Triple.setEnvironment(isHardFloat ? llvm::Triple::GNUEABIHFT64
: llvm::Triple::GNUEABIT64);
break;
case llvm::Triple::EABI:
case llvm::Triple::EABIHF:
Triple.setEnvironment(isHardFloat ? llvm::Triple::EABIHF
Expand Down Expand Up @@ -414,10 +419,12 @@ arm::FloatABI arm::getDefaultFloatABI(const llvm::Triple &Triple) {
return FloatABI::Soft;
switch (Triple.getEnvironment()) {
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABIHFT64:
case llvm::Triple::MuslEABIHF:
case llvm::Triple::EABIHF:
return FloatABI::Hard;
case llvm::Triple::GNUEABI:
case llvm::Triple::GNUEABIT64:
case llvm::Triple::MuslEABI:
case llvm::Triple::EABI:
// EABI is always AAPCS, and if it was not marked 'hard', it's softfp
Expand Down
2 changes: 2 additions & 0 deletions clang/lib/Driver/ToolChains/Gnu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2698,6 +2698,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
case llvm::Triple::thumb:
LibDirs.append(begin(ARMLibDirs), end(ARMLibDirs));
if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||
TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||
TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||
TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {
TripleAliases.append(begin(ARMHFTriples), end(ARMHFTriples));
Expand All @@ -2709,6 +2710,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
case llvm::Triple::thumbeb:
LibDirs.append(begin(ARMebLibDirs), end(ARMebLibDirs));
if (TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHF ||
TargetTriple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||
TargetTriple.getEnvironment() == llvm::Triple::MuslEABIHF ||
TargetTriple.getEnvironment() == llvm::Triple::EABIHF) {
TripleAliases.append(begin(ARMebHFTriples), end(ARMebHFTriples));
Expand Down
1 change: 1 addition & 0 deletions clang/lib/Driver/ToolChains/Linux.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,7 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
case llvm::Triple::thumbeb: {
const bool HF =
Triple.getEnvironment() == llvm::Triple::GNUEABIHF ||
Triple.getEnvironment() == llvm::Triple::GNUEABIHFT64 ||
tools::arm::getARMFloatABI(*this, Args) == tools::arm::FloatABI::Hard;

LibDir = "lib";
Expand Down
12 changes: 12 additions & 0 deletions clang/test/Preprocessor/time64.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
// RUN: %clang_cc1 -E -dM -triple=i686-pc-linux-gnu /dev/null | FileCheck -match-full-lines -check-prefix TIME32 %s
// RUN: %clang_cc1 -E -dM -triple=i686-pc-linux-gnut64 /dev/null | FileCheck -match-full-lines -check-prefix TIME64 %s
// RUN: %clang_cc1 -E -dM -triple=armv5tel-softfloat-linux-gnueabi /dev/null | FileCheck -match-full-lines -check-prefix TIME32 %s
// RUN: %clang_cc1 -E -dM -triple=armv5tel-softfloat-linux-gnueabit64 /dev/null | FileCheck -match-full-lines -check-prefix TIME64 %s
// RUN: %clang_cc1 -E -dM -triple=armv7a-unknown-linux-gnueabihf /dev/null | FileCheck -match-full-lines -check-prefix TIME32 %s
// RUN: %clang_cc1 -E -dM -triple=armv7a-unknown-linux-gnueabihft64 /dev/null | FileCheck -match-full-lines -check-prefix TIME64 %s
//
// TIME32-NOT:#define _FILE_OFFSET_BITS 64
// TIME32-NOT:#define _TIME_BITS 64
//
// TIME64:#define _FILE_OFFSET_BITS 64
// TIME64:#define _TIME_BITS 64
32 changes: 27 additions & 5 deletions llvm/include/llvm/TargetParser/Triple.h
Original file line number Diff line number Diff line change
Expand Up @@ -244,10 +244,13 @@ class Triple {
UnknownEnvironment,

GNU,
GNUT64,
GNUABIN32,
GNUABI64,
GNUEABI,
GNUEABIT64,
GNUEABIHF,
GNUEABIHFT64,
GNUF32,
GNUF64,
GNUSF,
Expand Down Expand Up @@ -608,11 +611,12 @@ class Triple {

bool isGNUEnvironment() const {
EnvironmentType Env = getEnvironment();
return Env == Triple::GNU || Env == Triple::GNUABIN32 ||
Env == Triple::GNUABI64 || Env == Triple::GNUEABI ||
Env == Triple::GNUEABIHF || Env == Triple::GNUF32 ||
Env == Triple::GNUF64 || Env == Triple::GNUSF ||
Env == Triple::GNUX32;
return Env == Triple::GNU || Env == Triple::GNUT64 ||
Env == Triple::GNUABIN32 || Env == Triple::GNUABI64 ||
Env == Triple::GNUEABI || Env == Triple::GNUEABIT64 ||
Env == Triple::GNUEABIHF || Env == Triple::GNUEABIHFT64 ||
Env == Triple::GNUF32 || Env == Triple::GNUF64 ||
Env == Triple::GNUSF || Env == Triple::GNUX32;
}

/// Tests whether the OS is Haiku.
Expand Down Expand Up @@ -873,9 +877,11 @@ class Triple {
return (isARM() || isThumb()) &&
(getEnvironment() == Triple::EABI ||
getEnvironment() == Triple::GNUEABI ||
getEnvironment() == Triple::GNUEABIT64 ||
getEnvironment() == Triple::MuslEABI ||
getEnvironment() == Triple::EABIHF ||
getEnvironment() == Triple::GNUEABIHF ||
getEnvironment() == Triple::GNUEABIHFT64 ||
getEnvironment() == Triple::OpenHOS ||
getEnvironment() == Triple::MuslEABIHF || isAndroid()) &&
isOSBinFormatELF();
Expand Down Expand Up @@ -1059,6 +1065,22 @@ class Triple {
return getArch() == Triple::bpfel || getArch() == Triple::bpfeb;
}

/// Tests if the target forces 64-bit time_t on a 32-bit architecture.
bool isTime64ABI() const {
EnvironmentType Env = getEnvironment();
return Env == Triple::GNUT64 || Env == Triple::GNUEABIT64 ||
Env == Triple::GNUEABIHFT64;
}

/// Tests if the target forces hardfloat.
bool isHardFloatABI() const {
EnvironmentType Env = getEnvironment();
return Env == llvm::Triple::GNUEABIHF ||
Env == llvm::Triple::GNUEABIHFT64 ||
Env == llvm::Triple::MuslEABIHF ||
Env == llvm::Triple::EABIHF;
}

/// Tests whether the target supports comdat
bool supportsCOMDAT() const {
return !(isOSBinFormatMachO() || isOSBinFormatXCOFF() ||
Expand Down
4 changes: 3 additions & 1 deletion llvm/lib/Target/ARM/ARMSubtarget.h
Original file line number Diff line number Diff line change
Expand Up @@ -344,7 +344,9 @@ class ARMSubtarget : public ARMGenSubtargetInfo {
}
bool isTargetGNUAEABI() const {
return (TargetTriple.getEnvironment() == Triple::GNUEABI ||
TargetTriple.getEnvironment() == Triple::GNUEABIHF) &&
TargetTriple.getEnvironment() == Triple::GNUEABIT64 ||
TargetTriple.getEnvironment() == Triple::GNUEABIHF ||
TargetTriple.getEnvironment() == Triple::GNUEABIHFT64) &&
!isTargetDarwin() && !isTargetWindows();
}
bool isTargetMuslAEABI() const {
Expand Down
2 changes: 2 additions & 0 deletions llvm/lib/Target/ARM/ARMTargetMachine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,9 @@ ARMBaseTargetMachine::ARMBaseTargetMachine(const Target &T, const Triple &TT,
Options.EABIVersion == EABI::Unknown) {
// musl is compatible with glibc with regard to EABI version
if ((TargetTriple.getEnvironment() == Triple::GNUEABI ||
TargetTriple.getEnvironment() == Triple::GNUEABIT64 ||
TargetTriple.getEnvironment() == Triple::GNUEABIHF ||
TargetTriple.getEnvironment() == Triple::GNUEABIHFT64 ||
TargetTriple.getEnvironment() == Triple::MuslEABI ||
TargetTriple.getEnvironment() == Triple::MuslEABIHF ||
TargetTriple.getEnvironment() == Triple::OpenHOS) &&
Expand Down
1 change: 1 addition & 0 deletions llvm/lib/Target/ARM/ARMTargetMachine.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ class ARMBaseTargetMachine : public LLVMTargetMachine {

bool isTargetHardFloat() const {
return TargetTriple.getEnvironment() == Triple::GNUEABIHF ||
TargetTriple.getEnvironment() == Triple::GNUEABIHFT64 ||
TargetTriple.getEnvironment() == Triple::MuslEABIHF ||
TargetTriple.getEnvironment() == Triple::EABIHF ||
(TargetTriple.isOSBinFormatMachO() &&
Expand Down
3 changes: 3 additions & 0 deletions llvm/lib/TargetParser/ARMTargetParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -556,7 +556,9 @@ StringRef ARM::computeDefaultTargetABI(const Triple &TT, StringRef CPU) {
switch (TT.getEnvironment()) {
case Triple::Android:
case Triple::GNUEABI:
case Triple::GNUEABIT64:
case Triple::GNUEABIHF:
case Triple::GNUEABIHFT64:
case Triple::MuslEABI:
case Triple::MuslEABIHF:
case Triple::OpenHOS:
Expand Down Expand Up @@ -637,6 +639,7 @@ StringRef ARM::getARMCPUForArch(const llvm::Triple &Triple, StringRef MArch) {
switch (Triple.getEnvironment()) {
case llvm::Triple::EABIHF:
case llvm::Triple::GNUEABIHF:
case llvm::Triple::GNUEABIHFT64:
case llvm::Triple::MuslEABIHF:
return "arm1176jzf-s";
default:
Expand Down
6 changes: 6 additions & 0 deletions llvm/lib/TargetParser/Triple.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -312,10 +312,13 @@ StringRef Triple::getEnvironmentTypeName(EnvironmentType Kind) {
case EABI: return "eabi";
case EABIHF: return "eabihf";
case GNU: return "gnu";
case GNUT64: return "gnut64";
case GNUABI64: return "gnuabi64";
case GNUABIN32: return "gnuabin32";
case GNUEABI: return "gnueabi";
case GNUEABIT64: return "gnueabit64";
case GNUEABIHF: return "gnueabihf";
case GNUEABIHFT64: return "gnueabihft64";
case GNUF32: return "gnuf32";
case GNUF64: return "gnuf64";
case GNUSF: return "gnusf";
Expand Down Expand Up @@ -692,14 +695,17 @@ static Triple::EnvironmentType parseEnvironment(StringRef EnvironmentName) {
.StartsWith("eabi", Triple::EABI)
.StartsWith("gnuabin32", Triple::GNUABIN32)
.StartsWith("gnuabi64", Triple::GNUABI64)
.StartsWith("gnueabihft64", Triple::GNUEABIHFT64)
.StartsWith("gnueabihf", Triple::GNUEABIHF)
.StartsWith("gnueabit64", Triple::GNUEABIT64)
.StartsWith("gnueabi", Triple::GNUEABI)
.StartsWith("gnuf32", Triple::GNUF32)
.StartsWith("gnuf64", Triple::GNUF64)
.StartsWith("gnusf", Triple::GNUSF)
.StartsWith("gnux32", Triple::GNUX32)
.StartsWith("gnu_ilp32", Triple::GNUILP32)
.StartsWith("code16", Triple::CODE16)
.StartsWith("gnut64", Triple::GNUT64)
.StartsWith("gnu", Triple::GNU)
.StartsWith("android", Triple::Android)
.StartsWith("muslabin32", Triple::MuslABIN32)
Expand Down
58 changes: 58 additions & 0 deletions llvm/unittests/TargetParser/TripleTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,13 @@ TEST(TripleTest, ParsedIDs) {
EXPECT_EQ(Triple::Hurd, T.getOS());
EXPECT_EQ(Triple::GNU, T.getEnvironment());

T = Triple("i686-pc-linux-gnu");
EXPECT_EQ(Triple::x86, T.getArch());
EXPECT_EQ(Triple::PC, T.getVendor());
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::GNU, T.getEnvironment());
EXPECT_FALSE(T.isTime64ABI());

T = Triple("x86_64-pc-linux-gnu");
EXPECT_EQ(Triple::x86_64, T.getArch());
EXPECT_EQ(Triple::PC, T.getVendor());
Expand Down Expand Up @@ -187,24 +194,52 @@ TEST(TripleTest, ParsedIDs) {
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());
EXPECT_EQ(Triple::EABI, T.getEnvironment());
EXPECT_FALSE(T.isHardFloatABI());

T = Triple("arm-none-none-eabihf");
EXPECT_EQ(Triple::arm, T.getArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::UnknownOS, T.getOS());
EXPECT_EQ(Triple::EABIHF, T.getEnvironment());
EXPECT_TRUE(T.isHardFloatABI());

T = Triple("arm-none-linux-musleabi");
EXPECT_EQ(Triple::arm, T.getArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::MuslEABI, T.getEnvironment());
EXPECT_FALSE(T.isHardFloatABI());

T = Triple("arm-none-linux-musleabihf");
EXPECT_EQ(Triple::arm, T.getArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::MuslEABIHF, T.getEnvironment());
EXPECT_TRUE(T.isHardFloatABI());

T = Triple("armv6hl-none-linux-gnueabi");
EXPECT_EQ(Triple::arm, T.getArch());
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::GNUEABI, T.getEnvironment());
EXPECT_FALSE(T.isTime64ABI());
EXPECT_FALSE(T.isHardFloatABI());

T = Triple("armv7hl-none-linux-gnueabi");
EXPECT_EQ(Triple::arm, T.getArch());
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::GNUEABI, T.getEnvironment());
EXPECT_FALSE(T.isTime64ABI());
EXPECT_FALSE(T.isHardFloatABI());

T = Triple("armv7hl-none-linux-gnueabihf");
EXPECT_EQ(Triple::arm, T.getArch());
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::GNUEABIHF, T.getEnvironment());
EXPECT_FALSE(T.isTime64ABI());
EXPECT_TRUE(T.isHardFloatABI());

T = Triple("amdil-unknown-unknown");
EXPECT_EQ(Triple::amdil, T.getArch());
Expand Down Expand Up @@ -1283,6 +1318,29 @@ TEST(TripleTest, ParsedIDs) {
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::PAuthTest, T.getEnvironment());

// Gentoo time64 triples
T = Triple("i686-pc-linux-gnut64");
EXPECT_EQ(Triple::x86, T.getArch());
EXPECT_EQ(Triple::PC, T.getVendor());
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::GNUT64, T.getEnvironment());
EXPECT_TRUE(T.isTime64ABI());

T = Triple("armv5tel-softfloat-linux-gnueabit64");
EXPECT_EQ(Triple::arm, T.getArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::GNUEABIT64, T.getEnvironment());
EXPECT_TRUE(T.isTime64ABI());

T = Triple("armv7a-unknown-linux-gnueabihft64");
EXPECT_EQ(Triple::arm, T.getArch());
EXPECT_EQ(Triple::UnknownVendor, T.getVendor());
EXPECT_EQ(Triple::Linux, T.getOS());
EXPECT_EQ(Triple::GNUEABIHFT64, T.getEnvironment());
EXPECT_TRUE(T.isTime64ABI());
EXPECT_TRUE(T.isHardFloatABI());

T = Triple("huh");
EXPECT_EQ(Triple::UnknownArch, T.getArch());
}
Expand Down

0 comments on commit 387b37a

Please sign in to comment.