]> granicus.if.org Git - clang/commitdiff
[RISCV] Move architecture parsing code into its own function
authorRoger Ferrer Ibanez <rofirrim@gmail.com>
Tue, 10 Sep 2019 07:47:34 +0000 (07:47 +0000)
committerRoger Ferrer Ibanez <rofirrim@gmail.com>
Tue, 10 Sep 2019 07:47:34 +0000 (07:47 +0000)
I plan to reuse it in a later patch.

This is almost NFC except a small change in control flow when diagnosing
+d without +f.

Differential Revision: https://reviews.llvm.org/D66002

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@371492 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Driver/ToolChains/Arch/RISCV.cpp

index 355dce3c10d47015601292cee8916369134d8e21..fc2f9ed5a28c423ea638a5f4838d1129ed318955 100644 (file)
@@ -189,167 +189,177 @@ static void getExtensionFeatures(const Driver &D,
   }
 }
 
-void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
-                                   std::vector<StringRef> &Features) {
-  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
-    StringRef MArch = A->getValue();
+// Returns false if an error is diagnosed.
+static bool getArchFeatures(const Driver &D, StringRef MArch,
+                            std::vector<StringRef> &Features,
+                            const ArgList &Args) {
+  // RISC-V ISA strings must be lowercase.
+  if (llvm::any_of(MArch, [](char c) { return isupper(c); })) {
+    D.Diag(diag::err_drv_invalid_riscv_arch_name)
+        << MArch << "string must be lowercase";
+    return false;
+  }
 
-    // RISC-V ISA strings must be lowercase.
-    if (llvm::any_of(MArch, [](char c) { return isupper(c); })) {
-      D.Diag(diag::err_drv_invalid_riscv_arch_name)
-          << MArch << "string must be lowercase";
-      return;
-    }
+  // ISA string must begin with rv32 or rv64.
+  if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) ||
+      (MArch.size() < 5)) {
+    D.Diag(diag::err_drv_invalid_riscv_arch_name)
+        << MArch << "string must begin with rv32{i,e,g} or rv64{i,g}";
+    return false;
+  }
 
-    // ISA string must begin with rv32 or rv64.
-    if (!(MArch.startswith("rv32") || MArch.startswith("rv64")) ||
-        (MArch.size() < 5)) {
-      D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
-        << "string must begin with rv32{i,e,g} or rv64{i,g}";
-      return;
-    }
+  bool HasRV64 = MArch.startswith("rv64");
+
+  // The canonical order specified in ISA manual.
+  // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
+  StringRef StdExts = "mafdqlcbjtpvn";
+  bool HasF = false, HasD = false;
+  char Baseline = MArch[4];
+
+  // First letter should be 'e', 'i' or 'g'.
+  switch (Baseline) {
+  default:
+    D.Diag(diag::err_drv_invalid_riscv_arch_name)
+        << MArch << "first letter should be 'e', 'i' or 'g'";
+    return false;
+  case 'e': {
+    StringRef Error;
+    // Currently LLVM does not support 'e'.
+    // Extension 'e' is not allowed in rv64.
+    if (HasRV64)
+      Error = "standard user-level extension 'e' requires 'rv32'";
+    else
+      Error = "unsupported standard user-level extension 'e'";
+    D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch << Error;
+    return false;
+  }
+  case 'i':
+    break;
+  case 'g':
+    // g = imafd
+    StdExts = StdExts.drop_front(4);
+    Features.push_back("+m");
+    Features.push_back("+a");
+    Features.push_back("+f");
+    Features.push_back("+d");
+    HasF = true;
+    HasD = true;
+    break;
+  }
 
-    bool HasRV64 = MArch.startswith("rv64");
+  // Skip rvxxx
+  StringRef Exts = MArch.substr(5);
+
+  // Remove non-standard extensions and supervisor-level extensions.
+  // They have 'x', 's', 'sx' prefixes. Parse them at the end.
+  // Find the very first occurrence of 's' or 'x'.
+  StringRef OtherExts;
+  size_t Pos = Exts.find_first_of("sx");
+  if (Pos != StringRef::npos) {
+    OtherExts = Exts.substr(Pos);
+    Exts = Exts.substr(0, Pos);
+  }
 
-    // The canonical order specified in ISA manual.
-    // Ref: Table 22.1 in RISC-V User-Level ISA V2.2
-    StringRef StdExts = "mafdqlcbjtpvn";
-    bool HasF = false, HasD = false;
-    char Baseline = MArch[4];
+  std::string Major, Minor;
+  if (!getExtensionVersion(D, MArch, std::string(1, Baseline), Exts, Major,
+                           Minor))
+    return false;
 
