1 //===--- CSKY.cpp - CSKY Helpers for Tools --------------------*- C++ -*-===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 #include "ToolChains/CommonArgs.h"
11 #include "clang/Basic/CharInfo.h"
12 #include "clang/Driver/Driver.h"
13 #include "clang/Driver/DriverDiagnostic.h"
14 #include "clang/Driver/Options.h"
15 #include "llvm/ADT/StringSwitch.h"
16 #include "llvm/Option/ArgList.h"
17 #include "llvm/Support/raw_ostream.h"
18 #include "llvm/TargetParser/CSKYTargetParser.h"
19 #include "llvm/TargetParser/Host.h"
20 #include "llvm/TargetParser/TargetParser.h"
22 using namespace clang::driver
;
23 using namespace clang::driver::tools
;
24 using namespace clang
;
25 using namespace llvm::opt
;
27 std::optional
<llvm::StringRef
>
28 csky::getCSKYArchName(const Driver
&D
, const ArgList
&Args
,
29 const llvm::Triple
&Triple
) {
30 if (const Arg
*A
= Args
.getLastArg(options::OPT_march_EQ
)) {
31 llvm::CSKY::ArchKind ArchKind
= llvm::CSKY::parseArch(A
->getValue());
33 if (ArchKind
== llvm::CSKY::ArchKind::INVALID
) {
34 D
.Diag(clang::diag::err_drv_invalid_arch_name
) << A
->getAsString(Args
);
37 return std::optional
<llvm::StringRef
>(A
->getValue());
40 if (const Arg
*A
= Args
.getLastArg(clang::driver::options::OPT_mcpu_EQ
)) {
41 llvm::CSKY::ArchKind ArchKind
= llvm::CSKY::parseCPUArch(A
->getValue());
42 if (ArchKind
== llvm::CSKY::ArchKind::INVALID
) {
43 D
.Diag(clang::diag::err_drv_clang_unsupported
) << A
->getAsString(Args
);
46 return std::optional
<llvm::StringRef
>(llvm::CSKY::getArchName(ArchKind
));
49 return std::optional
<llvm::StringRef
>("ck810");
52 csky::FloatABI
csky::getCSKYFloatABI(const Driver
&D
, const ArgList
&Args
) {
53 csky::FloatABI ABI
= FloatABI::Soft
;
55 Args
.getLastArg(options::OPT_msoft_float
, options::OPT_mhard_float
,
56 options::OPT_mfloat_abi_EQ
)) {
57 if (A
->getOption().matches(options::OPT_msoft_float
)) {
59 } else if (A
->getOption().matches(options::OPT_mhard_float
)) {
62 ABI
= llvm::StringSwitch
<csky::FloatABI
>(A
->getValue())
63 .Case("soft", FloatABI::Soft
)
64 .Case("softfp", FloatABI::SoftFP
)
65 .Case("hard", FloatABI::Hard
)
66 .Default(FloatABI::Invalid
);
67 if (ABI
== FloatABI::Invalid
) {
68 D
.Diag(diag::err_drv_invalid_mfloat_abi
) << A
->getAsString(Args
);
78 static llvm::CSKY::CSKYFPUKind
79 getCSKYFPUFeatures(const Driver
&D
, const Arg
*A
, const ArgList
&Args
,
80 StringRef FPU
, std::vector
<StringRef
> &Features
) {
82 llvm::CSKY::CSKYFPUKind FPUID
=
83 llvm::StringSwitch
<llvm::CSKY::CSKYFPUKind
>(FPU
)
84 .Case("auto", llvm::CSKY::FK_AUTO
)
85 .Case("fpv2", llvm::CSKY::FK_FPV2
)
86 .Case("fpv2_divd", llvm::CSKY::FK_FPV2_DIVD
)
87 .Case("fpv2_sf", llvm::CSKY::FK_FPV2_SF
)
88 .Case("fpv3", llvm::CSKY::FK_FPV3
)
89 .Case("fpv3_hf", llvm::CSKY::FK_FPV3_HF
)
90 .Case("fpv3_hsf", llvm::CSKY::FK_FPV3_HSF
)
91 .Case("fpv3_sdf", llvm::CSKY::FK_FPV3_SDF
)
92 .Default(llvm::CSKY::FK_INVALID
);
93 if (FPUID
== llvm::CSKY::FK_INVALID
) {
94 D
.Diag(clang::diag::err_drv_clang_unsupported
) << A
->getAsString(Args
);
95 return llvm::CSKY::FK_INVALID
;
98 auto RemoveTargetFPUFeature
=
99 [&Features
](ArrayRef
<const char *> FPUFeatures
) {
100 for (auto FPUFeature
: FPUFeatures
) {
101 auto it
= llvm::find(Features
, FPUFeature
);
102 if (it
!= Features
.end())
107 RemoveTargetFPUFeature({"+fpuv2_sf", "+fpuv2_df", "+fdivdu", "+fpuv3_hi",
108 "+fpuv3_hf", "+fpuv3_sf", "+fpuv3_df"});
110 if (!llvm::CSKY::getFPUFeatures(FPUID
, Features
)) {
111 D
.Diag(clang::diag::err_drv_clang_unsupported
) << A
->getAsString(Args
);
112 return llvm::CSKY::FK_INVALID
;
118 void csky::getCSKYTargetFeatures(const Driver
&D
, const llvm::Triple
&Triple
,
119 const ArgList
&Args
, ArgStringList
&CmdArgs
,
120 std::vector
<llvm::StringRef
> &Features
) {
121 llvm::StringRef archName
;
122 llvm::StringRef cpuName
;
123 llvm::CSKY::ArchKind ArchKind
= llvm::CSKY::ArchKind::INVALID
;
124 if (const Arg
*A
= Args
.getLastArg(options::OPT_march_EQ
)) {
125 ArchKind
= llvm::CSKY::parseArch(A
->getValue());
126 if (ArchKind
== llvm::CSKY::ArchKind::INVALID
) {
127 D
.Diag(clang::diag::err_drv_invalid_arch_name
) << A
->getAsString(Args
);
130 archName
= A
->getValue();
133 if (const Arg
*A
= Args
.getLastArg(clang::driver::options::OPT_mcpu_EQ
)) {
134 llvm::CSKY::ArchKind Kind
= llvm::CSKY::parseCPUArch(A
->getValue());
135 if (Kind
== llvm::CSKY::ArchKind::INVALID
) {
136 D
.Diag(clang::diag::err_drv_clang_unsupported
) << A
->getAsString(Args
);
139 if (!archName
.empty() && Kind
!= ArchKind
) {
140 D
.Diag(clang::diag::err_drv_clang_unsupported
) << A
->getAsString(Args
);
143 cpuName
= A
->getValue();
144 if (archName
.empty())
145 archName
= llvm::CSKY::getArchName(Kind
);
148 if (archName
.empty() && cpuName
.empty()) {
151 } else if (!archName
.empty() && cpuName
.empty()) {
155 csky::FloatABI FloatABI
= csky::getCSKYFloatABI(D
, Args
);
157 if (FloatABI
== csky::FloatABI::Hard
) {
158 Features
.push_back("+hard-float-abi");
159 Features
.push_back("+hard-float");
160 } else if (FloatABI
== csky::FloatABI::SoftFP
) {
161 Features
.push_back("+hard-float");
164 uint64_t Extension
= llvm::CSKY::getDefaultExtensions(cpuName
);
165 llvm::CSKY::getExtensionFeatures(Extension
, Features
);
167 if (const Arg
*FPUArg
= Args
.getLastArg(options::OPT_mfpu_EQ
))
168 getCSKYFPUFeatures(D
, FPUArg
, Args
, FPUArg
->getValue(), Features
);