diff options
Diffstat (limited to 'clang')
-rw-r--r-- | clang/lib/Basic/Targets.cpp | 28 | ||||
-rw-r--r-- | clang/lib/CodeGen/TargetInfo.cpp | 8 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.cpp | 46 | ||||
-rw-r--r-- | clang/lib/Driver/Tools.h | 6 | ||||
-rw-r--r-- | clang/test/CodeGen/ppc64-elf-abi.c | 40 | ||||
-rw-r--r-- | clang/test/Driver/linux-ld.c | 35 | ||||
-rw-r--r-- | clang/test/Driver/ppc-abi.c | 19 | ||||
-rw-r--r-- | clang/test/Preprocessor/init.c | 9 |
8 files changed, 184 insertions, 7 deletions
diff --git a/clang/lib/Basic/Targets.cpp b/clang/lib/Basic/Targets.cpp index 3a80d0f2ac0..08d6bdd4d15 100644 --- a/clang/lib/Basic/Targets.cpp +++ b/clang/lib/Basic/Targets.cpp @@ -682,6 +682,9 @@ class PPCTargetInfo : public TargetInfo { // Target cpu features. bool HasVSX; +protected: + std::string ABI; + public: PPCTargetInfo(const llvm::Triple &Triple) : TargetInfo(Triple), HasVSX(false) { @@ -770,6 +773,9 @@ public: return CPUKnown; } + + StringRef getABI() const override { return ABI; } + void getTargetBuiltins(const Builtin::Info *&Records, unsigned &NumRecords) const override { Records = BuiltinInfo; @@ -965,13 +971,18 @@ void PPCTargetInfo::getTargetDefines(const LangOptions &Opts, // Target properties. if (getTriple().getArch() == llvm::Triple::ppc64le) { Builder.defineMacro("_LITTLE_ENDIAN"); - Builder.defineMacro("_CALL_ELF","2"); } else { if (getTriple().getOS() != llvm::Triple::NetBSD && getTriple().getOS() != llvm::Triple::OpenBSD) Builder.defineMacro("_BIG_ENDIAN"); } + // ABI options. + if (ABI == "elfv1") + Builder.defineMacro("_CALL_ELF", "1"); + if (ABI == "elfv2") + Builder.defineMacro("_CALL_ELF", "2"); + // Subtarget options. Builder.defineMacro("__NATURAL_ALIGNMENT__"); Builder.defineMacro("__REGISTER_PREFIX__", ""); @@ -1121,6 +1132,9 @@ void PPCTargetInfo::getDefaultFeatures(llvm::StringMap<bool> &Features) const { .Default(false); Features["qpx"] = (CPU == "a2q"); + + if (!ABI.empty()) + Features[ABI] = true; } bool PPCTargetInfo::hasFeature(StringRef Feature) const { @@ -1283,10 +1297,12 @@ public: } else { if ((Triple.getArch() == llvm::Triple::ppc64le)) { DescriptionString = "e-m:e-i64:64-n32:64"; + ABI = "elfv2"; } else { DescriptionString = "E-m:e-i64:64-n32:64"; + ABI = "elfv1"; } -} + } // PPC64 supports atomics up to 8 bytes. MaxAtomicPromoteWidth = MaxAtomicInlineWidth = 64; @@ -1294,6 +1310,14 @@ public: BuiltinVaListKind getBuiltinVaListKind() const override { return TargetInfo::CharPtrBuiltinVaList; } + // PPC64 Linux-specifc ABI options. + bool setABI(const std::string &Name) override { + if (Name == "elfv1" || Name == "elfv2") { + ABI = Name; + return true; + } + return false; + } }; } // end anonymous namespace. diff --git a/clang/lib/CodeGen/TargetInfo.cpp b/clang/lib/CodeGen/TargetInfo.cpp index 1a1ac8bd925..ca99ba580a5 100644 --- a/clang/lib/CodeGen/TargetInfo.cpp +++ b/clang/lib/CodeGen/TargetInfo.cpp @@ -6799,16 +6799,20 @@ const TargetCodeGenInfo &CodeGenModule::getTargetCodeGenInfo() { return *(TheTargetCodeGenInfo = new PPC32TargetCodeGenInfo(Types)); case llvm::Triple::ppc64: if (Triple.isOSBinFormatELF()) { - // FIXME: Should be switchable via command-line option. PPC64_SVR4_ABIInfo::ABIKind Kind = PPC64_SVR4_ABIInfo::ELFv1; + if (getTarget().getABI() == "elfv2") + Kind = PPC64_SVR4_ABIInfo::ELFv2; + return *(TheTargetCodeGenInfo = new PPC64_SVR4_TargetCodeGenInfo(Types, Kind)); } else return *(TheTargetCodeGenInfo = new PPC64TargetCodeGenInfo(Types)); case llvm::Triple::ppc64le: { assert(Triple.isOSBinFormatELF() && "PPC64 LE non-ELF not supported!"); - // FIXME: Should be switchable via command-line option. PPC64_SVR4_ABIInfo::ABIKind Kind = PPC64_SVR4_ABIInfo::ELFv2; + if (getTarget().getABI() == "elfv1") + Kind = PPC64_SVR4_ABIInfo::ELFv1; + return *(TheTargetCodeGenInfo = new PPC64_SVR4_TargetCodeGenInfo(Types, Kind)); } diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 403642e736e..adbe0944891 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -1228,6 +1228,35 @@ static void getPPCTargetFeatures(const ArgList &Args, options::OPT_fno_altivec, "altivec"); } +void Clang::AddPPCTargetArgs(const ArgList &Args, + ArgStringList &CmdArgs) const { + // Select the ABI to use. + const char *ABIName = nullptr; + if (Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) { + ABIName = A->getValue(); + } else if (getToolChain().getTriple().isOSLinux()) + switch(getToolChain().getArch()) { + case llvm::Triple::ppc64: + ABIName = "elfv1"; + break; + case llvm::Triple::ppc64le: + ABIName = "elfv2"; + break; + default: + break; + } + + if (ABIName) { + CmdArgs.push_back("-target-abi"); + CmdArgs.push_back(ABIName); + } +} + +bool ppc::hasPPCAbiArg(const ArgList &Args, const char *Value) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue() == StringRef(Value)); +} + /// Get the (LLVM) name of the R600 gpu we are targeting. static std::string getR600TargetGPU(const ArgList &Args) { if (Arg *A = Args.getLastArg(options::OPT_mcpu_EQ)) { @@ -3021,6 +3050,12 @@ void Clang::ConstructJob(Compilation &C, const JobAction &JA, AddMIPSTargetArgs(Args, CmdArgs); break; + case llvm::Triple::ppc: + case llvm::Triple::ppc64: + case llvm::Triple::ppc64le: + AddPPCTargetArgs(Args, CmdArgs); + break; + case llvm::Triple::sparc: case llvm::Triple::sparcv9: AddSparcTargetArgs(Args, CmdArgs); @@ -7212,11 +7247,16 @@ static StringRef getLinuxDynamicLinker(const ArgList &Args, ? "/lib64/ld-linux-mipsn8.so.1" : "/lib64/ld.so.1"; } else if (ToolChain.getArch() == llvm::Triple::ppc) return "/lib/ld.so.1"; - else if (ToolChain.getArch() == llvm::Triple::ppc64 || - ToolChain.getArch() == llvm::Triple::systemz) + else if (ToolChain.getArch() == llvm::Triple::ppc64) { + if (ppc::hasPPCAbiArg(Args, "elfv2")) + return "/lib64/ld64.so.2"; return "/lib64/ld64.so.1"; - else if (ToolChain.getArch() == llvm::Triple::ppc64le) + } else if (ToolChain.getArch() == llvm::Triple::ppc64le) { + if (ppc::hasPPCAbiArg(Args, "elfv1")) + return "/lib64/ld64.so.1"; return "/lib64/ld64.so.2"; + } else if (ToolChain.getArch() == llvm::Triple::systemz) + return "/lib64/ld64.so.1"; else if (ToolChain.getArch() == llvm::Triple::sparcv9) return "/lib64/ld-linux.so.2"; else if (ToolChain.getArch() == llvm::Triple::x86_64 && diff --git a/clang/lib/Driver/Tools.h b/clang/lib/Driver/Tools.h index 4c89676e0e1..1b314111789 100644 --- a/clang/lib/Driver/Tools.h +++ b/clang/lib/Driver/Tools.h @@ -63,6 +63,8 @@ using llvm::opt::ArgStringList; llvm::opt::ArgStringList &CmdArgs) const; void AddMIPSTargetArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; + void AddPPCTargetArgs(const llvm::opt::ArgList &Args, + llvm::opt::ArgStringList &CmdArgs) const; void AddR600TargetArgs(const llvm::opt::ArgList &Args, llvm::opt::ArgStringList &CmdArgs) const; void AddSparcTargetArgs(const llvm::opt::ArgList &Args, @@ -226,6 +228,10 @@ namespace mips { StringRef ABIName); } +namespace ppc { + bool hasPPCAbiArg(const llvm::opt::ArgList &Args, const char *Value); +} + namespace darwin { llvm::Triple::ArchType getArchTypeForMachOArchName(StringRef Str); void setTripleTypeForMachOArchName(llvm::Triple &T, StringRef Str); diff --git a/clang/test/CodeGen/ppc64-elf-abi.c b/clang/test/CodeGen/ppc64-elf-abi.c new file mode 100644 index 00000000000..0dd183e2a6d --- /dev/null +++ b/clang/test/CodeGen/ppc64-elf-abi.c @@ -0,0 +1,40 @@ +// REQUIRES: powerpc-registered-target + +// Verify ABI selection by the front end + +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=CHECK-ELFv1 +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: -target-abi elfv1 | FileCheck %s --check-prefix=CHECK-ELFv1 +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: -target-abi elfv2 | FileCheck %s --check-prefix=CHECK-ELFv2 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: | FileCheck %s --check-prefix=CHECK-ELFv2 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: -target-abi elfv1 | FileCheck %s --check-prefix=CHECK-ELFv1 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -emit-llvm -o - %s \ +// RUN: -target-abi elfv2 | FileCheck %s --check-prefix=CHECK-ELFv2 + +// CHECK-ELFv1: define void @func_fab(%struct.fab* noalias sret %agg.result, i64 %x.coerce) +// CHECK-ELFv2: define [2 x float] @func_fab([2 x float] %x.coerce) +struct fab { float a; float b; }; +struct fab func_fab(struct fab x) { return x; } + +// Verify ABI choice is passed on to the back end + +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -S -o - %s \ +// RUN: | FileCheck %s --check-prefix=CHECK-ASM-ELFv1 +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -S -o - %s \ +// RUN: -target-abi elfv1 | FileCheck %s --check-prefix=CHECK-ASM-ELFv1 +// RUN: %clang_cc1 -triple powerpc64-unknown-linux-gnu -S -o - %s \ +// RUN: -target-abi elfv2 | FileCheck %s --check-prefix=CHECK-ASM-ELFv2 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -S -o - %s \ +// RUN: | FileCheck %s --check-prefix=CHECK-ASM-ELFv2 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -S -o - %s \ +// RUN: -target-abi elfv1 | FileCheck %s --check-prefix=CHECK-ASM-ELFv1 +// RUN: %clang_cc1 -triple powerpc64le-unknown-linux-gnu -S -o - %s \ +// RUN: -target-abi elfv2 | FileCheck %s --check-prefix=CHECK-ASM-ELFv2 + +// CHECK-ASM-ELFv2: .abiversion 2 +// CHECK-ASM-ELFv1-NOT: .abiversion 2 + diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index 6a47d08274d..dbdaaa1e1c4 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -524,12 +524,47 @@ // CHECK-ARM-HF: "-dynamic-linker" "{{.*}}/lib/ld-linux-armhf.so.3" // // RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: --target=powerpc64-linux-gnu \ +// RUN: | FileCheck --check-prefix=CHECK-PPC64 %s +// CHECK-PPC64: "{{.*}}ld{{(.exe)?}}" +// CHECK-PPC64: "-m" "elf64ppc" +// CHECK-PPC64: "-dynamic-linker" "{{.*}}/lib64/ld64.so.1" +// +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: --target=powerpc64-linux-gnu -mabi=elfv1 \ +// RUN: | FileCheck --check-prefix=CHECK-PPC64-ELFv1 %s +// CHECK-PPC64-ELFv1: "{{.*}}ld{{(.exe)?}}" +// CHECK-PPC64-ELFv1: "-m" "elf64ppc" +// CHECK-PPC64-ELFv1: "-dynamic-linker" "{{.*}}/lib64/ld64.so.1" +// +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: --target=powerpc64-linux-gnu -mabi=elfv2 \ +// RUN: | FileCheck --check-prefix=CHECK-PPC64-ELFv2 %s +// CHECK-PPC64-ELFv2: "{{.*}}ld{{(.exe)?}}" +// CHECK-PPC64-ELFv2: "-m" "elf64ppc" +// CHECK-PPC64-ELFv2: "-dynamic-linker" "{{.*}}/lib64/ld64.so.2" +// +// RUN: %clang %s -### -o %t.o 2>&1 \ // RUN: --target=powerpc64le-linux-gnu \ // RUN: | FileCheck --check-prefix=CHECK-PPC64LE %s // CHECK-PPC64LE: "{{.*}}ld{{(.exe)?}}" // CHECK-PPC64LE: "-m" "elf64lppc" // CHECK-PPC64LE: "-dynamic-linker" "{{.*}}/lib64/ld64.so.2" // +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: --target=powerpc64le-linux-gnu -mabi=elfv1 \ +// RUN: | FileCheck --check-prefix=CHECK-PPC64LE-ELFv1 %s +// CHECK-PPC64LE-ELFv1: "{{.*}}ld{{(.exe)?}}" +// CHECK-PPC64LE-ELFv1: "-m" "elf64lppc" +// CHECK-PPC64LE-ELFv1: "-dynamic-linker" "{{.*}}/lib64/ld64.so.1" +// +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: --target=powerpc64le-linux-gnu -mabi=elfv2 \ +// RUN: | FileCheck --check-prefix=CHECK-PPC64LE-ELFv2 %s +// CHECK-PPC64LE-ELFv2: "{{.*}}ld{{(.exe)?}}" +// CHECK-PPC64LE-ELFv2: "-m" "elf64lppc" +// CHECK-PPC64LE-ELFv2: "-dynamic-linker" "{{.*}}/lib64/ld64.so.2" +// // Check that we do not pass --hash-style=gnu and --hash-style=both to linker // and provide correct path to the dynamic linker and emulation mode when build // for MIPS platforms. diff --git a/clang/test/Driver/ppc-abi.c b/clang/test/Driver/ppc-abi.c new file mode 100644 index 00000000000..6fee63a303c --- /dev/null +++ b/clang/test/Driver/ppc-abi.c @@ -0,0 +1,19 @@ +// Check passing PowerPC ABI options to the backend. + +// RUN: %clang -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv1 %s +// RUN: %clang -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \ +// RUN: -mabi=elfv1 | FileCheck -check-prefix=CHECK-ELFv1 %s +// RUN: %clang -target powerpc64-unknown-linux-gnu %s -### -o %t.o 2>&1 \ +// RUN: -mabi=elfv2 | FileCheck -check-prefix=CHECK-ELFv2 %s + +// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \ +// RUN: | FileCheck -check-prefix=CHECK-ELFv2 %s +// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \ +// RUN: -mabi=elfv1 | FileCheck -check-prefix=CHECK-ELFv1 %s +// RUN: %clang -target powerpc64le-unknown-linux-gnu %s -### -o %t.o 2>&1 \ +// RUN: -mabi=elfv2 | FileCheck -check-prefix=CHECK-ELFv2 %s + +// CHECK-ELFv1: "-target-abi" "elfv1" +// CHECK-ELFv2: "-target-abi" "elfv2" + diff --git a/clang/test/Preprocessor/init.c b/clang/test/Preprocessor/init.c index 48f586a7de3..3342225ddc9 100644 --- a/clang/test/Preprocessor/init.c +++ b/clang/test/Preprocessor/init.c @@ -4916,6 +4916,15 @@ // PPC64-LINUX:#define __powerpc__ 1 // PPC64-LINUX:#define __ppc64__ 1 // PPC64-LINUX:#define __ppc__ 1 + +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu < /dev/null | FileCheck -check-prefix PPC64-ELFv1 %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -target-abi elfv1 < /dev/null | FileCheck -check-prefix PPC64-ELFv1 %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64-unknown-linux-gnu -target-abi elfv2 < /dev/null | FileCheck -check-prefix PPC64-ELFv2 %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64le-unknown-linux-gnu < /dev/null | FileCheck -check-prefix PPC64-ELFv2 %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64le-unknown-linux-gnu -target-abi elfv1 < /dev/null | FileCheck -check-prefix PPC64-ELFv1 %s +// RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc64le-unknown-linux-gnu -target-abi elfv2 < /dev/null | FileCheck -check-prefix PPC64-ELFv2 %s +// PPC64-ELFv1:#define _CALL_ELF 1 +// PPC64-ELFv2:#define _CALL_ELF 2 // // RUN: %clang_cc1 -E -dM -ffreestanding -triple=powerpc-none-none -fno-signed-char < /dev/null | FileCheck -check-prefix PPC %s // |