1 | //===--- Sparc.cpp - Tools Implementations ----------------------*- C++ -*-===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #include "Sparc.h" |
10 | #include "clang/Driver/Driver.h" |
11 | #include "clang/Driver/Options.h" |
12 | #include "llvm/ADT/StringSwitch.h" |
13 | #include "llvm/Option/ArgList.h" |
14 | #include "llvm/TargetParser/Host.h" |
15 | |
16 | using namespace clang::driver; |
17 | using namespace clang::driver::tools; |
18 | using namespace clang; |
19 | using namespace llvm::opt; |
20 | |
21 | const char *sparc::getSparcAsmModeForCPU(StringRef Name, |
22 | const llvm::Triple &Triple) { |
23 | if (Triple.getArch() == llvm::Triple::sparcv9) { |
24 | const char *DefV9CPU; |
25 | |
26 | if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD()) |
27 | DefV9CPU = "-Av9a" ; |
28 | else |
29 | DefV9CPU = "-Av9" ; |
30 | |
31 | return llvm::StringSwitch<const char *>(Name) |
32 | .Case(S: "niagara" , Value: "-Av9b" ) |
33 | .Case(S: "niagara2" , Value: "-Av9b" ) |
34 | .Case(S: "niagara3" , Value: "-Av9d" ) |
35 | .Case(S: "niagara4" , Value: "-Av9d" ) |
36 | .Default(Value: DefV9CPU); |
37 | } else { |
38 | return llvm::StringSwitch<const char *>(Name) |
39 | .Case(S: "v8" , Value: "-Av8" ) |
40 | .Case(S: "supersparc" , Value: "-Av8" ) |
41 | .Case(S: "sparclite" , Value: "-Asparclite" ) |
42 | .Case(S: "f934" , Value: "-Asparclite" ) |
43 | .Case(S: "hypersparc" , Value: "-Av8" ) |
44 | .Case(S: "sparclite86x" , Value: "-Asparclite" ) |
45 | .Case(S: "sparclet" , Value: "-Asparclet" ) |
46 | .Case(S: "tsc701" , Value: "-Asparclet" ) |
47 | .Case(S: "v9" , Value: "-Av8plus" ) |
48 | .Case(S: "ultrasparc" , Value: "-Av8plus" ) |
49 | .Case(S: "ultrasparc3" , Value: "-Av8plus" ) |
50 | .Case(S: "niagara" , Value: "-Av8plusb" ) |
51 | .Case(S: "niagara2" , Value: "-Av8plusb" ) |
52 | .Case(S: "niagara3" , Value: "-Av8plusd" ) |
53 | .Case(S: "niagara4" , Value: "-Av8plusd" ) |
54 | .Case(S: "ma2100" , Value: "-Aleon" ) |
55 | .Case(S: "ma2150" , Value: "-Aleon" ) |
56 | .Case(S: "ma2155" , Value: "-Aleon" ) |
57 | .Case(S: "ma2450" , Value: "-Aleon" ) |
58 | .Case(S: "ma2455" , Value: "-Aleon" ) |
59 | .Case(S: "ma2x5x" , Value: "-Aleon" ) |
60 | .Case(S: "ma2080" , Value: "-Aleon" ) |
61 | .Case(S: "ma2085" , Value: "-Aleon" ) |
62 | .Case(S: "ma2480" , Value: "-Aleon" ) |
63 | .Case(S: "ma2485" , Value: "-Aleon" ) |
64 | .Case(S: "ma2x8x" , Value: "-Aleon" ) |
65 | .Case(S: "leon2" , Value: "-Av8" ) |
66 | .Case(S: "at697e" , Value: "-Av8" ) |
67 | .Case(S: "at697f" , Value: "-Av8" ) |
68 | .Case(S: "leon3" , Value: "-Aleon" ) |
69 | .Case(S: "ut699" , Value: "-Av8" ) |
70 | .Case(S: "gr712rc" , Value: "-Aleon" ) |
71 | .Case(S: "leon4" , Value: "-Aleon" ) |
72 | .Case(S: "gr740" , Value: "-Aleon" ) |
73 | .Default(Value: "-Av8" ); |
74 | } |
75 | } |
76 | |
77 | sparc::FloatABI sparc::getSparcFloatABI(const Driver &D, |
78 | const ArgList &Args) { |
79 | sparc::FloatABI ABI = sparc::FloatABI::Invalid; |
80 | if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mno_fpu, |
81 | options::OPT_mhard_float, options::OPT_mfpu, |
82 | options::OPT_mfloat_abi_EQ)) { |
83 | if (A->getOption().matches(options::ID: OPT_msoft_float) || |
84 | A->getOption().matches(options::ID: OPT_mno_fpu)) |
85 | ABI = sparc::FloatABI::Soft; |
86 | else if (A->getOption().matches(options::ID: OPT_mhard_float) || |
87 | A->getOption().matches(options::ID: OPT_mfpu)) |
88 | ABI = sparc::FloatABI::Hard; |
89 | else { |
90 | ABI = llvm::StringSwitch<sparc::FloatABI>(A->getValue()) |
91 | .Case(S: "soft" , Value: sparc::FloatABI::Soft) |
92 | .Case(S: "hard" , Value: sparc::FloatABI::Hard) |
93 | .Default(Value: sparc::FloatABI::Invalid); |
94 | if (ABI == sparc::FloatABI::Invalid && |
95 | !StringRef(A->getValue()).empty()) { |
96 | D.Diag(clang::diag::DiagID: err_drv_invalid_mfloat_abi) << A->getAsString(Args); |
97 | ABI = sparc::FloatABI::Hard; |
98 | } |
99 | } |
100 | } |
101 | |
102 | // If unspecified, choose the default based on the platform. |
103 | // Only the hard-float ABI on Sparc is standardized, and it is the |
104 | // default. GCC also supports a nonstandard soft-float ABI mode, also |
105 | // implemented in LLVM. However as this is not standard we set the default |
106 | // to be hard-float. |
107 | if (ABI == sparc::FloatABI::Invalid) { |
108 | ABI = sparc::FloatABI::Hard; |
109 | } |
110 | |
111 | return ABI; |
112 | } |
113 | |
114 | std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args, |
115 | const llvm::Triple &Triple) { |
116 | if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) { |
117 | StringRef CPUName = A->getValue(); |
118 | if (CPUName == "native" ) { |
119 | std::string CPU = std::string(llvm::sys::getHostCPUName()); |
120 | if (!CPU.empty() && CPU != "generic" ) |
121 | return CPU; |
122 | return "" ; |
123 | } |
124 | return std::string(CPUName); |
125 | } |
126 | |
127 | if (Triple.getArch() == llvm::Triple::sparc && |
128 | (Triple.isOSSolaris() || Triple.isOSLinux())) |
129 | return "v9" ; |
130 | return "" ; |
131 | } |
132 | |
133 | void sparc::getSparcTargetFeatures(const Driver &D, const ArgList &Args, |
134 | std::vector<StringRef> &Features) { |
135 | sparc::FloatABI FloatABI = sparc::getSparcFloatABI(D, Args); |
136 | if (FloatABI == sparc::FloatABI::Soft) |
137 | Features.push_back(x: "+soft-float" ); |
138 | |
139 | if (Arg *A = Args.getLastArg(options::OPT_mfsmuld, options::OPT_mno_fsmuld)) { |
140 | if (A->getOption().matches(options::ID: OPT_mfsmuld)) |
141 | Features.push_back(x: "+fsmuld" ); |
142 | else |
143 | Features.push_back(x: "-fsmuld" ); |
144 | } |
145 | |
146 | if (Arg *A = Args.getLastArg(options::OPT_mpopc, options::OPT_mno_popc)) { |
147 | if (A->getOption().matches(options::ID: OPT_mpopc)) |
148 | Features.push_back(x: "+popc" ); |
149 | else |
150 | Features.push_back(x: "-popc" ); |
151 | } |
152 | |
153 | if (Arg *A = Args.getLastArg(options::OPT_mvis, options::OPT_mno_vis)) { |
154 | if (A->getOption().matches(options::ID: OPT_mvis)) |
155 | Features.push_back(x: "+vis" ); |
156 | else |
157 | Features.push_back(x: "-vis" ); |
158 | } |
159 | |
160 | if (Arg *A = Args.getLastArg(options::OPT_mvis2, options::OPT_mno_vis2)) { |
161 | if (A->getOption().matches(options::ID: OPT_mvis2)) |
162 | Features.push_back(x: "+vis2" ); |
163 | else |
164 | Features.push_back(x: "-vis2" ); |
165 | } |
166 | |
167 | if (Arg *A = Args.getLastArg(options::OPT_mvis3, options::OPT_mno_vis3)) { |
168 | if (A->getOption().matches(options::ID: OPT_mvis3)) |
169 | Features.push_back(x: "+vis3" ); |
170 | else |
171 | Features.push_back(x: "-vis3" ); |
172 | } |
173 | |
174 | if (Arg *A = Args.getLastArg(options::OPT_mhard_quad_float, |
175 | options::OPT_msoft_quad_float)) { |
176 | if (A->getOption().matches(options::ID: OPT_mhard_quad_float)) |
177 | Features.push_back(x: "+hard-quad-float" ); |
178 | else |
179 | Features.push_back(x: "-hard-quad-float" ); |
180 | } |
181 | |
182 | if (Arg *A = Args.getLastArg(options::OPT_mv8plus, options::OPT_mno_v8plus)) { |
183 | if (A->getOption().matches(options::ID: OPT_mv8plus)) |
184 | Features.push_back(x: "+v8plus" ); |
185 | } |
186 | |
187 | if (Args.hasArg(options::OPT_ffixed_g1)) |
188 | Features.push_back(x: "+reserve-g1" ); |
189 | |
190 | if (Args.hasArg(options::OPT_ffixed_g2)) |
191 | Features.push_back(x: "+reserve-g2" ); |
192 | |
193 | if (Args.hasArg(options::OPT_ffixed_g3)) |
194 | Features.push_back(x: "+reserve-g3" ); |
195 | |
196 | if (Args.hasArg(options::OPT_ffixed_g4)) |
197 | Features.push_back(x: "+reserve-g4" ); |
198 | |
199 | if (Args.hasArg(options::OPT_ffixed_g5)) |
200 | Features.push_back(x: "+reserve-g5" ); |
201 | |
202 | if (Args.hasArg(options::OPT_ffixed_g6)) |
203 | Features.push_back(x: "+reserve-g6" ); |
204 | |
205 | if (Args.hasArg(options::OPT_ffixed_g7)) |
206 | Features.push_back(x: "+reserve-g7" ); |
207 | |
208 | if (Args.hasArg(options::OPT_ffixed_o0)) |
209 | Features.push_back(x: "+reserve-o0" ); |
210 | |
211 | if (Args.hasArg(options::OPT_ffixed_o1)) |
212 | Features.push_back(x: "+reserve-o1" ); |
213 | |
214 | if (Args.hasArg(options::OPT_ffixed_o2)) |
215 | Features.push_back(x: "+reserve-o2" ); |
216 | |
217 | if (Args.hasArg(options::OPT_ffixed_o3)) |
218 | Features.push_back(x: "+reserve-o3" ); |
219 | |
220 | if (Args.hasArg(options::OPT_ffixed_o4)) |
221 | Features.push_back(x: "+reserve-o4" ); |
222 | |
223 | if (Args.hasArg(options::OPT_ffixed_o5)) |
224 | Features.push_back(x: "+reserve-o5" ); |
225 | |
226 | if (Args.hasArg(options::OPT_ffixed_l0)) |
227 | Features.push_back(x: "+reserve-l0" ); |
228 | |
229 | if (Args.hasArg(options::OPT_ffixed_l1)) |
230 | Features.push_back(x: "+reserve-l1" ); |
231 | |
232 | if (Args.hasArg(options::OPT_ffixed_l2)) |
233 | Features.push_back(x: "+reserve-l2" ); |
234 | |
235 | if (Args.hasArg(options::OPT_ffixed_l3)) |
236 | Features.push_back(x: "+reserve-l3" ); |
237 | |
238 | if (Args.hasArg(options::OPT_ffixed_l4)) |
239 | Features.push_back(x: "+reserve-l4" ); |
240 | |
241 | if (Args.hasArg(options::OPT_ffixed_l5)) |
242 | Features.push_back(x: "+reserve-l5" ); |
243 | |
244 | if (Args.hasArg(options::OPT_ffixed_l6)) |
245 | Features.push_back(x: "+reserve-l6" ); |
246 | |
247 | if (Args.hasArg(options::OPT_ffixed_l7)) |
248 | Features.push_back(x: "+reserve-l7" ); |
249 | |
250 | if (Args.hasArg(options::OPT_ffixed_i0)) |
251 | Features.push_back(x: "+reserve-i0" ); |
252 | |
253 | if (Args.hasArg(options::OPT_ffixed_i1)) |
254 | Features.push_back(x: "+reserve-i1" ); |
255 | |
256 | if (Args.hasArg(options::OPT_ffixed_i2)) |
257 | Features.push_back(x: "+reserve-i2" ); |
258 | |
259 | if (Args.hasArg(options::OPT_ffixed_i3)) |
260 | Features.push_back(x: "+reserve-i3" ); |
261 | |
262 | if (Args.hasArg(options::OPT_ffixed_i4)) |
263 | Features.push_back(x: "+reserve-i4" ); |
264 | |
265 | if (Args.hasArg(options::OPT_ffixed_i5)) |
266 | Features.push_back(x: "+reserve-i5" ); |
267 | |
268 | if (Args.hasArg(options::OPT_mfix_gr712rc)) { |
269 | Features.push_back(x: "+fix-tn0009" ); |
270 | Features.push_back(x: "+fix-tn0011" ); |
271 | Features.push_back(x: "+fix-tn0012" ); |
272 | Features.push_back(x: "+fix-tn0013" ); |
273 | } |
274 | |
275 | if (Args.hasArg(options::OPT_mfix_ut700)) { |
276 | Features.push_back(x: "+fix-tn0009" ); |
277 | Features.push_back(x: "+fix-tn0010" ); |
278 | Features.push_back(x: "+fix-tn0013" ); |
279 | } |
280 | } |
281 | |