[clang][bytecode] Fix reporting failed local constexpr initializers (#123588)
[llvm-project.git] / llvm / lib / Support / ARMAttributeParser.cpp
blob43a11730b67ea9d0717496e3b51dccdfc3dc073e
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 //===----------------------------------------------------------------------===//
9 #include "llvm/Support/ARMAttributeParser.h"
10 #include "llvm/ADT/StringExtras.h"
11 #include "llvm/Support/ARMBuildAttributes.h"
12 #include "llvm/Support/Errc.h"
13 #include "llvm/Support/ScopedPrinter.h"
14 #include <optional>
16 using namespace llvm;
17 using namespace llvm::ARMBuildAttrs;
19 #define ATTRIBUTE_HANDLER(attr) \
20 { ARMBuildAttrs::attr, &ARMAttributeParser::attr }
22 const ARMAttributeParser::DisplayHandler ARMAttributeParser::displayRoutines[] =
24 {ARMBuildAttrs::CPU_raw_name, &ARMAttributeParser::stringAttribute},
25 {ARMBuildAttrs::CPU_name, &ARMAttributeParser::stringAttribute},
26 ATTRIBUTE_HANDLER(CPU_arch),
27 ATTRIBUTE_HANDLER(CPU_arch_profile),
28 ATTRIBUTE_HANDLER(ARM_ISA_use),
29 ATTRIBUTE_HANDLER(THUMB_ISA_use),
30 ATTRIBUTE_HANDLER(FP_arch),
31 ATTRIBUTE_HANDLER(WMMX_arch),
32 ATTRIBUTE_HANDLER(Advanced_SIMD_arch),
33 ATTRIBUTE_HANDLER(MVE_arch),
34 ATTRIBUTE_HANDLER(PCS_config),
35 ATTRIBUTE_HANDLER(ABI_PCS_R9_use),
36 ATTRIBUTE_HANDLER(ABI_PCS_RW_data),
37 ATTRIBUTE_HANDLER(ABI_PCS_RO_data),
38 ATTRIBUTE_HANDLER(ABI_PCS_GOT_use),
39 ATTRIBUTE_HANDLER(ABI_PCS_wchar_t),
40 ATTRIBUTE_HANDLER(ABI_FP_rounding),
41 ATTRIBUTE_HANDLER(ABI_FP_denormal),
42 ATTRIBUTE_HANDLER(ABI_FP_exceptions),
43 ATTRIBUTE_HANDLER(ABI_FP_user_exceptions),
44 ATTRIBUTE_HANDLER(ABI_FP_number_model),
45 ATTRIBUTE_HANDLER(ABI_align_needed),
46 ATTRIBUTE_HANDLER(ABI_align_preserved),
47 ATTRIBUTE_HANDLER(ABI_enum_size),
48 ATTRIBUTE_HANDLER(ABI_HardFP_use),
49 ATTRIBUTE_HANDLER(ABI_VFP_args),
50 ATTRIBUTE_HANDLER(ABI_WMMX_args),
51 ATTRIBUTE_HANDLER(ABI_optimization_goals),
52 ATTRIBUTE_HANDLER(ABI_FP_optimization_goals),
53 ATTRIBUTE_HANDLER(compatibility),
54 ATTRIBUTE_HANDLER(CPU_unaligned_access),
55 ATTRIBUTE_HANDLER(FP_HP_extension),
56 ATTRIBUTE_HANDLER(ABI_FP_16bit_format),
57 ATTRIBUTE_HANDLER(MPextension_use),
58 ATTRIBUTE_HANDLER(DIV_use),
59 ATTRIBUTE_HANDLER(DSP_extension),
60 ATTRIBUTE_HANDLER(T2EE_use),
61 ATTRIBUTE_HANDLER(Virtualization_use),
62 ATTRIBUTE_HANDLER(PAC_extension),
63 ATTRIBUTE_HANDLER(BTI_extension),
64 ATTRIBUTE_HANDLER(PACRET_use),
65 ATTRIBUTE_HANDLER(BTI_use),
66 ATTRIBUTE_HANDLER(nodefaults),
67 ATTRIBUTE_HANDLER(also_compatible_with),
70 #undef ATTRIBUTE_HANDLER
72 Error ARMAttributeParser::stringAttribute(AttrType tag) {
73 StringRef tagName =
74 ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
75 StringRef desc = de.getCStrRef(cursor);
77 if (sw) {
78 DictScope scope(*sw, "Attribute");
79 sw->printNumber("Tag", tag);
80 if (!tagName.empty())
81 sw->printString("TagName", tagName);
82 sw->printString("Value", desc);
84 return Error::success();
87 static const char *const CPU_arch_strings[] = {"Pre-v4",
88 "ARM v4",
89 "ARM v4T",
90 "ARM v5T",
91 "ARM v5TE",
92 "ARM v5TEJ",
93 "ARM v6",
94 "ARM v6KZ",
95 "ARM v6T2",
96 "ARM v6K",
97 "ARM v7",
98 "ARM v6-M",
99 "ARM v6S-M",
100 "ARM v7E-M",
101 "ARM v8-A",
102 "ARM v8-R",
103 "ARM v8-M Baseline",
104 "ARM v8-M Mainline",
105 nullptr,
106 nullptr,
107 nullptr,
108 "ARM v8.1-M Mainline",
109 "ARM v9-A"};
111 Error ARMAttributeParser::CPU_arch(AttrType tag) {
112 return parseStringAttribute("CPU_arch", tag, ArrayRef(CPU_arch_strings));
115 Error ARMAttributeParser::CPU_arch_profile(AttrType tag) {
116 uint64_t value = de.getULEB128(cursor);
118 StringRef profile;
119 switch (value) {
120 default: profile = "Unknown"; break;
121 case 'A': profile = "Application"; break;
122 case 'R': profile = "Real-time"; break;
123 case 'M': profile = "Microcontroller"; break;
124 case 'S': profile = "Classic"; break;
125 case 0: profile = "None"; break;
128 printAttribute(tag, value, profile);
129 return Error::success();
132 Error ARMAttributeParser::ARM_ISA_use(AttrType tag) {
133 static const char *const strings[] = {"Not Permitted", "Permitted"};
134 return parseStringAttribute("ARM_ISA_use", tag, ArrayRef(strings));
137 Error ARMAttributeParser::THUMB_ISA_use(AttrType tag) {
138 static const char *const strings[] = {"Not Permitted", "Thumb-1", "Thumb-2",
139 "Permitted"};
140 return parseStringAttribute("THUMB_ISA_use", tag, ArrayRef(strings));
143 Error ARMAttributeParser::FP_arch(AttrType tag) {
144 static const char *const strings[] = {
145 "Not Permitted", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16",
146 "VFPv4", "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16"};
147 return parseStringAttribute("FP_arch", tag, ArrayRef(strings));
150 Error ARMAttributeParser::WMMX_arch(AttrType tag) {
151 static const char *const strings[] = {"Not Permitted", "WMMXv1", "WMMXv2"};
152 return parseStringAttribute("WMMX_arch", tag, ArrayRef(strings));
155 Error ARMAttributeParser::Advanced_SIMD_arch(AttrType tag) {
156 static const char *const strings[] = {"Not Permitted", "NEONv1", "NEONv2+FMA",
157 "ARMv8-a NEON", "ARMv8.1-a NEON"};
158 return parseStringAttribute("Advanced_SIMD_arch", tag, ArrayRef(strings));
161 Error ARMAttributeParser::MVE_arch(AttrType tag) {
162 static const char *const strings[] = {"Not Permitted", "MVE integer",
163 "MVE integer and float"};
164 return parseStringAttribute("MVE_arch", tag, ArrayRef(strings));
167 Error ARMAttributeParser::PCS_config(AttrType tag) {
168 static const char *const strings[] = {"None",
169 "Bare Platform",
170 "Linux Application",
171 "Linux DSO",
172 "Palm OS 2004",
173 "Reserved (Palm OS)",
174 "Symbian OS 2004",
175 "Reserved (Symbian OS)"};
176 return parseStringAttribute("PCS_config", tag, ArrayRef(strings));
179 Error ARMAttributeParser::ABI_PCS_R9_use(AttrType tag) {
180 static const char *const strings[] = {"v6", "Static Base", "TLS", "Unused"};
181 return parseStringAttribute("ABI_PCS_R9_use", tag, ArrayRef(strings));
184 Error ARMAttributeParser::ABI_PCS_RW_data(AttrType tag) {
185 static const char *const strings[] = {"Absolute", "PC-relative",
186 "SB-relative", "Not Permitted"};
187 return parseStringAttribute("ABI_PCS_RW_data", tag, ArrayRef(strings));
190 Error ARMAttributeParser::ABI_PCS_RO_data(AttrType tag) {
191 static const char *const strings[] = {"Absolute", "PC-relative",
192 "Not Permitted"};
193 return parseStringAttribute("ABI_PCS_RO_data", tag, ArrayRef(strings));
196 Error ARMAttributeParser::ABI_PCS_GOT_use(AttrType tag) {
197 static const char *const strings[] = {"Not Permitted", "Direct",
198 "GOT-Indirect"};
199 return parseStringAttribute("ABI_PCS_GOT_use", tag, ArrayRef(strings));
202 Error ARMAttributeParser::ABI_PCS_wchar_t(AttrType tag) {
203 static const char *const strings[] = {"Not Permitted", "Unknown", "2-byte",
204 "Unknown", "4-byte"};
205 return parseStringAttribute("ABI_PCS_wchar_t", tag, ArrayRef(strings));
208 Error ARMAttributeParser::ABI_FP_rounding(AttrType tag) {
209 static const char *const strings[] = {"IEEE-754", "Runtime"};
210 return parseStringAttribute("ABI_FP_rounding", tag, ArrayRef(strings));
213 Error ARMAttributeParser::ABI_FP_denormal(AttrType tag) {
214 static const char *const strings[] = {"Unsupported", "IEEE-754", "Sign Only"};
215 return parseStringAttribute("ABI_FP_denormal", tag, ArrayRef(strings));
218 Error ARMAttributeParser::ABI_FP_exceptions(AttrType tag) {
219 static const char *const strings[] = {"Not Permitted", "IEEE-754"};
220 return parseStringAttribute("ABI_FP_exceptions", tag, ArrayRef(strings));
222 Error ARMAttributeParser::ABI_FP_user_exceptions(AttrType tag) {
223 static const char *const strings[] = {"Not Permitted", "IEEE-754"};
224 return parseStringAttribute("ABI_FP_user_exceptions", tag, ArrayRef(strings));
227 Error ARMAttributeParser::ABI_FP_number_model(AttrType tag) {
228 static const char *const strings[] = {"Not Permitted", "Finite Only", "RTABI",
229 "IEEE-754"};
230 return parseStringAttribute("ABI_FP_number_model", tag, ArrayRef(strings));
233 Error ARMAttributeParser::ABI_align_needed(AttrType tag) {
234 static const char *const strings[] = {"Not Permitted", "8-byte alignment",
235 "4-byte alignment", "Reserved"};
237 uint64_t value = de.getULEB128(cursor);
239 std::string description;
240 if (value < std::size(strings))
241 description = strings[value];
242 else if (value <= 12)
243 description = "8-byte alignment, " + utostr(1ULL << value) +
244 "-byte extended alignment";
245 else
246 description = "Invalid";
248 printAttribute(tag, value, description);
249 return Error::success();
252 Error ARMAttributeParser::ABI_align_preserved(AttrType tag) {
253 static const char *strings[] = {"Not Required", "8-byte data alignment",
254 "8-byte data and code alignment", "Reserved"};
256 uint64_t value = de.getULEB128(cursor);
258 std::string description;
259 if (value < std::size(strings))
260 description = std::string(strings[value]);
261 else if (value <= 12)
262 description = std::string("8-byte stack alignment, ") +
263 utostr(1ULL << value) + std::string("-byte data alignment");
264 else
265 description = "Invalid";
267 printAttribute(tag, value, description);
268 return Error::success();
271 Error ARMAttributeParser::ABI_enum_size(AttrType tag) {
272 static const char *const strings[] = {"Not Permitted", "Packed", "Int32",
273 "External Int32"};
274 return parseStringAttribute("ABI_enum_size", tag, ArrayRef(strings));
277 Error ARMAttributeParser::ABI_HardFP_use(AttrType tag) {
278 static const char *const strings[] = {"Tag_FP_arch", "Single-Precision",
279 "Reserved", "Tag_FP_arch (deprecated)"};
280 return parseStringAttribute("ABI_HardFP_use", tag, ArrayRef(strings));
283 Error ARMAttributeParser::ABI_VFP_args(AttrType tag) {
284 static const char *const strings[] = {"AAPCS", "AAPCS VFP", "Custom",
285 "Not Permitted"};
286 return parseStringAttribute("ABI_VFP_args", tag, ArrayRef(strings));
289 Error ARMAttributeParser::ABI_WMMX_args(AttrType tag) {
290 static const char *const strings[] = {"AAPCS", "iWMMX", "Custom"};
291 return parseStringAttribute("ABI_WMMX_args", tag, ArrayRef(strings));
294 Error ARMAttributeParser::ABI_optimization_goals(AttrType tag) {
295 static const char *const strings[] = {
296 "None", "Speed", "Aggressive Speed",
297 "Size", "Aggressive Size", "Debugging",
298 "Best Debugging"};
299 return parseStringAttribute("ABI_optimization_goals", tag, ArrayRef(strings));
302 Error ARMAttributeParser::ABI_FP_optimization_goals(AttrType tag) {
303 static const char *const strings[] = {
304 "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size",
305 "Accuracy", "Best Accuracy"};
306 return parseStringAttribute("ABI_FP_optimization_goals", tag,
307 ArrayRef(strings));
310 Error ARMAttributeParser::compatibility(AttrType tag) {
311 uint64_t integer = de.getULEB128(cursor);
312 StringRef string = de.getCStrRef(cursor);
314 if (sw) {
315 DictScope scope(*sw, "Attribute");
316 sw->printNumber("Tag", tag);
317 sw->startLine() << "Value: " << integer << ", " << string << '\n';
318 sw->printString("TagName",
319 ELFAttrs::attrTypeAsString(tag, tagToStringMap,
320 /*hasTagPrefix=*/false));
321 switch (integer) {
322 case 0:
323 sw->printString("Description", StringRef("No Specific Requirements"));
324 break;
325 case 1:
326 sw->printString("Description", StringRef("AEABI Conformant"));
327 break;
328 default:
329 sw->printString("Description", StringRef("AEABI Non-Conformant"));
330 break;
333 return Error::success();
336 Error ARMAttributeParser::CPU_unaligned_access(AttrType tag) {
337 static const char *const strings[] = {"Not Permitted", "v6-style"};
338 return parseStringAttribute("CPU_unaligned_access", tag, ArrayRef(strings));
341 Error ARMAttributeParser::FP_HP_extension(AttrType tag) {
342 static const char *const strings[] = {"If Available", "Permitted"};
343 return parseStringAttribute("FP_HP_extension", tag, ArrayRef(strings));
346 Error ARMAttributeParser::ABI_FP_16bit_format(AttrType tag) {
347 static const char *const strings[] = {"Not Permitted", "IEEE-754", "VFPv3"};
348 return parseStringAttribute("ABI_FP_16bit_format", tag, ArrayRef(strings));
351 Error ARMAttributeParser::MPextension_use(AttrType tag) {
352 static const char *const strings[] = {"Not Permitted", "Permitted"};
353 return parseStringAttribute("MPextension_use", tag, ArrayRef(strings));
356 Error ARMAttributeParser::DIV_use(AttrType tag) {
357 static const char *const strings[] = {"If Available", "Not Permitted",
358 "Permitted"};
359 return parseStringAttribute("DIV_use", tag, ArrayRef(strings));
362 Error ARMAttributeParser::DSP_extension(AttrType tag) {
363 static const char *const strings[] = {"Not Permitted", "Permitted"};
364 return parseStringAttribute("DSP_extension", tag, ArrayRef(strings));
367 Error ARMAttributeParser::T2EE_use(AttrType tag) {
368 static const char *const strings[] = {"Not Permitted", "Permitted"};
369 return parseStringAttribute("T2EE_use", tag, ArrayRef(strings));
372 Error ARMAttributeParser::Virtualization_use(AttrType tag) {
373 static const char *const strings[] = {
374 "Not Permitted", "TrustZone", "Virtualization Extensions",
375 "TrustZone + Virtualization Extensions"};
376 return parseStringAttribute("Virtualization_use", tag, ArrayRef(strings));
379 Error ARMAttributeParser::PAC_extension(ARMBuildAttrs::AttrType tag) {
380 static const char *const strings[] = {"Not Permitted",
381 "Permitted in NOP space", "Permitted"};
382 return parseStringAttribute("PAC_extension", tag, ArrayRef(strings));
385 Error ARMAttributeParser::BTI_extension(ARMBuildAttrs::AttrType tag) {
386 static const char *const strings[] = {"Not Permitted",
387 "Permitted in NOP space", "Permitted"};
388 return parseStringAttribute("BTI_extension", tag, ArrayRef(strings));
391 Error ARMAttributeParser::PACRET_use(ARMBuildAttrs::AttrType tag) {
392 static const char *const strings[] = {"Not Used", "Used"};
393 return parseStringAttribute("PACRET_use", tag, ArrayRef(strings));
396 Error ARMAttributeParser::BTI_use(ARMBuildAttrs::AttrType tag) {
397 static const char *const strings[] = {"Not Used", "Used"};
398 return parseStringAttribute("BTI_use", tag, ArrayRef(strings));
401 Error ARMAttributeParser::nodefaults(AttrType tag) {
402 uint64_t value = de.getULEB128(cursor);
403 printAttribute(tag, value, "Unspecified Tags UNDEFINED");
404 return Error::success();
407 Error ARMAttributeParser::also_compatible_with(AttrType tag) {
408 // Parse value as a C string first in order to print it in escaped form later.
409 // Then, parse it again to catch errors or to pretty print if Tag_CPU_arch.
410 std::optional<Error> returnValue;
412 SmallString<8> Description;
413 raw_svector_ostream DescStream(Description);
415 uint64_t InitialOffset = cursor.tell();
416 StringRef RawStringValue = de.getCStrRef(cursor);
417 uint64_t FinalOffset = cursor.tell();
418 cursor.seek(InitialOffset);
419 uint64_t InnerTag = de.getULEB128(cursor);
421 bool ValidInnerTag =
422 any_of(tagToStringMap, [InnerTag](const TagNameItem &Item) {
423 return Item.attr == InnerTag;
426 if (!ValidInnerTag) {
427 returnValue =
428 createStringError(errc::argument_out_of_domain,
429 Twine(InnerTag) + " is not a valid tag number");
430 } else {
431 switch (InnerTag) {
432 case ARMBuildAttrs::CPU_arch: {
433 uint64_t InnerValue = de.getULEB128(cursor);
434 auto strings = ArrayRef(CPU_arch_strings);
435 if (InnerValue >= strings.size()) {
436 returnValue = createStringError(
437 errc::argument_out_of_domain,
438 Twine(InnerValue) + " is not a valid " +
439 ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) +
440 " value");
441 } else {
442 DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
443 << " = " << InnerValue;
444 if (strings[InnerValue])
445 DescStream << " (" << strings[InnerValue] << ')';
447 break;
449 case ARMBuildAttrs::also_compatible_with:
450 returnValue = createStringError(
451 errc::invalid_argument,
452 ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) +
453 " cannot be recursively defined");
454 break;
455 case ARMBuildAttrs::CPU_raw_name:
456 case ARMBuildAttrs::CPU_name:
457 case ARMBuildAttrs::compatibility:
458 case ARMBuildAttrs::conformance: {
459 StringRef InnerValue = de.getCStrRef(cursor);
460 DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
461 << " = " << InnerValue;
462 break;
464 default: {
465 uint64_t InnerValue = de.getULEB128(cursor);
466 DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
467 << " = " << InnerValue;
472 setAttributeString(tag, RawStringValue);
473 if (sw) {
474 DictScope scope(*sw, "Attribute");
475 sw->printNumber("Tag", tag);
476 sw->printString("TagName",
477 ELFAttrs::attrTypeAsString(tag, tagToStringMap, false));
478 sw->printStringEscaped("Value", RawStringValue);
479 if (!Description.empty()) {
480 sw->printString("Description", Description);
484 cursor.seek(FinalOffset);
486 return returnValue ? std::move(*returnValue) : Error::success();
489 Error ARMAttributeParser::handler(uint64_t tag, bool &handled) {
490 handled = false;
491 for (const auto &AH : displayRoutines) {
492 if (uint64_t(AH.attribute) == tag) {
493 if (Error e = (this->*AH.routine)(static_cast<AttrType>(tag)))
494 return e;
495 handled = true;
496 break;
500 return Error::success();