[X32] Add Triple::isX32(), use it.

So far, support for x86_64-linux-gnux32 has been handled by explicit
comparisons of Triple.getEnvironment() to GNUX32. This worked as long as
x86_64-linux-gnux32 was the only X32 environment to worry about, but we
now have x86_64-linux-muslx32 as well. To support this, this change adds
an isX32() function and uses it. It replaces all checks for GNUX32 or
MuslX32 by isX32(), except for the following:

- Triple::isGNUEnvironment() and Triple::isMusl() are supposed to treat
  GNUX32 and MuslX32 differently.
- computeTargetTriple() needs to be able to transform triples to add or
  remove X32 from the environment and needs to map GNU to GNUX32, and
  Musl to MuslX32.
- getMultiarchTriple() completely lacks any Musl support and retains the
  explicit check for GNUX32 as it can only return x86_64-linux-gnux32.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D103777
This commit is contained in:
Harald van Dijk 2021-06-07 20:48:39 +01:00
parent 6de45b9e6a
commit 75521bd9d8
No known key found for this signature in database
GPG key ID: 7D71BB318A5BD56D
14 changed files with 33 additions and 26 deletions

View file

@ -661,7 +661,7 @@ class LLVM_LIBRARY_VISIBILITY X86_64TargetInfo : public X86TargetInfo {
public:
X86_64TargetInfo(const llvm::Triple &Triple, const TargetOptions &Opts)
: X86TargetInfo(Triple, Opts) {
const bool IsX32 = getTriple().getEnvironment() == llvm::Triple::GNUX32;
const bool IsX32 = getTriple().isX32();
bool IsWinCOFF =
getTriple().isOSWindows() && getTriple().isOSBinFormatCOFF();
LongWidth = LongAlign = PointerWidth = PointerAlign = IsX32 ? 32 : 64;

View file

@ -519,14 +519,21 @@ static llvm::Triple computeTargetTriple(const Driver &D,
AT = Target.get64BitArchVariant().getArch();
if (Target.getEnvironment() == llvm::Triple::GNUX32)
Target.setEnvironment(llvm::Triple::GNU);
else if (Target.getEnvironment() == llvm::Triple::MuslX32)
Target.setEnvironment(llvm::Triple::Musl);
} else if (A->getOption().matches(options::OPT_mx32) &&
Target.get64BitArchVariant().getArch() == llvm::Triple::x86_64) {
AT = llvm::Triple::x86_64;
Target.setEnvironment(llvm::Triple::GNUX32);
if (Target.getEnvironment() == llvm::Triple::Musl)
Target.setEnvironment(llvm::Triple::MuslX32);
else
Target.setEnvironment(llvm::Triple::GNUX32);
} else if (A->getOption().matches(options::OPT_m32)) {
AT = Target.get32BitArchVariant().getArch();
if (Target.getEnvironment() == llvm::Triple::GNUX32)
Target.setEnvironment(llvm::Triple::GNU);
else if (Target.getEnvironment() == llvm::Triple::MuslX32)
Target.setEnvironment(llvm::Triple::Musl);
} else if (A->getOption().matches(options::OPT_m16) &&
Target.get32BitArchVariant().getArch() == llvm::Triple::x86) {
AT = llvm::Triple::x86;

View file

@ -294,7 +294,7 @@ static const char *getLDMOption(const llvm::Triple &T, const ArgList &Args) {
case llvm::Triple::systemz:
return "elf64_s390";
case llvm::Triple::x86_64:
if (T.getEnvironment() == llvm::Triple::GNUX32)
if (T.isX32())
return "elf32_x86_64";
return "elf_x86_64";
case llvm::Triple::ve:
@ -725,7 +725,7 @@ void tools::gnutools::Assembler::ConstructJob(Compilation &C,
CmdArgs.push_back("--32");
break;
case llvm::Triple::x86_64:
if (getToolChain().getTriple().getEnvironment() == llvm::Triple::GNUX32)
if (getToolChain().getTriple().isX32())
CmdArgs.push_back("--x32");
else
CmdArgs.push_back("--64");
@ -1733,7 +1733,7 @@ static bool findBiarchMultilibs(const Driver &D,
// Determine default multilib from: 32, 64, x32
// Also handle cases such as 64 on 32, 32 on 64, etc.
enum { UNKNOWN, WANT32, WANT64, WANTX32 } Want = UNKNOWN;
const bool IsX32 = TargetTriple.getEnvironment() == llvm::Triple::GNUX32;
const bool IsX32 = TargetTriple.isX32();
if (TargetTriple.isArch32Bit() && !NonExistent(Alt32))
Want = WANT64;
else if (TargetTriple.isArch64Bit() && IsX32 && !NonExistent(Altx32))
@ -2339,7 +2339,7 @@ void Generic_GCC::GCCInstallationDetector::AddDefaultGCCPrefixes(
TripleAliases.append(begin(AVRTriples), end(AVRTriples));
break;
case llvm::Triple::x86_64:
if (TargetTriple.getEnvironment() == llvm::Triple::GNUX32) {
if (TargetTriple.isX32()) {
LibDirs.append(begin(X32LibDirs), end(X32LibDirs));
TripleAliases.append(begin(X32Triples), end(X32Triples));
BiarchLibDirs.append(begin(X86_64LibDirs), end(X86_64LibDirs));

View file

@ -166,8 +166,7 @@ static StringRef getOSLibDir(const llvm::Triple &Triple, const ArgList &Args) {
Triple.getArch() == llvm::Triple::sparc)
return "lib32";
if (Triple.getArch() == llvm::Triple::x86_64 &&
Triple.getEnvironment() == llvm::Triple::GNUX32)
if (Triple.getArch() == llvm::Triple::x86_64 && Triple.isX32())
return "libx32";
if (Triple.getArch() == llvm::Triple::riscv32)
@ -402,9 +401,7 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
ArchName = "i386";
break;
case llvm::Triple::x86_64:
ArchName = Triple.getEnvironment() == llvm::Triple::MuslX32
? "x32"
: Triple.getArchName().str();
ArchName = Triple.isX32() ? "x32" : Triple.getArchName().str();
break;
default:
ArchName = Triple.getArchName().str();
@ -515,7 +512,7 @@ std::string Linux::getDynamicLinker(const ArgList &Args) const {
Loader = "ld-linux.so.2";
break;
case llvm::Triple::x86_64: {
bool X32 = Triple.getEnvironment() == llvm::Triple::GNUX32;
bool X32 = Triple.isX32();
LibDir = X32 ? "libx32" : "lib64";
Loader = X32 ? "ld-linux-x32.so.2" : "ld-linux-x86-64.so.2";

View file

@ -136,4 +136,6 @@
// RUN: %clang -### %s --target=x86_64-linux-muslx32 --sysroot= \
// RUN: --stdlib=platform --rtlib=platform 2>&1 | FileCheck %s --check-prefix=MUSL_X32
// RUN: %clang -### %s --target=i686-linux-musl -mx32 --sysroot= \
// RUN: --stdlib=platform --rtlib=platform 2>&1 | FileCheck %s --check-prefix=MUSL_X32
// MUSL_X32: "-dynamic-linker" "/lib/ld-musl-x32.so.1"

View file

@ -805,6 +805,12 @@ public:
getSubArch() == Triple::AArch64SubArch_arm64e;
}
/// Tests whether the target is X32.
bool isX32() const {
EnvironmentType Env = getEnvironment();
return Env == Triple::GNUX32 || Env == Triple::MuslX32;
}
/// Tests whether the target supports comdat
bool supportsCOMDAT() const {
return !(isOSBinFormatMachO() || isOSBinFormatXCOFF());

View file

@ -1631,7 +1631,7 @@ MCAsmBackend *llvm::createX86_64AsmBackend(const Target &T,
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TheTriple.getOS());
if (TheTriple.getEnvironment() == Triple::GNUX32)
if (TheTriple.isX32())
return new ELFX86_X32AsmBackend(T, OSABI, STI);
return new ELFX86_64AsmBackend(T, OSABI, STI);
}

View file

@ -81,7 +81,7 @@ void X86ELFMCAsmInfo::anchor() { }
X86ELFMCAsmInfo::X86ELFMCAsmInfo(const Triple &T) {
bool is64Bit = T.getArch() == Triple::x86_64;
bool isX32 = T.getEnvironment() == Triple::GNUX32;
bool isX32 = T.isX32();
// For ELF, x86-64 pointer size depends on the ABI.
// For x86-64 without the x32 ABI, pointer size is 8. For x86 and for x86-64

View file

@ -1231,8 +1231,7 @@ bool X86MCCodeEmitter::emitREXPrefix(int MemOperand, const MCInst &MI,
// FIXME: The caller of determineREXPrefix slaps this prefix onto
// anything that returns non-zero.
REX |= 0x40; // REX fixed encoding prefix
} else if (MO.isExpr() &&
STI.getTargetTriple().getEnvironment() == Triple::GNUX32) {
} else if (MO.isExpr() && STI.getTargetTriple().isX32()) {
// GOTTPOFF and TLSDESC relocations require a REX prefix to allow
// linker optimizations: even if the instructions we see may not require
// any prefix, they may be replaced by instructions that do. This is

View file

@ -643,8 +643,7 @@ void X86AsmPrinter::emitStartOfAsmFile(Module &M) {
OutStreamer->SwitchSection(Nt);
// Emitting note header.
const int WordSize =
TT.isArch64Bit() && TT.getEnvironment() != Triple::GNUX32 ? 8 : 4;
const int WordSize = TT.isArch64Bit() && !TT.isX32() ? 8 : 4;
emitAlignment(WordSize == 4 ? Align(4) : Align(8));
OutStreamer->emitIntValue(4, 4 /*size*/); // data size for "GNU\0"
OutStreamer->emitIntValue(8 + WordSize, 4 /*size*/); // Elf_Prop size

View file

@ -62,7 +62,7 @@ X86RegisterInfo::X86RegisterInfo(const Triple &TT)
// This matches the simplified 32-bit pointer code in the data layout
// computation.
// FIXME: Should use the data layout?
bool Use64BitReg = TT.getEnvironment() != Triple::GNUX32;
bool Use64BitReg = !TT.isX32();
StackPtr = Use64BitReg ? X86::RSP : X86::ESP;
FramePtr = Use64BitReg ? X86::RBP : X86::EBP;
BasePtr = Use64BitReg ? X86::RBX : X86::EBX;

View file

@ -610,14 +610,12 @@ public:
/// Is this x86_64 with the ILP32 programming model (x32 ABI)?
bool isTarget64BitILP32() const {
return In64BitMode && (TargetTriple.getEnvironment() == Triple::GNUX32 ||
TargetTriple.isOSNaCl());
return In64BitMode && (TargetTriple.isX32() || TargetTriple.isOSNaCl());
}
/// Is this x86_64 with the LP64 programming model (standard AMD64, no x32)?
bool isTarget64BitLP64() const {
return In64BitMode && (TargetTriple.getEnvironment() != Triple::GNUX32 &&
!TargetTriple.isOSNaCl());
return In64BitMode && (!TargetTriple.isX32() && !TargetTriple.isOSNaCl());
}
PICStyles::Style getPICStyle() const { return PICStyle; }

View file

@ -110,9 +110,7 @@ static std::string computeDataLayout(const Triple &TT) {
Ret += DataLayout::getManglingComponent(TT);
// X86 and x32 have 32 bit pointers.
if ((TT.isArch64Bit() &&
(TT.getEnvironment() == Triple::GNUX32 || TT.isOSNaCl())) ||
!TT.isArch64Bit())
if (!TT.isArch64Bit() || TT.isX32() || TT.isOSNaCl())
Ret += "-p:32:32";
// Address spaces for 32 bit signed, 32 bit unsigned, and 64 bit pointers.

View file

@ -1,5 +1,6 @@
; NOTE: Assertions have been autogenerated by utils/update_llc_test_checks.py
; RUN: llc < %s -mtriple=x86_64-linux-gnux32 -O0 | FileCheck %s
; RUN: llc < %s -mtriple=x86_64-linux-muslx32 -O0 | FileCheck %s
define void @foo(i32** %p) {
; CHECK-LABEL: foo: