arichardson created this revision. arichardson added reviewers: MaskRay, phosek. Herald added subscribers: frasercrmck, luismarques, apazos, sameer.abuasal, pengfei, s.egerton, Jim, jocewei, PkmX, the_o, brucehoult, MartinMosbeck, rogfer01, edward-jones, zzheng, jrtc27, niosHD, sabuasal, simoncook, johnrusso, rbar, asb, krytarowski, emaste. arichardson requested review of this revision. Herald added a project: clang. Herald added a subscriber: cfe-commits.
I was trying to use -DLLVM_ENABLE_RUNTIMES=compiler-rt on FreeBSD and this failed since the 32-bit build ended up linking against the 64-bit ASAN runtime and linking with "/usr/local/bin/x86_64-unknown-freebsd12.2-ld". Looking at the driver code shows that the triple used as a prefix for tools and libaries is always the raw value passed to -target and is not affected by flags such as -m32/-march/etc. This commit uses computeTargetTriple() to update the triple used as a prefix for tools such as the linker. If computeTargetTriple() results in a different triple, we update the RawTargetTriple and now search for i386-unknown-freebsd12.2-ld when -m32 is passed. It is important to note that we do not normalize the triple passed to -target since adding additional could result in an unexpected behaviour change. For example, `clang -target x86_64-freebsd13` should search for x86_64-freebsd13-ld and not the normalized x86_64-unknown-freebsd13-ld and `clang -target x86_64-freebsd13 -m32` tries to find i386-unknown-freebsd13-ld. Depends on D99996 <https://reviews.llvm.org/D99996> (not functionally, but required to compile correctly) Repository: rG LLVM Github Monorepo https://reviews.llvm.org/D100054 Files: clang/include/clang/Driver/Driver.h clang/lib/Driver/Driver.cpp clang/lib/Driver/ToolChain.cpp clang/lib/Driver/ToolChains/BareMetal.cpp clang/lib/Driver/ToolChains/RISCVToolchain.cpp clang/test/Driver/Inputs/basic_freebsd64_tree/usr/bin/i386-unknown-freebsd12.2-ld clang/test/Driver/Inputs/basic_freebsd64_tree/usr/bin/x86_64-unknown-freebsd12.2-ld clang/test/Driver/freebsd-m32.c
Index: clang/test/Driver/freebsd-m32.c =================================================================== --- /dev/null +++ clang/test/Driver/freebsd-m32.c @@ -0,0 +1,52 @@ +// Check that building with -m32 links with x86_64-unknown-freebsd12.2-ld +// instead of x86_64-unknown-freebsd12.2-ld. + +/// We should select x86_64-unknown-freebsd12.2-ld since it matches the triple argument +/// Note: The paths specified by -B are not searched for triple-prefixed tools, so +/// we also have to set $PATH. +// RUN: env PATH=%S/Inputs/basic_freebsd64_tree/usr/bin %clang -no-canonical-prefixes \ +// RUN: -target x86_64-unknown-freebsd12.2 %s \ +// RUN: -B%S/Inputs/basic_freebsd64_tree/usr/bin -### 2>&1 | FileCheck %s --check-prefix=PREFIXED-64 +// PREFIXED-64: "-cc1" "-triple" "x86_64-unknown-freebsd12.2" +// PREFIXED-64-NEXT: "{{.+}}/Inputs/basic_freebsd64_tree/usr/bin/x86_64-unknown-freebsd12.2-ld" "--eh-frame-hdr" +// RUN: env PATH=/this/path/does/not/exist %clang -no-canonical-prefixes \ +// RUN: -target x86_64-unknown-freebsd12.2 %s \ +// RUN: -B%S/Inputs/basic_freebsd64_tree/usr/bin -### 2>&1 | FileCheck %s --check-prefix=MINUS-B-NO-TRIPLE-PREFIX +// MINUS-B-NO-TRIPLE-PREFIX: "-cc1" "-triple" "x86_64-unknown-freebsd12.2" +// MINUS-B-NO-TRIPLE-PREFIX-NEXT: "ld" "--eh-frame-hdr" + +/// The triple passed to clang -cc1 should be normalized, but the prefix when searching +/// for ld should not be normalized. Since there is no x86_64-freebsd12.2-ld, passing +/// -target x86_64-freebsd12.2 should not find a a valid linker: +// RUN: env PATH=%S/Inputs/basic_freebsd64_tree/usr/bin %clang -no-canonical-prefixes \ +// RUN: -target x86_64-freebsd12.2 %s \ +// RUN: -B%S/Inputs/basic_freebsd64_tree/usr/bin -### 2>&1 | FileCheck %s --check-prefix=NO-NORMALIZE-LD-PREFIX-64 +// NO-NORMALIZE-LD-PREFIX-64: "-cc1" "-triple" "x86_64-unknown-freebsd12.2" +// NO-NORMALIZE-LD-PREFIX-64: "ld" "--eh-frame-hdr" + +/// We should search for i386-unknown-freebsd12.2-ld when -m32 is passed: +// RUN: env PATH=%S/Inputs/basic_freebsd64_tree/usr/bin %clang -no-canonical-prefixes \ +// RUN: -target x86_64-unknown-freebsd12.2 %s -m32 \ +// RUN: -B%S/Inputs/basic_freebsd64_tree/usr/bin -### 2>&1 | FileCheck %s --check-prefix=PREFIXED-M32 +// PREFIXED-M32: "-cc1" "-triple" "i386-unknown-freebsd12.2" +// PREFIXED-M32-NEXT: "{{.+}}/Inputs/basic_freebsd64_tree/usr/bin/i386-unknown-freebsd12.2-ld" "--eh-frame-hdr" +/// Only the -cc1 triple should be normalized even when adjusted by -m32: +// RUN: env PATH=%S/Inputs/basic_freebsd64_tree/usr/bin %clang -no-canonical-prefixes \ +// RUN: -target x86_64-freebsd12.2 %s -m32 \ +// RUN: -B%S/Inputs/basic_freebsd64_tree/usr/bin -### 2>&1 | FileCheck %s --check-prefix=NO-NORMALIZE-LD-PREFIX-M32 +// NO-NORMALIZE-LD-PREFIX-M32: "-cc1" "-triple" "i386-unknown-freebsd12.2" +// NO-NORMALIZE-LD-PREFIX-M32-NEXT: "ld" "--eh-frame-hdr" + +/// Check that -m32 also affects the library name for the sanitizer runtime. +// RUN: env PATH=%S/Inputs/basic_freebsd64_tree/usr/bin %clang -no-canonical-prefixes \ +// RUN: -target x86_64-unknown-freebsd12.2 %s -fsanitize=address \ +// RUN: -B%S/Inputs/basic_freebsd64_tree/usr/bin -### 2>&1 | FileCheck %s --check-prefix=ASAN-64 +// ASAN-64: "-cc1" "-triple" "x86_64-unknown-freebsd12.2" +// ASAN-64-NEXT: "{{.+}}/Inputs/basic_freebsd64_tree/usr/bin/x86_64-unknown-freebsd12.2-ld" "--eh-frame-hdr" +// ASAN-64-SAME: lib/freebsd/libclang_rt.asan-x86_64.a" +// RUN: env PATH=%S/Inputs/basic_freebsd64_tree/usr/bin %clang -no-canonical-prefixes \ +// RUN: -target x86_64-unknown-freebsd12.2 %s -fsanitize=address -m32 \ +// RUN: -B%S/Inputs/basic_freebsd64_tree/usr/bin -### 2>&1 | FileCheck %s --check-prefix=ASAN-M32 +// ASAN-M32: "-cc1" "-triple" "i386-unknown-freebsd12.2" +// ASAN-M32-NEXT: "{{.+}}/Inputs/basic_freebsd64_tree/usr/bin/i386-unknown-freebsd12.2-ld" "--eh-frame-hdr" +// ASAN-M32-SAME: lib/freebsd/libclang_rt.asan-i386.a" Index: clang/test/Driver/Inputs/basic_freebsd64_tree/usr/bin/x86_64-unknown-freebsd12.2-ld =================================================================== --- /dev/null +++ clang/test/Driver/Inputs/basic_freebsd64_tree/usr/bin/x86_64-unknown-freebsd12.2-ld @@ -0,0 +1 @@ +#!/bin/true Index: clang/test/Driver/Inputs/basic_freebsd64_tree/usr/bin/i386-unknown-freebsd12.2-ld =================================================================== --- /dev/null +++ clang/test/Driver/Inputs/basic_freebsd64_tree/usr/bin/i386-unknown-freebsd12.2-ld @@ -0,0 +1 @@ +#!/bin/true Index: clang/lib/Driver/ToolChains/RISCVToolchain.cpp =================================================================== --- clang/lib/Driver/ToolChains/RISCVToolchain.cpp +++ clang/lib/Driver/ToolChains/RISCVToolchain.cpp @@ -41,7 +41,7 @@ return true; SmallString<128> GCCDir; - llvm::sys::path::append(GCCDir, D.Dir, "..", D.getTargetTriple(), + llvm::sys::path::append(GCCDir, D.Dir, "..", D.getRawTargetTriple(), "lib/crt0.o"); return llvm::sys::fs::exists(GCCDir); } @@ -129,7 +129,7 @@ // Use the triple as provided to the driver. Unlike the parsed triple // this has not been normalized to always contain every field. llvm::sys::path::append(SysRootDir, getDriver().Dir, "..", - getDriver().getTargetTriple()); + getDriver().getRawTargetTriple()); } if (!llvm::sys::fs::exists(SysRootDir)) Index: clang/lib/Driver/ToolChains/BareMetal.cpp =================================================================== --- clang/lib/Driver/ToolChains/BareMetal.cpp +++ clang/lib/Driver/ToolChains/BareMetal.cpp @@ -179,7 +179,7 @@ SmallString<128> SysRootDir; llvm::sys::path::append(SysRootDir, getDriver().Dir, "../lib/clang-runtimes", - getDriver().getTargetTriple()); + getDriver().getRawTargetTriple()); SysRootDir += SelectedMultilib.osSuffix(); return std::string(SysRootDir); Index: clang/lib/Driver/ToolChain.cpp =================================================================== --- clang/lib/Driver/ToolChain.cpp +++ clang/lib/Driver/ToolChain.cpp @@ -487,7 +487,7 @@ // First try the triple passed to driver as --target=<triple>. P.assign(D.ResourceDir); - llvm::sys::path::append(P, "lib", D.getTargetTriple()); + llvm::sys::path::append(P, "lib", D.getRawTargetTriple()); if (getVFS().exists(P)) return llvm::Optional<std::string>(std::string(P.str())); @@ -505,7 +505,7 @@ // First try the triple passed to driver as --target=<triple>. P.assign(D.Dir); - llvm::sys::path::append(P, "..", "lib", D.getTargetTriple(), "c++"); + llvm::sys::path::append(P, "..", "lib", D.getRawTargetTriple(), "c++"); if (getVFS().exists(P)) return llvm::Optional<std::string>(std::string(P.str())); Index: clang/lib/Driver/Driver.cpp =================================================================== --- clang/lib/Driver/Driver.cpp +++ clang/lib/Driver/Driver.cpp @@ -139,7 +139,7 @@ CCPrintHeadersFilename(), CCLogDiagnosticsFilename(), CCCPrintBindings(false), CCPrintOptions(false), CCPrintHeaders(false), CCLogDiagnostics(false), CCGenDiagnostics(false), - CCPrintProcessStats(false), TargetTriple(TargetTriple), + CCPrintProcessStats(false), RawTargetTriple(TargetTriple), CCCGenericGCCName(""), Saver(Alloc), CheckInputsExist(true), GenReproducer(false), SuppressMissingInputWarning(false) { // Provide a sane fallback if no VFS is specified. @@ -437,15 +437,16 @@ /// /// This routine provides the logic to compute a target triple from various /// args passed to the driver and the default triple string. -static llvm::Triple computeTargetTriple(const Driver &D, - StringRef TargetTriple, +static llvm::Triple computeTargetTriple(const Driver &D, StringRef TargetTriple, const ArgList &Args, - StringRef DarwinArchName = "") { + StringRef DarwinArchName = "", + bool Normalize = true) { // FIXME: Already done in Compilation *Driver::BuildCompilation if (const Arg *A = Args.getLastArg(options::OPT_target)) TargetTriple = A->getValue(); - llvm::Triple Target(llvm::Triple::normalize(TargetTriple)); + llvm::Triple Target(Normalize ? llvm::Triple::normalize(TargetTriple) + : TargetTriple); // GNU/Hurd's triples should have been -hurd-gnu*, but were historically made // -gnu* only, and we can not change this, so we have to detect that case as @@ -1109,15 +1110,13 @@ // and getToolChain is const. if (IsCLMode()) { // clang-cl targets MSVC-style Win32. - llvm::Triple T(TargetTriple); + llvm::Triple T(RawTargetTriple); T.setOS(llvm::Triple::Win32); T.setVendor(llvm::Triple::PC); T.setEnvironment(llvm::Triple::MSVC); T.setObjectFormat(llvm::Triple::COFF); - TargetTriple = T.str(); + RawTargetTriple = T; } - if (const Arg *A = Args.getLastArg(options::OPT_target)) - TargetTriple = A->getValue(); if (const Arg *A = Args.getLastArg(options::OPT_ccc_install_dir)) Dir = InstalledDir = A->getValue(); for (const Arg *A : Args.filtered(options::OPT_B)) { @@ -1173,9 +1172,22 @@ // Perform the default argument translations. DerivedArgList *TranslatedArgs = TranslateInputArgs(*UArgs); - // Owned by the host. - const ToolChain &TC = getToolChain( - *UArgs, computeTargetTriple(*this, TargetTriple, *UArgs)); + // If command line flags such as -m32, etc. changed parts of the triple that + // are not just changes to normalization, we also need to update the raw + // triple string that is used to find tools. This ensures e.g. that clang -m32 + // searches for i386-*-ld instead of x86_64-*-ld when linking (and also uses + // the triple-prefixed library paths). + // Note: It is important that we don't normalize this triple to avoid adding + // empty triple components. + if (const Arg *A = Args.getLastArg(options::OPT_target)) + RawTargetTriple = llvm::Triple(A->getValue()); + llvm::Triple EffectiveTriple = computeTargetTriple( + *this, RawTargetTriple.str(), *UArgs, "", /*Normalize=*/false); + if (RawTargetTriple != EffectiveTriple) + RawTargetTriple = EffectiveTriple; + // Owned by the host (and unlike RawTargetTriple this triple is normalized). + const ToolChain &TC = + getToolChain(*UArgs, llvm::Triple(EffectiveTriple.normalize())); // The compilation takes ownership of Args. Compilation *C = new Compilation(*this, TC, UArgs.release(), TranslatedArgs, @@ -4562,7 +4574,7 @@ if (!ArchName.empty()) TC = &getToolChain(C.getArgs(), - computeTargetTriple(*this, TargetTriple, + computeTargetTriple(*this, RawTargetTriple.str(), C.getArgs(), ArchName)); else TC = &C.getDefaultToolChain(); @@ -4752,8 +4764,7 @@ } const char *Driver::getDefaultImageName() const { - llvm::Triple Target(llvm::Triple::normalize(TargetTriple)); - return Target.isOSWindows() ? "a.exe" : "a.out"; + return RawTargetTriple.isOSWindows() ? "a.exe" : "a.out"; } /// Create output filename based on ArgValue, which could either be a @@ -5067,8 +5078,7 @@ void Driver::generatePrefixedToolNames( StringRef Tool, const ToolChain &TC, SmallVectorImpl<std::string> &Names) const { - // FIXME: Needs a better variable than TargetTriple - Names.emplace_back((TargetTriple + "-" + Tool).str()); + Names.emplace_back((RawTargetTriple.str() + "-" + Tool).str()); Names.emplace_back(Tool); } Index: clang/include/clang/Driver/Driver.h =================================================================== --- clang/include/clang/Driver/Driver.h +++ clang/include/clang/Driver/Driver.h @@ -219,8 +219,8 @@ CC1ToolFunc CC1Main = nullptr; private: - /// Raw target triple. - std::string TargetTriple; + /// Raw target triple (not normalized, since it is used as a prefix). + llvm::Triple RawTargetTriple; /// Name to use when invoking gcc/g++. std::string CCCGenericGCCName; @@ -334,7 +334,7 @@ const std::string &getTitle() { return DriverTitle; } void setTitle(std::string Value) { DriverTitle = std::move(Value); } - std::string getTargetTriple() const { return TargetTriple; } + std::string getRawTargetTriple() const { return RawTargetTriple.str(); } /// Get the path to the main clang executable. const char *getClangProgramPath() const {
_______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits