kito-cheng updated this revision to Diff 328407.
kito-cheng added a comment.

Reupload


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D97916/new/

https://reviews.llvm.org/D97916

Files:
  clang/include/clang/Basic/DiagnosticDriverKinds.td
  clang/include/clang/Basic/DiagnosticGroups.td
  clang/lib/Driver/ToolChains/Arch/RISCV.cpp
  clang/lib/Driver/ToolChains/Arch/RISCV.h
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/bin/riscv32-unknown-elf-gcc
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/lib/gcc/riscv32-unknown-elf/8.2.0/crtbegin.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/lib/gcc/riscv32-unknown-elf/8.2.0/crtend.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/lib/gcc/riscv32-unknown-elf/8.2.0/rv32iac/ilp32/crtbegin.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/lib/gcc/riscv32-unknown-elf/8.2.0/rv32iac/ilp32/crtend.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/lib/gcc/riscv32-unknown-elf/8.2.0/rv32imafc/ilp32f/crtbegin.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/lib/gcc/riscv32-unknown-elf/8.2.0/rv32imafc/ilp32f/crtend.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/lib/gcc/riscv32-unknown-elf/8.2.0/rv64imafdc/lp64d/crtbegin.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/lib/gcc/riscv32-unknown-elf/8.2.0/rv64imafdc/lp64d/crtend.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/riscv32-unknown-elf/lib/crt0.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/riscv32-unknown-elf/lib/rv32iac/ilp32/crt0.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/riscv32-unknown-elf/lib/rv32imafc/ilp32f/crt0.o
  
clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/riscv32-unknown-elf/lib/rv64imac/lp64/crt0.o
  clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/bin/riscv64-unknown-elf-gcc
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/crtbegin.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/crtend.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv32iac/ilp32/crtbegin.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv32iac/ilp32/crtend.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv32imafc/ilp32f/crtbegin.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv32imafc/ilp32f/crtend.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv64imafdc/lp64d/crtbegin.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/lib/gcc/riscv64-unknown-elf/8.2.0/rv64imafdc/lp64d/crtend.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/riscv64-unknown-elf/lib/crt0.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/riscv64-unknown-elf/lib/rv32iac/ilp32/crt0.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/riscv64-unknown-elf/lib/rv32imafc/ilp32f/crt0.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/riscv64-unknown-elf/lib/rv64imac/lp64/crt0.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk_bad/bin/riscv64-unknown-elf-gcc
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk_bad/lib/gcc/riscv64-unknown-elf/8.2.0/crtbegin.o
  
clang/test/Driver/Inputs/multilib_riscv64_elf_sdk_bad/riscv64-unknown-elf/lib/crt0.o
  clang/test/Driver/riscv32-toolchain.c
  clang/test/Driver/riscv64-toolchain.c

Index: clang/test/Driver/riscv64-toolchain.c
===================================================================
--- clang/test/Driver/riscv64-toolchain.c
+++ clang/test/Driver/riscv64-toolchain.c
@@ -153,6 +153,24 @@
 // C-RV64-RTLIB-COMPILERRT-LP64: "--start-group" "-lc" "-lgloss" "--end-group" "{{.*}}libclang_rt.builtins-riscv64.a"
 // C-RV64-RTLIB-COMPILERRT-LP64: "{{.*}}clang_rt.crtend-riscv64.o"
 
+// Test for multi-lib config from GCC.
+// RUN: %clang %s \
+// RUN:   -target riscv64-unknown-elf \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv64_elf_sdk \
+// RUN:   --print-multi-lib \
+// RUN:   | FileCheck -check-prefix=C-RV64-GCC-MULTI-LIB %s
+// C-RV64-GCC-MULTI-LIB: rv32iac/ilp32;@march=rv32iac@mabi=ilp32
+// C-RV64-GCC-MULTI-LIB-NEXT: rv32imafc/ilp32f;@march=rv32iac@mabi=ilp32f
+// C-RV64-GCC-MULTI-LIB-NEXT: rv64imafdc/lp64d;@march=rv64imafdc@mabi=lp64d
+// C-RV64-GCC-MULTI-LIB-NOT:  {{^.+$}}
+
+// RUN: %clang %s \
+// RUN:   -target riscv64-unknown-elf \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv64_elf_sdk_bad \
+// RUN:   --print-multi-lib 2>&1 \
+// RUN:   | FileCheck -check-prefix=C-RV64-GCC-MULTI-LIB-BAD %s
+// C-RV64-GCC-MULTI-LIB-BAD: warning: xxx option unrecognized in multi-lib configuration when parsing config from GCC, falling back to built-in multi-lib configuration. [-Wmultilib-fallback]
+
 // RUN: %clang -target riscv64 %s -emit-llvm -S -o - | FileCheck %s
 
 typedef __builtin_va_list va_list;
