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