blob: 2f828b7f1ded6ea958c9b229e742d41cdd3db7da [file] [log] [blame]
Erich Keaneebba5922017-07-21 22:37:03 +00001//===--- ARM.cpp - Implement ARM target feature support -------------------===//
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// This file implements ARM TargetInfo objects.
11//
12//===----------------------------------------------------------------------===//
13
14#include "ARM.h"
15#include "clang/Basic/Builtins.h"
16#include "clang/Basic/Diagnostic.h"
17#include "clang/Basic/TargetBuiltins.h"
18#include "llvm/ADT/StringExtras.h"
19#include "llvm/ADT/StringRef.h"
20#include "llvm/ADT/StringSwitch.h"
21
22using namespace clang;
23using namespace clang::targets;
24
Tim Northoverad4c5db2017-07-24 17:06:23 +000025void ARMTargetInfo::setABIAAPCS() {
26 IsAAPCS = true;
27
28 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
29 const llvm::Triple &T = getTriple();
30
31 // size_t is unsigned long on MachO-derived environments, NetBSD, and
32 // OpenBSD.
33 if (T.isOSBinFormatMachO() || T.getOS() == llvm::Triple::NetBSD ||
34 T.getOS() == llvm::Triple::OpenBSD)
35 SizeType = UnsignedLong;
36 else
37 SizeType = UnsignedInt;
38
39 switch (T.getOS()) {
40 case llvm::Triple::NetBSD:
41 case llvm::Triple::OpenBSD:
42 WCharType = SignedInt;
43 break;
44 case llvm::Triple::Win32:
45 WCharType = UnsignedShort;
46 break;
47 case llvm::Triple::Linux:
48 default:
49 // AAPCS 7.1.1, ARM-Linux ABI 2.4: type of wchar_t is unsigned int.
50 WCharType = UnsignedInt;
51 break;
52 }
53
54 UseBitFieldTypeAlignment = true;
55
56 ZeroLengthBitfieldBoundary = 0;
57
58 // Thumb1 add sp, #imm requires the immediate value be multiple of 4,
59 // so set preferred for small types to 32.
60 if (T.isOSBinFormatMachO()) {
61 resetDataLayout(BigEndian
62 ? "E-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
63 : "e-m:o-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
64 } else if (T.isOSWindows()) {
65 assert(!BigEndian && "Windows on ARM does not support big endian");
66 resetDataLayout("e"
67 "-m:w"
68 "-p:32:32"
69 "-i64:64"
70 "-v128:64:128"
71 "-a:0:32"
72 "-n32"
73 "-S64");
74 } else if (T.isOSNaCl()) {
75 assert(!BigEndian && "NaCl on ARM does not support big endian");
76 resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S128");
77 } else {
78 resetDataLayout(BigEndian
79 ? "E-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64"
80 : "e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
81 }
82
83 // FIXME: Enumerated types are variable width in straight AAPCS.
84}
85
86void ARMTargetInfo::setABIAPCS(bool IsAAPCS16) {
87 const llvm::Triple &T = getTriple();
88
89 IsAAPCS = false;
90
91 if (IsAAPCS16)
92 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 64;
93 else
94 DoubleAlign = LongLongAlign = LongDoubleAlign = SuitableAlign = 32;
95
96 // size_t is unsigned int on FreeBSD.
97 if (T.getOS() == llvm::Triple::FreeBSD)
98 SizeType = UnsignedInt;
99 else
100 SizeType = UnsignedLong;
101
102 // Revert to using SignedInt on apcs-gnu to comply with existing behaviour.
103 WCharType = SignedInt;
104
105 // Do not respect the alignment of bit-field types when laying out
106 // structures. This corresponds to PCC_BITFIELD_TYPE_MATTERS in gcc.
107 UseBitFieldTypeAlignment = false;
108
109 /// gcc forces the alignment to 4 bytes, regardless of the type of the
110 /// zero length bitfield. This corresponds to EMPTY_FIELD_BOUNDARY in
111 /// gcc.
112 ZeroLengthBitfieldBoundary = 32;
113
114 if (T.isOSBinFormatMachO() && IsAAPCS16) {
115 assert(!BigEndian && "AAPCS16 does not support big-endian");
116 resetDataLayout("e-m:o-p:32:32-i64:64-a:0:32-n32-S128");
117 } else if (T.isOSBinFormatMachO())
118 resetDataLayout(
119 BigEndian
120 ? "E-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
121 : "e-m:o-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
122 else
123 resetDataLayout(
124 BigEndian
125 ? "E-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32"
126 : "e-m:e-p:32:32-f64:32:64-v64:32:64-v128:32:128-a:0:32-n32-S32");
127
128 // FIXME: Override "preferred align" for double and long long.
129}
130
131void ARMTargetInfo::setArchInfo() {
132 StringRef ArchName = getTriple().getArchName();
133
134 ArchISA = llvm::ARM::parseArchISA(ArchName);
135 CPU = llvm::ARM::getDefaultCPU(ArchName);
136 unsigned AK = llvm::ARM::parseArch(ArchName);
137 if (AK != llvm::ARM::AK_INVALID)
138 ArchKind = AK;
139 setArchInfo(ArchKind);
140}
141
142void ARMTargetInfo::setArchInfo(unsigned Kind) {
143 StringRef SubArch;
144
145 // cache TargetParser info
146 ArchKind = Kind;
147 SubArch = llvm::ARM::getSubArch(ArchKind);
148 ArchProfile = llvm::ARM::parseArchProfile(SubArch);
149 ArchVersion = llvm::ARM::parseArchVersion(SubArch);
150
151 // cache CPU related strings
152 CPUAttr = getCPUAttr();
153 CPUProfile = getCPUProfile();
154}
155
156void ARMTargetInfo::setAtomic() {
157 // when triple does not specify a sub arch,
158 // then we are not using inline atomics
159 bool ShouldUseInlineAtomic =
160 (ArchISA == llvm::ARM::IK_ARM && ArchVersion >= 6) ||
161 (ArchISA == llvm::ARM::IK_THUMB && ArchVersion >= 7);
162 // Cortex M does not support 8 byte atomics, while general Thumb2 does.
163 if (ArchProfile == llvm::ARM::PK_M) {
164 MaxAtomicPromoteWidth = 32;
165 if (ShouldUseInlineAtomic)
166 MaxAtomicInlineWidth = 32;
167 } else {
168 MaxAtomicPromoteWidth = 64;
169 if (ShouldUseInlineAtomic)
170 MaxAtomicInlineWidth = 64;
171 }
172}
173
174bool ARMTargetInfo::isThumb() const { return (ArchISA == llvm::ARM::IK_THUMB); }
175
176bool ARMTargetInfo::supportsThumb() const {
177 return CPUAttr.count('T') || ArchVersion >= 6;
178}
179
180bool ARMTargetInfo::supportsThumb2() const {
181 return CPUAttr.equals("6T2") ||
182 (ArchVersion >= 7 && !CPUAttr.equals("8M_BASE"));
183}
184
185StringRef ARMTargetInfo::getCPUAttr() const {
186 // For most sub-arches, the build attribute CPU name is enough.
187 // For Cortex variants, it's slightly different.
188 switch (ArchKind) {
189 default:
190 return llvm::ARM::getCPUAttr(ArchKind);
191 case llvm::ARM::AK_ARMV6M:
192 return "6M";
193 case llvm::ARM::AK_ARMV7S:
194 return "7S";
195 case llvm::ARM::AK_ARMV7A:
196 return "7A";
197 case llvm::ARM::AK_ARMV7R:
198 return "7R";
199 case llvm::ARM::AK_ARMV7M:
200 return "7M";
201 case llvm::ARM::AK_ARMV7EM:
202 return "7EM";
203 case llvm::ARM::AK_ARMV7VE:
204 return "7VE";
205 case llvm::ARM::AK_ARMV8A:
206 return "8A";
207 case llvm::ARM::AK_ARMV8_1A:
208 return "8_1A";
209 case llvm::ARM::AK_ARMV8_2A:
210 return "8_2A";
211 case llvm::ARM::AK_ARMV8MBaseline:
212 return "8M_BASE";
213 case llvm::ARM::AK_ARMV8MMainline:
214 return "8M_MAIN";
215 case llvm::ARM::AK_ARMV8R:
216 return "8R";
217 }
218}
219
220StringRef ARMTargetInfo::getCPUProfile() const {
221 switch (ArchProfile) {
222 case llvm::ARM::PK_A:
223 return "A";
224 case llvm::ARM::PK_R:
225 return "R";
226 case llvm::ARM::PK_M:
227 return "M";
228 default:
229 return "";
230 }
231}
232
233ARMTargetInfo::ARMTargetInfo(const llvm::Triple &Triple,
234 const TargetOptions &Opts)
235 : TargetInfo(Triple), FPMath(FP_Default), IsAAPCS(true), LDREX(0),
236 HW_FP(0) {
237
238 switch (getTriple().getOS()) {
239 case llvm::Triple::NetBSD:
240 case llvm::Triple::OpenBSD:
241 PtrDiffType = SignedLong;
242 break;
243 default:
244 PtrDiffType = SignedInt;
245 break;
246 }
247
248 // Cache arch related info.
249 setArchInfo();
250
251 // {} in inline assembly are neon specifiers, not assembly variant
252 // specifiers.
253 NoAsmVariants = true;
254
255 // FIXME: This duplicates code from the driver that sets the -target-abi
256 // option - this code is used if -target-abi isn't passed and should
257 // be unified in some way.
258 if (Triple.isOSBinFormatMachO()) {
259 // The backend is hardwired to assume AAPCS for M-class processors, ensure
260 // the frontend matches that.
261 if (Triple.getEnvironment() == llvm::Triple::EABI ||
262 Triple.getOS() == llvm::Triple::UnknownOS ||
263 ArchProfile == llvm::ARM::PK_M) {
264 setABI("aapcs");
265 } else if (Triple.isWatchABI()) {
266 setABI("aapcs16");
267 } else {
268 setABI("apcs-gnu");
269 }
270 } else if (Triple.isOSWindows()) {
271 // FIXME: this is invalid for WindowsCE
272 setABI("aapcs");
273 } else {
274 // Select the default based on the platform.
275 switch (Triple.getEnvironment()) {
276 case llvm::Triple::Android:
277 case llvm::Triple::GNUEABI:
278 case llvm::Triple::GNUEABIHF:
279 case llvm::Triple::MuslEABI:
280 case llvm::Triple::MuslEABIHF:
281 setABI("aapcs-linux");
282 break;
283 case llvm::Triple::EABIHF:
284 case llvm::Triple::EABI:
285 setABI("aapcs");
286 break;
287 case llvm::Triple::GNU:
288 setABI("apcs-gnu");
289 break;
290 default:
291 if (Triple.getOS() == llvm::Triple::NetBSD)
292 setABI("apcs-gnu");
293 else if (Triple.getOS() == llvm::Triple::OpenBSD)
294 setABI("aapcs-linux");
295 else
296 setABI("aapcs");
297 break;
298 }
299 }
300
301 // ARM targets default to using the ARM C++ ABI.
302 TheCXXABI.set(TargetCXXABI::GenericARM);
303
304 // ARM has atomics up to 8 bytes
305 setAtomic();
306
307 // Maximum alignment for ARM NEON data types should be 64-bits (AAPCS)
308 if (IsAAPCS && (Triple.getEnvironment() != llvm::Triple::Android))
309 MaxVectorAlign = 64;
310
311 // Do force alignment of members that follow zero length bitfields. If
312 // the alignment of the zero-length bitfield is greater than the member
313 // that follows it, `bar', `bar' will be aligned as the type of the
314 // zero length bitfield.
315 UseZeroLengthBitfieldAlignment = true;
316
317 if (Triple.getOS() == llvm::Triple::Linux ||
318 Triple.getOS() == llvm::Triple::UnknownOS)
319 this->MCountName = Opts.EABIVersion == llvm::EABI::GNU
320 ? "\01__gnu_mcount_nc"
321 : "\01mcount";
322}
323
324StringRef ARMTargetInfo::getABI() const { return ABI; }
325
326bool ARMTargetInfo::setABI(const std::string &Name) {
327 ABI = Name;
328
329 // The defaults (above) are for AAPCS, check if we need to change them.
330 //
331 // FIXME: We need support for -meabi... we could just mangle it into the
332 // name.
333 if (Name == "apcs-gnu" || Name == "aapcs16") {
334 setABIAPCS(Name == "aapcs16");
Erich Keaneebba5922017-07-21 22:37:03 +0000335 return true;
Tim Northoverad4c5db2017-07-24 17:06:23 +0000336 }
337 if (Name == "aapcs" || Name == "aapcs-vfp" || Name == "aapcs-linux") {
338 setABIAAPCS();
Erich Keaneebba5922017-07-21 22:37:03 +0000339 return true;
340 }
341 return false;
342}
343
Tim Northoverad4c5db2017-07-24 17:06:23 +0000344// FIXME: This should be based on Arch attributes, not CPU names.
345bool ARMTargetInfo::initFeatureMap(
346 llvm::StringMap<bool> &Features, DiagnosticsEngine &Diags, StringRef CPU,
347 const std::vector<std::string> &FeaturesVec) const {
Erich Keaneebba5922017-07-21 22:37:03 +0000348
Tim Northoverad4c5db2017-07-24 17:06:23 +0000349 std::vector<StringRef> TargetFeatures;
350 unsigned Arch = llvm::ARM::parseArch(getTriple().getArchName());
Erich Keaneebba5922017-07-21 22:37:03 +0000351
Tim Northoverad4c5db2017-07-24 17:06:23 +0000352 // get default FPU features
353 unsigned FPUKind = llvm::ARM::getDefaultFPU(CPU, Arch);
354 llvm::ARM::getFPUFeatures(FPUKind, TargetFeatures);
Erich Keaneebba5922017-07-21 22:37:03 +0000355
Tim Northoverad4c5db2017-07-24 17:06:23 +0000356 // get default Extension features
357 unsigned Extensions = llvm::ARM::getDefaultExtensions(CPU, Arch);
358 llvm::ARM::getExtensionFeatures(Extensions, TargetFeatures);
Erich Keaneebba5922017-07-21 22:37:03 +0000359
Tim Northoverad4c5db2017-07-24 17:06:23 +0000360 for (auto Feature : TargetFeatures)
361 if (Feature[0] == '+')
362 Features[Feature.drop_front(1)] = true;
363
364 // Enable or disable thumb-mode explicitly per function to enable mixed
365 // ARM and Thumb code generation.
366 if (isThumb())
367 Features["thumb-mode"] = true;
368 else
369 Features["thumb-mode"] = false;
370
371 // Convert user-provided arm and thumb GNU target attributes to
372 // [-|+]thumb-mode target features respectively.
373 std::vector<std::string> UpdatedFeaturesVec(FeaturesVec);
374 for (auto &Feature : UpdatedFeaturesVec) {
375 if (Feature.compare("+arm") == 0)
376 Feature = "-thumb-mode";
377 else if (Feature.compare("+thumb") == 0)
378 Feature = "+thumb-mode";
379 }
380
381 return TargetInfo::initFeatureMap(Features, Diags, CPU, UpdatedFeaturesVec);
Erich Keaneebba5922017-07-21 22:37:03 +0000382}
383
Erich Keaneebba5922017-07-21 22:37:03 +0000384
Tim Northoverad4c5db2017-07-24 17:06:23 +0000385bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
386 DiagnosticsEngine &Diags) {
387 FPU = 0;
388 CRC = 0;
389 Crypto = 0;
390 DSP = 0;
391 Unaligned = 1;
392 SoftFloat = SoftFloatABI = false;
393 HWDiv = 0;
394
395 // This does not diagnose illegal cases like having both
396 // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".
397 uint32_t HW_FP_remove = 0;
398 for (const auto &Feature : Features) {
399 if (Feature == "+soft-float") {
400 SoftFloat = true;
401 } else if (Feature == "+soft-float-abi") {
402 SoftFloatABI = true;
403 } else if (Feature == "+vfp2") {
404 FPU |= VFP2FPU;
405 HW_FP |= HW_FP_SP | HW_FP_DP;
406 } else if (Feature == "+vfp3") {
407 FPU |= VFP3FPU;
408 HW_FP |= HW_FP_SP | HW_FP_DP;
409 } else if (Feature == "+vfp4") {
410 FPU |= VFP4FPU;
411 HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
412 } else if (Feature == "+fp-armv8") {
413 FPU |= FPARMV8;
414 HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
415 } else if (Feature == "+neon") {
416 FPU |= NeonFPU;
417 HW_FP |= HW_FP_SP | HW_FP_DP;
418 } else if (Feature == "+hwdiv") {
419 HWDiv |= HWDivThumb;
420 } else if (Feature == "+hwdiv-arm") {
421 HWDiv |= HWDivARM;
422 } else if (Feature == "+crc") {
423 CRC = 1;
424 } else if (Feature == "+crypto") {
425 Crypto = 1;
426 } else if (Feature == "+dsp") {
427 DSP = 1;
428 } else if (Feature == "+fp-only-sp") {
429 HW_FP_remove |= HW_FP_DP;
430 } else if (Feature == "+strict-align") {
431 Unaligned = 0;
432 } else if (Feature == "+fp16") {
433 HW_FP |= HW_FP_HP;
434 }
435 }
436 HW_FP &= ~HW_FP_remove;
437
438 switch (ArchVersion) {
439 case 6:
440 if (ArchProfile == llvm::ARM::PK_M)
441 LDREX = 0;
442 else if (ArchKind == llvm::ARM::AK_ARMV6K)
443 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
444 else
445 LDREX = LDREX_W;
446 break;
447 case 7:
448 if (ArchProfile == llvm::ARM::PK_M)
449 LDREX = LDREX_W | LDREX_H | LDREX_B;
450 else
451 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
452 break;
453 case 8:
454 LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
455 }
456
457 if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
458 Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
459 return false;
460 }
461
462 if (FPMath == FP_Neon)
463 Features.push_back("+neonfp");
464 else if (FPMath == FP_VFP)
465 Features.push_back("-neonfp");
466
467 // Remove front-end specific options which the backend handles differently.
468 auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi");
469 if (Feature != Features.end())
470 Features.erase(Feature);
471
472 return true;
Erich Keaneebba5922017-07-21 22:37:03 +0000473}
474
Erich Keaneebba5922017-07-21 22:37:03 +0000475bool ARMTargetInfo::hasFeature(StringRef Feature) const {
476 return llvm::StringSwitch<bool>(Feature)
477 .Case("arm", true)
478 .Case("aarch32", true)
479 .Case("softfloat", SoftFloat)
480 .Case("thumb", isThumb())
481 .Case("neon", (FPU & NeonFPU) && !SoftFloat)
482 .Case("vfp", FPU && !SoftFloat)
483 .Case("hwdiv", HWDiv & HWDivThumb)
484 .Case("hwdiv-arm", HWDiv & HWDivARM)
485 .Default(false);
486}
487
Tim Northoverad4c5db2017-07-24 17:06:23 +0000488bool ARMTargetInfo::isValidCPUName(StringRef Name) const {
489 return Name == "generic" ||
490 llvm::ARM::parseCPUArch(Name) != llvm::ARM::AK_INVALID;
491}
492
493bool ARMTargetInfo::setCPU(const std::string &Name) {
494 if (Name != "generic")
495 setArchInfo(llvm::ARM::parseCPUArch(Name));
496
497 if (ArchKind == llvm::ARM::AK_INVALID)
498 return false;
499 setAtomic();
500 CPU = Name;
501 return true;
502}
503
504bool ARMTargetInfo::setFPMath(StringRef Name) {
505 if (Name == "neon") {
506 FPMath = FP_Neon;
507 return true;
508 } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
509 Name == "vfp4") {
510 FPMath = FP_VFP;
511 return true;
512 }
513 return false;
514}
515
516void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
517 MacroBuilder &Builder) const {
518 Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
519}
520
521void ARMTargetInfo::getTargetDefinesARMV82A(const LangOptions &Opts,
522 MacroBuilder &Builder) const {
523 // Also include the ARMv8.1-A defines
524 getTargetDefinesARMV81A(Opts, Builder);
525}
526
Erich Keaneebba5922017-07-21 22:37:03 +0000527void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
528 MacroBuilder &Builder) const {
529 // Target identification.
530 Builder.defineMacro("__arm");
531 Builder.defineMacro("__arm__");
532 // For bare-metal none-eabi.
533 if (getTriple().getOS() == llvm::Triple::UnknownOS &&
534 (getTriple().getEnvironment() == llvm::Triple::EABI ||
535 getTriple().getEnvironment() == llvm::Triple::EABIHF))
536 Builder.defineMacro("__ELF__");
537
538 // Target properties.
539 Builder.defineMacro("__REGISTER_PREFIX__", "");
540
541 // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
542 // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
543 if (getTriple().isWatchABI())
544 Builder.defineMacro("__ARM_ARCH_7K__", "2");
545
546 if (!CPUAttr.empty())
547 Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
548
549 // ACLE 6.4.1 ARM/Thumb instruction set architecture
550 // __ARM_ARCH is defined as an integer value indicating the current ARM ISA
551 Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
552
553 if (ArchVersion >= 8) {
554 // ACLE 6.5.7 Crypto Extension
555 if (Crypto)
556 Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
557 // ACLE 6.5.8 CRC32 Extension
558 if (CRC)
559 Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
560 // ACLE 6.5.10 Numeric Maximum and Minimum
561 Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
562 // ACLE 6.5.9 Directed Rounding
563 Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
564 }
565
566 // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA. It
567 // is not defined for the M-profile.
568 // NOTE that the default profile is assumed to be 'A'
569 if (CPUProfile.empty() || ArchProfile != llvm::ARM::PK_M)
570 Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");
571
572 // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
573 // Thumb ISA (including v6-M and v8-M Baseline). It is set to 2 if the
574 // core supports the Thumb-2 ISA as found in the v6T2 architecture and all
575 // v7 and v8 architectures excluding v8-M Baseline.
576 if (supportsThumb2())
577 Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
578 else if (supportsThumb())
579 Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
580
581 // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
582 // instruction set such as ARM or Thumb.
583 Builder.defineMacro("__ARM_32BIT_STATE", "1");
584
585 // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
586
587 // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
588 if (!CPUProfile.empty())
589 Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
590
591 // ACLE 6.4.3 Unaligned access supported in hardware
592 if (Unaligned)
593 Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
594
595 // ACLE 6.4.4 LDREX/STREX
596 if (LDREX)
597 Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + llvm::utohexstr(LDREX));
598
599 // ACLE 6.4.5 CLZ
600 if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||
601 ArchVersion > 6)
602 Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
603
604 // ACLE 6.5.1 Hardware Floating Point
605 if (HW_FP)
606 Builder.defineMacro("__ARM_FP", "0x" + llvm::utohexstr(HW_FP));
607
608 // ACLE predefines.
609 Builder.defineMacro("__ARM_ACLE", "200");
610
611 // FP16 support (we currently only support IEEE format).
612 Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
613 Builder.defineMacro("__ARM_FP16_ARGS", "1");
614
615 // ACLE 6.5.3 Fused multiply-accumulate (FMA)
616 if (ArchVersion >= 7 && (FPU & VFP4FPU))
617 Builder.defineMacro("__ARM_FEATURE_FMA", "1");
618
619 // Subtarget options.
620
621 // FIXME: It's more complicated than this and we don't really support
622 // interworking.
623 // Windows on ARM does not "support" interworking
624 if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
625 Builder.defineMacro("__THUMB_INTERWORK__");
626
627 if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
628 // Embedded targets on Darwin follow AAPCS, but not EABI.
629 // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
630 if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
631 Builder.defineMacro("__ARM_EABI__");
632 Builder.defineMacro("__ARM_PCS", "1");
633 }
634
635 if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")
636 Builder.defineMacro("__ARM_PCS_VFP", "1");
637
638 if (SoftFloat)
639 Builder.defineMacro("__SOFTFP__");
640
641 if (ArchKind == llvm::ARM::AK_XSCALE)
642 Builder.defineMacro("__XSCALE__");
643
644 if (isThumb()) {
645 Builder.defineMacro("__THUMBEL__");
646 Builder.defineMacro("__thumb__");
647 if (supportsThumb2())
648 Builder.defineMacro("__thumb2__");
649 }
650
651 // ACLE 6.4.9 32-bit SIMD instructions
652 if (ArchVersion >= 6 && (CPUProfile != "M" || CPUAttr == "7EM"))
653 Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
654
655 // ACLE 6.4.10 Hardware Integer Divide
656 if (((HWDiv & HWDivThumb) && isThumb()) ||
657 ((HWDiv & HWDivARM) && !isThumb())) {
658 Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
659 Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
660 }
661
662 // Note, this is always on in gcc, even though it doesn't make sense.
663 Builder.defineMacro("__APCS_32__");
664
665 if (FPUModeIsVFP((FPUMode)FPU)) {
666 Builder.defineMacro("__VFP_FP__");
667 if (FPU & VFP2FPU)
668 Builder.defineMacro("__ARM_VFPV2__");
669 if (FPU & VFP3FPU)
670 Builder.defineMacro("__ARM_VFPV3__");
671 if (FPU & VFP4FPU)
672 Builder.defineMacro("__ARM_VFPV4__");
673 if (FPU & FPARMV8)
674 Builder.defineMacro("__ARM_FPV5__");
675 }
676
677 // This only gets set when Neon instructions are actually available, unlike
678 // the VFP define, hence the soft float and arch check. This is subtly
679 // different from gcc, we follow the intent which was that it should be set
680 // when Neon instructions are actually available.
681 if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
682 Builder.defineMacro("__ARM_NEON", "1");
683 Builder.defineMacro("__ARM_NEON__");
684 // current AArch32 NEON implementations do not support double-precision
685 // floating-point even when it is present in VFP.
686 Builder.defineMacro("__ARM_NEON_FP",
687 "0x" + llvm::utohexstr(HW_FP & ~HW_FP_DP));
688 }
689
690 Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4");
691
692 Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
693
694 if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
695 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
696 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
697 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
698 Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
699 }
700
701 // ACLE 6.4.7 DSP instructions
702 if (DSP) {
703 Builder.defineMacro("__ARM_FEATURE_DSP", "1");
704 }
705
706 // ACLE 6.4.8 Saturation instructions
707 bool SAT = false;
708 if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {
709 Builder.defineMacro("__ARM_FEATURE_SAT", "1");
710 SAT = true;
711 }
712
713 // ACLE 6.4.6 Q (saturation) flag
714 if (DSP || SAT)
715 Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
716
717 if (Opts.UnsafeFPMath)
718 Builder.defineMacro("__ARM_FP_FAST", "1");
719
720 switch (ArchKind) {
721 default:
722 break;
723 case llvm::ARM::AK_ARMV8_1A:
724 getTargetDefinesARMV81A(Opts, Builder);
725 break;
726 case llvm::ARM::AK_ARMV8_2A:
727 getTargetDefinesARMV82A(Opts, Builder);
728 break;
729 }
730}
731
Tim Northoverad4c5db2017-07-24 17:06:23 +0000732const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
733#define BUILTIN(ID, TYPE, ATTRS) \
734 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
735#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
736 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
737#include "clang/Basic/BuiltinsNEON.def"
Erich Keaneebba5922017-07-21 22:37:03 +0000738
Tim Northoverad4c5db2017-07-24 17:06:23 +0000739#define BUILTIN(ID, TYPE, ATTRS) \
740 {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
741#define LANGBUILTIN(ID, TYPE, ATTRS, LANG) \
742 {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
743#define LIBBUILTIN(ID, TYPE, ATTRS, HEADER) \
744 {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
745#define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE) \
746 {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
747#include "clang/Basic/BuiltinsARM.def"
748};
749
750ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
751 return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin -
752 Builtin::FirstTSBuiltin);
753}
754
755bool ARMTargetInfo::isCLZForZeroUndef() const { return false; }
756TargetInfo::BuiltinVaListKind ARMTargetInfo::getBuiltinVaListKind() const {
757 return IsAAPCS
758 ? AAPCSABIBuiltinVaList
759 : (getTriple().isWatchABI() ? TargetInfo::CharPtrBuiltinVaList
760 : TargetInfo::VoidPtrBuiltinVaList);
761}
762
763const char *const ARMTargetInfo::GCCRegNames[] = {
764 // Integer registers
765 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
766 "r12", "sp", "lr", "pc",
767
768 // Float registers
769 "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
770 "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
771 "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
772
773 // Double registers
774 "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
775 "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
776 "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
777
778 // Quad registers
779 "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
780 "q12", "q13", "q14", "q15"};
781
782ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
783 return llvm::makeArrayRef(GCCRegNames);
784}
785
786const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
787 {{"a1"}, "r0"}, {{"a2"}, "r1"}, {{"a3"}, "r2"}, {{"a4"}, "r3"},
788 {{"v1"}, "r4"}, {{"v2"}, "r5"}, {{"v3"}, "r6"}, {{"v4"}, "r7"},
789 {{"v5"}, "r8"}, {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},
790 {{"ip"}, "r12"}, {{"r13"}, "sp"}, {{"r14"}, "lr"}, {{"r15"}, "pc"},
791 // The S, D and Q registers overlap, but aren't really aliases; we
792 // don't want to substitute one of these for a different-sized one.
793};
794
795ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
796 return llvm::makeArrayRef(GCCRegAliases);
797}
798
799bool ARMTargetInfo::validateAsmConstraint(
800 const char *&Name, TargetInfo::ConstraintInfo &Info) const {
801 switch (*Name) {
802 default:
803 break;
804 case 'l': // r0-r7
805 case 'h': // r8-r15
806 case 't': // VFP Floating point register single precision
807 case 'w': // VFP Floating point register double precision
808 Info.setAllowsRegister();
809 return true;
810 case 'I':
811 case 'J':
812 case 'K':
813 case 'L':
814 case 'M':
815 // FIXME
816 return true;
817 case 'Q': // A memory address that is a single base register.
818 Info.setAllowsMemory();
819 return true;
820 case 'U': // a memory reference...
821 switch (Name[1]) {
822 case 'q': // ...ARMV4 ldrsb
823 case 'v': // ...VFP load/store (reg+constant offset)
824 case 'y': // ...iWMMXt load/store
825 case 't': // address valid for load/store opaque types wider
826 // than 128-bits
827 case 'n': // valid address for Neon doubleword vector load/store
828 case 'm': // valid address for Neon element and structure load/store
829 case 's': // valid address for non-offset loads/stores of quad-word
830 // values in four ARM registers
831 Info.setAllowsMemory();
832 Name++;
833 return true;
Erich Keaneebba5922017-07-21 22:37:03 +0000834 }
835 }
Tim Northoverad4c5db2017-07-24 17:06:23 +0000836 return false;
837}
Erich Keaneebba5922017-07-21 22:37:03 +0000838
Tim Northoverad4c5db2017-07-24 17:06:23 +0000839std::string ARMTargetInfo::convertConstraint(const char *&Constraint) const {
840 std::string R;
841 switch (*Constraint) {
842 case 'U': // Two-character constraint; add "^" hint for later parsing.
843 R = std::string("^") + std::string(Constraint, 2);
844 Constraint++;
Erich Keaneebba5922017-07-21 22:37:03 +0000845 break;
Tim Northoverad4c5db2017-07-24 17:06:23 +0000846 case 'p': // 'p' should be translated to 'r' by default.
847 R = std::string("r");
Erich Keaneebba5922017-07-21 22:37:03 +0000848 break;
Tim Northoverad4c5db2017-07-24 17:06:23 +0000849 default:
850 return std::string(1, *Constraint);
Erich Keaneebba5922017-07-21 22:37:03 +0000851 }
Tim Northoverad4c5db2017-07-24 17:06:23 +0000852 return R;
853}
Erich Keaneebba5922017-07-21 22:37:03 +0000854
Tim Northoverad4c5db2017-07-24 17:06:23 +0000855bool ARMTargetInfo::validateConstraintModifier(
856 StringRef Constraint, char Modifier, unsigned Size,
857 std::string &SuggestedModifier) const {
858 bool isOutput = (Constraint[0] == '=');
859 bool isInOut = (Constraint[0] == '+');
860
861 // Strip off constraint modifiers.
862 while (Constraint[0] == '=' || Constraint[0] == '+' || Constraint[0] == '&')
863 Constraint = Constraint.substr(1);
864
865 switch (Constraint[0]) {
866 default:
867 break;
868 case 'r': {
869 switch (Modifier) {
870 default:
871 return (isInOut || isOutput || Size <= 64);
872 case 'q':
873 // A register of size 32 cannot fit a vector type.
874 return false;
875 }
Erich Keaneebba5922017-07-21 22:37:03 +0000876 }
Tim Northoverad4c5db2017-07-24 17:06:23 +0000877 }
Erich Keaneebba5922017-07-21 22:37:03 +0000878
879 return true;
880}
Tim Northoverad4c5db2017-07-24 17:06:23 +0000881const char *ARMTargetInfo::getClobbers() const {
882 // FIXME: Is this really right?
883 return "";
Erich Keaneebba5922017-07-21 22:37:03 +0000884}
885
Tim Northoverad4c5db2017-07-24 17:06:23 +0000886TargetInfo::CallingConvCheckResult
887ARMTargetInfo::checkCallingConvention(CallingConv CC) const {
888 switch (CC) {
889 case CC_AAPCS:
890 case CC_AAPCS_VFP:
891 case CC_Swift:
892 case CC_OpenCLKernel:
893 return CCCR_OK;
894 default:
895 return CCCR_Warning;
896 }
897}
898
899int ARMTargetInfo::getEHDataRegisterNumber(unsigned RegNo) const {
900 if (RegNo == 0)
901 return 0;
902 if (RegNo == 1)
903 return 1;
904 return -1;
905}
906
907bool ARMTargetInfo::hasSjLjLowering() const { return true; }
908
909ARMleTargetInfo::ARMleTargetInfo(const llvm::Triple &Triple,
910 const TargetOptions &Opts)
911 : ARMTargetInfo(Triple, Opts) {}
912
Erich Keaneebba5922017-07-21 22:37:03 +0000913void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
914 MacroBuilder &Builder) const {
915 Builder.defineMacro("__ARMEL__");
916 ARMTargetInfo::getTargetDefines(Opts, Builder);
917}
918
Tim Northoverad4c5db2017-07-24 17:06:23 +0000919ARMbeTargetInfo::ARMbeTargetInfo(const llvm::Triple &Triple,
920 const TargetOptions &Opts)
921 : ARMTargetInfo(Triple, Opts) {}
922
Erich Keaneebba5922017-07-21 22:37:03 +0000923void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
924 MacroBuilder &Builder) const {
925 Builder.defineMacro("__ARMEB__");
926 Builder.defineMacro("__ARM_BIG_ENDIAN");
927 ARMTargetInfo::getTargetDefines(Opts, Builder);
928}
929
Tim Northoverad4c5db2017-07-24 17:06:23 +0000930WindowsARMTargetInfo::WindowsARMTargetInfo(const llvm::Triple &Triple,
931 const TargetOptions &Opts)
932 : WindowsTargetInfo<ARMleTargetInfo>(Triple, Opts), Triple(Triple) {
933 WCharType = UnsignedShort;
934 SizeType = UnsignedInt;
935}
936
Erich Keaneebba5922017-07-21 22:37:03 +0000937void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
938 MacroBuilder &Builder) const {
939 WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder);
940
941 // FIXME: this is invalid for WindowsCE
942 Builder.defineMacro("_M_ARM_NT", "1");
943 Builder.defineMacro("_M_ARMT", "_M_ARM");
944 Builder.defineMacro("_M_THUMB", "_M_ARM");
945
946 assert((Triple.getArch() == llvm::Triple::arm ||
947 Triple.getArch() == llvm::Triple::thumb) &&
948 "invalid architecture for Windows ARM target info");
949 unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
950 Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
951
952 // TODO map the complete set of values
953 // 31: VFPv3 40: VFPv4
954 Builder.defineMacro("_M_ARM_FP", "31");
955}
956
Tim Northoverad4c5db2017-07-24 17:06:23 +0000957TargetInfo::BuiltinVaListKind
958WindowsARMTargetInfo::getBuiltinVaListKind() const {
959 return TargetInfo::CharPtrBuiltinVaList;
960}
961
962TargetInfo::CallingConvCheckResult
963WindowsARMTargetInfo::checkCallingConvention(CallingConv CC) const {
964 switch (CC) {
965 case CC_X86StdCall:
966 case CC_X86ThisCall:
967 case CC_X86FastCall:
968 case CC_X86VectorCall:
969 return CCCR_Ignore;
970 case CC_C:
971 case CC_OpenCLKernel:
972 return CCCR_OK;
973 default:
974 return CCCR_Warning;
975 }
976}
977
978// Windows ARM + Itanium C++ ABI Target
979ItaniumWindowsARMleTargetInfo::ItaniumWindowsARMleTargetInfo(
980 const llvm::Triple &Triple, const TargetOptions &Opts)
981 : WindowsARMTargetInfo(Triple, Opts) {
982 TheCXXABI.set(TargetCXXABI::GenericARM);
983}
984
985void ItaniumWindowsARMleTargetInfo::getTargetDefines(
986 const LangOptions &Opts, MacroBuilder &Builder) const {
987 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
988
989 if (Opts.MSVCCompat)
990 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
991}
992
993// Windows ARM, MS (C++) ABI
994MicrosoftARMleTargetInfo::MicrosoftARMleTargetInfo(const llvm::Triple &Triple,
995 const TargetOptions &Opts)
996 : WindowsARMTargetInfo(Triple, Opts) {
997 TheCXXABI.set(TargetCXXABI::Microsoft);
998}
999
1000void MicrosoftARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
1001 MacroBuilder &Builder) const {
1002 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1003 WindowsARMTargetInfo::getVisualStudioDefines(Opts, Builder);
1004}
1005
1006MinGWARMTargetInfo::MinGWARMTargetInfo(const llvm::Triple &Triple,
1007 const TargetOptions &Opts)
1008 : WindowsARMTargetInfo(Triple, Opts) {
1009 TheCXXABI.set(TargetCXXABI::GenericARM);
1010}
1011
Erich Keaneebba5922017-07-21 22:37:03 +00001012void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
1013 MacroBuilder &Builder) const {
1014 WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
1015 DefineStd(Builder, "WIN32", Opts);
1016 DefineStd(Builder, "WINNT", Opts);
1017 Builder.defineMacro("_ARM_");
1018 addMinGWDefines(Opts, Builder);
1019}
1020
Tim Northoverad4c5db2017-07-24 17:06:23 +00001021CygwinARMTargetInfo::CygwinARMTargetInfo(const llvm::Triple &Triple,
1022 const TargetOptions &Opts)
1023 : ARMleTargetInfo(Triple, Opts) {
1024 TLSSupported = false;
1025 WCharType = UnsignedShort;
1026 DoubleAlign = LongLongAlign = 64;
1027 resetDataLayout("e-m:e-p:32:32-i64:64-v128:64:128-a:0:32-n32-S64");
1028}
1029
Erich Keaneebba5922017-07-21 22:37:03 +00001030void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
1031 MacroBuilder &Builder) const {
1032 ARMleTargetInfo::getTargetDefines(Opts, Builder);
1033 Builder.defineMacro("_ARM_");
1034 Builder.defineMacro("__CYGWIN__");
1035 Builder.defineMacro("__CYGWIN32__");
1036 DefineStd(Builder, "unix", Opts);
1037 if (Opts.CPlusPlus)
1038 Builder.defineMacro("_GNU_SOURCE");
1039}
1040
Tim Northoverad4c5db2017-07-24 17:06:23 +00001041DarwinARMTargetInfo::DarwinARMTargetInfo(const llvm::Triple &Triple,
1042 const TargetOptions &Opts)
1043 : DarwinTargetInfo<ARMleTargetInfo>(Triple, Opts) {
1044 HasAlignMac68kSupport = true;
1045 // iOS always has 64-bit atomic instructions.
1046 // FIXME: This should be based off of the target features in
1047 // ARMleTargetInfo.
1048 MaxAtomicInlineWidth = 64;
1049
1050 if (Triple.isWatchABI()) {
1051 // Darwin on iOS uses a variant of the ARM C++ ABI.
1052 TheCXXABI.set(TargetCXXABI::WatchOS);
1053
1054 // The 32-bit ABI is silent on what ptrdiff_t should be, but given that
1055 // size_t is long, it's a bit weird for it to be int.
1056 PtrDiffType = SignedLong;
1057
1058 // BOOL should be a real boolean on the new ABI
1059 UseSignedCharForObjCBool = false;
1060 } else
1061 TheCXXABI.set(TargetCXXABI::iOS);
1062}
1063
1064void DarwinARMTargetInfo::getOSDefines(const LangOptions &Opts,
1065 const llvm::Triple &Triple,
1066 MacroBuilder &Builder) const {
1067 getDarwinDefines(Builder, Opts, Triple, PlatformName, PlatformMinVersion);
1068}
1069
1070RenderScript32TargetInfo::RenderScript32TargetInfo(const llvm::Triple &Triple,
1071 const TargetOptions &Opts)
1072 : ARMleTargetInfo(llvm::Triple("armv7", Triple.getVendorName(),
1073 Triple.getOSName(),
1074 Triple.getEnvironmentName()),
1075 Opts) {
1076 IsRenderScriptTarget = true;
1077 LongWidth = LongAlign = 64;
1078}
1079
Erich Keaneebba5922017-07-21 22:37:03 +00001080void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,
1081 MacroBuilder &Builder) const {
1082 Builder.defineMacro("__RENDERSCRIPT__");
1083 ARMleTargetInfo::getTargetDefines(Opts, Builder);
1084}