diff --git a/clang/include/clang/Basic/DiagnosticDriverKinds.td b/clang/include/clang/Basic/DiagnosticDriverKinds.td --- a/clang/include/clang/Basic/DiagnosticDriverKinds.td +++ b/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">; } diff --git a/clang/include/clang/Driver/Options.td b/clang/include/clang/Driver/Options.td --- a/clang/include/clang/Driver/Options.td +++ b/clang/include/clang/Driver/Options.td @@ -3910,8 +3910,8 @@ def mno_dsp : Flag<["-"], "mno-dsp">, Group; def mdspr2 : Flag<["-"], "mdspr2">, Group; def mno_dspr2 : Flag<["-"], "mno-dspr2">, Group; -def msingle_float : Flag<["-"], "msingle-float">, Group; -def mdouble_float : Flag<["-"], "mdouble-float">, Group; +def msingle_float : Flag<["-"], "msingle-float">, Group; +def mdouble_float : Flag<["-"], "mdouble-float">, Group; def mmadd4 : Flag<["-"], "mmadd4">, Group, HelpText<"Enable the generation of 4-operand madd.s, madd.d and related instructions.">; def mno_madd4 : Flag<["-"], "mno-madd4">, Group, diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.h b/clang/lib/Driver/ToolChains/Arch/LoongArch.h --- a/clang/lib/Driver/ToolChains/Arch/LoongArch.h +++ b/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 &Features); +StringRef getLoongArchABI(const Driver &D, const llvm::opt::ArgList &Args, const llvm::Triple &Triple); void getLoongArchTargetFeatures(const Driver &D, const llvm::Triple &Triple, diff --git a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp b/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp --- a/clang/lib/Driver/ToolChains/Arch/LoongArch.cpp +++ b/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 &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; + } + } } diff --git a/clang/lib/Driver/ToolChains/Clang.cpp b/clang/lib/Driver/ToolChains/Clang.cpp --- a/clang/lib/Driver/ToolChains/Clang.cpp +++ b/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, diff --git a/clang/lib/Driver/ToolChains/Linux.cpp b/clang/lib/Driver/ToolChains/Linux.cpp --- a/clang/lib/Driver/ToolChains/Linux.cpp +++ b/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: diff --git a/clang/test/Driver/loongarch-default-features.c b/clang/test/Driver/loongarch-default-features.c --- a/clang/test/Driver/loongarch-default-features.c +++ b/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) { diff --git a/clang/test/Driver/loongarch-march-error.c b/clang/test/Driver/loongarch-march-error.c new file mode 100644 --- /dev/null +++ b/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' diff --git a/clang/test/Driver/loongarch-march.c b/clang/test/Driver/loongarch-march.c new file mode 100644 --- /dev/null +++ b/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; +} diff --git a/clang/test/Driver/loongarch-mdouble-float.c b/clang/test/Driver/loongarch-mdouble-float.c new file mode 100644 --- /dev/null +++ b/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; +} diff --git a/clang/test/Driver/loongarch-mfpu-error.c b/clang/test/Driver/loongarch-mfpu-error.c new file mode 100644 --- /dev/null +++ b/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 diff --git a/clang/test/Driver/loongarch-mfpu.c b/clang/test/Driver/loongarch-mfpu.c new file mode 100644 --- /dev/null +++ b/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; +} diff --git a/clang/test/Driver/loongarch-msingle-float.c b/clang/test/Driver/loongarch-msingle-float.c new file mode 100644 --- /dev/null +++ b/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; +} diff --git a/clang/test/Driver/loongarch-msoft-float.c b/clang/test/Driver/loongarch-msoft-float.c new file mode 100644 --- /dev/null +++ b/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; +} diff --git a/llvm/include/llvm/Support/LoongArchTargetParser.h b/llvm/include/llvm/Support/LoongArchTargetParser.h new file mode 100644 --- /dev/null +++ b/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 + +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 &Features); + +} // namespace LoongArch + +} // namespace llvm + +#endif // LLVM_SUPPORT_LOONGARCHTARGETPARSER_H diff --git a/llvm/include/llvm/Support/LoongArchTargetParser.def b/llvm/include/llvm/Support/LoongArchTargetParser.def new file mode 100644 --- /dev/null +++ b/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 diff --git a/llvm/lib/Support/CMakeLists.txt b/llvm/lib/Support/CMakeLists.txt --- a/llvm/lib/Support/CMakeLists.txt +++ b/llvm/lib/Support/CMakeLists.txt @@ -187,6 +187,7 @@ LineIterator.cpp Locale.cpp LockFileManager.cpp + LoongArchTargetParser.cpp LowLevelType.cpp ManagedStatic.cpp MathExtras.cpp diff --git a/llvm/lib/Support/LoongArchTargetParser.cpp b/llvm/lib/Support/LoongArchTargetParser.cpp new file mode 100644 --- /dev/null +++ b/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 &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; +}