This revision was automatically updated to reflect the committed changes.
Closed by commit rGe3d5ff5a0b10: [RISCV] Match GCC `-march`/`-mabi` driver 
defaults (authored by lenary).

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D69383

Files:
  clang/docs/ReleaseNotes.rst
  clang/lib/Driver/ToolChains/Arch/RISCV.cpp
  clang/lib/Driver/ToolChains/Arch/RISCV.h
  clang/lib/Driver/ToolChains/Gnu.cpp
  clang/test/Driver/riscv-abi.c
  clang/test/Driver/riscv-gnutools.c

Index: clang/test/Driver/riscv-gnutools.c
===================================================================
--- clang/test/Driver/riscv-gnutools.c
+++ clang/test/Driver/riscv-gnutools.c
@@ -1,19 +1,40 @@
 // Check gnutools are invoked with propagated values for -mabi and -march.
+//
+// This test also checks the default -march/-mabi for certain targets.
 
-// RUN: %clang -target riscv32 -fno-integrated-as %s -###  -c \
-// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP32 %s
+// 32-bit checks
 
-// RUN: %clang -target riscv32 -fno-integrated-as -march=rv32g %s -### -c \
-// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP32-MARCH-G %s
+// Check default on riscv32-unknown-elf
+// RUN: %clang -target riscv32-unknown-elf -fno-integrated-as %s -### -c \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-RV32IMAC-ILP32 %s
 
-// RUN: %clang -target riscv64 -fno-integrated-as %s -###  -c \
-// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP64 %s
+// Check default on riscv32-unknown-linux-gnu
+// RUN: %clang -target riscv32-unknown-linux-gnu -fno-integrated-as %s -### -c \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-RV32IMAFDC-ILP32D %s
 
-// RUN: %clang -target riscv64 -fno-integrated-as -march=rv64g %s -### -c \
-// RUN: 2>&1 | FileCheck -check-prefix=MABI-ILP64-MARCH-G %s
+// Check default when -march=rv32g specified
+// RUN: %clang -target riscv32 -fno-integrated-as %s -### -c -march=rv32g \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-RV32G-ILP32D %s
 
-// MABI-ILP32: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32"
-// MABI-ILP32-MARCH-G: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32" "-march" "rv32g"
+// CHECK-RV32IMAC-ILP32: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32" "-march" "rv32imac"
+// CHECK-RV32IMAFDC-ILP32D: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32d" "-march" "rv32imafdc"
+// CHECK-RV32G-ILP32D: "{{.*}}as{{(.exe)?}}" "-mabi" "ilp32d" "-march" "rv32g"
 
-// MABI-ILP64: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64"
-// MABI-ILP64-MARCH-G: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64" "-march" "rv64g"
+
+// 64-bit checks
+
+// Check default on riscv64-unknown-elf
+// RUN: %clang -target riscv64-unknown-elf -fno-integrated-as %s -### -c \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-RV64IMAC-LP64 %s
+
+// Check default on riscv64-unknown-linux-gnu
+// RUN: %clang -target riscv64-unknown-linux-gnu -fno-integrated-as %s -### -c \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-RV64IMAFDC-LP64D %s
+
+// Check default when -march=rv64g specified
+// RUN: %clang -target riscv64 -fno-integrated-as %s -### -c -march=rv64g \
+// RUN: 2>&1 | FileCheck -check-prefix=CHECK-RV64G-LP64D %s
+
+// CHECK-RV64IMAC-LP64: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64" "-march" "rv64imac"
+// CHECK-RV64IMAFDC-LP64D: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64d" "-march" "rv64imafdc"
+// CHECK-RV64G-LP64D: "{{.*}}as{{(.exe)?}}" "-mabi" "lp64d" "-march" "rv64g"
Index: clang/test/Driver/riscv-abi.c
===================================================================
--- clang/test/Driver/riscv-abi.c
+++ clang/test/Driver/riscv-abi.c
@@ -16,6 +16,10 @@
 
 // RUN: %clang -target riscv32-unknown-elf %s -### -o %t.o -march=rv32ifd -mabi=ilp32d 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-ILP32D %s
+// RUN: %clang -target riscv32-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-ILP32D %s
+// RUN: %clang -target riscv32-unknown-linux-gnu -x assembler %s -### -o %t.o 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-ILP32D %s
 
 // CHECK-ILP32D: "-target-abi" "ilp32d"
 
@@ -42,6 +46,10 @@
 
 // RUN: %clang -target riscv64-unknown-elf %s -### -o %t.o -march=rv64d -mabi=lp64d 2>&1 \
 // RUN:   | FileCheck -check-prefix=CHECK-LP64D %s
