simoncook updated this revision to Diff 242080.
simoncook added a comment.

Don't put option in m_riscv_Features_Group, we don't want it being handled like 
a feature.


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

https://reviews.llvm.org/D73891

Files:
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Arch/RISCV.cpp
  clang/test/Driver/riscv-arch.c

Index: clang/test/Driver/riscv-arch.c
===================================================================
--- clang/test/Driver/riscv-arch.c
+++ clang/test/Driver/riscv-arch.c
@@ -327,3 +327,22 @@
 // RUN: %clang -target riscv64-unknown-elf -march=rv64i -### %s \
 // RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV64-TARGET %s
 // RV64-TARGET: "-triple" "riscv64-unknown-unknown-elf"
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ib -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-NOFLAG %s
+// RV32-EXPERIMENTAL-NOFLAG: error: invalid arch name 'rv32ib'
+// RV32-EXPERIMENTAL-NOFLAG: requires '-menable-experimental-extensions'
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ib -menable-experimental-extensions -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-NOVERS %s
+// RV32-EXPERIMENTAL-NOVERS: error: invalid arch name 'rv32ib'
+// RV32-EXPERIMENTAL-NOVERS: experimental extension requires explicit version number
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ib0p1 -menable-experimental-extensions -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-BADVERS %s
+// RV32-EXPERIMENTAL-BADVERS: error: invalid arch name 'rv32ib0p1'
+// RV32-EXPERIMENTAL-BADVERS: unsupported version number 0.1 for experimental extension
+
+// RUN: %clang -target riscv32-unknown-elf -march=rv32ib0p92 -menable-experimental-extensions -### %s \
+// RUN: -fsyntax-only 2>&1 | FileCheck -check-prefix=RV32-EXPERIMENTAL-GOODVERS %s
+// RV32-EXPERIMENTAL-GOODVERS: "-target-feature" "+b"
Index: clang/lib/Driver/ToolChains/Arch/RISCV.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/RISCV.cpp
+++ clang/lib/Driver/ToolChains/Arch/RISCV.cpp
@@ -47,20 +47,32 @@
   return false;
 }
 
+static bool isExperimentalExtension(StringRef Ext) {
+  // Currently 'b' is the only supported experimental extension
+  if (Ext == "b")
+    return true;
+  return false;
+}
+
+static std::pair<StringRef, StringRef>
+getExperimentalExtensionVersion(StringRef Ext) {
+  if (Ext == "b")
+    return {"0", "92"};
+  return {"", ""};
+}
+
 // Extensions may have a version number, and may be separated by
 // an underscore '_' e.g.: rv32i2_m2.
 // Version number is divided into major and minor version numbers,
 // separated by a 'p'. If the minor version is 0 then 'p0' can be
 // omitted from the version string. E.g., rv32i2p0, rv32i2, rv32i2p1.
