/Users/buildslave/jenkins/sharedspace/clang-stage2-coverage-R@2/llvm/tools/clang/lib/Driver/ToolChains/Arch/ARM.cpp
Line | Count | Source (jump to first uncovered line) |
1 | | //===--- ARM.cpp - ARM (not AArch64) Helpers for Tools ----------*- C++ -*-===// |
2 | | // |
3 | | // The LLVM Compiler Infrastructure |
4 | | // |
5 | | // This file is distributed under the University of Illinois Open Source |
6 | | // License. See LICENSE.TXT for details. |
7 | | // |
8 | | //===----------------------------------------------------------------------===// |
9 | | |
10 | | #include "ARM.h" |
11 | | #include "clang/Driver/Driver.h" |
12 | | #include "clang/Driver/DriverDiagnostic.h" |
13 | | #include "clang/Driver/Options.h" |
14 | | #include "llvm/ADT/StringSwitch.h" |
15 | | #include "llvm/Option/ArgList.h" |
16 | | #include "llvm/Support/TargetParser.h" |
17 | | |
18 | | using namespace clang::driver; |
19 | | using namespace clang::driver::tools; |
20 | | using namespace clang; |
21 | | using namespace llvm::opt; |
22 | | |
23 | | // Get SubArch (vN). |
24 | 11.7k | int arm::getARMSubArchVersionNumber(const llvm::Triple &Triple) { |
25 | 11.7k | llvm::StringRef Arch = Triple.getArchName(); |
26 | 11.7k | return llvm::ARM::parseArchVersion(Arch); |
27 | 11.7k | } |
28 | | |
29 | | // True if M-profile. |
30 | 20 | bool arm::isARMMProfile(const llvm::Triple &Triple) { |
31 | 20 | llvm::StringRef Arch = Triple.getArchName(); |
32 | 20 | return llvm::ARM::parseArchProfile(Arch) == llvm::ARM::ProfileKind::M; |
33 | 20 | } |
34 | | |
35 | | // Get Arch/CPU from args. |
36 | | void arm::getARMArchCPUFromArgs(const ArgList &Args, llvm::StringRef &Arch, |
37 | 8.01k | llvm::StringRef &CPU, bool FromAs) { |
38 | 8.01k | if (const Arg *A = Args.getLastArg(clang::driver::options::OPT_mcpu_EQ)) |
39 | 773 | CPU = A->getValue(); |
40 | 8.01k | if (const Arg *A = Args.getLastArg(options::OPT_march_EQ)) |
41 | 6.16k | Arch = A->getValue(); |
42 | 8.01k | if (!FromAs) |
43 | 7.32k | return; |
44 | 693 | |
45 | 693 | for (const Arg *A : |
46 | 12 | Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { |
47 | 12 | StringRef Value = A->getValue(); |
48 | 12 | if (Value.startswith("-mcpu=")) |
49 | 3 | CPU = Value.substr(6); |
50 | 12 | if (Value.startswith("-march=")) |
51 | 2 | Arch = Value.substr(7); |
52 | 12 | } |
53 | 8.01k | } |
54 | | |
55 | | // Handle -mhwdiv=. |
56 | | // FIXME: Use ARMTargetParser. |
57 | | static void getARMHWDivFeatures(const Driver &D, const Arg *A, |
58 | | const ArgList &Args, StringRef HWDiv, |
59 | 25 | std::vector<StringRef> &Features) { |
60 | 25 | unsigned HWDivID = llvm::ARM::parseHWDiv(HWDiv); |
61 | 25 | if (!llvm::ARM::getHWDivFeatures(HWDivID, Features)) |
62 | 1 | D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); |
63 | 25 | } |
64 | | |
65 | | // Handle -mfpu=. |
66 | | static void getARMFPUFeatures(const Driver &D, const Arg *A, |
67 | | const ArgList &Args, StringRef FPU, |
68 | 89 | std::vector<StringRef> &Features) { |
69 | 89 | unsigned FPUID = llvm::ARM::parseFPU(FPU); |
70 | 89 | if (!llvm::ARM::getFPUFeatures(FPUID, Features)) |
71 | 5 | D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); |
72 | 89 | } |
73 | | |
74 | | // Decode ARM features from string like +[no]featureA+[no]featureB+... |
75 | | static bool DecodeARMFeatures(const Driver &D, StringRef text, |
76 | 22 | std::vector<StringRef> &Features) { |
77 | 22 | SmallVector<StringRef, 8> Split; |
78 | 22 | text.split(Split, StringRef("+"), -1, false); |
79 | 22 | |
80 | 22 | for (StringRef Feature : Split) { |
81 | 22 | StringRef FeatureName = llvm::ARM::getArchExtFeature(Feature); |
82 | 22 | if (!FeatureName.empty()) |
83 | 22 | Features.push_back(FeatureName); |
84 | 22 | else |
85 | 0 | return false; |
86 | 22 | } |
87 | 22 | return true; |
88 | 22 | } |
89 | | |
90 | | static void DecodeARMFeaturesFromCPU(const Driver &D, StringRef CPU, |
91 | 389 | std::vector<StringRef> &Features) { |
92 | 389 | if (CPU != "generic"389 ) { |
93 | 362 | llvm::ARM::ArchKind ArchKind = llvm::ARM::parseCPUArch(CPU); |
94 | 362 | unsigned Extension = llvm::ARM::getDefaultExtensions(CPU, ArchKind); |
95 | 362 | llvm::ARM::getExtensionFeatures(Extension, Features); |
96 | 362 | } |
97 | 389 | } |
98 | | |
99 | | // Check if -march is valid by checking if it can be canonicalised and parsed. |
100 | | // getARMArch is used here instead of just checking the -march value in order |
101 | | // to handle -march=native correctly. |
102 | | static void checkARMArchName(const Driver &D, const Arg *A, const ArgList &Args, |
103 | | llvm::StringRef ArchName, |
104 | | std::vector<StringRef> &Features, |
105 | 3.40k | const llvm::Triple &Triple) { |
106 | 3.40k | std::pair<StringRef, StringRef> Split = ArchName.split("+"); |
107 | 3.40k | |
108 | 3.40k | std::string MArch = arm::getARMArch(ArchName, Triple); |
109 | 3.40k | if (llvm::ARM::parseArch(MArch) == llvm::ARM::ArchKind::INVALID || |
110 | 3.40k | (Split.second.size() && 3.40k !DecodeARMFeatures(D, Split.second, Features)12 )) |
111 | 5 | D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); |
112 | 3.40k | } |
113 | | |
114 | | // Check -mcpu=. Needs ArchName to handle -mcpu=generic. |
115 | | static void checkARMCPUName(const Driver &D, const Arg *A, const ArgList &Args, |
116 | | llvm::StringRef CPUName, llvm::StringRef ArchName, |
117 | | std::vector<StringRef> &Features, |
118 | 389 | const llvm::Triple &Triple) { |
119 | 389 | std::pair<StringRef, StringRef> Split = CPUName.split("+"); |
120 | 389 | |
121 | 389 | std::string CPU = arm::getARMTargetCPU(CPUName, ArchName, Triple); |
122 | 389 | if (arm::getLLVMArchSuffixForARM(CPU, ArchName, Triple).empty() || |
123 | 387 | (Split.second.size() && 387 !DecodeARMFeatures(D, Split.second, Features)10 )) |
124 | 2 | D.Diag(clang::diag::err_drv_clang_unsupported) << A->getAsString(Args); |
125 | 389 | } |
126 | | |
127 | 2.72k | bool arm::useAAPCSForMachO(const llvm::Triple &T) { |
128 | 2.72k | // The backend is hardwired to assume AAPCS for M-class processors, ensure |
129 | 2.72k | // the frontend matches that. |
130 | 2.72k | return T.getEnvironment() == llvm::Triple::EABI || |
131 | 2.72k | T.getOS() == llvm::Triple::UnknownOS1.71k || isARMMProfile(T)8 ; |
132 | 2.72k | } |
133 | | |
134 | | // Select mode for reading thread pointer (-mtp=soft/cp15). |
135 | 4.34k | arm::ReadTPMode arm::getReadTPMode(const ToolChain &TC, const ArgList &Args) { |
136 | 4.34k | if (Arg *A4.34k = Args.getLastArg(options::OPT_mtp_mode_EQ)) { |
137 | 2 | const Driver &D = TC.getDriver(); |
138 | 2 | arm::ReadTPMode ThreadPointer = |
139 | 2 | llvm::StringSwitch<arm::ReadTPMode>(A->getValue()) |
140 | 2 | .Case("cp15", ReadTPMode::Cp15) |
141 | 2 | .Case("soft", ReadTPMode::Soft) |
142 | 2 | .Default(ReadTPMode::Invalid); |
143 | 2 | if (ThreadPointer != ReadTPMode::Invalid) |
144 | 2 | return ThreadPointer; |
145 | 0 | if (0 StringRef(A->getValue()).empty()0 ) |
146 | 0 | D.Diag(diag::err_drv_missing_arg_mtp) << A->getAsString(Args); |
147 | 0 | else |
148 | 0 | D.Diag(diag::err_drv_invalid_mtp) << A->getAsString(Args); |
149 | 2 | return ReadTPMode::Invalid; |
150 | 2 | } |
151 | 4.34k | return ReadTPMode::Soft; |
152 | 4.34k | } |
153 | | |
154 | | // Select the float ABI as determined by -msoft-float, -mhard-float, and |
155 | | // -mfloat-abi=. |
156 | 8.16k | arm::FloatABI arm::getARMFloatABI(const ToolChain &TC, const ArgList &Args) { |
157 | 8.16k | const Driver &D = TC.getDriver(); |
158 | 8.16k | const llvm::Triple &Triple = TC.getEffectiveTriple(); |
159 | 8.16k | auto SubArch = getARMSubArchVersionNumber(Triple); |
160 | 8.16k | arm::FloatABI ABI = FloatABI::Invalid; |
161 | 8.16k | if (Arg *A = |
162 | 8.16k | Args.getLastArg(options::OPT_msoft_float, options::OPT_mhard_float, |
163 | 2.77k | options::OPT_mfloat_abi_EQ)) { |
164 | 2.77k | if (A->getOption().matches(options::OPT_msoft_float)2.77k ) { |
165 | 8 | ABI = FloatABI::Soft; |
166 | 2.77k | } else if (2.76k A->getOption().matches(options::OPT_mhard_float)2.76k ) { |
167 | 20 | ABI = FloatABI::Hard; |
168 | 2.76k | } else { |
169 | 2.74k | ABI = llvm::StringSwitch<arm::FloatABI>(A->getValue()) |
170 | 2.74k | .Case("soft", FloatABI::Soft) |
171 | 2.74k | .Case("softfp", FloatABI::SoftFP) |
172 | 2.74k | .Case("hard", FloatABI::Hard) |
173 | 2.74k | .Default(FloatABI::Invalid); |
174 | 2.74k | if (ABI == FloatABI::Invalid && 2.74k !StringRef(A->getValue()).empty()0 ) { |
175 | 0 | D.Diag(diag::err_drv_invalid_mfloat_abi) << A->getAsString(Args); |
176 | 0 | ABI = FloatABI::Soft; |
177 | 0 | } |
178 | 2.76k | } |
179 | 2.77k | |
180 | 2.77k | // It is incorrect to select hard float ABI on MachO platforms if the ABI is |
181 | 2.77k | // "apcs-gnu". |
182 | 2.77k | if (Triple.isOSBinFormatMachO() && 2.77k !useAAPCSForMachO(Triple)2.72k && |
183 | 2.77k | ABI == FloatABI::Hard8 ) { |
184 | 4 | D.Diag(diag::err_drv_unsupported_opt_for_target) << A->getAsString(Args) |
185 | 4 | << Triple.getArchName(); |
186 | 4 | } |
187 | 2.77k | } |
188 | 8.16k | |
189 | 8.16k | // If unspecified, choose the default based on the platform. |
190 | 8.16k | if (ABI == FloatABI::Invalid8.16k ) { |
191 | 5.39k | switch (Triple.getOS()) { |
192 | 3.00k | case llvm::Triple::Darwin: |
193 | 3.00k | case llvm::Triple::MacOSX: |
194 | 3.00k | case llvm::Triple::IOS: |
195 | 3.00k | case llvm::Triple::TvOS: { |
196 | 3.00k | // Darwin defaults to "softfp" for v6 and v7. |
197 | 3.00k | ABI = (SubArch == 6 || SubArch == 72.98k ) ? FloatABI::SoftFP2.99k : FloatABI::Soft10 ; |
198 | 3.00k | ABI = Triple.isWatchABI() ? FloatABI::Hard1.29k : ABI1.71k ; |
199 | 3.00k | break; |
200 | 3.00k | } |
201 | 38 | case llvm::Triple::WatchOS: |
202 | 38 | ABI = FloatABI::Hard; |
203 | 38 | break; |
204 | 3.00k | |
205 | 3.00k | // FIXME: this is invalid for WindowsCE |
206 | 125 | case llvm::Triple::Win32: |
207 | 125 | ABI = FloatABI::Hard; |
208 | 125 | break; |
209 | 3.00k | |
210 | 62 | case llvm::Triple::NetBSD: |
211 | 62 | switch (Triple.getEnvironment()) { |
212 | 12 | case llvm::Triple::EABIHF: |
213 | 12 | case llvm::Triple::GNUEABIHF: |
214 | 12 | ABI = FloatABI::Hard; |
215 | 12 | break; |
216 | 50 | default: |
217 | 50 | ABI = FloatABI::Soft; |
218 | 50 | break; |
219 | 62 | } |
220 | 62 | break; |
221 | 62 | |
222 | 15 | case llvm::Triple::FreeBSD: |
223 | 15 | switch (Triple.getEnvironment()) { |
224 | 7 | case llvm::Triple::GNUEABIHF: |
225 | 7 | ABI = FloatABI::Hard; |
226 | 7 | break; |
227 | 8 | default: |
228 | 8 | // FreeBSD defaults to soft float |
229 | 8 | ABI = FloatABI::Soft; |
230 | 8 | break; |
231 | 15 | } |
232 | 15 | break; |
233 | 15 | |
234 | 10 | case llvm::Triple::OpenBSD: |
235 | 10 | ABI = FloatABI::Soft; |
236 | 10 | break; |
237 | 15 | |
238 | 2.13k | default: |
239 | 2.13k | switch (Triple.getEnvironment()) { |
240 | 100 | case llvm::Triple::GNUEABIHF: |
241 | 100 | case llvm::Triple::MuslEABIHF: |
242 | 100 | case llvm::Triple::EABIHF: |
243 | 100 | ABI = FloatABI::Hard; |
244 | 100 | break; |
245 | 919 | case llvm::Triple::GNUEABI: |
246 | 919 | case llvm::Triple::MuslEABI: |
247 | 919 | case llvm::Triple::EABI: |
248 | 919 | // EABI is always AAPCS, and if it was not marked 'hard', it's softfp |
249 | 919 | ABI = FloatABI::SoftFP; |
250 | 919 | break; |
251 | 115 | case llvm::Triple::Android: |
252 | 115 | ABI = (SubArch == 7) ? FloatABI::SoftFP15 : FloatABI::Soft100 ; |
253 | 115 | break; |
254 | 999 | default: |
255 | 999 | // Assume "soft", but warn the user we are guessing. |
256 | 999 | if (Triple.isOSBinFormatMachO() && |
257 | 75 | Triple.getSubArch() == llvm::Triple::ARMSubArch_v7em) |
258 | 18 | ABI = FloatABI::Hard; |
259 | 999 | else |
260 | 981 | ABI = FloatABI::Soft; |
261 | 999 | |
262 | 999 | if (Triple.getOS() != llvm::Triple::UnknownOS || |
263 | 831 | !Triple.isOSBinFormatMachO()) |
264 | 924 | D.Diag(diag::warn_drv_assuming_mfloat_abi_is) << "soft"; |
265 | 100 | break; |
266 | 8.16k | } |
267 | 5.39k | } |
268 | 5.39k | } |
269 | 8.16k | |
270 | 8.16k | assert(ABI != FloatABI::Invalid && "must select an ABI"); |
271 | 8.16k | return ABI; |
272 | 8.16k | } |
273 | | |
274 | | void arm::getARMTargetFeatures(const ToolChain &TC, |
275 | | const llvm::Triple &Triple, |
276 | | const ArgList &Args, |
277 | | ArgStringList &CmdArgs, |
278 | | std::vector<StringRef> &Features, |
279 | 4.34k | bool ForAS) { |
280 | 4.34k | const Driver &D = TC.getDriver(); |
281 | 4.34k | |
282 | 4.34k | bool KernelOrKext = |
283 | 4.34k | Args.hasArg(options::OPT_mkernel, options::OPT_fapple_kext); |
284 | 4.34k | arm::FloatABI ABI = arm::getARMFloatABI(TC, Args); |
285 | 4.34k | arm::ReadTPMode ThreadPointer = arm::getReadTPMode(TC, Args); |
286 | 4.34k | const Arg *WaCPU = nullptr, *WaFPU = nullptr; |
287 | 4.34k | const Arg *WaHDiv = nullptr, *WaArch = nullptr; |
288 | 4.34k | |
289 | 4.34k | if (!ForAS4.34k ) { |
290 | 3.66k | // FIXME: Note, this is a hack, the LLVM backend doesn't actually use these |
291 | 3.66k | // yet (it uses the -mfloat-abi and -msoft-float options), and it is |
292 | 3.66k | // stripped out by the ARM target. We should probably pass this a new |
293 | 3.66k | // -target-option, which is handled by the -cc1/-cc1as invocation. |
294 | 3.66k | // |
295 | 3.66k | // FIXME2: For consistency, it would be ideal if we set up the target |
296 | 3.66k | // machine state the same when using the frontend or the assembler. We don't |
297 | 3.66k | // currently do that for the assembler, we pass the options directly to the |
298 | 3.66k | // backend and never even instantiate the frontend TargetInfo. If we did, |
299 | 3.66k | // and used its handleTargetFeatures hook, then we could ensure the |
300 | 3.66k | // assembler and the frontend behave the same. |
301 | 3.66k | |
302 | 3.66k | // Use software floating point operations? |
303 | 3.66k | if (ABI == arm::FloatABI::Soft) |
304 | 1.34k | Features.push_back("+soft-float"); |
305 | 3.66k | |
306 | 3.66k | // Use software floating point argument passing? |
307 | 3.66k | if (ABI != arm::FloatABI::Hard) |
308 | 2.52k | Features.push_back("+soft-float-abi"); |
309 | 4.34k | } else { |
310 | 684 | // Here, we make sure that -Wa,-mfpu/cpu/arch/hwdiv will be passed down |
311 | 684 | // to the assembler correctly. |
312 | 684 | for (const Arg *A : |
313 | 12 | Args.filtered(options::OPT_Wa_COMMA, options::OPT_Xassembler)) { |
314 | 12 | StringRef Value = A->getValue(); |
315 | 12 | if (Value.startswith("-mfpu=")12 ) { |
316 | 3 | WaFPU = A; |
317 | 12 | } else if (9 Value.startswith("-mcpu=")9 ) { |
318 | 3 | WaCPU = A; |
319 | 9 | } else if (6 Value.startswith("-mhwdiv=")6 ) { |
320 | 4 | WaHDiv = A; |
321 | 6 | } else if (2 Value.startswith("-march=")2 ) { |
322 | 2 | WaArch = A; |
323 | 2 | } |
324 | 12 | } |
325 | 684 | } |
326 | 4.34k | |
327 | 4.34k | if (ThreadPointer == arm::ReadTPMode::Cp15) |
328 | 1 | Features.push_back("+read-tp-hard"); |
329 | 4.34k | |
330 | 4.34k | // Check -march. ClangAs gives preference to -Wa,-march=. |
331 | 4.34k | const Arg *ArchArg = Args.getLastArg(options::OPT_march_EQ); |
332 | 4.34k | StringRef ArchName; |
333 | 4.34k | if (WaArch4.34k ) { |
334 | 2 | if (ArchArg) |
335 | 1 | D.Diag(clang::diag::warn_drv_unused_argument) |
336 | 1 | << ArchArg->getAsString(Args); |
337 | 2 | ArchName = StringRef(WaArch->getValue()).substr(7); |
338 | 2 | checkARMArchName(D, WaArch, Args, ArchName, Features, Triple); |
339 | 2 | // FIXME: Set Arch. |
340 | 2 | D.Diag(clang::diag::warn_drv_unused_argument) << WaArch->getAsString(Args); |
341 | 4.34k | } else if (4.34k ArchArg4.34k ) { |
342 | 3.40k | ArchName = ArchArg->getValue(); |
343 | 3.40k | checkARMArchName(D, ArchArg, Args, ArchName, Features, Triple); |
344 | 3.40k | } |
345 | 4.34k | |
346 | 4.34k | // Check -mcpu. ClangAs gives preference to -Wa,-mcpu=. |
347 | 4.34k | const Arg *CPUArg = Args.getLastArg(options::OPT_mcpu_EQ); |
348 | 4.34k | StringRef CPUName; |
349 | 4.34k | if (WaCPU4.34k ) { |
350 | 3 | if (CPUArg) |
351 | 1 | D.Diag(clang::diag::warn_drv_unused_argument) |
352 | 1 | << CPUArg->getAsString(Args); |
353 | 3 | CPUName = StringRef(WaCPU->getValue()).substr(6); |
354 | 3 | checkARMCPUName(D, WaCPU, Args, CPUName, ArchName, Features, Triple); |
355 | 4.34k | } else if (4.34k CPUArg4.34k ) { |
356 | 386 | CPUName = CPUArg->getValue(); |
357 | 386 | checkARMCPUName(D, CPUArg, Args, CPUName, ArchName, Features, Triple); |
358 | 386 | } |
359 | 4.34k | |
360 | 4.34k | // Add CPU features for generic CPUs |
361 | 4.34k | if (CPUName == "native"4.34k ) { |
362 | 0 | llvm::StringMap<bool> HostFeatures; |
363 | 0 | if (llvm::sys::getHostCPUFeatures(HostFeatures)) |
364 | 0 | for (auto &F : HostFeatures) |
365 | 0 | Features.push_back( |
366 | 0 | Args.MakeArgString((F.second ? "+"0 : "-"0 ) + F.first())); |
367 | 4.34k | } else if (4.34k !CPUName.empty()4.34k ) { |
368 | 389 | DecodeARMFeaturesFromCPU(D, CPUName, Features); |
369 | 389 | } |
370 | 4.34k | |
371 | 4.34k | // Honor -mfpu=. ClangAs gives preference to -Wa,-mfpu=. |
372 | 4.34k | const Arg *FPUArg = Args.getLastArg(options::OPT_mfpu_EQ); |
373 | 4.34k | if (WaFPU4.34k ) { |
374 | 3 | if (FPUArg) |
375 | 1 | D.Diag(clang::diag::warn_drv_unused_argument) |
376 | 1 | << FPUArg->getAsString(Args); |
377 | 3 | getARMFPUFeatures(D, WaFPU, Args, StringRef(WaFPU->getValue()).substr(6), |
378 | 3 | Features); |
379 | 4.34k | } else if (4.34k FPUArg4.34k ) { |
380 | 86 | getARMFPUFeatures(D, FPUArg, Args, FPUArg->getValue(), Features); |
381 | 86 | } |
382 | 4.34k | |
383 | 4.34k | // Honor -mhwdiv=. ClangAs gives preference to -Wa,-mhwdiv=. |
384 | 4.34k | const Arg *HDivArg = Args.getLastArg(options::OPT_mhwdiv_EQ); |
385 | 4.34k | if (WaHDiv4.34k ) { |
386 | 4 | if (HDivArg) |
387 | 1 | D.Diag(clang::diag::warn_drv_unused_argument) |
388 | 1 | << HDivArg->getAsString(Args); |
389 | 4 | getARMHWDivFeatures(D, WaHDiv, Args, |
390 | 4 | StringRef(WaHDiv->getValue()).substr(8), Features); |
391 | 4.34k | } else if (4.34k HDivArg4.34k ) |
392 | 21 | getARMHWDivFeatures(D, HDivArg, Args, HDivArg->getValue(), Features); |
393 | 4.34k | |
394 | 4.34k | // Setting -msoft-float effectively disables NEON because of the GCC |
395 | 4.34k | // implementation, although the same isn't true of VFP or VFP3. |
396 | 4.34k | if (ABI == arm::FloatABI::Soft4.34k ) { |
397 | 1.51k | Features.push_back("-neon"); |
398 | 1.51k | // Also need to explicitly disable features which imply NEON. |
399 | 1.51k | Features.push_back("-crypto"); |
400 | 1.51k | } |
401 | 4.34k | |
402 | 4.34k | // En/disable crc code generation. |
403 | 4.34k | if (Arg *A4.34k = Args.getLastArg(options::OPT_mcrc, options::OPT_mnocrc)) { |
404 | 3 | if (A->getOption().matches(options::OPT_mcrc)) |
405 | 1 | Features.push_back("+crc"); |
406 | 3 | else |
407 | 2 | Features.push_back("-crc"); |
408 | 3 | } |
409 | 4.34k | |
410 | 4.34k | // Look for the last occurrence of -mlong-calls or -mno-long-calls. If |
411 | 4.34k | // neither options are specified, see if we are compiling for kernel/kext and |
412 | 4.34k | // decide whether to pass "+long-calls" based on the OS and its version. |
413 | 4.34k | if (Arg *A = Args.getLastArg(options::OPT_mlong_calls, |
414 | 4 | options::OPT_mno_long_calls)) { |
415 | 4 | if (A->getOption().matches(options::OPT_mlong_calls)) |
416 | 3 | Features.push_back("+long-calls"); |
417 | 4.34k | } else if (4.34k KernelOrKext && 4.34k (!Triple.isiOS() || 811 Triple.isOSVersionLT(6)808 ) && |
418 | 4.34k | !Triple.isWatchOS()6 ) { |
419 | 4 | Features.push_back("+long-calls"); |
420 | 4 | } |
421 | 4.34k | |
422 | 4.34k | // Generate execute-only output (no data access to code sections). |
423 | 4.34k | // This only makes sense for the compiler, not for the assembler. |
424 | 4.34k | if (!ForAS4.34k ) { |
425 | 3.66k | // Supported only on ARMv6T2 and ARMv7 and above. |
426 | 3.66k | // Cannot be combined with -mno-movt or -mlong-calls |
427 | 3.66k | if (Arg *A3.66k = Args.getLastArg(options::OPT_mexecute_only, options::OPT_mno_execute_only)) { |
428 | 22 | if (A->getOption().matches(options::OPT_mexecute_only)22 ) { |
429 | 14 | if (getARMSubArchVersionNumber(Triple) < 7 && |
430 | 4 | llvm::ARM::parseArch(Triple.getArchName()) != llvm::ARM::ArchKind::ARMV6T2) |
431 | 2 | D.Diag(diag::err_target_unsupported_execute_only) << Triple.getArchName(); |
432 | 12 | else if (Arg *12 B12 = Args.getLastArg(options::OPT_mno_movt)) |
433 | 2 | D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); |
434 | 12 | // Long calls create constant pool entries and have not yet been fixed up |
435 | 12 | // to play nicely with execute-only. Hence, they cannot be used in |
436 | 12 | // execute-only code for now |
437 | 10 | else if (Arg *10 B10 = Args.getLastArg(options::OPT_mlong_calls, options::OPT_mno_long_calls)) { |
438 | 2 | if (B->getOption().matches(options::OPT_mlong_calls)) |
439 | 2 | D.Diag(diag::err_opt_not_valid_with_opt) << A->getAsString(Args) << B->getAsString(Args); |
440 | 12 | } |
441 | 14 | Features.push_back("+execute-only"); |
442 | 14 | } |
443 | 22 | } |
444 | 3.66k | } |
445 | 4.34k | |
446 | 4.34k | // Kernel code has more strict alignment requirements. |
447 | 4.34k | if (KernelOrKext) |
448 | 811 | Features.push_back("+strict-align"); |
449 | 3.53k | else if (Arg *3.53k A3.53k = Args.getLastArg(options::OPT_mno_unaligned_access, |
450 | 11 | options::OPT_munaligned_access)) { |
451 | 11 | if (A->getOption().matches(options::OPT_munaligned_access)11 ) { |
452 | 6 | // No v6M core supports unaligned memory access (v6M ARM ARM A3.2). |
453 | 6 | if (Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) |
454 | 2 | D.Diag(diag::err_target_unsupported_unaligned) << "v6m"; |
455 | 6 | // v8M Baseline follows on from v6M, so doesn't support unaligned memory |
456 | 6 | // access either. |
457 | 4 | else if (4 Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v8m_baseline4 ) |
458 | 1 | D.Diag(diag::err_target_unsupported_unaligned) << "v8m.base"; |
459 | 6 | } else |
460 | 5 | Features.push_back("+strict-align"); |
461 | 3.53k | } else { |
462 | 3.52k | // Assume pre-ARMv6 doesn't support unaligned accesses. |
463 | 3.52k | // |
464 | 3.52k | // ARMv6 may or may not support unaligned accesses depending on the |
465 | 3.52k | // SCTLR.U bit, which is architecture-specific. We assume ARMv6 |
466 | 3.52k | // Darwin and NetBSD targets support unaligned accesses, and others don't. |
467 | 3.52k | // |
468 | 3.52k | // ARMv7 always has SCTLR.U set to 1, but it has a new SCTLR.A bit |
469 | 3.52k | // which raises an alignment fault on unaligned accesses. Linux |
470 | 3.52k | // defaults this bit to 0 and handles it as a system-wide (not |
471 | 3.52k | // per-process) setting. It is therefore safe to assume that ARMv7+ |
472 | 3.52k | // Linux targets support unaligned accesses. The same goes for NaCl. |
473 | 3.52k | // |
474 | 3.52k | // The above behavior is consistent with GCC. |
475 | 3.52k | int VersionNum = getARMSubArchVersionNumber(Triple); |
476 | 3.52k | if (Triple.isOSDarwin() || 3.52k Triple.isOSNetBSD()2.04k ) { |
477 | 1.50k | if (VersionNum < 6 || |
478 | 1.47k | Triple.getSubArch() == llvm::Triple::SubArchType::ARMSubArch_v6m) |
479 | 29 | Features.push_back("+strict-align"); |
480 | 3.52k | } else if (2.01k Triple.isOSLinux() || 2.01k Triple.isOSNaCl()1.61k ) { |
481 | 406 | if (VersionNum < 7) |
482 | 169 | Features.push_back("+strict-align"); |
483 | 406 | } else |
484 | 1.61k | Features.push_back("+strict-align"); |
485 | 3.53k | } |
486 | 4.34k | |
487 | 4.34k | // llvm does not support reserving registers in general. There is support |
488 | 4.34k | // for reserving r9 on ARM though (defined as a platform-specific register |
489 | 4.34k | // in ARM EABI). |
490 | 4.34k | if (Args.hasArg(options::OPT_ffixed_r9)) |
491 | 1 | Features.push_back("+reserve-r9"); |
492 | 4.34k | |
493 | 4.34k | // The kext linker doesn't know how to deal with movw/movt. |
494 | 4.34k | if (KernelOrKext || 4.34k Args.hasArg(options::OPT_mno_movt)3.53k ) |
495 | 814 | Features.push_back("+no-movt"); |
496 | 4.34k | |
497 | 4.34k | if (Args.hasArg(options::OPT_mno_neg_immediates)) |
498 | 1 | Features.push_back("+no-neg-immediates"); |
499 | 4.34k | } |
500 | | |
501 | 23.7k | const std::string arm::getARMArch(StringRef Arch, const llvm::Triple &Triple) { |
502 | 23.7k | std::string MArch; |
503 | 23.7k | if (!Arch.empty()) |
504 | 21.3k | MArch = Arch; |
505 | 23.7k | else |
506 | 2.38k | MArch = Triple.getArchName(); |
507 | 23.7k | MArch = StringRef(MArch).split("+").first.lower(); |
508 | 23.7k | |
509 | 23.7k | // Handle -march=native. |
510 | 23.7k | if (MArch == "native"23.7k ) { |
511 | 0 | std::string CPU = llvm::sys::getHostCPUName(); |
512 | 0 | if (CPU != "generic"0 ) { |
513 | 0 | // Translate the native cpu into the architecture suffix for that CPU. |
514 | 0 | StringRef Suffix = arm::getLLVMArchSuffixForARM(CPU, MArch, Triple); |
515 | 0 | // If there is no valid architecture suffix for this CPU we don't know how |
516 | 0 | // to handle it, so return no architecture. |
517 | 0 | if (Suffix.empty()) |
518 | 0 | MArch = ""; |
519 | 0 | else |
520 | 0 | MArch = std::string("arm") + Suffix.str(); |
521 | 0 | } |
522 | 0 | } |
523 | 23.7k | |
524 | 23.7k | return MArch; |
525 | 23.7k | } |
526 | | |
527 | | /// Get the (LLVM) name of the minimum ARM CPU for the arch we are targeting. |
528 | 15.2k | StringRef arm::getARMCPUForMArch(StringRef Arch, const llvm::Triple &Triple) { |
529 | 15.2k | std::string MArch = getARMArch(Arch, Triple); |
530 | 15.2k | // getARMCPUForArch defaults to the triple if MArch is empty, but empty MArch |
531 | 15.2k | // here means an -march=native that we can't handle, so instead return no CPU. |
532 | 15.2k | if (MArch.empty()) |
533 | 0 | return StringRef(); |
534 | 15.2k | |
535 | 15.2k | // We need to return an empty string here on invalid MArch values as the |
536 | 15.2k | // various places that call this function can't cope with a null result. |
537 | 15.2k | return Triple.getARMCPUForArch(MArch); |
538 | 15.2k | } |
539 | | |
540 | | /// getARMTargetCPU - Get the (LLVM) name of the ARM cpu we are targeting. |
541 | | std::string arm::getARMTargetCPU(StringRef CPU, StringRef Arch, |
542 | 9.83k | const llvm::Triple &Triple) { |
543 | 9.83k | // FIXME: Warn on inconsistent use of -mcpu and -march. |
544 | 9.83k | // If we have -mcpu=, use that. |
545 | 9.83k | if (!CPU.empty()9.83k ) { |
546 | 1.56k | std::string MCPU = StringRef(CPU).split("+").first.lower(); |
547 | 1.56k | // Handle -mcpu=native. |
548 | 1.56k | if (MCPU == "native") |
549 | 0 | return llvm::sys::getHostCPUName(); |
550 | 1.56k | else |
551 | 1.56k | return MCPU; |
552 | 8.27k | } |
553 | 8.27k | |
554 | 8.27k | return getARMCPUForMArch(Arch, Triple); |
555 | 8.27k | } |
556 | | |
557 | | /// getLLVMArchSuffixForARM - Get the LLVM arch name to use for a particular |
558 | | /// CPU (or Arch, if CPU is generic). |
559 | | // FIXME: This is redundant with -mcpu, why does LLVM use this. |
560 | | StringRef arm::getLLVMArchSuffixForARM(StringRef CPU, StringRef Arch, |
561 | 8.80k | const llvm::Triple &Triple) { |
562 | 8.80k | llvm::ARM::ArchKind ArchKind; |
563 | 8.80k | if (CPU == "generic"8.80k ) { |
564 | 5.04k | std::string ARMArch = tools::arm::getARMArch(Arch, Triple); |
565 | 5.04k | ArchKind = llvm::ARM::parseArch(ARMArch); |
566 | 5.04k | if (ArchKind == llvm::ARM::ArchKind::INVALID) |
567 | 5.04k | // In case of generic Arch, i.e. "arm", |
568 | 5.04k | // extract arch from default cpu of the Triple |
569 | 6 | ArchKind = llvm::ARM::parseCPUArch(Triple.getARMCPUForArch(ARMArch)); |
570 | 8.80k | } else { |
571 | 3.76k | // FIXME: horrible hack to get around the fact that Cortex-A7 is only an |
572 | 3.76k | // armv7k triple if it's actually been specified via "-arch armv7k". |
573 | 3.72k | ArchKind = (Arch == "armv7k" || Arch == "thumbv7k") |
574 | 43 | ? llvm::ARM::ArchKind::ARMV7K |
575 | 3.72k | : llvm::ARM::parseCPUArch(CPU); |
576 | 3.76k | } |
577 | 8.80k | if (ArchKind == llvm::ARM::ArchKind::INVALID) |
578 | 5 | return ""; |
579 | 8.80k | return llvm::ARM::getSubArch(ArchKind); |
580 | 8.80k | } |
581 | | |
582 | | void arm::appendEBLinkFlags(const ArgList &Args, ArgStringList &CmdArgs, |
583 | 18 | const llvm::Triple &Triple) { |
584 | 18 | if (Args.hasArg(options::OPT_r)) |
585 | 1 | return; |
586 | 17 | |
587 | 17 | // ARMv7 (and later) and ARMv6-M do not support BE-32, so instruct the linker |
588 | 17 | // to generate BE-8 executables. |
589 | 17 | if (17 arm::getARMSubArchVersionNumber(Triple) >= 7 || 17 arm::isARMMProfile(Triple)12 ) |
590 | 5 | CmdArgs.push_back("--be8"); |
591 | 18 | } |