This revision was landed with ongoing or failed builds.
This revision was automatically updated to reflect the committed changes.
Closed by commit rG135a9272a4c9: [Clang][LoongArch] Handle 
-march/-m{single,double,soft}-float/-mfpu options (authored by SixWeining, 
committed by gonglingqin).

Changed prior to commit:
  https://reviews.llvm.org/D136146?vs=474414&id=474471#toc

Repository:
  rG LLVM Github Monorepo

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

https://reviews.llvm.org/D136146

Files:
  clang/include/clang/Basic/DiagnosticDriverKinds.td
  clang/include/clang/Driver/Options.td
  clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
  clang/lib/Driver/ToolChains/Arch/LoongArch.h
  clang/lib/Driver/ToolChains/Clang.cpp
  clang/lib/Driver/ToolChains/Linux.cpp
  clang/test/Driver/loongarch-default-features.c
  clang/test/Driver/loongarch-march-error.c
  clang/test/Driver/loongarch-march.c
  clang/test/Driver/loongarch-mdouble-float.c
  clang/test/Driver/loongarch-mfpu-error.c
  clang/test/Driver/loongarch-mfpu.c
  clang/test/Driver/loongarch-msingle-float.c
  clang/test/Driver/loongarch-msoft-float.c
  llvm/include/llvm/Support/LoongArchTargetParser.def
  llvm/include/llvm/Support/LoongArchTargetParser.h
  llvm/lib/Support/CMakeLists.txt
  llvm/lib/Support/LoongArchTargetParser.cpp

Index: llvm/lib/Support/LoongArchTargetParser.cpp
===================================================================
--- /dev/null
+++ llvm/lib/Support/LoongArchTargetParser.cpp
@@ -0,0 +1,53 @@
+//==-- LoongArch64TargetParser - Parser for LoongArch64 features --*- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise LoongArch hardware features
+// such as CPU/ARCH and extension names.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Support/LoongArchTargetParser.h"
+#include "llvm/ADT/StringSwitch.h"
+
+using namespace llvm;
+using namespace llvm::LoongArch;
+
+const FeatureInfo AllFeatures[] = {
+#define LOONGARCH_FEATURE(NAME, KIND) {NAME, KIND},
+#include "llvm/Support/LoongArchTargetParser.def"
+};
+
+const ArchInfo AllArchs[] = {
+#define LOONGARCH_ARCH(NAME, KIND, FEATURES)                                   \
+  {NAME, LoongArch::ArchKind::KIND, FEATURES},
+#include "llvm/Support/LoongArchTargetParser.def"
+};
+
+LoongArch::ArchKind LoongArch::parseArch(StringRef Arch) {
+  for (const auto A : AllArchs) {
+    if (A.Name == Arch)
+      return A.Kind;
+  }
+
+  return LoongArch::ArchKind::AK_INVALID;
+}
+
+bool LoongArch::getArchFeatures(StringRef Arch,
+                                std::vector<StringRef> &Features) {
+  for (const auto A : AllArchs) {
+    if (A.Name == Arch) {
+      for (const auto F : AllFeatures) {
+        if ((A.Features & F.Kind) == F.Kind && F.Kind != FK_INVALID) {
+          Features.push_back(F.Name);
+        }
+      }
+      return true;
+    }
+  }
+  return false;
+}
Index: llvm/lib/Support/CMakeLists.txt
===================================================================
--- llvm/lib/Support/CMakeLists.txt
+++ llvm/lib/Support/CMakeLists.txt
@@ -187,6 +187,7 @@
   LineIterator.cpp
   Locale.cpp
   LockFileManager.cpp
+  LoongArchTargetParser.cpp
   LowLevelType.cpp
   ManagedStatic.cpp
   MathExtras.cpp
