1 //===--- 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 
22 using namespace clang;
23 using namespace clang::targets;
24 
25 bool ARMTargetInfo::setFPMath(StringRef Name) {
26   if (Name == "neon") {
27     FPMath = FP_Neon;
28     return true;
29   } else if (Name == "vfp" || Name == "vfp2" || Name == "vfp3" ||
30              Name == "vfp4") {
31     FPMath = FP_VFP;
32     return true;
33   }
34   return false;
35 }
36 
37 const char *const ARMTargetInfo::GCCRegNames[] = {
38     // Integer registers
39     "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", "r8", "r9", "r10", "r11",
40     "r12", "sp", "lr", "pc",
41 
42     // Float registers
43     "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8", "s9", "s10", "s11",
44     "s12", "s13", "s14", "s15", "s16", "s17", "s18", "s19", "s20", "s21", "s22",
45     "s23", "s24", "s25", "s26", "s27", "s28", "s29", "s30", "s31",
46 
47     // Double registers
48     "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", "d8", "d9", "d10", "d11",
49     "d12", "d13", "d14", "d15", "d16", "d17", "d18", "d19", "d20", "d21", "d22",
50     "d23", "d24", "d25", "d26", "d27", "d28", "d29", "d30", "d31",
51 
52     // Quad registers
53     "q0", "q1", "q2", "q3", "q4", "q5", "q6", "q7", "q8", "q9", "q10", "q11",
54     "q12", "q13", "q14", "q15"
55 };
56 
57 ArrayRef<const char *> ARMTargetInfo::getGCCRegNames() const {
58   return llvm::makeArrayRef(GCCRegNames);
59 }
60 
61 const TargetInfo::GCCRegAlias ARMTargetInfo::GCCRegAliases[] = {
62     {{"a1"}, "r0"},  {{"a2"}, "r1"},        {{"a3"}, "r2"},  {{"a4"}, "r3"},
63     {{"v1"}, "r4"},  {{"v2"}, "r5"},        {{"v3"}, "r6"},  {{"v4"}, "r7"},
64     {{"v5"}, "r8"},  {{"v6", "rfp"}, "r9"}, {{"sl"}, "r10"}, {{"fp"}, "r11"},
65     {{"ip"}, "r12"}, {{"r13"}, "sp"},       {{"r14"}, "lr"}, {{"r15"}, "pc"},
66     // The S, D and Q registers overlap, but aren't really aliases; we
67     // don't want to substitute one of these for a different-sized one.
68 };
69 
70 ArrayRef<TargetInfo::GCCRegAlias> ARMTargetInfo::getGCCRegAliases() const {
71   return llvm::makeArrayRef(GCCRegAliases);
72 }
73 
74 const Builtin::Info ARMTargetInfo::BuiltinInfo[] = {
75 #define BUILTIN(ID, TYPE, ATTRS)                                               \
76   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
77 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
78   {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
79 #include "clang/Basic/BuiltinsNEON.def"
80 
81 #define BUILTIN(ID, TYPE, ATTRS)                                               \
82   {#ID, TYPE, ATTRS, nullptr, ALL_LANGUAGES, nullptr},
83 #define LANGBUILTIN(ID, TYPE, ATTRS, LANG)                                     \
84   {#ID, TYPE, ATTRS, nullptr, LANG, nullptr},
85 #define LIBBUILTIN(ID, TYPE, ATTRS, HEADER)                                    \
86   {#ID, TYPE, ATTRS, HEADER, ALL_LANGUAGES, nullptr},
87 #define TARGET_HEADER_BUILTIN(ID, TYPE, ATTRS, HEADER, LANGS, FEATURE)         \
88   {#ID, TYPE, ATTRS, HEADER, LANGS, FEATURE},
89 #include "clang/Basic/BuiltinsARM.def"
90 };
91 
92 bool ARMTargetInfo::hasFeature(StringRef Feature) const {
93   return llvm::StringSwitch<bool>(Feature)
94       .Case("arm", true)
95       .Case("aarch32", true)
96       .Case("softfloat", SoftFloat)
97       .Case("thumb", isThumb())
98       .Case("neon", (FPU & NeonFPU) && !SoftFloat)
99       .Case("vfp", FPU && !SoftFloat)
100       .Case("hwdiv", HWDiv & HWDivThumb)
101       .Case("hwdiv-arm", HWDiv & HWDivARM)
102       .Default(false);
103 }
104 
105 void ARMTargetInfo::getTargetDefines(const LangOptions &Opts,
106                                      MacroBuilder &Builder) const {
107   // Target identification.
108   Builder.defineMacro("__arm");
109   Builder.defineMacro("__arm__");
110   // For bare-metal none-eabi.
111   if (getTriple().getOS() == llvm::Triple::UnknownOS &&
112       (getTriple().getEnvironment() == llvm::Triple::EABI ||
113        getTriple().getEnvironment() == llvm::Triple::EABIHF))
114     Builder.defineMacro("__ELF__");
115 
116   // Target properties.
117   Builder.defineMacro("__REGISTER_PREFIX__", "");
118 
119   // Unfortunately, __ARM_ARCH_7K__ is now more of an ABI descriptor. The CPU
120   // happens to be Cortex-A7 though, so it should still get __ARM_ARCH_7A__.
121   if (getTriple().isWatchABI())
122     Builder.defineMacro("__ARM_ARCH_7K__", "2");
123 
124   if (!CPUAttr.empty())
125     Builder.defineMacro("__ARM_ARCH_" + CPUAttr + "__");
126 
127   // ACLE 6.4.1 ARM/Thumb instruction set architecture
128   // __ARM_ARCH is defined as an integer value indicating the current ARM ISA
129   Builder.defineMacro("__ARM_ARCH", Twine(ArchVersion));
130 
131   if (ArchVersion >= 8) {
132     // ACLE 6.5.7 Crypto Extension
133     if (Crypto)
134       Builder.defineMacro("__ARM_FEATURE_CRYPTO", "1");
135     // ACLE 6.5.8 CRC32 Extension
136     if (CRC)
137       Builder.defineMacro("__ARM_FEATURE_CRC32", "1");
138     // ACLE 6.5.10 Numeric Maximum and Minimum
139     Builder.defineMacro("__ARM_FEATURE_NUMERIC_MAXMIN", "1");
140     // ACLE 6.5.9 Directed Rounding
141     Builder.defineMacro("__ARM_FEATURE_DIRECTED_ROUNDING", "1");
142   }
143 
144   // __ARM_ARCH_ISA_ARM is defined to 1 if the core supports the ARM ISA.  It
145   // is not defined for the M-profile.
146   // NOTE that the default profile is assumed to be 'A'
147   if (CPUProfile.empty() || ArchProfile != llvm::ARM::PK_M)
148     Builder.defineMacro("__ARM_ARCH_ISA_ARM", "1");
149 
150   // __ARM_ARCH_ISA_THUMB is defined to 1 if the core supports the original
151   // Thumb ISA (including v6-M and v8-M Baseline).  It is set to 2 if the
152   // core supports the Thumb-2 ISA as found in the v6T2 architecture and all
153   // v7 and v8 architectures excluding v8-M Baseline.
154   if (supportsThumb2())
155     Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "2");
156   else if (supportsThumb())
157     Builder.defineMacro("__ARM_ARCH_ISA_THUMB", "1");
158 
159   // __ARM_32BIT_STATE is defined to 1 if code is being generated for a 32-bit
160   // instruction set such as ARM or Thumb.
161   Builder.defineMacro("__ARM_32BIT_STATE", "1");
162 
163   // ACLE 6.4.2 Architectural Profile (A, R, M or pre-Cortex)
164 
165   // __ARM_ARCH_PROFILE is defined as 'A', 'R', 'M' or 'S', or unset.
166   if (!CPUProfile.empty())
167     Builder.defineMacro("__ARM_ARCH_PROFILE", "'" + CPUProfile + "'");
168 
169   // ACLE 6.4.3 Unaligned access supported in hardware
170   if (Unaligned)
171     Builder.defineMacro("__ARM_FEATURE_UNALIGNED", "1");
172 
173   // ACLE 6.4.4 LDREX/STREX
174   if (LDREX)
175     Builder.defineMacro("__ARM_FEATURE_LDREX", "0x" + llvm::utohexstr(LDREX));
176 
177   // ACLE 6.4.5 CLZ
178   if (ArchVersion == 5 || (ArchVersion == 6 && CPUProfile != "M") ||
179       ArchVersion > 6)
180     Builder.defineMacro("__ARM_FEATURE_CLZ", "1");
181 
182   // ACLE 6.5.1 Hardware Floating Point
183   if (HW_FP)
184     Builder.defineMacro("__ARM_FP", "0x" + llvm::utohexstr(HW_FP));
185 
186   // ACLE predefines.
187   Builder.defineMacro("__ARM_ACLE", "200");
188 
189   // FP16 support (we currently only support IEEE format).
190   Builder.defineMacro("__ARM_FP16_FORMAT_IEEE", "1");
191   Builder.defineMacro("__ARM_FP16_ARGS", "1");
192 
193   // ACLE 6.5.3 Fused multiply-accumulate (FMA)
194   if (ArchVersion >= 7 && (FPU & VFP4FPU))
195     Builder.defineMacro("__ARM_FEATURE_FMA", "1");
196 
197   // Subtarget options.
198 
199   // FIXME: It's more complicated than this and we don't really support
200   // interworking.
201   // Windows on ARM does not "support" interworking
202   if (5 <= ArchVersion && ArchVersion <= 8 && !getTriple().isOSWindows())
203     Builder.defineMacro("__THUMB_INTERWORK__");
204 
205   if (ABI == "aapcs" || ABI == "aapcs-linux" || ABI == "aapcs-vfp") {
206     // Embedded targets on Darwin follow AAPCS, but not EABI.
207     // Windows on ARM follows AAPCS VFP, but does not conform to EABI.
208     if (!getTriple().isOSBinFormatMachO() && !getTriple().isOSWindows())
209       Builder.defineMacro("__ARM_EABI__");
210     Builder.defineMacro("__ARM_PCS", "1");
211   }
212 
213   if ((!SoftFloat && !SoftFloatABI) || ABI == "aapcs-vfp" || ABI == "aapcs16")
214     Builder.defineMacro("__ARM_PCS_VFP", "1");
215 
216   if (SoftFloat)
217     Builder.defineMacro("__SOFTFP__");
218 
219   if (ArchKind == llvm::ARM::AK_XSCALE)
220     Builder.defineMacro("__XSCALE__");
221 
222   if (isThumb()) {
223     Builder.defineMacro("__THUMBEL__");
224     Builder.defineMacro("__thumb__");
225     if (supportsThumb2())
226       Builder.defineMacro("__thumb2__");
227   }
228 
229   // ACLE 6.4.9 32-bit SIMD instructions
230   if (ArchVersion >= 6 && (CPUProfile != "M" || CPUAttr == "7EM"))
231     Builder.defineMacro("__ARM_FEATURE_SIMD32", "1");
232 
233   // ACLE 6.4.10 Hardware Integer Divide
234   if (((HWDiv & HWDivThumb) && isThumb()) ||
235       ((HWDiv & HWDivARM) && !isThumb())) {
236     Builder.defineMacro("__ARM_FEATURE_IDIV", "1");
237     Builder.defineMacro("__ARM_ARCH_EXT_IDIV__", "1");
238   }
239 
240   // Note, this is always on in gcc, even though it doesn't make sense.
241   Builder.defineMacro("__APCS_32__");
242 
243   if (FPUModeIsVFP((FPUMode)FPU)) {
244     Builder.defineMacro("__VFP_FP__");
245     if (FPU & VFP2FPU)
246       Builder.defineMacro("__ARM_VFPV2__");
247     if (FPU & VFP3FPU)
248       Builder.defineMacro("__ARM_VFPV3__");
249     if (FPU & VFP4FPU)
250       Builder.defineMacro("__ARM_VFPV4__");
251     if (FPU & FPARMV8)
252       Builder.defineMacro("__ARM_FPV5__");
253   }
254 
255   // This only gets set when Neon instructions are actually available, unlike
256   // the VFP define, hence the soft float and arch check. This is subtly
257   // different from gcc, we follow the intent which was that it should be set
258   // when Neon instructions are actually available.
259   if ((FPU & NeonFPU) && !SoftFloat && ArchVersion >= 7) {
260     Builder.defineMacro("__ARM_NEON", "1");
261     Builder.defineMacro("__ARM_NEON__");
262     // current AArch32 NEON implementations do not support double-precision
263     // floating-point even when it is present in VFP.
264     Builder.defineMacro("__ARM_NEON_FP",
265                         "0x" + llvm::utohexstr(HW_FP & ~HW_FP_DP));
266   }
267 
268   Builder.defineMacro("__ARM_SIZEOF_WCHAR_T", Opts.ShortWChar ? "2" : "4");
269 
270   Builder.defineMacro("__ARM_SIZEOF_MINIMAL_ENUM", Opts.ShortEnums ? "1" : "4");
271 
272   if (ArchVersion >= 6 && CPUAttr != "6M" && CPUAttr != "8M_BASE") {
273     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_1");
274     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_2");
275     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_4");
276     Builder.defineMacro("__GCC_HAVE_SYNC_COMPARE_AND_SWAP_8");
277   }
278 
279   // ACLE 6.4.7 DSP instructions
280   if (DSP) {
281     Builder.defineMacro("__ARM_FEATURE_DSP", "1");
282   }
283 
284   // ACLE 6.4.8 Saturation instructions
285   bool SAT = false;
286   if ((ArchVersion == 6 && CPUProfile != "M") || ArchVersion > 6) {
287     Builder.defineMacro("__ARM_FEATURE_SAT", "1");
288     SAT = true;
289   }
290 
291   // ACLE 6.4.6 Q (saturation) flag
292   if (DSP || SAT)
293     Builder.defineMacro("__ARM_FEATURE_QBIT", "1");
294 
295   if (Opts.UnsafeFPMath)
296     Builder.defineMacro("__ARM_FP_FAST", "1");
297 
298   switch (ArchKind) {
299   default:
300     break;
301   case llvm::ARM::AK_ARMV8_1A:
302     getTargetDefinesARMV81A(Opts, Builder);
303     break;
304   case llvm::ARM::AK_ARMV8_2A:
305     getTargetDefinesARMV82A(Opts, Builder);
306     break;
307   }
308 }
309 
310 bool ARMTargetInfo::handleTargetFeatures(std::vector<std::string> &Features,
311                                          DiagnosticsEngine &Diags) {
312   FPU = 0;
313   CRC = 0;
314   Crypto = 0;
315   DSP = 0;
316   Unaligned = 1;
317   SoftFloat = SoftFloatABI = false;
318   HWDiv = 0;
319 
320   // This does not diagnose illegal cases like having both
321   // "+vfpv2" and "+vfpv3" or having "+neon" and "+fp-only-sp".
322   uint32_t HW_FP_remove = 0;
323   for (const auto &Feature : Features) {
324     if (Feature == "+soft-float") {
325       SoftFloat = true;
326     } else if (Feature == "+soft-float-abi") {
327       SoftFloatABI = true;
328     } else if (Feature == "+vfp2") {
329       FPU |= VFP2FPU;
330       HW_FP |= HW_FP_SP | HW_FP_DP;
331     } else if (Feature == "+vfp3") {
332       FPU |= VFP3FPU;
333       HW_FP |= HW_FP_SP | HW_FP_DP;
334     } else if (Feature == "+vfp4") {
335       FPU |= VFP4FPU;
336       HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
337     } else if (Feature == "+fp-armv8") {
338       FPU |= FPARMV8;
339       HW_FP |= HW_FP_SP | HW_FP_DP | HW_FP_HP;
340     } else if (Feature == "+neon") {
341       FPU |= NeonFPU;
342       HW_FP |= HW_FP_SP | HW_FP_DP;
343     } else if (Feature == "+hwdiv") {
344       HWDiv |= HWDivThumb;
345     } else if (Feature == "+hwdiv-arm") {
346       HWDiv |= HWDivARM;
347     } else if (Feature == "+crc") {
348       CRC = 1;
349     } else if (Feature == "+crypto") {
350       Crypto = 1;
351     } else if (Feature == "+dsp") {
352       DSP = 1;
353     } else if (Feature == "+fp-only-sp") {
354       HW_FP_remove |= HW_FP_DP;
355     } else if (Feature == "+strict-align") {
356       Unaligned = 0;
357     } else if (Feature == "+fp16") {
358       HW_FP |= HW_FP_HP;
359     }
360   }
361   HW_FP &= ~HW_FP_remove;
362 
363   switch (ArchVersion) {
364   case 6:
365     if (ArchProfile == llvm::ARM::PK_M)
366       LDREX = 0;
367     else if (ArchKind == llvm::ARM::AK_ARMV6K)
368       LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
369     else
370       LDREX = LDREX_W;
371     break;
372   case 7:
373     if (ArchProfile == llvm::ARM::PK_M)
374       LDREX = LDREX_W | LDREX_H | LDREX_B;
375     else
376       LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
377     break;
378   case 8:
379     LDREX = LDREX_D | LDREX_W | LDREX_H | LDREX_B;
380   }
381 
382   if (!(FPU & NeonFPU) && FPMath == FP_Neon) {
383     Diags.Report(diag::err_target_unsupported_fpmath) << "neon";
384     return false;
385   }
386 
387   if (FPMath == FP_Neon)
388     Features.push_back("+neonfp");
389   else if (FPMath == FP_VFP)
390     Features.push_back("-neonfp");
391 
392   // Remove front-end specific options which the backend handles differently.
393   auto Feature = std::find(Features.begin(), Features.end(), "+soft-float-abi");
394   if (Feature != Features.end())
395     Features.erase(Feature);
396 
397   return true;
398 }
399 
400 void ARMTargetInfo::getTargetDefinesARMV81A(const LangOptions &Opts,
401                                             MacroBuilder &Builder) const {
402   Builder.defineMacro("__ARM_FEATURE_QRDMX", "1");
403 }
404 
405 void ARMleTargetInfo::getTargetDefines(const LangOptions &Opts,
406                                        MacroBuilder &Builder) const {
407   Builder.defineMacro("__ARMEL__");
408   ARMTargetInfo::getTargetDefines(Opts, Builder);
409 }
410 
411 void ARMbeTargetInfo::getTargetDefines(const LangOptions &Opts,
412                                        MacroBuilder &Builder) const {
413   Builder.defineMacro("__ARMEB__");
414   Builder.defineMacro("__ARM_BIG_ENDIAN");
415   ARMTargetInfo::getTargetDefines(Opts, Builder);
416 }
417 
418 void WindowsARMTargetInfo::getVisualStudioDefines(const LangOptions &Opts,
419                                                   MacroBuilder &Builder) const {
420   WindowsTargetInfo<ARMleTargetInfo>::getVisualStudioDefines(Opts, Builder);
421 
422   // FIXME: this is invalid for WindowsCE
423   Builder.defineMacro("_M_ARM_NT", "1");
424   Builder.defineMacro("_M_ARMT", "_M_ARM");
425   Builder.defineMacro("_M_THUMB", "_M_ARM");
426 
427   assert((Triple.getArch() == llvm::Triple::arm ||
428           Triple.getArch() == llvm::Triple::thumb) &&
429          "invalid architecture for Windows ARM target info");
430   unsigned Offset = Triple.getArch() == llvm::Triple::arm ? 4 : 6;
431   Builder.defineMacro("_M_ARM", Triple.getArchName().substr(Offset));
432 
433   // TODO map the complete set of values
434   // 31: VFPv3 40: VFPv4
435   Builder.defineMacro("_M_ARM_FP", "31");
436 }
437 
438 void MinGWARMTargetInfo::getTargetDefines(const LangOptions &Opts,
439                                           MacroBuilder &Builder) const {
440   WindowsARMTargetInfo::getTargetDefines(Opts, Builder);
441   DefineStd(Builder, "WIN32", Opts);
442   DefineStd(Builder, "WINNT", Opts);
443   Builder.defineMacro("_ARM_");
444   addMinGWDefines(Opts, Builder);
445 }
446 
447 void CygwinARMTargetInfo::getTargetDefines(const LangOptions &Opts,
448                                            MacroBuilder &Builder) const {
449   ARMleTargetInfo::getTargetDefines(Opts, Builder);
450   Builder.defineMacro("_ARM_");
451   Builder.defineMacro("__CYGWIN__");
452   Builder.defineMacro("__CYGWIN32__");
453   DefineStd(Builder, "unix", Opts);
454   if (Opts.CPlusPlus)
455     Builder.defineMacro("_GNU_SOURCE");
456 }
457 
458 void RenderScript32TargetInfo::getTargetDefines(const LangOptions &Opts,
459                                                 MacroBuilder &Builder) const {
460   Builder.defineMacro("__RENDERSCRIPT__");
461   ARMleTargetInfo::getTargetDefines(Opts, Builder);
462 }
463 
464 ArrayRef<Builtin::Info> ARMTargetInfo::getTargetBuiltins() const {
465   return llvm::makeArrayRef(BuiltinInfo, clang::ARM::LastTSBuiltin -
466                                              Builtin::FirstTSBuiltin);
467 }
468