xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/CSKY.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
181ad6265SDimitry Andric //===--- CSKY.cpp - CSKY Helpers for Tools --------------------*- C++ -*-===//
281ad6265SDimitry Andric //
381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
681ad6265SDimitry Andric //
781ad6265SDimitry Andric //===----------------------------------------------------------------------===//
881ad6265SDimitry Andric 
981ad6265SDimitry Andric #include "CSKY.h"
1081ad6265SDimitry Andric #include "ToolChains/CommonArgs.h"
1181ad6265SDimitry Andric #include "clang/Basic/CharInfo.h"
1281ad6265SDimitry Andric #include "clang/Driver/Driver.h"
1381ad6265SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
1481ad6265SDimitry Andric #include "clang/Driver/Options.h"
1581ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h"
1681ad6265SDimitry Andric #include "llvm/Option/ArgList.h"
1781ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
18*06c3fb27SDimitry Andric #include "llvm/TargetParser/CSKYTargetParser.h"
19*06c3fb27SDimitry Andric #include "llvm/TargetParser/Host.h"
20*06c3fb27SDimitry Andric #include "llvm/TargetParser/TargetParser.h"
2181ad6265SDimitry Andric 
2281ad6265SDimitry Andric using namespace clang::driver;
2381ad6265SDimitry Andric using namespace clang::driver::tools;
2481ad6265SDimitry Andric using namespace clang;
2581ad6265SDimitry Andric using namespace llvm::opt;
2681ad6265SDimitry Andric 
27bdd1243dSDimitry Andric std::optional<llvm::StringRef>
getCSKYArchName(const Driver & D,const ArgList & Args,const llvm::Triple & Triple)2881ad6265SDimitry Andric csky::getCSKYArchName(const Driver &D, const ArgList &Args,
2981ad6265SDimitry Andric                       const llvm::Triple &Triple) {
3081ad6265SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
3181ad6265SDimitry Andric     llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseArch(A->getValue());
3281ad6265SDimitry Andric 
3381ad6265SDimitry Andric     if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
3481ad6265SDimitry Andric       D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
35bdd1243dSDimitry Andric       return std::nullopt;
3681ad6265SDimitry Andric     }
37bdd1243dSDimitry Andric     return std::optional<llvm::StringRef>(A->getValue());
3881ad6265SDimitry Andric   }
3981ad6265SDimitry Andric 
4081ad6265SDimitry Andric   if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
4181ad6265SDimitry Andric     llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseCPUArch(A->getValue());
4281ad6265SDimitry Andric     if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
4381ad6265SDimitry Andric       D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
44bdd1243dSDimitry Andric       return std::nullopt;
4581ad6265SDimitry Andric     }
46bdd1243dSDimitry Andric     return std::optional<llvm::StringRef>(llvm::CSKY::getArchName(ArchKind));
4781ad6265SDimitry Andric   }
4881ad6265SDimitry Andric 
49bdd1243dSDimitry Andric   return std::optional<llvm::StringRef>("ck810");
5081ad6265SDimitry Andric }
5181ad6265SDimitry Andric 
getCSKYFloatABI(const Driver & D,const ArgList & Args)5281ad6265SDimitry Andric csky::FloatABI csky::getCSKYFloatABI(const Driver &D, const ArgList &Args) {
5381ad6265SDimitry Andric   csky::FloatABI ABI = FloatABI::Soft;
5481ad6265SDimitry Andric   if (Arg *A =
5581ad6265SDimitry Andric           Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
5681ad6265SDimitry Andric                           options::OPT_mfloat_abi_EQ)) {
5781ad6265SDimitry Andric     if (A->getOption().matches(options::OPT_msoft_float)) {
5881ad6265SDimitry Andric       ABI = FloatABI::Soft;
5981ad6265SDimitry Andric     } else if (A->getOption().matches(options::OPT_mhard_float)) {
6081ad6265SDimitry Andric       ABI = FloatABI::Hard;
6181ad6265SDimitry Andric     } else {
6281ad6265SDimitry Andric       ABI = llvm::StringSwitch<csky::FloatABI>(A->getValue())
6381ad6265SDimitry Andric                 .Case("soft", FloatABI::Soft)
6481ad6265SDimitry Andric                 .Case("softfp", FloatABI::SoftFP)
6581ad6265SDimitry Andric                 .Case("hard", FloatABI::Hard)
6681ad6265SDimitry Andric                 .Default(FloatABI::Invalid);
6781ad6265SDimitry Andric       if (ABI == FloatABI::Invalid) {
6881ad6265SDimitry Andric         D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
6981ad6265SDimitry Andric         ABI = FloatABI::Soft;
7081ad6265SDimitry Andric       }
7181ad6265SDimitry Andric     }
7281ad6265SDimitry Andric   }
7381ad6265SDimitry Andric 
7481ad6265SDimitry Andric   return ABI;
7581ad6265SDimitry Andric }
7681ad6265SDimitry Andric 
7781ad6265SDimitry Andric // Handle -mfpu=.
7881ad6265SDimitry Andric static llvm::CSKY::CSKYFPUKind
getCSKYFPUFeatures(const Driver & D,const Arg * A,const ArgList & Args,StringRef FPU,std::vector<StringRef> & Features)7981ad6265SDimitry Andric getCSKYFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args,
8081ad6265SDimitry Andric                    StringRef FPU, std::vector<StringRef> &Features) {
8181ad6265SDimitry Andric 
8281ad6265SDimitry Andric   llvm::CSKY::CSKYFPUKind FPUID =
8381ad6265SDimitry Andric       llvm::StringSwitch<llvm::CSKY::CSKYFPUKind>(FPU)
8481ad6265SDimitry Andric           .Case("auto", llvm::CSKY::FK_AUTO)
8581ad6265SDimitry Andric           .Case("fpv2", llvm::CSKY::FK_FPV2)
8681ad6265SDimitry Andric           .Case("fpv2_divd", llvm::CSKY::FK_FPV2_DIVD)
8781ad6265SDimitry Andric           .Case("fpv2_sf", llvm::CSKY::FK_FPV2_SF)
8881ad6265SDimitry Andric           .Case("fpv3", llvm::CSKY::FK_FPV3)
8981ad6265SDimitry Andric           .Case("fpv3_hf", llvm::CSKY::FK_FPV3_HF)
9081ad6265SDimitry Andric           .Case("fpv3_hsf", llvm::CSKY::FK_FPV3_HSF)
9181ad6265SDimitry Andric           .Case("fpv3_sdf", llvm::CSKY::FK_FPV3_SDF)
9281ad6265SDimitry Andric           .Default(llvm::CSKY::FK_INVALID);
9381ad6265SDimitry Andric   if (FPUID == llvm::CSKY::FK_INVALID) {
9481ad6265SDimitry Andric     D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
9581ad6265SDimitry Andric     return llvm::CSKY::FK_INVALID;
9681ad6265SDimitry Andric   }
9781ad6265SDimitry Andric 
9881ad6265SDimitry Andric   auto RemoveTargetFPUFeature =
9981ad6265SDimitry Andric       [&Features](ArrayRef<const char *> FPUFeatures) {
10081ad6265SDimitry Andric         for (auto FPUFeature : FPUFeatures) {
101bdd1243dSDimitry Andric           auto it = llvm::find(Features, FPUFeature);
10281ad6265SDimitry Andric           if (it != Features.end())
10381ad6265SDimitry Andric             Features.erase(it);
10481ad6265SDimitry Andric         }
10581ad6265SDimitry Andric       };
10681ad6265SDimitry Andric 
10781ad6265SDimitry Andric   RemoveTargetFPUFeature({"+fpuv2_sf", "+fpuv2_df", "+fdivdu", "+fpuv3_hi",
10881ad6265SDimitry Andric                           "+fpuv3_hf", "+fpuv3_sf", "+fpuv3_df"});
10981ad6265SDimitry Andric 
11081ad6265SDimitry Andric   if (!llvm::CSKY::getFPUFeatures(FPUID, Features)) {
11181ad6265SDimitry Andric     D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
11281ad6265SDimitry Andric     return llvm::CSKY::FK_INVALID;
11381ad6265SDimitry Andric   }
11481ad6265SDimitry Andric 
11581ad6265SDimitry Andric   return FPUID;
11681ad6265SDimitry Andric }
11781ad6265SDimitry Andric 
getCSKYTargetFeatures(const Driver & D,const llvm::Triple & Triple,const ArgList & Args,ArgStringList & CmdArgs,std::vector<llvm::StringRef> & Features)11881ad6265SDimitry Andric void csky::getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple,
11981ad6265SDimitry Andric                                  const ArgList &Args, ArgStringList &CmdArgs,
12081ad6265SDimitry Andric                                  std::vector<llvm::StringRef> &Features) {
12181ad6265SDimitry Andric   llvm::StringRef archName;
12281ad6265SDimitry Andric   llvm::StringRef cpuName;
12381ad6265SDimitry Andric   llvm::CSKY::ArchKind ArchKind = llvm::CSKY::ArchKind::INVALID;
12481ad6265SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
12581ad6265SDimitry Andric     ArchKind = llvm::CSKY::parseArch(A->getValue());
12681ad6265SDimitry Andric     if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
12781ad6265SDimitry Andric       D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
12881ad6265SDimitry Andric       return;
12981ad6265SDimitry Andric     }
13081ad6265SDimitry Andric     archName = A->getValue();
13181ad6265SDimitry Andric   }
13281ad6265SDimitry Andric 
13381ad6265SDimitry Andric   if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
13481ad6265SDimitry Andric     llvm::CSKY::ArchKind Kind = llvm::CSKY::parseCPUArch(A->getValue());
13581ad6265SDimitry Andric     if (Kind == llvm::CSKY::ArchKind::INVALID) {
13681ad6265SDimitry Andric       D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
13781ad6265SDimitry Andric       return;
13881ad6265SDimitry Andric     }
13981ad6265SDimitry Andric     if (!archName.empty() && Kind != ArchKind) {
14081ad6265SDimitry Andric       D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
14181ad6265SDimitry Andric       return;
14281ad6265SDimitry Andric     }
14381ad6265SDimitry Andric     cpuName = A->getValue();
14481ad6265SDimitry Andric     if (archName.empty())
14581ad6265SDimitry Andric       archName = llvm::CSKY::getArchName(Kind);
14681ad6265SDimitry Andric   }
14781ad6265SDimitry Andric 
14881ad6265SDimitry Andric   if (archName.empty() && cpuName.empty()) {
14981ad6265SDimitry Andric     archName = "ck810";
15081ad6265SDimitry Andric     cpuName = "ck810";
15181ad6265SDimitry Andric   } else if (!archName.empty() && cpuName.empty()) {
15281ad6265SDimitry Andric     cpuName = archName;
15381ad6265SDimitry Andric   }
15481ad6265SDimitry Andric 
15581ad6265SDimitry Andric   csky::FloatABI FloatABI = csky::getCSKYFloatABI(D, Args);
15681ad6265SDimitry Andric 
15781ad6265SDimitry Andric   if (FloatABI == csky::FloatABI::Hard) {
15881ad6265SDimitry Andric     Features.push_back("+hard-float-abi");
15981ad6265SDimitry Andric     Features.push_back("+hard-float");
16081ad6265SDimitry Andric   } else if (FloatABI == csky::FloatABI::SoftFP) {
16181ad6265SDimitry Andric     Features.push_back("+hard-float");
16281ad6265SDimitry Andric   }
16381ad6265SDimitry Andric 
16481ad6265SDimitry Andric   uint64_t Extension = llvm::CSKY::getDefaultExtensions(cpuName);
16581ad6265SDimitry Andric   llvm::CSKY::getExtensionFeatures(Extension, Features);
16681ad6265SDimitry Andric 
16781ad6265SDimitry Andric   if (const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ))
16881ad6265SDimitry Andric     getCSKYFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
16981ad6265SDimitry Andric }
170