Index: llvm/include/llvm/Support/LoongArchTargetParser.h
===================================================================
--- /dev/null
+++ llvm/include/llvm/Support/LoongArchTargetParser.h
@@ -0,0 +1,74 @@
+//==-- LoongArch64TargetParser - Parser for LoongArch64 features --*- C++ -*-=//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// This file implements a target parser to recognise LoongArch hardware features
+// such as CPU/ARCH and extension names.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_SUPPORT_LOONGARCHTARGETPARSER_H
+#define LLVM_SUPPORT_LOONGARCHTARGETPARSER_H
+
+#include "llvm/ADT/Triple.h"
+#include <vector>
+
+namespace llvm {
+class StringRef;
+
+namespace LoongArch {
+
+enum FeatureKind : uint32_t {
+  FK_INVALID = 0,
+  FK_NONE = 1,
+
+  // 64-bit ISA is available.
+  FK_64BIT = 1 << 1,
+
+  // Single-precision floating-point instructions are available.
+  FK_FP32 = 1 << 2,
+
+  // Double-precision floating-point instructions are available.
+  FK_FP64 = 1 << 3,
+
+  // Loongson SIMD Extension is available.
+  FK_LSX = 1 << 4,
+
+  // Loongson Advanced SIMD Extension is available.
+  FK_LASX = 1 << 5,
+
+  // Loongson Binary Translation Extension is available.
+  FK_LBT = 1 << 6,
+
+  // Loongson Virtualization Extension is available.
+  FK_LVZ = 1 << 7,
+};
+
+struct FeatureInfo {
+  StringRef Name;
+  FeatureKind Kind;
+};
+
+enum class ArchKind {
+#define LOONGARCH_ARCH(NAME, KIND, FEATURES) KIND,
+#include "LoongArchTargetParser.def"
+};
+
+struct ArchInfo {
+  StringRef Name;
+  ArchKind Kind;
+  uint32_t Features;
+};
+
+ArchKind parseArch(StringRef Arch);
+bool getArchFeatures(StringRef Arch, std::vector<StringRef> &Features);
+
+} // namespace LoongArch
+
+} // namespace llvm
+
+#endif // LLVM_SUPPORT_LOONGARCHTARGETPARSER_H
Index: llvm/include/llvm/Support/LoongArchTargetParser.def
===================================================================
--- /dev/null
+++ llvm/include/llvm/Support/LoongArchTargetParser.def
@@ -0,0 +1,25 @@
+#ifndef LOONGARCH_FEATURE
+#define LOONGARCH_FEATURE(NAME, KIND)
+#endif
+
+LOONGARCH_FEATURE("invalid", FK_INVALID)
+LOONGARCH_FEATURE("none", FK_NONE)
+LOONGARCH_FEATURE("+64bit", FK_64BIT)
+LOONGARCH_FEATURE("+f", FK_FP32)
+LOONGARCH_FEATURE("+d", FK_FP64)
+LOONGARCH_FEATURE("+lsx", FK_LSX)
+LOONGARCH_FEATURE("+lasx", FK_LASX)
+LOONGARCH_FEATURE("+lbt", FK_LBT)
+LOONGARCH_FEATURE("+lvz", FK_LVZ)
+
+#undef LOONGARCH_FEATURE
+
+#ifndef LOONGARCH_ARCH
+#define LOONGARCH_ARCH(NAME, KIND, FEATURES)
+#endif
+
+LOONGARCH_ARCH("invalid", AK_INVALID, FK_INVALID)
+LOONGARCH_ARCH("loongarch64", AK_LOONGARCH64, FK_64BIT | FK_FP32 | FK_FP64)
+LOONGARCH_ARCH("la464", AK_LA464, FK_64BIT | FK_FP32 | FK_FP64 | FK_LSX | FK_LASX)
+
+#undef LOONGARCH_ARCH
Index: clang/test/Driver/loongarch-msoft-float.c
===================================================================
--- /dev/null
+++ clang/test/Driver/loongarch-msoft-float.c
@@ -0,0 +1,18 @@
+// RUN: %clang --target=loongarch64 -msoft-float -fsyntax-only %s -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1
+// RUN: %clang --target=loongarch64 -msoft-float -S -emit-llvm %s -o - \
+// RUN:   | FileCheck %s --check-prefix=IR
+
+// CC1-NOT: "-target-feature"
+// CC1: "-target-feature" "+64bit"
+// CC1-SAME: {{^}} "-target-feature" "-f"
+// CC1-SAME: {{^}} "-target-feature" "-d"
+// CC1-NOT: "-target-feature"
+// CC1: "-target-abi" "lp64s"
+
+// IR: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,-d,-f"
+
+/// Dummy function
+int foo(void) {
+  return  3;
+}
Index: clang/test/Driver/loongarch-msingle-float.c
===================================================================
--- /dev/null
+++ clang/test/Driver/loongarch-msingle-float.c
@@ -0,0 +1,18 @@
+// RUN: %clang --target=loongarch64 -msingle-float -fsyntax-only %s -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1
+// RUN: %clang --target=loongarch64 -msingle-float -S -emit-llvm %s -o - \
+// RUN:   | FileCheck %s --check-prefix=IR
+
+// CC1-NOT: "-target-feature"
+// CC1: "-target-feature" "+64bit"
+// CC1-SAME: {{^}} "-target-feature" "+f"
+// CC1-SAME: {{^}} "-target-feature" "-d"
+// CC1-NOT: "-target-feature"
+// CC1: "-target-abi" "lp64f"
+
+// IR: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+f,-d"
+
+/// Dummy function
+int foo(void) {
+  return  3;
+}
Index: clang/test/Driver/loongarch-mfpu.c
===================================================================
--- /dev/null
+++ clang/test/Driver/loongarch-mfpu.c
@@ -0,0 +1,47 @@
+// RUN: %clang --target=loongarch64 -mfpu=64 -fsyntax-only %s -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1-FPU64
+// RUN: %clang --target=loongarch64 -mfpu=32 -fsyntax-only %s -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1-FPU32
+// RUN: %clang --target=loongarch64 -mfpu=0 -fsyntax-only %s -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1-FPU0
+// RUN: %clang --target=loongarch64 -mfpu=none -fsyntax-only %s -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1-FPU0
+
+// RUN: %clang --target=loongarch64 -mfpu=64 -S -emit-llvm %s -o - \
+// RUN:   | FileCheck %s --check-prefix=IR-FPU64
+// RUN: %clang --target=loongarch64 -mfpu=32 -S -emit-llvm %s -o - \
+// RUN:   | FileCheck %s --check-prefix=IR-FPU32
+// RUN: %clang --target=loongarch64 -mfpu=0 -S -emit-llvm %s -o - \
+// RUN:   | FileCheck %s --check-prefix=IR-FPU0
+// RUN: %clang --target=loongarch64 -mfpu=none -S -emit-llvm %s -o - \
+// RUN:   | FileCheck %s --check-prefix=IR-FPU0
+
+// CC1-FPU64-NOT: "-target-feature"
+// CC1-FPU64: "-target-feature" "+64bit"
+// CC1-FPU64-SAME: "-target-feature" "+f"
+// CC1-FPU64-SAME: "-target-feature" "+d"
+// CC1-FPU64-NOT: "-target-feature"
+// CC1-FPU64: "-target-abi" "lp64d"
+
+// CC1-FPU32-NOT: "-target-feature"
+// CC1-FPU32: "-target-feature" "+64bit"
+// CC1-FPU32-SAME: "-target-feature" "+f"
+// CC1-FPU32-SAME: "-target-feature" "-d"
+// CC1-FPU32-NOT: "-target-feature"
+// CC1-FPU32: "-target-abi" "lp64f"
+
+// CC1-FPU0-NOT: "-target-feature"
+// CC1-FPU0: "-target-feature" "+64bit"
+// CC1-FPU0-SAME: "-target-feature" "-f"
+// CC1-FPU0-SAME: "-target-feature" "-d"
+// CC1-FPU0-NOT: "-target-feature"
+// CC1-FPU0: "-target-abi" "lp64s"
+
+// IR-FPU64: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+d,+f"
+// IR-FPU32: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+f,-d"
+// IR-FPU0: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,-d,-f"
+
+/// Dummy function
+int foo(void) {
+  return  3;
+}
Index: clang/test/Driver/loongarch-mfpu-error.c
===================================================================
--- /dev/null
+++ clang/test/Driver/loongarch-mfpu-error.c
@@ -0,0 +1,4 @@
+// RUN: %clang --target=loongarch64 -mfpu=xxx -fsyntax-only %s -### 2>&1 \
+// RUN:   | FileCheck %s
+
+// CHECK: invalid argument 'xxx' to -mfpu=; must be one of: 64, 32, 0, none
Index: clang/test/Driver/loongarch-mdouble-float.c
===================================================================
--- /dev/null
+++ clang/test/Driver/loongarch-mdouble-float.c
@@ -0,0 +1,18 @@
+// RUN: %clang --target=loongarch64 -mdouble-float -fsyntax-only %s -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1
+// RUN: %clang --target=loongarch64 -mdouble-float -S -emit-llvm %s -o - \
+// RUN:   | FileCheck %s --check-prefix=IR
+
+// CC1-NOT: "-target-feature"
+// CC1: "-target-feature" "+64bit"
+// CC1-SAME: {{^}} "-target-feature" "+f"
+// CC1-SAME: {{^}} "-target-feature" "+d"
+// CC1-NOT: "-target-feature"
+// CC1: "-target-abi" "lp64d"
+
+// IR: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+d,+f"
+
+/// Dummy function
+int foo(void) {
+  return  3;
+}
Index: clang/test/Driver/loongarch-march.c
===================================================================
--- /dev/null
+++ clang/test/Driver/loongarch-march.c
@@ -0,0 +1,32 @@
+// RUN: %clang --target=loongarch64 -march=loongarch64 -fsyntax-only %s -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1-LOONGARCH64
+// RUN: %clang --target=loongarch64 -march=la464 -fsyntax-only %s -### 2>&1 \
+// RUN:   | FileCheck %s --check-prefix=CC1-LA464
+// RUN: %clang --target=loongarch64 -march=loongarch64 -S -emit-llvm %s -o - \
+// RUN:   | FileCheck %s --check-prefix=IR-LOONGARCH64
+// RUN: %clang --target=loongarch64 -march=la464 -S -emit-llvm %s -o - \
+// RUN:   | FileCheck %s --check-prefix=IR-LA464
+
+// CC1-LOONGARCH64-NOT: "-target-feature"
+// CC1-LOONGARCH64: "-target-feature" "+64bit"
+// CC1-LOONGARCH64-SAME: {{^}} "-target-feature" "+f"
+// CC1-LOONGARCH64-SAME: {{^}} "-target-feature" "+d"
+// CC1-LOONGARCH64-NOT: "-target-feature"
+// CC1-LOONGARCH64: "-target-abi" "lp64d"
+
+// CC1-LA464-NOT: "-target-feature"
+// CC1-LA464: "-target-feature" "+64bit"
+// CC1-LA464-SAME: {{^}} "-target-feature" "+f"
+// CC1-LA464-SAME: {{^}} "-target-feature" "+d"
+// CC1-LA464-SAME: {{^}} "-target-feature" "+lsx"
+// CC1-LA464-SAME: {{^}} "-target-feature" "+lasx"
+// CC1-LA464-NOT: "-target-feature"
+// CC1-LA464: "-target-abi" "lp64d"
+
+// IR-LOONGARCH64: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+d,+f"
+// IR-LA464: attributes #{{[0-9]+}} ={{.*}}"target-features"="+64bit,+d,+f,+lasx,+lsx"
+
+/// Dummy function
+int foo(void) {
+  return  3;
+}
Index: clang/test/Driver/loongarch-march-error.c
===================================================================
--- /dev/null
+++ clang/test/Driver/loongarch-march-error.c
@@ -0,0 +1,7 @@
+// RUN: not %clang --target=loongarch64 -march=loongarch -fsyntax-only %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=LOONGARCH %s
+// LOONGARCH: error: invalid arch name '-march=loongarch'
+
+// RUN: not %clang --target=loongarch64 -march=LA464 -fsyntax-only %s 2>&1 \
+// RUN:   | FileCheck --check-prefix=LA464-UPPER %s
+// LA464-UPPER: error: invalid arch name '-march=LA464'
Index: clang/test/Driver/loongarch-default-features.c
===================================================================
--- clang/test/Driver/loongarch-default-features.c
+++ clang/test/Driver/loongarch-default-features.c
@@ -1,8 +1,8 @@
 // RUN: %clang --target=loongarch32 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=LA32
 // RUN: %clang --target=loongarch64 -S -emit-llvm %s -o - | FileCheck %s --check-prefix=LA64
 