-    // First letter should be 'e', 'i' or 'g'.
-    switch (Baseline) {
-    default:
-      D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
-        << "first letter should be 'e', 'i' or 'g'";
-      return;
-    case 'e': {
+  // 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) {
+    char c = *I;
+
+    // Check ISA extensions are specified in the canonical order.
+    while (StdExtsItr != StdExtsEnd && *StdExtsItr != c)
+      ++StdExtsItr;
+
+    if (StdExtsItr == StdExtsEnd) {
+      // Either c contains a valid extension but it was not given in
+      // canonical order or it is an invalid extension.
       StringRef Error;
-      // Currently LLVM does not support 'e'.
-      // Extension 'e' is not allowed in rv64.
-      if (HasRV64)
-        Error = "standard user-level extension 'e' requires 'rv32'";
+      if (StdExts.contains(c))
+        Error = "standard user-level extension not given in canonical order";
       else
-        Error = "unsupported standard user-level extension 'e'";
-      D.Diag(diag::err_drv_invalid_riscv_arch_name)
-        << MArch << Error;
-      return;
+        Error = "invalid standard user-level extension";
+      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+          << MArch << Error << std::string(1, c);
+      return false;
     }
-    case 'i':
-      break;
-    case 'g':
-      // g = imafd
-      StdExts = StdExts.drop_front(4);
+
+    // 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.
+    }
+
+    // The order is OK, then push it into features.
+    switch (c) {
+    default:
+      // Currently LLVM supports only "mafdc".
+      D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
+          << MArch << "unsupported standard user-level extension"
+          << std::string(1, c);
+      return false;
+    case 'm':
       Features.push_back("+m");
+      break;
+    case 'a':
       Features.push_back("+a");
+      break;
+    case 'f':
       Features.push_back("+f");
-      Features.push_back("+d");
       HasF = true;
+      break;
+    case 'd':
+      Features.push_back("+d");
       HasD = true;
       break;
+    case 'c':
+      Features.push_back("+c");
+      break;
     }
+  }
 
-    // Skip rvxxx
-    StringRef Exts = MArch.substr(5);
-
-    // Remove non-standard extensions and supervisor-level extensions.
-    // They have 'x', 's', 'sx' prefixes. Parse them at the end.
-    // Find the very first occurrence of 's' or 'x'.
-    StringRef OtherExts;
-    size_t Pos = Exts.find_first_of("sx");
-    if (Pos != StringRef::npos) {
-      OtherExts = Exts.substr(Pos);
-      Exts = Exts.substr(0, Pos);
-    }
-
-    std::string Major, Minor;
-    if (!getExtensionVersion(D, MArch, std::string(1, Baseline),
-                             Exts, Major, Minor))
-      return;
-
-    // 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)  {
-      char c = *I;
-
-      // Check ISA extensions are specified in the canonical order.
-      while (StdExtsItr != StdExtsEnd && *StdExtsItr != c)
-        ++StdExtsItr;
-
-      if (StdExtsItr == StdExtsEnd) {
-        // Either c contains a valid extension but it was not given in
-        // canonical order or it is an invalid extension.
-        StringRef Error;
-        if (StdExts.contains(c))
-          Error = "standard user-level extension not given in canonical order";
-        else
-          Error = "invalid standard user-level extension";
-        D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
-          << MArch <<  Error << std::string(1, c);
-        return;
-      }
+  // Dependency check.
+  // It's illegal to specify the 'd' (double-precision floating point)
+  // extension without also specifying the 'f' (single precision
+  // floating-point) extension.
+  if (HasD && !HasF) {
+    D.Diag(diag::err_drv_invalid_riscv_arch_name)
+        << MArch << "d requires f extension to also be specified";
+    return false;
+  }
 
-      // Move to next char to prevent repeated letter.
-      ++StdExtsItr;
+  // Additional dependency checks.
+  // TODO: The 'q' extension requires rv64.
+  // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
 
-      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;
-
-        // TODO: Use version number when setting target features
-        // and consume the underscore '_' that might follow.
-      }
-
-      // The order is OK, then push it into features.
-      switch (c) {
-      default:
-        // Currently LLVM supports only "mafdc".
-        D.Diag(diag::err_drv_invalid_riscv_ext_arch_name)
-          << MArch << "unsupported standard user-level extension"
-          << std::string(1, c);
-        return;
-      case 'm':
-        Features.push_back("+m");
-        break;
-      case 'a':
-        Features.push_back("+a");
-        break;
-      case 'f':
-        Features.push_back("+f");
-        HasF = true;
-        break;
-      case 'd':
-        Features.push_back("+d");
-        HasD = true;
-        break;
-      case 'c':
-        Features.push_back("+c");
-        break;
-      }
-    }
+  // Handle all other types of extensions.
+  getExtensionFeatures(D, Args, Features, MArch, OtherExts);
 
-    // Dependency check.
-    // It's illegal to specify the 'd' (double-precision floating point)
-    // extension without also specifying the 'f' (single precision
-    // floating-point) extension.
-    if (HasD && !HasF)
-      D.Diag(diag::err_drv_invalid_riscv_arch_name) << MArch
-        << "d requires f extension to also be specified";
+  return true;
+}
 
-    // Additional dependency checks.
-    // TODO: The 'q' extension requires rv64.
-    // TODO: It is illegal to specify 'e' extensions with 'f' and 'd'.
+void riscv::getRISCVTargetFeatures(const Driver &D, const ArgList &Args,
+                                   std::vector<StringRef> &Features) {
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+    StringRef MArch = A->getValue();
 
-    // Handle all other types of extensions.
-    getExtensionFeatures(D, Args, Features, MArch, OtherExts);
+    if (!getArchFeatures(D, MArch, Features, Args))
+      return;
   }
 
   // -mrelax is default, unless -mno-relax is specified.