Index: clang/test/Driver/riscv32-toolchain.c
===================================================================
--- clang/test/Driver/riscv32-toolchain.c
+++ clang/test/Driver/riscv32-toolchain.c
@@ -197,6 +197,17 @@
 // C-RV32-RTLIB-COMPILERRT-ILP32: "--start-group" "-lc" "-lgloss" "--end-group" "{{.*}}libclang_rt.builtins-riscv32.a"
 // C-RV32-RTLIB-COMPILERRT-ILP32: "{{.*}}clang_rt.crtend-riscv32.o"
 
+// Test for multi-lib config from GCC.
+// RUN: %clang %s \
+// RUN:   -target riscv32-unknown-elf \
+// RUN:   --gcc-toolchain=%S/Inputs/multilib_riscv32_elf_sdk \
+// RUN:   --print-multi-lib \
+// RUN:   | FileCheck -check-prefix=C-RV32-GCC-MULTI-LIB %s
+// C-RV32-GCC-MULTI-LIB: rv32iac/ilp32;@march=rv32iac@mabi=ilp32
+// C-RV32-GCC-MULTI-LIB-NEXT: rv32imafc/ilp32f;@march=rv32iac@mabi=ilp32f
+// C-RV32-GCC-MULTI-LIB-NEXT: rv64imafdc/lp64d;@march=rv64imafdc@mabi=lp64d
+// C-RV32-GCC-MULTI-LIB-NOT:  {{^.+$}}
+
 // RUN: %clang -target riscv32 %s -emit-llvm -S -o - | FileCheck %s
 
 typedef __builtin_va_list va_list;
Index: clang/test/Driver/Inputs/multilib_riscv64_elf_sdk_bad/bin/riscv64-unknown-elf-gcc
===================================================================
--- /dev/null
+++ clang/test/Driver/Inputs/multilib_riscv64_elf_sdk_bad/bin/riscv64-unknown-elf-gcc
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+print ("rv32iac/ilp32;@march=rv32iac@mabi=ilp32")
+print ("rv32imafc/ilp32f;@march=rv32iac@mabi=ilp32f")
+print ("rv64imafdc/lp64d;@march=rv64imafdc@mabi=lp64d@xxx")
Index: clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/bin/riscv64-unknown-elf-gcc
===================================================================
--- /dev/null
+++ clang/test/Driver/Inputs/multilib_riscv64_elf_sdk/bin/riscv64-unknown-elf-gcc
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+print ("rv32iac/ilp32;@march=rv32iac@mabi=ilp32")
+print ("rv32imafc/ilp32f;@march=rv32iac@mabi=ilp32f")
+print ("rv64imafdc/lp64d;@march=rv64imafdc@mabi=lp64d")
Index: clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/bin/riscv32-unknown-elf-gcc
===================================================================
--- /dev/null
+++ clang/test/Driver/Inputs/multilib_riscv32_elf_sdk/bin/riscv32-unknown-elf-gcc
@@ -0,0 +1,5 @@
+#!/usr/bin/env python
+
+print ("rv32iac/ilp32;@march=rv32iac@mabi=ilp32")
+print ("rv32imafc/ilp32f;@march=rv32iac@mabi=ilp32f")
+print ("rv64imafdc/lp64d;@march=rv64imafdc@mabi=lp64d")
Index: clang/lib/Driver/ToolChains/Gnu.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Gnu.cpp
+++ clang/lib/Driver/ToolChains/Gnu.cpp
@@ -25,6 +25,7 @@
 #include "llvm/Option/ArgList.h"
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/Path.h"
+#include "llvm/Support/Program.h"
 #include "llvm/Support/TargetParser.h"
 #include "llvm/Support/VirtualFileSystem.h"
 #include <system_error>
@@ -1583,10 +1584,174 @@
   return false;
 }
 