+// RUN: %clang -target riscv64-unknown-linux-gnu %s -### -o %t.o 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-LP64D %s
+// RUN: %clang -target riscv64-unknown-linux-gnu -x assembler %s -### -o %t.o 2>&1 \
+// RUN:   | FileCheck -check-prefix=CHECK-LP64D  %s
 
 // CHECK-LP64D: "-target-abi" "lp64d"
 
Index: clang/lib/Driver/ToolChains/Gnu.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Gnu.cpp
+++ clang/lib/Driver/ToolChains/Gnu.cpp
@@ -709,11 +709,9 @@
     StringRef ABIName = riscv::getRISCVABI(Args, getToolChain().getTriple());
     CmdArgs.push_back("-mabi");
     CmdArgs.push_back(ABIName.data());
-    if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
-      StringRef MArch = A->getValue();
-      CmdArgs.push_back("-march");
-      CmdArgs.push_back(MArch.data());
-    }
+    StringRef MArchName = riscv::getRISCVArch(Args, getToolChain().getTriple());
+    CmdArgs.push_back("-march");
+    CmdArgs.push_back(MArchName.data());
     break;
   }
   case llvm::Triple::sparc:
Index: clang/lib/Driver/ToolChains/Arch/RISCV.h
===================================================================
--- clang/lib/Driver/ToolChains/Arch/RISCV.h
+++ clang/lib/Driver/ToolChains/Arch/RISCV.h
@@ -24,6 +24,8 @@
                             std::vector<llvm::StringRef> &Features);
 StringRef getRISCVABI(const llvm::opt::ArgList &Args,
                       const llvm::Triple &Triple);
+StringRef getRISCVArch(const llvm::opt::ArgList &Args,
+                       const llvm::Triple &Triple);
 } // 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
@@ -357,14 +357,9 @@
 void riscv::getRISCVTargetFeatures(const Driver &D, const llvm::Triple &Triple,
                                    const ArgList &Args,
                                    std::vector<StringRef> &Features) {
-  llvm::Optional<StringRef> MArch;
-  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
-    MArch = A->getValue();
-  else if (Triple.getOS() == llvm::Triple::Linux)
-    // RISC-V Linux defaults to rv{32,64}gc.
-    MArch = Triple.getArch() == llvm::Triple::riscv32 ? "rv32gc" : "rv64gc";
+  StringRef MArch = getRISCVArch(Args, Triple);
 
-  if (MArch.hasValue() && !getArchFeatures(D, *MArch, Features, Args))
+  if (!getArchFeatures(D, MArch, Features, Args))
     return;
 
   // Handle features corresponding to "-ffixed-X" options
@@ -455,12 +450,132 @@
           Triple.getArch() == llvm::Triple::riscv64) &&
          "Unexpected triple");
 
+  // GCC's logic around choosing a default `-mabi=` is complex. If GCC is not
+  // configured using `--with-abi=`, then the logic for the default choice is
+  // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
+  // deviate from GCC's default only on baremetal targets (UnknownOS) where
+  // neither `-march` nor `-mabi` is specified.
+  //
+  // The logic uses the following, in order:
+  // 1. Explicit choices using `--with-abi=`
+  // 2. A default based on `--with-arch=`, if provided
+  // 3. A default based on the target triple's arch
+  //
+  // The logic in config.gcc is a little circular but it is not inconsistent.
+  //
+  // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
+  // and `-mabi=` respectively instead.
+
+  // 1. If `-mabi=` is specified, use it.
   if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
     return A->getValue();
 
