xref: /freebsd-src/contrib/llvm-project/clang/lib/Driver/ToolChains/Arch/CSKY.cpp (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
1*81ad6265SDimitry Andric //===--- CSKY.cpp - CSKY Helpers for Tools --------------------*- C++ -*-===//
2*81ad6265SDimitry Andric //
3*81ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*81ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*81ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*81ad6265SDimitry Andric //
7*81ad6265SDimitry Andric //===----------------------------------------------------------------------===//
8*81ad6265SDimitry Andric 
9*81ad6265SDimitry Andric #include "CSKY.h"
10*81ad6265SDimitry Andric #include "ToolChains/CommonArgs.h"
11*81ad6265SDimitry Andric #include "clang/Basic/CharInfo.h"
12*81ad6265SDimitry Andric #include "clang/Driver/Driver.h"
13*81ad6265SDimitry Andric #include "clang/Driver/DriverDiagnostic.h"
14*81ad6265SDimitry Andric #include "clang/Driver/Options.h"
15*81ad6265SDimitry Andric #include "llvm/ADT/Optional.h"
16*81ad6265SDimitry Andric #include "llvm/ADT/StringSwitch.h"
17*81ad6265SDimitry Andric #include "llvm/Option/ArgList.h"
18*81ad6265SDimitry Andric #include "llvm/Support/CSKYTargetParser.h"
19*81ad6265SDimitry Andric #include "llvm/Support/Host.h"
20*81ad6265SDimitry Andric #include "llvm/Support/TargetParser.h"
21*81ad6265SDimitry Andric #include "llvm/Support/raw_ostream.h"
22*81ad6265SDimitry Andric 
23*81ad6265SDimitry Andric using namespace clang::driver;
24*81ad6265SDimitry Andric using namespace clang::driver::tools;
25*81ad6265SDimitry Andric using namespace clang;
26*81ad6265SDimitry Andric using namespace llvm::opt;
27*81ad6265SDimitry Andric 
28*81ad6265SDimitry Andric llvm::Optional<llvm::StringRef>
29*81ad6265SDimitry Andric csky::getCSKYArchName(const Driver &D, const ArgList &Args,
30*81ad6265SDimitry Andric                       const llvm::Triple &Triple) {
31*81ad6265SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
32*81ad6265SDimitry Andric     llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseArch(A->getValue());
33*81ad6265SDimitry Andric 
34*81ad6265SDimitry Andric     if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
35*81ad6265SDimitry Andric       D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
36*81ad6265SDimitry Andric       return llvm::Optional<llvm::StringRef>();
37*81ad6265SDimitry Andric     }
38*81ad6265SDimitry Andric     return llvm::Optional<llvm::StringRef>(A->getValue());
39*81ad6265SDimitry Andric   }
40*81ad6265SDimitry Andric 
41*81ad6265SDimitry Andric   if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
42*81ad6265SDimitry Andric     llvm::CSKY::ArchKind ArchKind = llvm::CSKY::parseCPUArch(A->getValue());
43*81ad6265SDimitry Andric     if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
44*81ad6265SDimitry Andric       D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
45*81ad6265SDimitry Andric       return llvm::Optional<llvm::StringRef>();
46*81ad6265SDimitry Andric     }
47*81ad6265SDimitry Andric     return llvm::Optional<llvm::StringRef>(llvm::CSKY::getArchName(ArchKind));
48*81ad6265SDimitry Andric   }
49*81ad6265SDimitry Andric 
50*81ad6265SDimitry Andric   return llvm::Optional<llvm::StringRef>("ck810");
51*81ad6265SDimitry Andric }
52*81ad6265SDimitry Andric 
53*81ad6265SDimitry Andric csky::FloatABI csky::getCSKYFloatABI(const Driver &D, const ArgList &Args) {
54*81ad6265SDimitry Andric   csky::FloatABI ABI = FloatABI::Soft;
55*81ad6265SDimitry Andric   if (Arg *A =
56*81ad6265SDimitry Andric           Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float,
57*81ad6265SDimitry Andric                           options::OPT_mfloat_abi_EQ)) {
58*81ad6265SDimitry Andric     if (A->getOption().matches(options::OPT_msoft_float)) {
59*81ad6265SDimitry Andric       ABI = FloatABI::Soft;
60*81ad6265SDimitry Andric     } else if (A->getOption().matches(options::OPT_mhard_float)) {
61*81ad6265SDimitry Andric       ABI = FloatABI::Hard;
62*81ad6265SDimitry Andric     } else {
63*81ad6265SDimitry Andric       ABI = llvm::StringSwitch<csky::FloatABI>(A->getValue())
64*81ad6265SDimitry Andric                 .Case("soft", FloatABI::Soft)
65*81ad6265SDimitry Andric                 .Case("softfp", FloatABI::SoftFP)
66*81ad6265SDimitry Andric                 .Case("hard", FloatABI::Hard)
67*81ad6265SDimitry Andric                 .Default(FloatABI::Invalid);
68*81ad6265SDimitry Andric       if (ABI == FloatABI::Invalid) {
69*81ad6265SDimitry Andric         D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args);
70*81ad6265SDimitry Andric         ABI = FloatABI::Soft;
71*81ad6265SDimitry Andric       }
72*81ad6265SDimitry Andric     }
73*81ad6265SDimitry Andric   }
74*81ad6265SDimitry Andric 
75*81ad6265SDimitry Andric   return ABI;
76*81ad6265SDimitry Andric }
77*81ad6265SDimitry Andric 
78*81ad6265SDimitry Andric // Handle -mfpu=.
79*81ad6265SDimitry Andric static llvm::CSKY::CSKYFPUKind
80*81ad6265SDimitry Andric getCSKYFPUFeatures(const Driver &D, const Arg *A, const ArgList &Args,
81*81ad6265SDimitry Andric                    StringRef FPU, std::vector<StringRef> &Features) {
82*81ad6265SDimitry Andric 
83*81ad6265SDimitry Andric   llvm::CSKY::CSKYFPUKind FPUID =
84*81ad6265SDimitry Andric       llvm::StringSwitch<llvm::CSKY::CSKYFPUKind>(FPU)
85*81ad6265SDimitry Andric           .Case("auto", llvm::CSKY::FK_AUTO)
86*81ad6265SDimitry Andric           .Case("fpv2", llvm::CSKY::FK_FPV2)
87*81ad6265SDimitry Andric           .Case("fpv2_divd", llvm::CSKY::FK_FPV2_DIVD)
88*81ad6265SDimitry Andric           .Case("fpv2_sf", llvm::CSKY::FK_FPV2_SF)
89*81ad6265SDimitry Andric           .Case("fpv3", llvm::CSKY::FK_FPV3)
90*81ad6265SDimitry Andric           .Case("fpv3_hf", llvm::CSKY::FK_FPV3_HF)
91*81ad6265SDimitry Andric           .Case("fpv3_hsf", llvm::CSKY::FK_FPV3_HSF)
92*81ad6265SDimitry Andric           .Case("fpv3_sdf", llvm::CSKY::FK_FPV3_SDF)
93*81ad6265SDimitry Andric           .Default(llvm::CSKY::FK_INVALID);
94*81ad6265SDimitry Andric   if (FPUID == llvm::CSKY::FK_INVALID) {
95*81ad6265SDimitry Andric     D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
96*81ad6265SDimitry Andric     return llvm::CSKY::FK_INVALID;
97*81ad6265SDimitry Andric   }
98*81ad6265SDimitry Andric 
99*81ad6265SDimitry Andric   auto RemoveTargetFPUFeature =
100*81ad6265SDimitry Andric       [&Features](ArrayRef<const char *> FPUFeatures) {
101*81ad6265SDimitry Andric         for (auto FPUFeature : FPUFeatures) {
102*81ad6265SDimitry Andric           auto it = std::find(Features.begin(), Features.end(), FPUFeature);
103*81ad6265SDimitry Andric           if (it != Features.end())
104*81ad6265SDimitry Andric             Features.erase(it);
105*81ad6265SDimitry Andric         }
106*81ad6265SDimitry Andric       };
107*81ad6265SDimitry Andric 
108*81ad6265SDimitry Andric   RemoveTargetFPUFeature({"+fpuv2_sf", "+fpuv2_df", "+fdivdu", "+fpuv3_hi",
109*81ad6265SDimitry Andric                           "+fpuv3_hf", "+fpuv3_sf", "+fpuv3_df"});
110*81ad6265SDimitry Andric 
111*81ad6265SDimitry Andric   if (!llvm::CSKY::getFPUFeatures(FPUID, Features)) {
112*81ad6265SDimitry Andric     D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
113*81ad6265SDimitry Andric     return llvm::CSKY::FK_INVALID;
114*81ad6265SDimitry Andric   }
115*81ad6265SDimitry Andric 
116*81ad6265SDimitry Andric   return FPUID;
117*81ad6265SDimitry Andric }
118*81ad6265SDimitry Andric 
119*81ad6265SDimitry Andric void csky::getCSKYTargetFeatures(const Driver &D, const llvm::Triple &Triple,
120*81ad6265SDimitry Andric                                  const ArgList &Args, ArgStringList &CmdArgs,
121*81ad6265SDimitry Andric                                  std::vector<llvm::StringRef> &Features) {
122*81ad6265SDimitry Andric   llvm::StringRef archName;
123*81ad6265SDimitry Andric   llvm::StringRef cpuName;
124*81ad6265SDimitry Andric   llvm::CSKY::ArchKind ArchKind = llvm::CSKY::ArchKind::INVALID;
125*81ad6265SDimitry Andric   if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) {
126*81ad6265SDimitry Andric     ArchKind = llvm::CSKY::parseArch(A->getValue());
127*81ad6265SDimitry Andric     if (ArchKind == llvm::CSKY::ArchKind::INVALID) {
128*81ad6265SDimitry Andric       D.Diag(clang::diag::err_drv_invalid_arch_name) << A->getAsString(Args);
129*81ad6265SDimitry Andric       return;
130*81ad6265SDimitry Andric     }
131*81ad6265SDimitry Andric     archName = A->getValue();
132*81ad6265SDimitry Andric   }
133*81ad6265SDimitry Andric 
134*81ad6265SDimitry Andric   if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) {
135*81ad6265SDimitry Andric     llvm::CSKY::ArchKind Kind = llvm::CSKY::parseCPUArch(A->getValue());
136*81ad6265SDimitry Andric     if (Kind == llvm::CSKY::ArchKind::INVALID) {
137*81ad6265SDimitry Andric       D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
138*81ad6265SDimitry Andric       return;
139*81ad6265SDimitry Andric     }
140*81ad6265SDimitry Andric     if (!archName.empty() && Kind != ArchKind) {
141*81ad6265SDimitry Andric       D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args);
142*81ad6265SDimitry Andric       return;
143*81ad6265SDimitry Andric     }
144*81ad6265SDimitry Andric     cpuName = A->getValue();
145*81ad6265SDimitry Andric     if (archName.empty())
146*81ad6265SDimitry Andric       archName = llvm::CSKY::getArchName(Kind);
147*81ad6265SDimitry Andric   }
148*81ad6265SDimitry Andric 
149*81ad6265SDimitry Andric   if (archName.empty() && cpuName.empty()) {
150*81ad6265SDimitry Andric     archName = "ck810";
151*81ad6265SDimitry Andric     cpuName = "ck810";
152*81ad6265SDimitry Andric   } else if (!archName.empty() && cpuName.empty()) {
153*81ad6265SDimitry Andric     cpuName = archName;
154*81ad6265SDimitry Andric   }
155*81ad6265SDimitry Andric 
156*81ad6265SDimitry Andric   csky::FloatABI FloatABI = csky::getCSKYFloatABI(D, Args);
157*81ad6265SDimitry Andric 
158*81ad6265SDimitry Andric   if (FloatABI == csky::FloatABI::Hard) {
159*81ad6265SDimitry Andric     Features.push_back("+hard-float-abi");
160*81ad6265SDimitry Andric     Features.push_back("+hard-float");
161*81ad6265SDimitry Andric   } else if (FloatABI == csky::FloatABI::SoftFP) {
162*81ad6265SDimitry Andric     Features.push_back("+hard-float");
163*81ad6265SDimitry Andric   }
164*81ad6265SDimitry Andric 
165*81ad6265SDimitry Andric   uint64_t Extension = llvm::CSKY::getDefaultExtensions(cpuName);
166*81ad6265SDimitry Andric   llvm::CSKY::getExtensionFeatures(Extension, Features);
167*81ad6265SDimitry Andric 
168*81ad6265SDimitry Andric   if (const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ))
169*81ad6265SDimitry Andric     getCSKYFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features);
170*81ad6265SDimitry Andric }
171