+static std::string findGCCPath(const Driver &D, llvm::StringRef BasePath) {
+  SmallString<128> GCCPath;
+  llvm::sys::path::append(GCCPath, BasePath, "bin",
+                          D.getTargetTriple() + "-gcc");
+
+  if (llvm::sys::fs::exists(GCCPath))
+    return GCCPath.str().str();
+
+  return "";
+}
+
+static std::string getGCCPath(const Driver &D, const ArgList &Args) {
+
+  // Find GCC from -gcc-toolchain if given.
+  if (const Arg *A =
+          Args.getLastArg(clang::driver::options::OPT_gcc_toolchain)) {
+    return findGCCPath(D, A->getValue());
+  } else {
+    // Try to find GCC from GCC_INSTALL_PREFIX if define.
+    llvm::StringRef GCCInstallPrefix = GCC_INSTALL_PREFIX;
+    std::string GCCPath;
+    if (!GCCInstallPrefix.empty())
+      GCCPath = findGCCPath(D, GCCInstallPrefix);
+    else {
+      // Try to find GCC from the same folder as driver.
+      SmallString<128> GCCBasePath;
+      llvm::sys::path::append(GCCBasePath, D.Dir, "..");
+      GCCPath = findGCCPath(D, GCCBasePath);
+    }
+    return GCCPath;
+  }
+}
+
+static bool scanRISCVGCCMultilibConfig(const Driver &D,
+                                       const llvm::Triple &TargetTriple,
+                                       StringRef Path, const ArgList &Args,
+                                       StringRef MultilibOutput,
+                                       DetectedMultilibs &Result) {
+  llvm::StringSet<> AllABI;
+  llvm::StringSet<> AllArch;
+  llvm::StringSet<> AllMCmodel;
+  Multilib::flags_list Flags;
+
+  FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
+
+  // Get current ABI, Arch, and code model.
+  StringRef ABIName = tools::riscv::getRISCVABI(Args, TargetTriple);
+  StringRef MArch = tools::riscv::getRISCVArch(Args, TargetTriple);
+  StringRef CodeModel = tools::riscv::getRISCVCodeModel(Args);
+
+  // Turns it into option style, to make it able to compare
+  // to multi-lib option list.
+  std::string CurrentABIOpt = Twine("mabi=", ABIName).str();
+  std::string CurrentArchOpt = Twine("march=", MArch).str();
+  std::string CurrentMCmodelOpt = llvm::StringSwitch<const char *>(CodeModel)
+                                      .Case("medium", "mcmodel=medany")
+                                      .Default("mcmodel=medlow");
+
+  llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> File =
+      D.getVFS().getBufferForFile(MultilibOutput);
+  std::vector<Multilib> Ms;
+
+  if (!File) {
+    // Ooops, some thing wrong during open file, let's fallback.
+    return false;
+  }
+
+  SmallVector<StringRef, 128> Lines;
+  File.get()->getBuffer().split(Lines, "\n");
+  for (StringRef Line : Lines) {
+    if (Line.empty())
+      continue;
+    // Format for multi-lib:
+    // <path>;@opt1@opt2
+    // For example:
+    // rv32ec/ilp32e;@march=rv32ec@mabi=ilp32e
+    // -march=rv32ec and -mabi=ilp32e using rv32ec/ilp32e.
+    auto MultilibInfo = Line.split(';');
+    StringRef Path = MultilibInfo.first;
+
+    // Skip default multi-lib path.
+    // Clang has implied a default multi-lib rule there,
+    // so we don't need to add it manually.
+    if (Path == ".")
+      continue;
+
+    StringRef Options = MultilibInfo.second.substr(1);
+    SmallVector<StringRef, 2> OptionList;
+    Options.split(OptionList, '@');
+    // multilib path rule is ${march}/${mabi}
+    auto Multilib = makeMultilib(Path);
+    for (StringRef Option : OptionList) {
+      Multilib.flag(Twine("+", Option).str());
+
+      // Gather all used option from multi-lib config.
+      if (Option.startswith("march=")) {
+        if (!AllArch.contains(Option)) {
+          // Make sure every option we only process once
+          AllArch.insert(Option);
+          addMultilibFlag(CurrentArchOpt == Option, Option.str().c_str(),
+                          Flags);
+        }
+      } else if (Option.startswith("mabi=")) {
+        if (!AllABI.contains(Option)) {
+          AllABI.insert(Option);
+          addMultilibFlag(CurrentABIOpt == Option, Option.str().c_str(), Flags);
+        }
+      } else if (Option.startswith("mcmodel=")) {
+        if (!AllMCmodel.contains(Option)) {
+          AllMCmodel.insert(Option);
+          addMultilibFlag(CurrentMCmodelOpt == Option, Option.str().c_str(),
+                          Flags);
+        }
+      } else {
+        // Got unrecognized option in multi-lib config, fallback.
+        D.Diag(diag::warn_drv_multilib_fallback) << Option;
+        return false;
+      }
+    }
+    Ms.emplace_back(Multilib);
+  }
+
+  MultilibSet RISCVMultilibs =
+      MultilibSet().FilterOut(NonExistent).Either(ArrayRef<Multilib>(Ms));
+
+  RISCVMultilibs.select(Flags, Result.SelectedMultilib);
+
+  Result.Multilibs = RISCVMultilibs;
+
+  return true;
+}
+
+static bool getRISCVMultilibFromGCC(const Driver &D,
+                                    const llvm::Triple &TargetTriple,
+                                    StringRef Path, const ArgList &Args,
+                                    DetectedMultilibs &Result) {
+  // Try to find where is GCC.
+  std::string GCCPath = getGCCPath(D, Args);
+
+  // Not found? fallback to built-in multi-lib.
+  if (GCCPath.empty())
+    return false;
+
+  // Ask GCC's multi-lib config via --print-multi-lib.
+  StringRef GCCArgs[] = {{GCCPath}, {"--print-multi-lib"}};
+  std::string MultilibOutput = D.GetTemporaryPath("gcc-output-", "");
+  Optional<StringRef> Redirects[] = {None, {MultilibOutput}, {""}};
+
+  int RC = llvm::sys::ExecuteAndWait(GCCPath, GCCArgs, None, Redirects);
+
+  // Any failed happen? let fallback to built-in multi-lib.
+  if (RC != 0)
+    return false;
+
+  // Parsing output of --print-multi-lib, and use that info to determine
+  // which multi-lib should be used.
+  return scanRISCVGCCMultilibConfig(D, TargetTriple, Path, Args, MultilibOutput,
+                                    Result);
+}
+
 static void findRISCVBareMetalMultilibs(const Driver &D,
                                         const llvm::Triple &TargetTriple,
                                         StringRef Path, const ArgList &Args,
                                         DetectedMultilibs &Result) {
+  // Try to get multilib from GCC first.
+  if (getRISCVMultilibFromGCC(D, TargetTriple, Path, Args, Result))
+    return;
+
   FilterNonExistent NonExistent(Path, "/crtbegin.o", D.getVFS());
   struct RiscvMultilib {
     StringRef march;
Index: clang/lib/Driver/ToolChains/Arch/RISCV.h
===================================================================
--- clang/lib/Driver/ToolChains/Arch/RISCV.h
+++ clang/lib/Driver/ToolChains/Arch/RISCV.h
@@ -26,6 +26,7 @@
                       const llvm::Triple &Triple);
 StringRef getRISCVArch(const llvm::opt::ArgList &Args,
                        const llvm::Triple &Triple);
+StringRef getRISCVCodeModel(const llvm::opt::ArgList &Args);
 } // end namespace riscv
 } // namespace tools
 } // end namespace driver
Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -721,3 +721,14 @@
       return "rv64imafdc";
   }
 }