-// LA32: "target-features"="+d,+f"
-// LA64: "target-features"="+d,+f"
+// LA32-NOT: "target-features"=
+// LA64: "target-features"="+64bit,+d,+f"
 
 /// Dummy function
 int foo(void) {
Index: clang/lib/Driver/ToolChains/Linux.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Linux.cpp
+++ clang/lib/Driver/ToolChains/Linux.cpp
@@ -469,16 +469,18 @@
   }
   case llvm::Triple::loongarch32: {
     LibDir = "lib32";
-    Loader = ("ld-linux-loongarch-" +
-              tools::loongarch::getLoongArchABI(Args, Triple) + ".so.1")
-                 .str();
+    Loader =
+        ("ld-linux-loongarch-" +
+         tools::loongarch::getLoongArchABI(getDriver(), Args, Triple) + ".so.1")
+            .str();
     break;
   }
   case llvm::Triple::loongarch64: {
     LibDir = "lib64";
-    Loader = ("ld-linux-loongarch-" +
-              tools::loongarch::getLoongArchABI(Args, Triple) + ".so.1")
-                 .str();
+    Loader =
+        ("ld-linux-loongarch-" +
+         tools::loongarch::getLoongArchABI(getDriver(), Args, Triple) + ".so.1")
+            .str();
     break;
   }
   case llvm::Triple::m68k:
