From 2d1b1ad831289d002665c25cc7d88711e2fcf30a Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Sun, 21 Oct 2012 11:44:57 +0000 Subject: [PATCH] Add support of MIPS n32 ABI to the Clang driver. The fix builds correct library/object files paths and passes appropriate command line options to the linker if user provides -mabi=n32 option. The patch reviewed by Rafael Espindola. llvm-svn: 166389 --- clang/lib/Driver/ToolChains.cpp | 40 +++++++++++++++++++++++-------- clang/lib/Driver/ToolChains.h | 1 + clang/lib/Driver/Tools.cpp | 29 ++++++++++++++++++----- clang/test/Driver/linux-ld.c | 52 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 106 insertions(+), 16 deletions(-) diff --git a/clang/lib/Driver/ToolChains.cpp b/clang/lib/Driver/ToolChains.cpp index e5773fb..e403e20 100644 --- a/clang/lib/Driver/ToolChains.cpp +++ b/clang/lib/Driver/ToolChains.cpp @@ -1127,7 +1127,8 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( if (!llvm::sys::fs::exists(LibDir)) continue; for (unsigned k = 0, ke = CandidateTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetArch, LibDir, CandidateTripleAliases[k]); + ScanLibDirForGCCTriple(TargetArch, Args, LibDir, + CandidateTripleAliases[k]); } for (unsigned j = 0, je = CandidateMultiarchLibDirs.size(); j < je; ++j) { const std::string LibDir @@ -1136,7 +1137,7 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( continue; for (unsigned k = 0, ke = CandidateMultiarchTripleAliases.size(); k < ke; ++k) - ScanLibDirForGCCTriple(TargetArch, LibDir, + ScanLibDirForGCCTriple(TargetArch, Args, LibDir, CandidateMultiarchTripleAliases[k], /*NeedsMultiarchSuffix=*/true); } @@ -1322,8 +1323,32 @@ Generic_GCC::GCCInstallationDetector::GCCInstallationDetector( MultiarchTripleAliases.push_back(MultiarchTriple.str()); } +// FIXME: There is the same routine in the Tools.cpp. +static bool hasMipsN32ABIArg(const ArgList &Args) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue(Args) == StringRef("n32")); +} + +static StringRef getTargetMultiarchSuffix(llvm::Triple::ArchType TargetArch, + const ArgList &Args) { + if (TargetArch == llvm::Triple::x86_64 || + TargetArch == llvm::Triple::ppc64) + return "/64"; + + if (TargetArch == llvm::Triple::mips64 || + TargetArch == llvm::Triple::mips64el) { + if (hasMipsN32ABIArg(Args)) + return "/n32"; + else + return "/64"; + } + + return "/32"; +} + void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( - llvm::Triple::ArchType TargetArch, const std::string &LibDir, + llvm::Triple::ArchType TargetArch, const ArgList &Args, + const std::string &LibDir, StringRef CandidateTriple, bool NeedsMultiarchSuffix) { // There are various different suffixes involving the triple we // check for. We also record what is necessary to walk from each back @@ -1370,11 +1395,7 @@ void Generic_GCC::GCCInstallationDetector::ScanLibDirForGCCTriple( // *if* there is a subdirectory of the right name with crtbegin.o in it, // we use that. If not, and if not a multiarch triple, we look for // crtbegin.o without the subdirectory. - StringRef MultiarchSuffix - = (TargetArch == llvm::Triple::x86_64 || - TargetArch == llvm::Triple::ppc64 || - TargetArch == llvm::Triple::mips64 || - TargetArch == llvm::Triple::mips64el) ? "/64" : "/32"; + StringRef MultiarchSuffix = getTargetMultiarchSuffix(TargetArch, Args); if (llvm::sys::fs::exists(LI->path() + MultiarchSuffix + "/crtbegin.o")) { GCCMultiarchSuffix = MultiarchSuffix.str(); } else { @@ -2129,8 +2150,7 @@ static StringRef getMultilibDir(const llvm::Triple &Triple, // lib32 directory has a special meaning on MIPS targets. // It contains N32 ABI binaries. Use this folder if produce // code for N32 ABI only. - Arg *A = Args.getLastArg(options::OPT_mabi_EQ); - if (A && (A->getValue(Args) == StringRef("n32"))) + if (hasMipsN32ABIArg(Args)) return "lib32"; return Triple.isArch32Bit() ? "lib" : "lib64"; diff --git a/clang/lib/Driver/ToolChains.h b/clang/lib/Driver/ToolChains.h index c3c874a..9095433 100644 --- a/clang/lib/Driver/ToolChains.h +++ b/clang/lib/Driver/ToolChains.h @@ -111,6 +111,7 @@ protected: SmallVectorImpl &MultiarchTripleAliases); void ScanLibDirForGCCTriple(llvm::Triple::ArchType TargetArch, + const ArgList &Args, const std::string &LibDir, StringRef CandidateTriple, bool NeedsMultiarchSuffix = false); diff --git a/clang/lib/Driver/Tools.cpp b/clang/lib/Driver/Tools.cpp index 80691ee..edaa1db 100644 --- a/clang/lib/Driver/Tools.cpp +++ b/clang/lib/Driver/Tools.cpp @@ -5719,6 +5719,11 @@ static void AddLibgcc(llvm::Triple Triple, const Driver &D, CmdArgs.push_back("-lgcc"); } +static bool hasMipsN32ABIArg(const ArgList &Args) { + Arg *A = Args.getLastArg(options::OPT_mabi_EQ); + return A && (A->getValue(Args) == StringRef("n32")); +} + void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, const InputInfo &Output, const InputInfoList &Inputs, @@ -5775,10 +5780,18 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, CmdArgs.push_back("elf32btsmip"); else if (ToolChain.getArch() == llvm::Triple::mipsel) CmdArgs.push_back("elf32ltsmip"); - else if (ToolChain.getArch() == llvm::Triple::mips64) - CmdArgs.push_back("elf64btsmip"); - else if (ToolChain.getArch() == llvm::Triple::mips64el) - CmdArgs.push_back("elf64ltsmip"); + else if (ToolChain.getArch() == llvm::Triple::mips64) { + if (hasMipsN32ABIArg(Args)) + CmdArgs.push_back("elf32btsmipn32"); + else + CmdArgs.push_back("elf64btsmip"); + } + else if (ToolChain.getArch() == llvm::Triple::mips64el) { + if (hasMipsN32ABIArg(Args)) + CmdArgs.push_back("elf32ltsmipn32"); + else + CmdArgs.push_back("elf64ltsmip"); + } else CmdArgs.push_back("elf_x86_64"); @@ -5816,8 +5829,12 @@ void linuxtools::Link::ConstructJob(Compilation &C, const JobAction &JA, ToolChain.getArch() == llvm::Triple::mipsel) CmdArgs.push_back("/lib/ld.so.1"); else if (ToolChain.getArch() == llvm::Triple::mips64 || - ToolChain.getArch() == llvm::Triple::mips64el) - CmdArgs.push_back("/lib64/ld.so.1"); + ToolChain.getArch() == llvm::Triple::mips64el) { + if (hasMipsN32ABIArg(Args)) + CmdArgs.push_back("/lib32/ld.so.1"); + else + CmdArgs.push_back("/lib64/ld.so.1"); + } else if (ToolChain.getArch() == llvm::Triple::ppc) CmdArgs.push_back("/lib/ld.so.1"); else if (ToolChain.getArch() == llvm::Triple::ppc64) diff --git a/clang/test/Driver/linux-ld.c b/clang/test/Driver/linux-ld.c index 496e175..dc223c7 100644 --- a/clang/test/Driver/linux-ld.c +++ b/clang/test/Driver/linux-ld.c @@ -265,6 +265,20 @@ // CHECK-MIPS64EL: "-m" "elf64ltsmip" // CHECK-MIPS64EL: "-dynamic-linker" "{{.*}}/lib64/ld.so.1" // CHECK-MIPS64EL-NOT: "--hash-style={{gnu|both}}" +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: -target mips64-linux-gnu -mabi=n32 \ +// RUN: | FileCheck --check-prefix=CHECK-MIPS64-N32 %s +// CHECK-MIPS64-N32: "{{.*}}ld{{(.exe)?}}" +// CHECK-MIPS64-N32: "-m" "elf32btsmipn32" +// CHECK-MIPS64-N32: "-dynamic-linker" "{{.*}}/lib32/ld.so.1" +// CHECK-MIPS64-N32-NOT: "--hash-style={{gnu|both}}" +// RUN: %clang %s -### -o %t.o 2>&1 \ +// RUN: -target mips64el-linux-gnu -mabi=n32 \ +// RUN: | FileCheck --check-prefix=CHECK-MIPS64EL-N32 %s +// CHECK-MIPS64EL-N32: "{{.*}}ld{{(.exe)?}}" +// CHECK-MIPS64EL-N32: "-m" "elf32ltsmipn32" +// CHECK-MIPS64EL-N32: "-dynamic-linker" "{{.*}}/lib32/ld.so.1" +// CHECK-MIPS64EL-N32-NOT: "--hash-style={{gnu|both}}" // // Thoroughly exercise the Debian multiarch environment. // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ @@ -361,6 +375,28 @@ // CHECK-DEBIAN-MIPS64EL: "-L[[SYSROOT]]/usr/lib/gcc/mipsel-linux-gnu/4.5/../../.." // CHECK-DEBIAN-MIPS64EL: "-L[[SYSROOT]]/lib" // CHECK-DEBIAN-MIPS64EL: "-L[[SYSROOT]]/usr/lib" +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target mips64-linux-gnu -mabi=n32 \ +// RUN: --sysroot=%S/Inputs/debian_multiarch_tree \ +// RUN: | FileCheck --check-prefix=CHECK-DEBIAN-MIPS64-N32 %s +// CHECK-DEBIAN-MIPS64-N32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-DEBIAN-MIPS64-N32: "{{.*}}/usr/lib/gcc/mips-linux-gnu/4.5/n32/crtbegin.o" +// CHECK-DEBIAN-MIPS64-N32: "-L[[SYSROOT]]/usr/lib/gcc/mips-linux-gnu/4.5/n32" +// CHECK-DEBIAN-MIPS64-N32: "-L[[SYSROOT]]/usr/lib/gcc/mips-linux-gnu/4.5" +// CHECK-DEBIAN-MIPS64-N32: "-L[[SYSROOT]]/usr/lib/gcc/mips-linux-gnu/4.5/../../.." +// CHECK-DEBIAN-MIPS64-N32: "-L[[SYSROOT]]/lib" +// CHECK-DEBIAN-MIPS64-N32: "-L[[SYSROOT]]/usr/lib" +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target mips64el-linux-gnu -mabi=n32 \ +// RUN: --sysroot=%S/Inputs/debian_multiarch_tree \ +// RUN: | FileCheck --check-prefix=CHECK-DEBIAN-MIPS64EL-N32 %s +// CHECK-DEBIAN-MIPS64EL-N32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-DEBIAN-MIPS64EL-N32: "{{.*}}/usr/lib/gcc/mipsel-linux-gnu/4.5/n32/crtbegin.o" +// CHECK-DEBIAN-MIPS64EL-N32: "-L[[SYSROOT]]/usr/lib/gcc/mipsel-linux-gnu/4.5/n32" +// CHECK-DEBIAN-MIPS64EL-N32: "-L[[SYSROOT]]/usr/lib/gcc/mipsel-linux-gnu/4.5" +// CHECK-DEBIAN-MIPS64EL-N32: "-L[[SYSROOT]]/usr/lib/gcc/mipsel-linux-gnu/4.5/../../.." +// CHECK-DEBIAN-MIPS64EL-N32: "-L[[SYSROOT]]/lib" +// CHECK-DEBIAN-MIPS64EL-N32: "-L[[SYSROOT]]/usr/lib" // // Test linker invocation on Android. // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ @@ -482,6 +518,22 @@ // CHECK-DEBIAN-ML-MIPS64EL: "-L[[SYSROOT]]/lib" // CHECK-DEBIAN-ML-MIPS64EL: "-L[[SYSROOT]]/usr/lib" // +// RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ +// RUN: -target mips64el-linux-gnu -mabi=n32 \ +// RUN: --sysroot=%S/Inputs/debian_6_mips_tree \ +// RUN: | FileCheck --check-prefix=CHECK-DEBIAN-ML-MIPS64EL-N32 %s +// CHECK-DEBIAN-ML-MIPS64EL-N32: "{{.*}}ld{{(.exe)?}}" "--sysroot=[[SYSROOT:[^"]+]]" +// CHECK-DEBIAN-ML-MIPS64EL-N32: "{{.*}}/usr/lib/gcc/mipsel-linux-gnu/4.4/../../../../lib32/crt1.o" +// CHECK-DEBIAN-ML-MIPS64EL-N32: "{{.*}}/usr/lib/gcc/mipsel-linux-gnu/4.4/../../../../lib32/crti.o" +// CHECK-DEBIAN-ML-MIPS64EL-N32: "{{.*}}/usr/lib/gcc/mipsel-linux-gnu/4.4/n32/crtbegin.o" +// CHECK-DEBIAN-ML-MIPS64EL-N32: "-L[[SYSROOT]]/usr/lib/gcc/mipsel-linux-gnu/4.4/n32" +// CHECK-DEBIAN-ML-MIPS64EL-N32: "-L[[SYSROOT]]/usr/lib/gcc/mipsel-linux-gnu/4.4/../../../../lib32" +// CHECK-DEBIAN-ML-MIPS64EL-N32: "-L[[SYSROOT]]/lib/../lib32" +// CHECK-DEBIAN-ML-MIPS64EL-N32: "-L[[SYSROOT]]/usr/lib/../lib32" +// CHECK-DEBIAN-ML-MIPS64EL-N32: "-L[[SYSROOT]]/usr/lib/gcc/mipsel-linux-gnu/4.4/../../.." +// CHECK-DEBIAN-ML-MIPS64EL-N32: "-L[[SYSROOT]]/lib" +// CHECK-DEBIAN-ML-MIPS64EL-N32: "-L[[SYSROOT]]/usr/lib" +// // Test linker invocation for Freescale SDK (OpenEmbedded). // RUN: %clang -no-canonical-prefixes %s -### -o %t.o 2>&1 \ // RUN: -target powerpc-fsl-linux \ -- 2.7.4