+
+StringRef riscv::getRISCVCodeModel(const llvm::opt::ArgList &Args) {
+  // Default code model is small(medlow).
+  StringRef CodeModel;
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+    CodeModel = A->getValue();
+  else
+    CodeModel = "small";
+
+  return CodeModel;
+}
Index: clang/include/clang/Basic/DiagnosticGroups.td
===================================================================
--- clang/include/clang/Basic/DiagnosticGroups.td
+++ clang/include/clang/Basic/DiagnosticGroups.td
@@ -767,6 +767,7 @@
 def GNUZeroLineDirective : DiagGroup<"gnu-zero-line-directive">;
 def GNUZeroVariadicMacroArguments : DiagGroup<"gnu-zero-variadic-macro-arguments">;
 def MisleadingIndentation : DiagGroup<"misleading-indentation">;
+def MultilibFallback : DiagGroup<"multilib-fallback">;
 
 // This covers both the deprecated case (in C++98)
 // and the extension case (in C++11 onwards).
Index: clang/include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -390,6 +390,11 @@
   "-ftest-module-file-extension argument '%0' is not of the required form "
   "'blockname:major:minor:hashed:user info'">;
 
+def warn_drv_multilib_fallback : Warning<
+  "%0 option unrecognized in multi-lib configuration when parsing config "
+  "from GCC, falling back to built-in multi-lib configuration.">,
+  InGroup<MultilibFallback>;
+
 def warn_slash_u_filename : Warning<"'/U%0' treated as the '/U' option">,
   InGroup<DiagGroup<"slash-u-filename">>;
 def note_use_dashdash : Note<"Use '--' to treat subsequent arguments as filenames">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to