Index: clang/lib/Driver/ToolChains/Clang.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Clang.cpp
+++ clang/lib/Driver/ToolChains/Clang.cpp
@@ -1921,8 +1921,9 @@
 void Clang::AddLoongArchTargetArgs(const ArgList &Args,
                                    ArgStringList &CmdArgs) const {
   CmdArgs.push_back("-target-abi");
-  CmdArgs.push_back(
-      loongarch::getLoongArchABI(Args, getToolChain().getTriple()).data());
+  CmdArgs.push_back(loongarch::getLoongArchABI(getToolChain().getDriver(), Args,
+                                               getToolChain().getTriple())
+                        .data());
 }
 
 void Clang::AddMIPSTargetArgs(const ArgList &Args,
Index: clang/lib/Driver/ToolChains/Arch/LoongArch.h
===================================================================
--- clang/lib/Driver/ToolChains/Arch/LoongArch.h
+++ clang/lib/Driver/ToolChains/Arch/LoongArch.h
@@ -17,7 +17,10 @@
 namespace driver {
 namespace tools {
 namespace loongarch {
-StringRef getLoongArchABI(const llvm::opt::ArgList &Args,
+void getLoongArchTargetFeatures(const Driver &D, const llvm::Triple &Triple,
+                                const llvm::opt::ArgList &Args,
+                                std::vector<llvm::StringRef> &Features);
+StringRef getLoongArchABI(const Driver &D, const llvm::opt::ArgList &Args,
                           const llvm::Triple &Triple);
 
 void getLoongArchTargetFeatures(const Driver &D, const llvm::Triple &Triple,
Index: clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
===================================================================
--- clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
+++ clang/lib/Driver/ToolChains/Arch/LoongArch.cpp
@@ -7,33 +7,109 @@
 //===----------------------------------------------------------------------===//
 
 #include "LoongArch.h"
+#include "clang/Basic/DiagnosticDriver.h"
+#include "clang/Driver/Driver.h"
+#include "clang/Driver/DriverDiagnostic.h"
+#include "clang/Driver/Options.h"
+#include "llvm/Support/LoongArchTargetParser.h"
 
+using namespace clang::driver;
 using namespace clang::driver::tools;
 using namespace clang;
 using namespace llvm::opt;
 
-StringRef loongarch::getLoongArchABI(const ArgList &Args,
+StringRef loongarch::getLoongArchABI(const Driver &D, const ArgList &Args,
                                      const llvm::Triple &Triple) {
   assert((Triple.getArch() == llvm::Triple::loongarch32 ||
           Triple.getArch() == llvm::Triple::loongarch64) &&
          "Unexpected triple");
+  bool IsLA32 = Triple.getArch() == llvm::Triple::loongarch32;
+
+  // Check -m*-float firstly since they have highest priority.
+  if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,
+                                     options::OPT_msingle_float,
+                                     options::OPT_msoft_float)) {
+    if (A->getOption().matches(options::OPT_mdouble_float))
+      return IsLA32 ? "ilp32d" : "lp64d";
+    if (A->getOption().matches(options::OPT_msingle_float))
+      return IsLA32 ? "ilp32f" : "lp64f";
+    if (A->getOption().matches(options::OPT_msoft_float))
+      return IsLA32 ? "ilp32s" : "lp64s";
+  }
 
   // If `-mabi=` is specified, use it.
   if (const Arg *A = Args.getLastArg(options::OPT_mabi_EQ))
     return A->getValue();
 
+  // Select abi based on -mfpu=xx.
+  if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
+    StringRef FPU = A->getValue();
+    if (FPU == "64")
+      return IsLA32 ? "ilp32d" : "lp64d";
+    if (FPU == "32")
+      return IsLA32 ? "ilp32f" : "lp64f";
+    if (FPU == "0" || FPU == "none")
+      return IsLA32 ? "ilp32s" : "lp64s";
+    D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU;
+  }
+
   // Choose a default based on the triple.
-  // TODO: select appropiate ABI.
-  return Triple.getArch() == llvm::Triple::loongarch32 ? "ilp32d" : "lp64d";
+  return IsLA32 ? "ilp32d" : "lp64d";
 }
 
 void loongarch::getLoongArchTargetFeatures(const Driver &D,
                                            const llvm::Triple &Triple,
                                            const ArgList &Args,
                                            std::vector<StringRef> &Features) {
-  // FIXME: hornor various clang options that may affect target features, e.g.
-  // -march/-mtune/-mdouble-float/-msingle-float/-msoft-float/-mfpu. See:
-  // https://loongson.github.io/LoongArch-Documentation/LoongArch-toolchain-conventions-EN.html
-  Features.push_back("+f");
-  Features.push_back("+d");
+  StringRef ArchName;
+  llvm::LoongArch::ArchKind ArchKind = llvm::LoongArch::ArchKind::AK_INVALID;
+  if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
+    ArchKind = llvm::LoongArch::parseArch(A->getValue());
+    if (ArchKind == llvm::LoongArch::ArchKind::AK_INVALID) {
+      D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
+      return;
+    }
+    ArchName = A->getValue();
+  }
+
+  // TODO: handle -march=native and -mtune=xx.
+
+  // Select a default arch name.
+  if (ArchName.empty() && Triple.getArch() == llvm::Triple::loongarch64)
+    ArchName = "loongarch64";
+
+  if (!ArchName.empty())
+    llvm::LoongArch::getArchFeatures(ArchName, Features);
+
+  // Select floating-point features determined by -mdouble-float,
+  // -msingle-float, -msoft-float and -mfpu.
+  // Note: -m*-float wins any other options.
+  if (const Arg *A = Args.getLastArg(options::OPT_mdouble_float,
+                                     options::OPT_msingle_float,
+                                     options::OPT_msoft_float)) {
+    if (A->getOption().matches(options::OPT_mdouble_float)) {
+      Features.push_back("+f");
+      Features.push_back("+d");
+    } else if (A->getOption().matches(options::OPT_msingle_float)) {
+      Features.push_back("+f");
+      Features.push_back("-d");
+    } else /*Soft-float*/ {
+      Features.push_back("-f");
+      Features.push_back("-d");
+    }
+  } else if (const Arg *A = Args.getLastArg(options::OPT_mfpu_EQ)) {
+    StringRef FPU = A->getValue();
+    if (FPU == "64") {
+      Features.push_back("+f");
+      Features.push_back("+d");
+    } else if (FPU == "32") {
+      Features.push_back("+f");
+      Features.push_back("-d");
+    } else if (FPU == "0" || FPU == "none") {
+      Features.push_back("-f");
+      Features.push_back("-d");
+    } else {
+      D.Diag(diag::err_drv_loongarch_invalid_mfpu_EQ) << FPU;
+    }
+  }
 }
Index: clang/include/clang/Driver/Options.td
===================================================================
--- clang/include/clang/Driver/Options.td
+++ clang/include/clang/Driver/Options.td
@@ -3910,8 +3910,8 @@
 def mno_dsp : Flag<["-"], "mno-dsp">, Group<m_mips_Features_Group>;
 def mdspr2 : Flag<["-"], "mdspr2">, Group<m_mips_Features_Group>;
 def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group<m_mips_Features_Group>;
-def msingle_float : Flag<["-"], "msingle-float">, Group<m_mips_Features_Group>;
-def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_mips_Features_Group>;
+def msingle_float : Flag<["-"], "msingle-float">, Group<m_Group>;
+def mdouble_float : Flag<["-"], "mdouble-float">, Group<m_Group>;
 def mmadd4 : Flag<["-"], "mmadd4">, Group<m_mips_Features_Group>,
   HelpText<"Enable the generation of 4-operand madd.s, madd.d and related instructions.">;
 def mno_madd4 : Flag<["-"], "mno-madd4">, Group<m_mips_Features_Group>,
Index: clang/include/clang/Basic/DiagnosticDriverKinds.td
===================================================================
--- clang/include/clang/Basic/DiagnosticDriverKinds.td
+++ clang/include/clang/Basic/DiagnosticDriverKinds.td
@@ -691,4 +691,7 @@
 
 def err_drv_riscv_unsupported_with_linker_relaxation : Error<
   "%0 is unsupported with RISC-V linker relaxation (-mrelax)">;
+
+def err_drv_loongarch_invalid_mfpu_EQ : Error<
+  "invalid argument '%0' to -mfpu=; must be one of: 64, 32, 0, none">;
 }
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to