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
  • [PATCH] D100054: Hand... Alexander Richardson via Phabricator via cfe-commits

Reply via email to