1 //===- ARMAttributeParser.cpp - ARM Attribute Information Printer ---------===//
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
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"
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
) {
74 ELFAttrs::attrTypeAsString(tag
, tagToStringMap
, /*hasTagPrefix=*/false);
75 StringRef desc
= de
.getCStrRef(cursor
);
78 DictScope
scope(*sw
, "Attribute");
79 sw
->printNumber("Tag", tag
);
81 sw
->printString("TagName", tagName
);
82 sw
->printString("Value", desc
);
84 return Error::success();
87 static const char *CPU_arch_strings
[] = {
88 "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ",
89 "ARM v6", "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M",
90 "ARM v6S-M", "ARM v7E-M", "ARM v8-A", "ARM v8-R", "ARM v8-M Baseline",
91 "ARM v8-M Mainline", nullptr, nullptr, nullptr, "ARM v8.1-M Mainline",
94 Error
ARMAttributeParser::CPU_arch(AttrType tag
) {
95 return parseStringAttribute("CPU_arch", tag
, ArrayRef(CPU_arch_strings
));
98 Error
ARMAttributeParser::CPU_arch_profile(AttrType tag
) {
99 uint64_t value
= de
.getULEB128(cursor
);
103 default: profile
= "Unknown"; break;
104 case 'A': profile
= "Application"; break;
105 case 'R': profile
= "Real-time"; break;
106 case 'M': profile
= "Microcontroller"; break;
107 case 'S': profile
= "Classic"; break;
108 case 0: profile
= "None"; break;
111 printAttribute(tag
, value
, profile
);
112 return Error::success();
115 Error
ARMAttributeParser::ARM_ISA_use(AttrType tag
) {
116 static const char *strings
[] = {"Not Permitted", "Permitted"};
117 return parseStringAttribute("ARM_ISA_use", tag
, ArrayRef(strings
));
120 Error
ARMAttributeParser::THUMB_ISA_use(AttrType tag
) {
121 static const char *strings
[] = {"Not Permitted", "Thumb-1", "Thumb-2", "Permitted"};
122 return parseStringAttribute("THUMB_ISA_use", tag
, ArrayRef(strings
));
125 Error
ARMAttributeParser::FP_arch(AttrType tag
) {
126 static const char *strings
[] = {
127 "Not Permitted", "VFPv1", "VFPv2", "VFPv3", "VFPv3-D16",
128 "VFPv4", "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16"};
129 return parseStringAttribute("FP_arch", tag
, ArrayRef(strings
));
132 Error
ARMAttributeParser::WMMX_arch(AttrType tag
) {
133 static const char *strings
[] = {"Not Permitted", "WMMXv1", "WMMXv2"};
134 return parseStringAttribute("WMMX_arch", tag
, ArrayRef(strings
));
137 Error
ARMAttributeParser::Advanced_SIMD_arch(AttrType tag
) {
138 static const char *strings
[] = {"Not Permitted", "NEONv1", "NEONv2+FMA",
139 "ARMv8-a NEON", "ARMv8.1-a NEON"};
140 return parseStringAttribute("Advanced_SIMD_arch", tag
, ArrayRef(strings
));
143 Error
ARMAttributeParser::MVE_arch(AttrType tag
) {
144 static const char *strings
[] = {"Not Permitted", "MVE integer",
145 "MVE integer and float"};
146 return parseStringAttribute("MVE_arch", tag
, ArrayRef(strings
));
149 Error
ARMAttributeParser::PCS_config(AttrType tag
) {
150 static const char *strings
[] = {
151 "None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004",
152 "Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)"};
153 return parseStringAttribute("PCS_config", tag
, ArrayRef(strings
));
156 Error
ARMAttributeParser::ABI_PCS_R9_use(AttrType tag
) {
157 static const char *strings
[] = {"v6", "Static Base", "TLS", "Unused"};
158 return parseStringAttribute("ABI_PCS_R9_use", tag
, ArrayRef(strings
));
161 Error
ARMAttributeParser::ABI_PCS_RW_data(AttrType tag
) {
162 static const char *strings
[] = {"Absolute", "PC-relative", "SB-relative",
164 return parseStringAttribute("ABI_PCS_RW_data", tag
, ArrayRef(strings
));
167 Error
ARMAttributeParser::ABI_PCS_RO_data(AttrType tag
) {
168 static const char *strings
[] = {"Absolute", "PC-relative", "Not Permitted"};
169 return parseStringAttribute("ABI_PCS_RO_data", tag
, ArrayRef(strings
));
172 Error
ARMAttributeParser::ABI_PCS_GOT_use(AttrType tag
) {
173 static const char *strings
[] = {"Not Permitted", "Direct", "GOT-Indirect"};
174 return parseStringAttribute("ABI_PCS_GOT_use", tag
, ArrayRef(strings
));
177 Error
ARMAttributeParser::ABI_PCS_wchar_t(AttrType tag
) {
178 static const char *strings
[] = {"Not Permitted", "Unknown", "2-byte",
179 "Unknown", "4-byte"};
180 return parseStringAttribute("ABI_PCS_wchar_t", tag
, ArrayRef(strings
));
183 Error
ARMAttributeParser::ABI_FP_rounding(AttrType tag
) {
184 static const char *strings
[] = {"IEEE-754", "Runtime"};
185 return parseStringAttribute("ABI_FP_rounding", tag
, ArrayRef(strings
));
188 Error
ARMAttributeParser::ABI_FP_denormal(AttrType tag
) {
189 static const char *strings
[] = {"Unsupported", "IEEE-754", "Sign Only"};
190 return parseStringAttribute("ABI_FP_denormal", tag
, ArrayRef(strings
));
193 Error
ARMAttributeParser::ABI_FP_exceptions(AttrType tag
) {
194 static const char *strings
[] = {"Not Permitted", "IEEE-754"};
195 return parseStringAttribute("ABI_FP_exceptions", tag
, ArrayRef(strings
));
197 Error
ARMAttributeParser::ABI_FP_user_exceptions(AttrType tag
) {
198 static const char *strings
[] = {"Not Permitted", "IEEE-754"};
199 return parseStringAttribute("ABI_FP_user_exceptions", tag
, ArrayRef(strings
));
202 Error
ARMAttributeParser::ABI_FP_number_model(AttrType tag
) {
203 static const char *strings
[] = {"Not Permitted", "Finite Only", "RTABI",
205 return parseStringAttribute("ABI_FP_number_model", tag
, ArrayRef(strings
));
208 Error
ARMAttributeParser::ABI_align_needed(AttrType tag
) {
209 static const char *strings
[] = {"Not Permitted", "8-byte alignment",
210 "4-byte alignment", "Reserved"};
212 uint64_t value
= de
.getULEB128(cursor
);
214 std::string description
;
215 if (value
< std::size(strings
))
216 description
= strings
[value
];
217 else if (value
<= 12)
218 description
= "8-byte alignment, " + utostr(1ULL << value
) +
219 "-byte extended alignment";
221 description
= "Invalid";
223 printAttribute(tag
, value
, description
);
224 return Error::success();
227 Error
ARMAttributeParser::ABI_align_preserved(AttrType tag
) {
228 static const char *strings
[] = {"Not Required", "8-byte data alignment",
229 "8-byte data and code alignment", "Reserved"};
231 uint64_t value
= de
.getULEB128(cursor
);
233 std::string description
;
234 if (value
< std::size(strings
))
235 description
= std::string(strings
[value
]);
236 else if (value
<= 12)
237 description
= std::string("8-byte stack alignment, ") +
238 utostr(1ULL << value
) + std::string("-byte data alignment");
240 description
= "Invalid";
242 printAttribute(tag
, value
, description
);
243 return Error::success();
246 Error
ARMAttributeParser::ABI_enum_size(AttrType tag
) {
247 static const char *strings
[] = {"Not Permitted", "Packed", "Int32",
249 return parseStringAttribute("ABI_enum_size", tag
, ArrayRef(strings
));
252 Error
ARMAttributeParser::ABI_HardFP_use(AttrType tag
) {
253 static const char *strings
[] = {"Tag_FP_arch", "Single-Precision", "Reserved",
254 "Tag_FP_arch (deprecated)"};
255 return parseStringAttribute("ABI_HardFP_use", tag
, ArrayRef(strings
));
258 Error
ARMAttributeParser::ABI_VFP_args(AttrType tag
) {
259 static const char *strings
[] = {"AAPCS", "AAPCS VFP", "Custom",
261 return parseStringAttribute("ABI_VFP_args", tag
, ArrayRef(strings
));
264 Error
ARMAttributeParser::ABI_WMMX_args(AttrType tag
) {
265 static const char *strings
[] = {"AAPCS", "iWMMX", "Custom"};
266 return parseStringAttribute("ABI_WMMX_args", tag
, ArrayRef(strings
));
269 Error
ARMAttributeParser::ABI_optimization_goals(AttrType tag
) {
270 static const char *strings
[] = {
271 "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Debugging",
274 return parseStringAttribute("ABI_optimization_goals", tag
, ArrayRef(strings
));
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
,
285 Error
ARMAttributeParser::compatibility(AttrType tag
) {
286 uint64_t integer
= de
.getULEB128(cursor
);
287 StringRef string
= de
.getCStrRef(cursor
);
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));
298 sw
->printString("Description", StringRef("No Specific Requirements"));
301 sw
->printString("Description", StringRef("AEABI Conformant"));
304 sw
->printString("Description", StringRef("AEABI Non-Conformant"));
308 return Error::success();
311 Error
ARMAttributeParser::CPU_unaligned_access(AttrType tag
) {
312 static const char *strings
[] = {"Not Permitted", "v6-style"};
313 return parseStringAttribute("CPU_unaligned_access", tag
, ArrayRef(strings
));
316 Error
ARMAttributeParser::FP_HP_extension(AttrType tag
) {
317 static const char *strings
[] = {"If Available", "Permitted"};
318 return parseStringAttribute("FP_HP_extension", tag
, ArrayRef(strings
));
321 Error
ARMAttributeParser::ABI_FP_16bit_format(AttrType tag
) {
322 static const char *strings
[] = {"Not Permitted", "IEEE-754", "VFPv3"};
323 return parseStringAttribute("ABI_FP_16bit_format", tag
, ArrayRef(strings
));
326 Error
ARMAttributeParser::MPextension_use(AttrType tag
) {
327 static const char *strings
[] = {"Not Permitted", "Permitted"};
328 return parseStringAttribute("MPextension_use", tag
, ArrayRef(strings
));
331 Error
ARMAttributeParser::DIV_use(AttrType tag
) {
332 static const char *strings
[] = {"If Available", "Not Permitted", "Permitted"};
333 return parseStringAttribute("DIV_use", tag
, ArrayRef(strings
));
336 Error
ARMAttributeParser::DSP_extension(AttrType tag
) {
337 static const char *strings
[] = {"Not Permitted", "Permitted"};
338 return parseStringAttribute("DSP_extension", tag
, ArrayRef(strings
));
341 Error
ARMAttributeParser::T2EE_use(AttrType tag
) {
342 static const char *strings
[] = {"Not Permitted", "Permitted"};
343 return parseStringAttribute("T2EE_use", tag
, ArrayRef(strings
));
346 Error
ARMAttributeParser::Virtualization_use(AttrType tag
) {
347 static const char *strings
[] = {"Not Permitted", "TrustZone",
348 "Virtualization Extensions",
349 "TrustZone + Virtualization Extensions"};
350 return parseStringAttribute("Virtualization_use", tag
, ArrayRef(strings
));
353 Error
ARMAttributeParser::PAC_extension(ARMBuildAttrs::AttrType tag
) {
354 static const char *strings
[] = {"Not Permitted", "Permitted in NOP space",
356 return parseStringAttribute("PAC_extension", tag
, ArrayRef(strings
));
359 Error
ARMAttributeParser::BTI_extension(ARMBuildAttrs::AttrType tag
) {
360 static const char *strings
[] = {"Not Permitted", "Permitted in NOP space",
362 return parseStringAttribute("BTI_extension", tag
, ArrayRef(strings
));
365 Error
ARMAttributeParser::PACRET_use(ARMBuildAttrs::AttrType tag
) {
366 static const char *strings
[] = {"Not Used", "Used"};
367 return parseStringAttribute("PACRET_use", tag
, ArrayRef(strings
));
370 Error
ARMAttributeParser::BTI_use(ARMBuildAttrs::AttrType tag
) {
371 static const char *strings
[] = {"Not Used", "Used"};
372 return parseStringAttribute("BTI_use", tag
, ArrayRef(strings
));
375 Error
ARMAttributeParser::nodefaults(AttrType tag
) {
376 uint64_t value
= de
.getULEB128(cursor
);
377 printAttribute(tag
, value
, "Unspecified Tags UNDEFINED");
378 return Error::success();
381 Error
ARMAttributeParser::also_compatible_with(AttrType tag
) {
382 // Parse value as a C string first in order to print it in escaped form later.
383 // Then, parse it again to catch errors or to pretty print if Tag_CPU_arch.
384 std::optional
<Error
> returnValue
;
386 SmallString
<8> Description
;
387 raw_svector_ostream
DescStream(Description
);
389 uint64_t InitialOffset
= cursor
.tell();
390 StringRef RawStringValue
= de
.getCStrRef(cursor
);
391 uint64_t FinalOffset
= cursor
.tell();
392 cursor
.seek(InitialOffset
);
393 uint64_t InnerTag
= de
.getULEB128(cursor
);
396 any_of(tagToStringMap
, [InnerTag
](const TagNameItem
&Item
) {
397 return Item
.attr
== InnerTag
;
400 if (!ValidInnerTag
) {
402 createStringError(errc::argument_out_of_domain
,
403 Twine(InnerTag
) + " is not a valid tag number");
406 case ARMBuildAttrs::CPU_arch
: {
407 uint64_t InnerValue
= de
.getULEB128(cursor
);
408 auto strings
= ArrayRef(CPU_arch_strings
);
409 if (InnerValue
>= strings
.size()) {
410 returnValue
= createStringError(
411 errc::argument_out_of_domain
,
412 Twine(InnerValue
) + " is not a valid " +
413 ELFAttrs::attrTypeAsString(InnerTag
, tagToStringMap
) +
416 DescStream
<< ELFAttrs::attrTypeAsString(InnerTag
, tagToStringMap
)
417 << " = " << InnerValue
;
418 if (strings
[InnerValue
])
419 DescStream
<< " (" << strings
[InnerValue
] << ')';
423 case ARMBuildAttrs::also_compatible_with
:
424 returnValue
= createStringError(
425 errc::invalid_argument
,
426 ELFAttrs::attrTypeAsString(InnerTag
, tagToStringMap
) +
427 " cannot be recursively defined");
429 case ARMBuildAttrs::CPU_raw_name
:
430 case ARMBuildAttrs::CPU_name
:
431 case ARMBuildAttrs::compatibility
:
432 case ARMBuildAttrs::conformance
: {
433 StringRef InnerValue
= de
.getCStrRef(cursor
);
434 DescStream
<< ELFAttrs::attrTypeAsString(InnerTag
, tagToStringMap
)
435 << " = " << InnerValue
;
439 uint64_t InnerValue
= de
.getULEB128(cursor
);
440 DescStream
<< ELFAttrs::attrTypeAsString(InnerTag
, tagToStringMap
)
441 << " = " << InnerValue
;
446 setAttributeString(tag
, RawStringValue
);
448 DictScope
scope(*sw
, "Attribute");
449 sw
->printNumber("Tag", tag
);
450 sw
->printString("TagName",
451 ELFAttrs::attrTypeAsString(tag
, tagToStringMap
, false));
452 sw
->printStringEscaped("Value", RawStringValue
);
453 if (!Description
.empty()) {
454 sw
->printString("Description", Description
);
458 cursor
.seek(FinalOffset
);
460 return returnValue
? std::move(*returnValue
) : Error::success();
463 Error
ARMAttributeParser::handler(uint64_t tag
, bool &handled
) {
465 for (const auto &AH
: displayRoutines
) {
466 if (uint64_t(AH
.attribute
) == tag
) {
467 if (Error e
= (this->*AH
.routine
)(static_cast<AttrType
>(tag
)))
474 return Error::success();