197e49605SZi Xuan Wu //===--- CSKY.cpp - CSKY Helpers for Tools --------------------*- C++ -*-===//
297e49605SZi Xuan Wu //
397e49605SZi Xuan Wu // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
497e49605SZi Xuan Wu // See https://llvm.org/LICENSE.txt for license information.
597e49605SZi Xuan Wu // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
697e49605SZi Xuan Wu //
797e49605SZi Xuan Wu //===----------------------------------------------------------------------===//
897e49605SZi Xuan Wu
997e49605SZi Xuan Wu #include "CSKY.h"
1097e49605SZi Xuan Wu #include "ToolChains/CommonArgs.h"
1197e49605SZi Xuan Wu #include "clang/Basic/CharInfo.h"
1297e49605SZi Xuan Wu #include "clang/Driver/Driver.h"
1397e49605SZi Xuan Wu #include "clang/Driver/DriverDiagnostic.h"
1497e49605SZi Xuan Wu #include "clang/Driver/Options.h"
1597e49605SZi Xuan Wu #include "llvm/ADT/StringSwitch.h"
1697e49605SZi Xuan Wu #include "llvm/Option/ArgList.h"
1797e49605SZi Xuan Wu #include "llvm/Support/raw_ostream.h"
18b9a1c4d5SArchibald Elliott #include "llvm/TargetParser/CSKYTargetParser.h"
19*d768bf99SArchibald Elliott #include "llvm/TargetParser/Host.h"
208e3d7cf5SArchibald Elliott #include "llvm/TargetParser/TargetParser.h"
2197e49605SZi Xuan Wu
2297e49605SZi Xuan Wu using namespace clang::driver;
2397e49605SZi Xuan Wu using namespace clang::driver::tools;
2497e49605SZi Xuan Wu using namespace clang;
2597e49605SZi Xuan Wu using namespace llvm::opt;
2697e49605SZi Xuan Wu
272c5d49cfSFangrui Song std::optional<llvm::StringRef>
getCSKYArchName(const Driver & D,const ArgList & Args,const llvm::Triple & Triple)2897e49605SZi Xuan Wu csky::getCSKYArchName(const Driver &D, const ArgList &Args,
2997e49605SZi Xuan Wu const llvm::Triple &Triple) {
3097e49605SZi Xuan Wu if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
3197e49605SZi Xuan Wu llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseArch(A->getValue());
3297e49605SZi Xuan Wu
3397e49605SZi Xuan Wu if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
3497e49605SZi Xuan Wu D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
350c2f6e36SFangrui Song return std::nullopt;
3697e49605SZi Xuan Wu }
372c5d49cfSFangrui Song return std::optional<llvm::StringRef>(A->getValue());
3897e49605SZi Xuan Wu }
3997e49605SZi Xuan Wu
4097e49605SZi Xuan Wu if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
4197e49605SZi Xuan Wu llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseCPUArch(A->getValue());
4297e49605SZi Xuan Wu if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
4397e49605SZi Xuan Wu D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
440c2f6e36SFangrui Song return std::nullopt;
4597e49605SZi Xuan Wu }
462c5d49cfSFangrui Song return std::optional<llvm::StringRef>(llvm::CSKY::getArchName(ArchKind));
4797e49605SZi Xuan Wu }
4897e49605SZi Xuan Wu
492c5d49cfSFangrui Song return std::optional<llvm::StringRef>("ck810");
5097e49605SZi Xuan Wu }
5197e49605SZi Xuan Wu
getCSKYFloatABI(const Driver & D,const ArgList & Args)5297e49605SZi Xuan Wu csky::FloatABI csky::getCSKYFloatABI(const Driver &D, const ArgList &Args) {
5397e49605SZi Xuan Wu csky::FloatABI ABI = FloatABI::Soft;
5497e49605SZi Xuan Wu if (Arg *A =
5597e49605SZi Xuan Wu Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
5697e49605SZi Xuan Wu options::OPT_mfloat_abi_EQ)) {
5797e49605SZi Xuan Wu if (A->getOption().matches(options::OPT_msoft_float)) {
5897e49605SZi Xuan Wu ABI = FloatABI::Soft;
5997e49605SZi Xuan Wu } else if (A->getOption().matches(options::OPT_mhard_float)) {
6097e49605SZi Xuan Wu ABI = FloatABI::Hard;
6197e49605SZi Xuan Wu } else {
6297e49605SZi Xuan Wu ABI = llvm::StringSwitch<csky::FloatABI>(A->getValue())
6397e49605SZi Xuan Wu .Case("soft", FloatABI::Soft)
6497e49605SZi Xuan Wu .Case("softfp", FloatABI::SoftFP)
6597e49605SZi Xuan Wu .Case("hard", FloatABI::Hard)
6697e49605SZi Xuan Wu .Default(FloatABI::Invalid);
6797e49605SZi Xuan Wu if (ABI == FloatABI::Invalid) {
6897e49605SZi Xuan Wu D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
6997e49605SZi Xuan Wu ABI = FloatABI::Soft;
7097e49605SZi Xuan Wu }
7197e49605SZi Xuan Wu }
7297e49605SZi Xuan Wu }
7397e49605SZi Xuan Wu
7497e49605SZi Xuan Wu return ABI;
7597e49605SZi Xuan Wu }
7697e49605SZi Xuan Wu
7797e49605SZi Xuan Wu // Handle -mfpu=.
7897e49605SZi Xuan Wu static llvm::CSKY::CSKYFPUKind
getCSKYFPUFeatures(const Driver & D,const Arg * A,const ArgList & Args,StringRef FPU,std::vector<StringRef> & Features)7997e49605SZi Xuan Wu getCSKYFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args,
8097e49605SZi Xuan Wu StringRef FPU, std::vector<StringRef> &Features) {
8197e49605SZi Xuan Wu
8297e49605SZi Xuan Wu llvm::CSKY::CSKYFPUKind FPUID =
8397e49605SZi Xuan Wu llvm::StringSwitch<llvm::CSKY::CSKYFPUKind>(FPU)
8497e49605SZi Xuan Wu .Case("auto", llvm::CSKY::FK_AUTO)
8597e49605SZi Xuan Wu .Case("fpv2", llvm::CSKY::FK_FPV2)
8697e49605SZi Xuan Wu .Case("fpv2_divd", llvm::CSKY::FK_FPV2_DIVD)
8797e49605SZi Xuan Wu .Case("fpv2_sf", llvm::CSKY::FK_FPV2_SF)
8897e49605SZi Xuan Wu .Case("fpv3", llvm::CSKY::FK_FPV3)
8997e49605SZi Xuan Wu .Case("fpv3_hf", llvm::CSKY::FK_FPV3_HF)
9097e49605SZi Xuan Wu .Case("fpv3_hsf", llvm::CSKY::FK_FPV3_HSF)
9197e49605SZi Xuan Wu .Case("fpv3_sdf", llvm::CSKY::FK_FPV3_SDF)
9297e49605SZi Xuan Wu .Default(llvm::CSKY::FK_INVALID);
93b86440ecSZi Xuan Wu (Zeson) if (FPUID == llvm::CSKY::FK_INVALID) {
94b86440ecSZi Xuan Wu (Zeson) D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
95b86440ecSZi Xuan Wu (Zeson) return llvm::CSKY::FK_INVALID;
96b86440ecSZi Xuan Wu (Zeson) }
97b86440ecSZi Xuan Wu (Zeson)
98b86440ecSZi Xuan Wu (Zeson) auto RemoveTargetFPUFeature =
99b86440ecSZi Xuan Wu (Zeson) [&Features](ArrayRef<const char *> FPUFeatures) {
100b86440ecSZi Xuan Wu (Zeson) for (auto FPUFeature : FPUFeatures) {
101d72de36dSKazu Hirata auto it = llvm::find(Features, FPUFeature);
102b86440ecSZi Xuan Wu (Zeson) if (it != Features.end())
103b86440ecSZi Xuan Wu (Zeson) Features.erase(it);
104b86440ecSZi Xuan Wu (Zeson) }
105b86440ecSZi Xuan Wu (Zeson) };
106b86440ecSZi Xuan Wu (Zeson)
107b86440ecSZi Xuan Wu (Zeson) RemoveTargetFPUFeature({"+fpuv2_sf", "+fpuv2_df", "+fdivdu", "+fpuv3_hi",
108b86440ecSZi Xuan Wu (Zeson) "+fpuv3_hf", "+fpuv3_sf", "+fpuv3_df"});
10997e49605SZi Xuan Wu
11097e49605SZi Xuan Wu if (!llvm::CSKY::getFPUFeatures(FPUID, Features)) {
11197e49605SZi Xuan Wu D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
11297e49605SZi Xuan Wu return llvm::CSKY::FK_INVALID;
11397e49605SZi Xuan Wu }
11497e49605SZi Xuan Wu
11597e49605SZi Xuan Wu return FPUID;
11697e49605SZi Xuan Wu }
11797e49605SZi Xuan Wu
getCSKYTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,ArgStringList & CmdArgs,std::vector<llvm::StringRef> & Features)11897e49605SZi Xuan Wu void csky::getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple,
11997e49605SZi Xuan Wu const ArgList &Args, ArgStringList &CmdArgs,
12097e49605SZi Xuan Wu std::vector<llvm::StringRef> &Features) {
12197e49605SZi Xuan Wu llvm::StringRef archName;
12297e49605SZi Xuan Wu llvm::StringRef cpuName;
12397e49605SZi Xuan Wu llvm::CSKY::ArchKind ArchKind = llvm::CSKY::ArchKind::INVALID;
12497e49605SZi Xuan Wu if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
12597e49605SZi Xuan Wu ArchKind = llvm::CSKY::parseArch(A->getValue());
12697e49605SZi Xuan Wu if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
12797e49605SZi Xuan Wu D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
12897e49605SZi Xuan Wu return;
12997e49605SZi Xuan Wu }
13097e49605SZi Xuan Wu archName = A->getValue();
13197e49605SZi Xuan Wu }
13297e49605SZi Xuan Wu
13397e49605SZi Xuan Wu if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
13497e49605SZi Xuan Wu llvm::CSKY::ArchKind Kind = llvm::CSKY::parseCPUArch(A->getValue());
13597e49605SZi Xuan Wu if (Kind == llvm::CSKY::ArchKind::INVALID) {
13697e49605SZi Xuan Wu D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
13797e49605SZi Xuan Wu return;
13897e49605SZi Xuan Wu }
13997e49605SZi Xuan Wu if (!archName.empty() && Kind != ArchKind) {
14097e49605SZi Xuan Wu D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
14197e49605SZi Xuan Wu return;
14297e49605SZi Xuan Wu }
14397e49605SZi Xuan Wu cpuName = A->getValue();
144b86440ecSZi Xuan Wu (Zeson) if (archName.empty())
145b86440ecSZi Xuan Wu (Zeson) archName = llvm::CSKY::getArchName(Kind);
14697e49605SZi Xuan Wu }
14797e49605SZi Xuan Wu
14897e49605SZi Xuan Wu if (archName.empty() && cpuName.empty()) {
14997e49605SZi Xuan Wu archName = "ck810";
15097e49605SZi Xuan Wu cpuName = "ck810";
15197e49605SZi Xuan Wu } else if (!archName.empty() && cpuName.empty()) {
15297e49605SZi Xuan Wu cpuName = archName;
15397e49605SZi Xuan Wu }
15497e49605SZi Xuan Wu
15597e49605SZi Xuan Wu csky::FloatABI FloatABI = csky::getCSKYFloatABI(D, Args);
15697e49605SZi Xuan Wu
15797e49605SZi Xuan Wu if (FloatABI == csky::FloatABI::Hard) {
15897e49605SZi Xuan Wu Features.push_back("+hard-float-abi");
15997e49605SZi Xuan Wu Features.push_back("+hard-float");
16097e49605SZi Xuan Wu } else if (FloatABI == csky::FloatABI::SoftFP) {
16197e49605SZi Xuan Wu Features.push_back("+hard-float");
16297e49605SZi Xuan Wu }
16397e49605SZi Xuan Wu
16497e49605SZi Xuan Wu uint64_t Extension = llvm::CSKY::getDefaultExtensions(cpuName);
16597e49605SZi Xuan Wu llvm::CSKY::getExtensionFeatures(Extension, Features);
166b86440ecSZi Xuan Wu (Zeson)
167b86440ecSZi Xuan Wu (Zeson) if (const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ))
168b86440ecSZi Xuan Wu (Zeson) getCSKYFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
16997e49605SZi Xuan Wu }
170