diff --git a/clang/lib/Basic/Targets/PPC.h b/clang/lib/Basic/Targets/PPC.h index 9f3a4cd2da716..4cceebf6c2826 100644 --- a/clang/lib/Basic/Targets/PPC.h +++ b/clang/lib/Basic/Targets/PPC.h @@ -445,27 +445,17 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo { LongWidth = LongAlign = PointerWidth = PointerAlign = 64; IntMaxType = SignedLong; Int64Type = SignedLong; - std::string DataLayout; if (Triple.isOSAIX()) { // TODO: Set appropriate ABI for AIX platform. - DataLayout = "E-m:a-Fi64-i64:64-i128:128-n32:64"; LongDoubleWidth = 64; LongDoubleAlign = DoubleAlign = 32; LongDoubleFormat = &llvm::APFloat::IEEEdouble(); - } else if ((Triple.getArch() == llvm::Triple::ppc64le)) { - DataLayout = "e-m:e-Fn32-i64:64-i128:128-n32:64"; + } else if ((Triple.getArch() == llvm::Triple::ppc64le) || + Triple.isPPC64ELFv2ABI()) { ABI = "elfv2"; } else { - DataLayout = "E-m:e"; - if (Triple.isPPC64ELFv2ABI()) { - ABI = "elfv2"; - DataLayout += "-Fn32"; - } else { - ABI = "elfv1"; - DataLayout += "-Fi64"; - } - DataLayout += "-i64:64-i128:128-n32:64"; + ABI = "elfv1"; } if (Triple.isOSFreeBSD() || Triple.isOSOpenBSD() || Triple.isMusl()) { @@ -473,14 +463,12 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo { LongDoubleFormat = &llvm::APFloat::IEEEdouble(); } - if (Triple.isOSAIX() || Triple.isOSLinux()) - DataLayout += "-S128-v256:256:256-v512:512:512"; - resetDataLayout(DataLayout); - // Newer PPC64 instruction sets support atomics up to 16 bytes. MaxAtomicPromoteWidth = 128; // Baseline PPC64 supports inlining atomics up to 8 bytes. MaxAtomicInlineWidth = 64; + + calculateDataLayout(); } void setMaxAtomicWidth() override { @@ -495,10 +483,33 @@ class LLVM_LIBRARY_VISIBILITY PPC64TargetInfo : public PPCTargetInfo { return TargetInfo::CharPtrBuiltinVaList; } + void calculateDataLayout() { + std::string DataLayout; + + if (getTriple().isOSAIX()) { + DataLayout = "E-m:a-Fi64-i64:64-i128:128-n32:64"; + } else if ((getTriple().getArch() == llvm::Triple::ppc64le)) { + DataLayout = "e-m:e-Fn32-i64:64-i128:128-n32:64"; + } else { + DataLayout = "E-m:e"; + if (ABI == "elfv2") { + DataLayout += "-Fn32"; + } else { + DataLayout += "-Fi64"; + } + DataLayout += "-i64:64-i128:128-n32:64"; + } + + if (getTriple().isOSAIX() || getTriple().isOSLinux()) + DataLayout += "-S128-v256:256:256-v512:512:512"; + resetDataLayout(DataLayout); + } + // PPC64 Linux-specific ABI options. bool setABI(const std::string &Name) override { if (Name == "elfv1" || Name == "elfv2") { ABI = Name; + calculateDataLayout(); return true; } return false; diff --git a/clang/test/CodeGen/PowerPC/ppc64-abi-override-datalayout.c b/clang/test/CodeGen/PowerPC/ppc64-abi-override-datalayout.c new file mode 100644 index 0000000000000..30b85d24a56fd --- /dev/null +++ b/clang/test/CodeGen/PowerPC/ppc64-abi-override-datalayout.c @@ -0,0 +1,8 @@ +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -target-abi elfv2 %s -o - -emit-llvm | FileCheck %s + +// REQUIRES: powerpc-registered-target + +// Make sure that overriding the ABI to ELFv2 on a target that defaults to +// ELFv1 changes the data layout: + +// CHECK: target datalayout = "E-m:e-Fn32-i64:64-i128:128-n32:64-S128-v256:256:256-v512:512:512" diff --git a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp index 000d29610678f..4ff489d482fa5 100644 --- a/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp +++ b/llvm/lib/Target/PowerPC/PPCTargetMachine.cpp @@ -296,8 +296,9 @@ PPCTargetMachine::PPCTargetMachine(const Target &T, const Triple &TT, std::optional RM, std::optional CM, CodeGenOptLevel OL, bool JIT) - : CodeGenTargetMachineImpl(T, TT.computeDataLayout(), TT, CPU, - computeFSAdditions(FS, OL, TT), Options, + : CodeGenTargetMachineImpl(T, + TT.computeDataLayout(Options.MCOptions.ABIName), + TT, CPU, computeFSAdditions(FS, OL, TT), Options, getEffectiveRelocModel(TT, RM), getEffectivePPCCodeModel(TT, CM, JIT), OL), TLOF(createTLOF(getTargetTriple())), diff --git a/llvm/lib/TargetParser/TargetDataLayout.cpp b/llvm/lib/TargetParser/TargetDataLayout.cpp index d765d9ccb284d..d7359234b02f7 100644 --- a/llvm/lib/TargetParser/TargetDataLayout.cpp +++ b/llvm/lib/TargetParser/TargetDataLayout.cpp @@ -208,7 +208,7 @@ static std::string computeMipsDataLayout(const Triple &TT, StringRef ABIName) { return Ret; } -static std::string computePowerDataLayout(const Triple &T) { +static std::string computePowerDataLayout(const Triple &T, StringRef ABIName) { bool is64Bit = T.isPPC64(); std::string Ret; @@ -228,7 +228,8 @@ static std::string computePowerDataLayout(const Triple &T) { // If the target ABI uses function descriptors, then the alignment of function // pointers depends on the alignment used to emit the descriptor. Otherwise, // function pointers are aligned to 32 bits because the instructions must be. - if ((T.getArch() == Triple::ppc64 && !T.isPPC64ELFv2ABI())) { + if ((T.getArch() == Triple::ppc64 && + (!T.isPPC64ELFv2ABI() && ABIName != "elfv2"))) { Ret += "-Fi64"; } else if (T.isOSAIX()) { Ret += is64Bit ? "-Fi64" : "-Fi32"; @@ -573,7 +574,7 @@ std::string Triple::computeDataLayout(StringRef ABIName) const { case Triple::ppcle: case Triple::ppc64: case Triple::ppc64le: - return computePowerDataLayout(*this); + return computePowerDataLayout(*this, ABIName); case Triple::r600: case Triple::amdgcn: return computeAMDDataLayout(*this);