-static bool getExtensionVersion(const Driver &D, StringRef MArch,
-                                StringRef Ext, StringRef In,
+static bool getExtensionVersion(const Driver &D, const ArgList &Args,
+                                StringRef MArch, StringRef Ext, StringRef In,
                                 std::string &Major, std::string &Minor) {
   Major = std::string(In.take_while(isDigit));
   In = In.substr(Major.size());
-  if (Major.empty())
-    return true;
 
-  if (In.consume_front("p")) {
+  if (Major.size() && In.consume_front("p")) {
     Minor = std::string(In.take_while(isDigit));
     In = In.substr(Major.size());
 
@@ -74,7 +86,43 @@
     }
   }
 
-  // TODO: Handle extensions with version number.
+  // If experimental extension, require use of current version number number
+  if (isExperimentalExtension(Ext)) {
+    if (!Args.hasArg(options::OPT_menable_experimental_extensions)) {
+      std::string Error =
+          "requires '-menable-experimental-extensions' for experimental extension";
+      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+          << MArch << Error << Ext;
+      return false;
+    } else if (Major.empty() && Minor.empty()) {
+      std::string Error =
+          "experimental extension requires explicit version number";
+      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+          << MArch << Error << Ext;
+      return false;
+    }
+    auto SupportedVers = getExperimentalExtensionVersion(Ext);
+    if (Major != SupportedVers.first || Minor != SupportedVers.second) {
+      std::string Error =
+          "unsupported version number " + Major;
+      if (!Minor.empty())
+        Error += "." + Minor;
+      Error += " for experimental extension (this compiler supports "
+            + SupportedVers.first.str() + "."
+            + SupportedVers.second.str() + ")";
+
+      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+          << MArch << Error << Ext;
+      return false;
+    }
+    return true;
+  }
+
+  // Allow extensions to declare no version number
+  if (Major.empty() && Minor.empty())
+    return true;
+
+  // TODO: Handle supported extensions with version number.
   std::string Error = "unsupported version number " + Major;
   if (!Minor.empty())
     Error += "." + Minor;
@@ -156,7 +204,7 @@
     if (Pos != StringRef::npos) {
       auto Next =  Name.substr(Pos);
       Name = Name.substr(0, Pos);
-      if (!getExtensionVersion(D, MArch, Ext, Next, Major, Minor))
+      if (!getExtensionVersion(D, Args, MArch, Ext, Next, Major, Minor))
         return;
     }
 
@@ -262,17 +310,23 @@
   }
 
   std::string Major, Minor;
-  if (!getExtensionVersion(D, MArch, std::string(1, Baseline), Exts, Major,
-                           Minor))
+  if (!getExtensionVersion(D, Args, MArch, std::string(1, Baseline), Exts,
+                           Major, Minor))
     return false;
 
+  // Consume the base ISA version number and any '_' between rvxxx and the
+  // first extension
+  Exts = Exts.drop_front(Major.size());
+  if (!Minor.empty())
+    Exts = Exts.drop_front(Minor.size() + 1 /*'p'*/);
+  Exts.consume_front("_");
+
   // TODO: Use version number when setting target features
-  // and consume the underscore '_' that might follow.
 
   auto StdExtsItr = StdExts.begin();
   auto StdExtsEnd = StdExts.end();
 
-  for (auto I = Exts.begin(), E = Exts.end(); I != E; ++I) {
+  for (auto I = Exts.begin(), E = Exts.end(); I != E; ) {
     char c = *I;
 
     // Check ISA extensions are specified in the canonical order.
@@ -295,18 +349,15 @@
     // Move to next char to prevent repeated letter.
     ++StdExtsItr;
 
-    if (std::next(I) != E) {
-      // Skip c.
-      std::string Next = std::string(std::next(I), E);
-      std::string Major, Minor;
-      if (!getExtensionVersion(D, MArch, std::string(1, c), Next, Major, Minor))
-        return false;
-
-      // TODO: Use version number when setting target features
-      // and consume the underscore '_' that might follow.
-    }
+    std::string Next, Major, Minor;
+    if (std::next(I) != E)
+      Next = std::string(std::next(I), E);
+    if (!getExtensionVersion(D, Args, MArch, std::string(1, c), Next, Major,
+                             Minor))
+      return false;
 
     // The order is OK, then push it into features.
+    // TODO: Use version number when setting target features
     switch (c) {
     default:
       // Currently LLVM supports only "mafdc".
@@ -331,7 +382,19 @@
     case 'c':
       Features.push_back("+c");
       break;
+    case 'b':
+      Features.push_back("+b");
+      break;
     }
+
+    // Consume full extension name and version, including any optional '_'
+    // between this extension and the next
+    ++I;
+    I += Major.size();
+    if (Minor.size())
+      I += Minor.size() + 1 /*'p'*/;
+    if (*I == '_')
+      ++I;
   }
 
   // Dependency check.
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -2291,6 +2291,8 @@
 def mcmodel_EQ_medany : Flag<["-"], "mcmodel=medany">, Group<m_riscv_Features_Group>,
   Flags<[CC1Option]>, Alias<mcmodel_EQ>, AliasArgs<["medium"]>,
   HelpText<"Equivalent to -mcmodel=medium, compatible with RISC-V gcc.">;
+def menable_experimental_extensions : Flag<["-"], "menable-experimental-extensions">, Group<m_Group>,
+  HelpText<"Enable use of experimental RISC-V extensions.">;
 
 def munaligned_access : Flag<["-"], "munaligned-access">, Group<m_arm_Features_Group>,
   HelpText<"Allow memory accesses to be unaligned (AArch32/AArch64 only)">;
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to