-  // RISC-V Linux defaults to ilp32d/lp64d
-  if (Triple.getOS() == llvm::Triple::Linux)
-    return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32d" : "lp64d";
-  else
-    return Triple.getArch() == llvm::Triple::riscv32 ? "ilp32" : "lp64";
+  // 2. Choose a default based on `-march=`
+  //
+  // rv32g | rv32*d -> ilp32d
+  // rv32e -> ilp32e
+  // rv32* -> ilp32
+  // rv64g | rv64*d -> lp64d
+  // rv64* -> lp64
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+    StringRef MArch = A->getValue();
+
+    if (MArch.startswith_lower("rv32")) {
+      // FIXME: parse `March` to find `D` extension properly
+      if (MArch.substr(4).contains_lower("d") ||
+          MArch.startswith_lower("rv32g"))
+        return "ilp32d";
+      else if (MArch.startswith_lower("rv32e"))
+        return "ilp32e";
+      else
+        return "ilp32";
+    } else if (MArch.startswith_lower("rv64")) {
+      // FIXME: parse `March` to find `D` extension properly
+      if (MArch.substr(4).contains_lower("d") ||
+          MArch.startswith_lower("rv64g"))
+        return "lp64d";
+      else
+        return "lp64";
+    }
+  }
+
+  // 3. Choose a default based on the triple
+  //
+  // We deviate from GCC's defaults here:
+  // - On `riscv{XLEN}-unknown-elf` we use the integer calling convention only.
+  // - On all other OSs we use the double floating point calling convention.
+  if (Triple.getArch() == llvm::Triple::riscv32) {
+    if (Triple.getOS() == llvm::Triple::UnknownOS)
+      return "ilp32";
+    else
+      return "ilp32d";
+  } else {
+    if (Triple.getOS() == llvm::Triple::UnknownOS)
+      return "lp64";
+    else
+      return "lp64d";
+  }
+}
+
+StringRef riscv::getRISCVArch(const llvm::opt::ArgList &Args,
+                              const llvm::Triple &Triple) {
+  assert((Triple.getArch() == llvm::Triple::riscv32 ||
+          Triple.getArch() == llvm::Triple::riscv64) &&
+         "Unexpected triple");
+
+  // GCC's logic around choosing a default `-march=` is complex. If GCC is not
+  // configured using `--with-arch=`, then the logic for the default choice is
+  // defined in config.gcc. This function is based on the logic in GCC 9.2.0. We
+  // deviate from GCC's default only on baremetal targets (UnknownOS) where
+  // neither `-march` nor `-mabi` is specified.
+  //
+  // The logic uses the following, in order:
+  // 1. Explicit choices using `--with-arch=`
+  // 2. A default based on `--with-abi=`, if provided
+  // 3. A default based on the target triple's arch
+  //
+  // The logic in config.gcc is a little circular but it is not inconsistent.
+  //
+  // Clang does not have `--with-arch=` or `--with-abi=`, so we use `-march=`
+  // and `-mabi=` respectively instead.
+  //
+  // Clang does not yet support MULTILIB_REUSE, so we use `rv{XLEN}imafdc`
+  // instead of `rv{XLEN}gc` though they are (currently) equivalent.
+
+  // 1. If `-march=` is specified, use it.
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ))
+    return A->getValue();
+
+  // 2. Choose a default based on `-mabi=`
+  //
+  // ilp32e -> rv32e
+  // ilp32 | ilp32f | ilp32d -> rv32imafdc
+  // lp64 | lp64f | lp64d -> rv64imafdc
+  if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ)) {
+    StringRef MABI = A->getValue();
+
+    if (MABI.equals_lower("ilp32e"))
+      return "rv32e";
+    else if (MABI.startswith_lower("ilp32"))
+      return "rv32imafdc";
+    else if (MABI.startswith_lower("lp64"))
+      return "rv64imafdc";
+  }
+
+  // 3. Choose a default based on the triple
+  //
+  // We deviate from GCC's defaults here:
+  // - On `riscv{XLEN}-unknown-elf` we default to `rv{XLEN}imac`
+  // - On all other OSs we use `rv{XLEN}imafdc` (equivalent to `rv{XLEN}gc`)
+  if (Triple.getArch() == llvm::Triple::riscv32) {
+    if (Triple.getOS() == llvm::Triple::UnknownOS)
+      return "rv32imac";
+    else
+      return "rv32imafdc";
+  } else {
+    if (Triple.getOS() == llvm::Triple::UnknownOS)
+      return "rv64imac";
+    else
+      return "rv64imafdc";
+  }
 }
Index: clang/docs/ReleaseNotes.rst
===================================================================
--- clang/docs/ReleaseNotes.rst
+++ clang/docs/ReleaseNotes.rst
@@ -223,6 +223,15 @@
   element. Clang now matches the gcc behavior on Linux and NetBSD. You can
   switch back to old API behavior with flag: -fclang-abi-compat=9.0.
 
+- RISC-V now chooses a default ``-march=`` and ``-mabi=`` to match (in almost
+  all cases) the GCC defaults. On baremetal targets, where neither ``-march=``
+  nor ``-mabi=`` are specified, Clang now differs from GCC by defaulting to
+  ``-march=rv32imac -mabi=ilp32`` or ``-march=rv64imac -mabi=lp64`` depending on
+  the architecture in the target triple. These do not always match the defaults
+  in Clang 9. We strongly suggest that you explicitly pass `-march=` and
+  `-mabi=` when compiling for RISC-V, due to how extensible this architecture
+  is.
+
 OpenMP Support in Clang
 -----------------------
 
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to