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/DriverDiagnostic.h" |
12 | #include "clang/Driver/Options.h" |
13 | #include "llvm/ADT/StringSwitch.h" |
14 | #include "llvm/Option/ArgList.h" |
15 | #include "llvm/TargetParser/Host.h" |
16 | |
17 | using namespace clang::driver; |
18 | using namespace clang::driver::tools; |
19 | using namespace clang; |
20 | using namespace llvm::opt; |
21 | |
22 | const char *sparc::getSparcAsmModeForCPU(StringRef Name, |
23 | const llvm::Triple &Triple) { |
24 | if (Triple.getArch() == llvm::Triple::sparcv9) { |
25 | const char *DefV9CPU; |
26 | |
27 | if (Triple.isOSLinux() || Triple.isOSFreeBSD() || Triple.isOSOpenBSD()) |
28 | DefV9CPU = "-Av9a" ; |
29 | else |
30 | DefV9CPU = "-Av9" ; |
31 | |
32 | return llvm::StringSwitch<const char *>(Name) |
33 | .Case(S: "niagara" , Value: "-Av9b" ) |
34 | .Case(S: "niagara2" , Value: "-Av9b" ) |
35 | .Case(S: "niagara3" , Value: "-Av9d" ) |
36 | .Case(S: "niagara4" , Value: "-Av9d" ) |
37 | .Default(Value: DefV9CPU); |
38 | } else { |
39 | return llvm::StringSwitch<const char *>(Name) |
40 | .Case(S: "v8" , Value: "-Av8" ) |
41 | .Case(S: "supersparc" , Value: "-Av8" ) |
42 | .Case(S: "sparclite" , Value: "-Asparclite" ) |
43 | .Case(S: "f934" , Value: "-Asparclite" ) |
44 | .Case(S: "hypersparc" , Value: "-Av8" ) |
45 | .Case(S: "sparclite86x" , Value: "-Asparclite" ) |
46 | .Case(S: "sparclet" , Value: "-Asparclet" ) |
47 | .Case(S: "tsc701" , Value: "-Asparclet" ) |
48 | .Case(S: "v9" , Value: "-Av8plus" ) |
49 | .Case(S: "ultrasparc" , Value: "-Av8plus" ) |
50 | .Case(S: "ultrasparc3" , Value: "-Av8plus" ) |
51 | .Case(S: "niagara" , Value: "-Av8plusb" ) |
52 | .Case(S: "niagara2" , Value: "-Av8plusb" ) |
53 | .Case(S: "niagara3" , Value: "-Av8plusd" ) |
54 | .Case(S: "niagara4" , Value: "-Av8plusd" ) |
55 | .Case(S: "ma2100" , Value: "-Aleon" ) |
56 | .Case(S: "ma2150" , Value: "-Aleon" ) |
57 | .Case(S: "ma2155" , Value: "-Aleon" ) |
58 | .Case(S: "ma2450" , Value: "-Aleon" ) |
59 | .Case(S: "ma2455" , Value: "-Aleon" ) |
60 | .Case(S: "ma2x5x" , Value: "-Aleon" ) |
61 | .Case(S: "ma2080" , Value: "-Aleon" ) |
62 | .Case(S: "ma2085" , Value: "-Aleon" ) |
63 | .Case(S: "ma2480" , Value: "-Aleon" ) |
64 | .Case(S: "ma2485" , Value: "-Aleon" ) |
65 | .Case(S: "ma2x8x" , Value: "-Aleon" ) |
66 | .Case(S: "leon2" , Value: "-Av8" ) |
67 | .Case(S: "at697e" , Value: "-Av8" ) |
68 | .Case(S: "at697f" , Value: "-Av8" ) |
69 | .Case(S: "leon3" , Value: "-Aleon" ) |
70 | .Case(S: "ut699" , Value: "-Av8" ) |
71 | .Case(S: "gr712rc" , Value: "-Aleon" ) |
72 | .Case(S: "leon4" , Value: "-Aleon" ) |
73 | .Case(S: "gr740" , Value: "-Aleon" ) |
74 | .Default(Value: "-Av8" ); |
75 | } |
76 | } |
77 | |
78 | sparc::FloatABI sparc::getSparcFloatABI(const Driver &D, |
79 | const ArgList &Args) { |
80 | sparc::FloatABI ABI = sparc::FloatABI::Invalid; |
81 | if (Arg *A = Args.getLastArg(options::OPT_msoft_float, options::OPT_mno_fpu, |
82 | options::OPT_mhard_float, options::OPT_mfpu, |
83 | options::OPT_mfloat_abi_EQ)) { |
84 | if (A->getOption().matches(options::ID: OPT_msoft_float) || |
85 | A->getOption().matches(options::ID: OPT_mno_fpu)) |
86 | ABI = sparc::FloatABI::Soft; |
87 | else if (A->getOption().matches(options::ID: OPT_mhard_float) || |
88 | A->getOption().matches(options::ID: OPT_mfpu)) |
89 | ABI = sparc::FloatABI::Hard; |
90 | else { |
91 | ABI = llvm::StringSwitch<sparc::FloatABI>(A->getValue()) |
92 | .Case(S: "soft" , Value: sparc::FloatABI::Soft) |
93 | .Case(S: "hard" , Value: sparc::FloatABI::Hard) |
94 | .Default(Value: sparc::FloatABI::Invalid); |
95 | if (ABI == sparc::FloatABI::Invalid && |
96 | !StringRef(A->getValue()).empty()) { |
97 | D.Diag(clang::diag::DiagID: err_drv_invalid_mfloat_abi) << A->getAsString(Args); |
98 | ABI = sparc::FloatABI::Hard; |
99 | } |
100 | } |
101 | } |
102 | |
103 | // If unspecified, choose the default based on the platform. |
104 | // Only the hard-float ABI on Sparc is standardized, and it is the |
105 | // default. GCC also supports a nonstandard soft-float ABI mode, also |
106 | // implemented in LLVM. However as this is not standard we set the default |
107 | // to be hard-float. |
108 | if (ABI == sparc::FloatABI::Invalid) { |
109 | ABI = sparc::FloatABI::Hard; |
110 | } |
111 | |
112 | return ABI; |
113 | } |
114 | |
115 | std::string sparc::getSparcTargetCPU(const Driver &D, const ArgList &Args, |
116 | const llvm::Triple &Triple) { |
117 | if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) { |
118 | StringRef CPUName = A->getValue(); |
119 | if (CPUName == "native" ) { |
120 | std::string CPU = std::string(llvm::sys::getHostCPUName()); |
121 | if (!CPU.empty() && CPU != "generic" ) |
122 | return CPU; |
123 | return "" ; |
124 | } |
125 | return std::string(CPUName); |
126 | } |
127 | |
128 | if (Triple.getArch() == llvm::Triple::sparc && Triple.isOSSolaris()) |
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 (Args.hasArg(options::OPT_ffixed_g1)) |
183 | Features.push_back(x: "+reserve-g1" ); |
184 | |
185 | if (Args.hasArg(options::OPT_ffixed_g2)) |
186 | Features.push_back(x: "+reserve-g2" ); |
187 | |
188 | if (Args.hasArg(options::OPT_ffixed_g3)) |
189 | Features.push_back(x: "+reserve-g3" ); |
190 | |
191 | if (Args.hasArg(options::OPT_ffixed_g4)) |
192 | Features.push_back(x: "+reserve-g4" ); |
193 | |
194 | if (Args.hasArg(options::OPT_ffixed_g5)) |
195 | Features.push_back(x: "+reserve-g5" ); |
196 | |
197 | if (Args.hasArg(options::OPT_ffixed_g6)) |
198 | Features.push_back(x: "+reserve-g6" ); |
199 | |
200 | if (Args.hasArg(options::OPT_ffixed_g7)) |
201 | Features.push_back(x: "+reserve-g7" ); |
202 | |
203 | if (Args.hasArg(options::OPT_ffixed_o0)) |
204 | Features.push_back(x: "+reserve-o0" ); |
205 | |
206 | if (Args.hasArg(options::OPT_ffixed_o1)) |
207 | Features.push_back(x: "+reserve-o1" ); |
208 | |
209 | if (Args.hasArg(options::OPT_ffixed_o2)) |
210 | Features.push_back(x: "+reserve-o2" ); |
211 | |
212 | if (Args.hasArg(options::OPT_ffixed_o3)) |
213 | Features.push_back(x: "+reserve-o3" ); |
214 | |
215 | if (Args.hasArg(options::OPT_ffixed_o4)) |
216 | Features.push_back(x: "+reserve-o4" ); |
217 | |
218 | if (Args.hasArg(options::OPT_ffixed_o5)) |
219 | Features.push_back(x: "+reserve-o5" ); |
220 | |
221 | if (Args.hasArg(options::OPT_ffixed_l0)) |
222 | Features.push_back(x: "+reserve-l0" ); |
223 | |
224 | if (Args.hasArg(options::OPT_ffixed_l1)) |
225 | Features.push_back(x: "+reserve-l1" ); |
226 | |
227 | if (Args.hasArg(options::OPT_ffixed_l2)) |
228 | Features.push_back(x: "+reserve-l2" ); |
229 | |
230 | if (Args.hasArg(options::OPT_ffixed_l3)) |
231 | Features.push_back(x: "+reserve-l3" ); |
232 | |
233 | if (Args.hasArg(options::OPT_ffixed_l4)) |
234 | Features.push_back(x: "+reserve-l4" ); |
235 | |
236 | if (Args.hasArg(options::OPT_ffixed_l5)) |
237 | Features.push_back(x: "+reserve-l5" ); |
238 | |
239 | if (Args.hasArg(options::OPT_ffixed_l6)) |
240 | Features.push_back(x: "+reserve-l6" ); |
241 | |
242 | if (Args.hasArg(options::OPT_ffixed_l7)) |
243 | Features.push_back(x: "+reserve-l7" ); |
244 | |
245 | if (Args.hasArg(options::OPT_ffixed_i0)) |
246 | Features.push_back(x: "+reserve-i0" ); |
247 | |
248 | if (Args.hasArg(options::OPT_ffixed_i1)) |
249 | Features.push_back(x: "+reserve-i1" ); |
250 | |
251 | if (Args.hasArg(options::OPT_ffixed_i2)) |
252 | Features.push_back(x: "+reserve-i2" ); |
253 | |
254 | if (Args.hasArg(options::OPT_ffixed_i3)) |
255 | Features.push_back(x: "+reserve-i3" ); |
256 | |
257 | if (Args.hasArg(options::OPT_ffixed_i4)) |
258 | Features.push_back(x: "+reserve-i4" ); |
259 | |
260 | if (Args.hasArg(options::OPT_ffixed_i5)) |
261 | Features.push_back(x: "+reserve-i5" ); |
262 | } |
263 | |