1 //===- ARMAttributeParser.cpp - ARM Attribute Information Printer ---------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "llvm/Support/ARMAttributeParser.h"
10 #include "llvm/ADT/STLArrayExtras.h"
11 #include "llvm/ADT/StringExtras.h"
12 #include "llvm/Support/ScopedPrinter.h"
13 
14 using namespace llvm;
15 using namespace llvm::ARMBuildAttrs;
16 
17 #define ATTRIBUTE_HANDLER(attr)                                                \
18   { ARMBuildAttrs::attr, &ARMAttributeParser::attr }
19 
20 const ARMAttributeParser::DisplayHandler ARMAttributeParser::displayRoutines[] =
21     {
22         {ARMBuildAttrs::CPU_raw_name, &ARMAttributeParser::stringAttribute},
23         {ARMBuildAttrs::CPU_name, &ARMAttributeParser::stringAttribute},
24         ATTRIBUTE_HANDLER(CPU_arch),
25         ATTRIBUTE_HANDLER(CPU_arch_profile),
26         ATTRIBUTE_HANDLER(ARM_ISA_use),
27         ATTRIBUTE_HANDLER(THUMB_ISA_use),
28         ATTRIBUTE_HANDLER(FP_arch),
29         ATTRIBUTE_HANDLER(WMMX_arch),
30         ATTRIBUTE_HANDLER(Advanced_SIMD_arch),
31         ATTRIBUTE_HANDLER(MVE_arch),
32         ATTRIBUTE_HANDLER(PCS_config),
33         ATTRIBUTE_HANDLER(ABI_PCS_R9_use),
34         ATTRIBUTE_HANDLER(ABI_PCS_RW_data),
35         ATTRIBUTE_HANDLER(ABI_PCS_RO_data),
36         ATTRIBUTE_HANDLER(ABI_PCS_GOT_use),
37         ATTRIBUTE_HANDLER(ABI_PCS_wchar_t),
38         ATTRIBUTE_HANDLER(ABI_FP_rounding),
39         ATTRIBUTE_HANDLER(ABI_FP_denormal),
40         ATTRIBUTE_HANDLER(ABI_FP_exceptions),
41         ATTRIBUTE_HANDLER(ABI_FP_user_exceptions),
42         ATTRIBUTE_HANDLER(ABI_FP_number_model),
43         ATTRIBUTE_HANDLER(ABI_align_needed),
44         ATTRIBUTE_HANDLER(ABI_align_preserved),
45         ATTRIBUTE_HANDLER(ABI_enum_size),
46         ATTRIBUTE_HANDLER(ABI_HardFP_use),
47         ATTRIBUTE_HANDLER(ABI_VFP_args),
48         ATTRIBUTE_HANDLER(ABI_WMMX_args),
49         ATTRIBUTE_HANDLER(ABI_optimization_goals),
50         ATTRIBUTE_HANDLER(ABI_FP_optimization_goals),
51         ATTRIBUTE_HANDLER(compatibility),
52         ATTRIBUTE_HANDLER(CPU_unaligned_access),
53         ATTRIBUTE_HANDLER(FP_HP_extension),
54         ATTRIBUTE_HANDLER(ABI_FP_16bit_format),
55         ATTRIBUTE_HANDLER(MPextension_use),
56         ATTRIBUTE_HANDLER(DIV_use),
57         ATTRIBUTE_HANDLER(DSP_extension),
58         ATTRIBUTE_HANDLER(T2EE_use),
59         ATTRIBUTE_HANDLER(Virtualization_use),
60         ATTRIBUTE_HANDLER(PAC_extension),
61         ATTRIBUTE_HANDLER(BTI_extension),
62         ATTRIBUTE_HANDLER(PACRET_use),
63         ATTRIBUTE_HANDLER(BTI_use),
64         ATTRIBUTE_HANDLER(nodefaults),
65 };
66 
67 #undef ATTRIBUTE_HANDLER
68 
69 Error ARMAttributeParser::stringAttribute(AttrType tag) {
70   StringRef tagName =
71       ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
72   StringRef desc = de.getCStrRef(cursor);
73 
74   if (sw) {
75     DictScope scope(*sw, "Attribute");
76     sw->printNumber("Tag", tag);
77     if (!tagName.empty())
78       sw->printString("TagName", tagName);
79     sw->printString("Value", desc);
80   }
81   return Error::success();
82 }
83 
84 Error ARMAttributeParser::CPU_arch(AttrType tag) {
85   static const char *strings[] = {
86     "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", "ARM v6",
87     "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", "ARM v6S-M",
88     "ARM v7E-M", "ARM v8-A", "ARM v8-R",
89     "ARM v8-M Baseline", "ARM v8-M Mainline", nullptr, nullptr, nullptr,
90     "ARM v8.1-M Mainline", "ARM v9-A"
91   };
92   return parseStringAttribute("CPU_arch", tag, makeArrayRef(strings));
93 }
94 
95 Error ARMAttributeParser::CPU_arch_profile(AttrType tag) {
96   uint64_t value = de.getULEB128(cursor);
97 
98   StringRef profile;
99   switch (value) {
100   default: profile = "Unknown"; break;
101   case 'A': profile = "Application"; break;
102   case 'R': profile = "Real-time"; break;
103   case 'M': profile = "Microcontroller"; break;
104   case 'S': profile = "Classic"; break;
105   case 0: profile = "None"; break;
106   }
107 
108   printAttribute(tag, value, profile);
109   return Error::success();
110 }
111 
112 Error ARMAttributeParser::ARM_ISA_use(AttrType tag) {
113   static const char *strings[] = {"Not Permitted", "Permitted"};
114   return parseStringAttribute("ARM_ISA_use", tag, makeArrayRef(strings));
115 }
116 
117 Error ARMAttributeParser::THUMB_ISA_use(AttrType tag) {
118   static const char *strings[] = {"Not Permitted", "Thumb-1", "Thumb-2", "Permitted"};
119   return parseStringAttribute("THUMB_ISA_use", tag, makeArrayRef(strings));
120 }
121 
122 Error ARMAttributeParser::FP_arch(AttrType tag) {
123   static const char *strings[] = {
124       "Not Permitted", "VFPv1",     "VFPv2",      "VFPv3",         "VFPv3-D16",
125       "VFPv4",         "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16"};
126   return parseStringAttribute("FP_arch", tag, makeArrayRef(strings));
127 }
128 
129 Error ARMAttributeParser::WMMX_arch(AttrType tag) {
130   static const char *strings[] = {"Not Permitted", "WMMXv1", "WMMXv2"};
131   return parseStringAttribute("WMMX_arch", tag, makeArrayRef(strings));
132 }
133 
134 Error ARMAttributeParser::Advanced_SIMD_arch(AttrType tag) {
135   static const char *strings[] = {"Not Permitted", "NEONv1", "NEONv2+FMA",
136                                   "ARMv8-a NEON", "ARMv8.1-a NEON"};
137   return parseStringAttribute("Advanced_SIMD_arch", tag, makeArrayRef(strings));
138 }
139 
140 Error ARMAttributeParser::MVE_arch(AttrType tag) {
141   static const char *strings[] = {"Not Permitted", "MVE integer",
142                                   "MVE integer and float"};
143   return parseStringAttribute("MVE_arch", tag, makeArrayRef(strings));
144 }
145 
146 Error ARMAttributeParser::PCS_config(AttrType tag) {
147   static const char *strings[] = {
148     "None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004",
149     "Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)"};
150   return parseStringAttribute("PCS_config", tag, makeArrayRef(strings));
151 }
152 
153 Error ARMAttributeParser::ABI_PCS_R9_use(AttrType tag) {
154   static const char *strings[] = {"v6", "Static Base", "TLS", "Unused"};
155   return parseStringAttribute("ABI_PCS_R9_use", tag, makeArrayRef(strings));
156 }
157 
158 Error ARMAttributeParser::ABI_PCS_RW_data(AttrType tag) {
159   static const char *strings[] = {"Absolute", "PC-relative", "SB-relative",
160                                   "Not Permitted"};
161   return parseStringAttribute("ABI_PCS_RW_data", tag, makeArrayRef(strings));
162 }
163 
164 Error ARMAttributeParser::ABI_PCS_RO_data(AttrType tag) {
165   static const char *strings[] = {"Absolute", "PC-relative", "Not Permitted"};
166   return parseStringAttribute("ABI_PCS_RO_data", tag, makeArrayRef(strings));
167 }
168 
169 Error ARMAttributeParser::ABI_PCS_GOT_use(AttrType tag) {
170   static const char *strings[] = {"Not Permitted", "Direct", "GOT-Indirect"};
171   return parseStringAttribute("ABI_PCS_GOT_use", tag, makeArrayRef(strings));
172 }
173 
174 Error ARMAttributeParser::ABI_PCS_wchar_t(AttrType tag) {
175   static const char *strings[] = {"Not Permitted", "Unknown", "2-byte",
176                                   "Unknown", "4-byte"};
177   return parseStringAttribute("ABI_PCS_wchar_t", tag, makeArrayRef(strings));
178 }
179 
180 Error ARMAttributeParser::ABI_FP_rounding(AttrType tag) {
181   static const char *strings[] = {"IEEE-754", "Runtime"};
182   return parseStringAttribute("ABI_FP_rounding", tag, makeArrayRef(strings));
183 }
184 
185 Error ARMAttributeParser::ABI_FP_denormal(AttrType tag) {
186   static const char *strings[] = {"Unsupported", "IEEE-754", "Sign Only"};
187   return parseStringAttribute("ABI_FP_denormal", tag, makeArrayRef(strings));
188 }
189 
190 Error ARMAttributeParser::ABI_FP_exceptions(AttrType tag) {
191   static const char *strings[] = {"Not Permitted", "IEEE-754"};
192   return parseStringAttribute("ABI_FP_exceptions", tag, makeArrayRef(strings));
193 }
194 Error ARMAttributeParser::ABI_FP_user_exceptions(AttrType tag) {
195   static const char *strings[] = {"Not Permitted", "IEEE-754"};
196   return parseStringAttribute("ABI_FP_user_exceptions", tag,
197                               makeArrayRef(strings));
198 }
199 
200 Error ARMAttributeParser::ABI_FP_number_model(AttrType tag) {
201   static const char *strings[] = {"Not Permitted", "Finite Only", "RTABI",
202                                   "IEEE-754"};
203   return parseStringAttribute("ABI_FP_number_model", tag,
204                               makeArrayRef(strings));
205 }
206 
207 Error ARMAttributeParser::ABI_align_needed(AttrType tag) {
208   static const char *strings[] = {"Not Permitted", "8-byte alignment",
209                                   "4-byte alignment", "Reserved"};
210 
211   uint64_t value = de.getULEB128(cursor);
212 
213   std::string description;
214   if (value < array_lengthof(strings))
215     description = strings[value];
216   else if (value <= 12)
217     description = "8-byte alignment, " + utostr(1ULL << value) +
218                   "-byte extended alignment";
219   else
220     description = "Invalid";
221 
222   printAttribute(tag, value, description);
223   return Error::success();
224 }
225 
226 Error ARMAttributeParser::ABI_align_preserved(AttrType tag) {
227   static const char *strings[] = {"Not Required", "8-byte data alignment",
228                                   "8-byte data and code alignment", "Reserved"};
229 
230   uint64_t value = de.getULEB128(cursor);
231 
232   std::string description;
233   if (value < array_lengthof(strings))
234     description = std::string(strings[value]);
235   else if (value <= 12)
236     description = std::string("8-byte stack alignment, ") +
237                   utostr(1ULL << value) + std::string("-byte data alignment");
238   else
239     description = "Invalid";
240 
241   printAttribute(tag, value, description);
242   return Error::success();
243 }
244 
245 Error ARMAttributeParser::ABI_enum_size(AttrType tag) {
246   static const char *strings[] = {"Not Permitted", "Packed", "Int32",
247                                   "External Int32"};
248   return parseStringAttribute("ABI_enum_size", tag, makeArrayRef(strings));
249 }
250 
251 Error ARMAttributeParser::ABI_HardFP_use(AttrType tag) {
252   static const char *strings[] = {"Tag_FP_arch", "Single-Precision", "Reserved",
253                                   "Tag_FP_arch (deprecated)"};
254   return parseStringAttribute("ABI_HardFP_use", tag, makeArrayRef(strings));
255 }
256 
257 Error ARMAttributeParser::ABI_VFP_args(AttrType tag) {
258   static const char *strings[] = {"AAPCS", "AAPCS VFP", "Custom",
259                                   "Not Permitted"};
260   return parseStringAttribute("ABI_VFP_args", tag, makeArrayRef(strings));
261 }
262 
263 Error ARMAttributeParser::ABI_WMMX_args(AttrType tag) {
264   static const char *strings[] = {"AAPCS", "iWMMX", "Custom"};
265   return parseStringAttribute("ABI_WMMX_args", tag, makeArrayRef(strings));
266 }
267 
268 Error ARMAttributeParser::ABI_optimization_goals(AttrType tag) {
269   static const char *strings[] = {
270     "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Debugging",
271     "Best Debugging"
272   };
273   return parseStringAttribute("ABI_optimization_goals", tag,
274                               makeArrayRef(strings));
275 }
276 
277 Error ARMAttributeParser::ABI_FP_optimization_goals(AttrType tag) {
278   static const char *strings[] = {
279       "None",     "Speed",        "Aggressive Speed", "Size", "Aggressive Size",
280       "Accuracy", "Best Accuracy"};
281   return parseStringAttribute("ABI_FP_optimization_goals", tag,
282                               makeArrayRef(strings));
283 }
284 
285 Error ARMAttributeParser::compatibility(AttrType tag) {
286   uint64_t integer = de.getULEB128(cursor);
287   StringRef string = de.getCStrRef(cursor);
288 
289   if (sw) {
290     DictScope scope(*sw, "Attribute");
291     sw->printNumber("Tag", tag);
292     sw->startLine() << "Value: " << integer << ", " << string << '\n';
293     sw->printString("TagName",
294                     ELFAttrs::attrTypeAsString(tag, tagToStringMap,
295                                                /*hasTagPrefix=*/false));
296     switch (integer) {
297     case 0:
298       sw->printString("Description", StringRef("No Specific Requirements"));
299       break;
300     case 1:
301       sw->printString("Description", StringRef("AEABI Conformant"));
302       break;
303     default:
304       sw->printString("Description", StringRef("AEABI Non-Conformant"));
305       break;
306     }
307   }
308   return Error::success();
309 }
310 
311 Error ARMAttributeParser::CPU_unaligned_access(AttrType tag) {
312   static const char *strings[] = {"Not Permitted", "v6-style"};
313   return parseStringAttribute("CPU_unaligned_access", tag,
314                               makeArrayRef(strings));
315 }
316 
317 Error ARMAttributeParser::FP_HP_extension(AttrType tag) {
318   static const char *strings[] = {"If Available", "Permitted"};
319   return parseStringAttribute("FP_HP_extension", tag, makeArrayRef(strings));
320 }
321 
322 Error ARMAttributeParser::ABI_FP_16bit_format(AttrType tag) {
323   static const char *strings[] = {"Not Permitted", "IEEE-754", "VFPv3"};
324   return parseStringAttribute("ABI_FP_16bit_format", tag,
325                               makeArrayRef(strings));
326 }
327 
328 Error ARMAttributeParser::MPextension_use(AttrType tag) {
329   static const char *strings[] = {"Not Permitted", "Permitted"};
330   return parseStringAttribute("MPextension_use", tag, makeArrayRef(strings));
331 }
332 
333 Error ARMAttributeParser::DIV_use(AttrType tag) {
334   static const char *strings[] = {"If Available", "Not Permitted", "Permitted"};
335   return parseStringAttribute("DIV_use", tag, makeArrayRef(strings));
336 }
337 
338 Error ARMAttributeParser::DSP_extension(AttrType tag) {
339   static const char *strings[] = {"Not Permitted", "Permitted"};
340   return parseStringAttribute("DSP_extension", tag, makeArrayRef(strings));
341 }
342 
343 Error ARMAttributeParser::T2EE_use(AttrType tag) {
344   static const char *strings[] = {"Not Permitted", "Permitted"};
345   return parseStringAttribute("T2EE_use", tag, makeArrayRef(strings));
346 }
347 
348 Error ARMAttributeParser::Virtualization_use(AttrType tag) {
349   static const char *strings[] = {"Not Permitted", "TrustZone",
350                                   "Virtualization Extensions",
351                                   "TrustZone + Virtualization Extensions"};
352   return parseStringAttribute("Virtualization_use", tag, makeArrayRef(strings));
353 }
354 
355 Error ARMAttributeParser::PAC_extension(ARMBuildAttrs::AttrType tag) {
356   static const char *strings[] = {"Not Permitted", "Permitted in NOP space",
357                                   "Permitted"};
358   return parseStringAttribute("PAC_extension", tag, makeArrayRef(strings));
359 }
360 
361 Error ARMAttributeParser::BTI_extension(ARMBuildAttrs::AttrType tag) {
362   static const char *strings[] = {"Not Permitted", "Permitted in NOP space",
363                                   "Permitted"};
364   return parseStringAttribute("BTI_extension", tag, makeArrayRef(strings));
365 }
366 
367 Error ARMAttributeParser::PACRET_use(ARMBuildAttrs::AttrType tag) {
368   static const char *strings[] = {"Not Used", "Used"};
369   return parseStringAttribute("PACRET_use", tag, makeArrayRef(strings));
370 }
371 
372 Error ARMAttributeParser::BTI_use(ARMBuildAttrs::AttrType tag) {
373   static const char *strings[] = {"Not Used", "Used"};
374   return parseStringAttribute("BTI_use", tag, makeArrayRef(strings));
375 }
376 
377 Error ARMAttributeParser::nodefaults(AttrType tag) {
378   uint64_t value = de.getULEB128(cursor);
379   printAttribute(tag, value, "Unspecified Tags UNDEFINED");
380   return Error::success();
381 }
382 
383 Error ARMAttributeParser::handler(uint64_t tag, bool &handled) {
384   handled = false;
385   for (unsigned AHI = 0, AHE = array_lengthof(displayRoutines); AHI != AHE;
386        ++AHI) {
387     if (uint64_t(displayRoutines[AHI].attribute) == tag) {
388       if (Error e =
389               (this->*displayRoutines[AHI].routine)(static_cast<AttrType>(tag)))
390         return e;
391       handled = true;
392       break;
393     }
394   }
395 
396   return Error::success();
397 }
398