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 *const CPU_arch_strings
[] = {"Pre-v4",
108 "ARM v8.1-M Mainline",
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
);
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",
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",
173 "Reserved (Palm OS)",
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",
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",
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",
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";
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");
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",
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",
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",
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
,
310 Error
ARMAttributeParser::compatibility(AttrType tag
) {
311 uint64_t integer
= de
.getULEB128(cursor
);
312 StringRef string
= de
.getCStrRef(cursor
);
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));
323 sw
->printString("Description", StringRef("No Specific Requirements"));
326 sw
->printString("Description", StringRef("AEABI Conformant"));
329 sw
->printString("Description", StringRef("AEABI Non-Conformant"));
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",
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
);
422 any_of(tagToStringMap
, [InnerTag
](const TagNameItem
&Item
) {
423 return Item
.attr
== InnerTag
;
426 if (!ValidInnerTag
) {
428 createStringError(errc::argument_out_of_domain
,
429 Twine(InnerTag
) + " is not a valid tag number");
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
) +
442 DescStream
<< ELFAttrs::attrTypeAsString(InnerTag
, tagToStringMap
)
443 << " = " << InnerValue
;
444 if (strings
[InnerValue
])
445 DescStream
<< " (" << strings
[InnerValue
] << ')';
449 case ARMBuildAttrs::also_compatible_with
:
450 returnValue
= createStringError(
451 errc::invalid_argument
,
452 ELFAttrs::attrTypeAsString(InnerTag
, tagToStringMap
) +
453 " cannot be recursively defined");
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
;
465 uint64_t InnerValue
= de
.getULEB128(cursor
);
466 DescStream
<< ELFAttrs::attrTypeAsString(InnerTag
, tagToStringMap
)
467 << " = " << InnerValue
;
472 setAttributeString(tag
, RawStringValue
);
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
) {
491 for (const auto &AH
: displayRoutines
) {
492 if (uint64_t(AH
.attribute
) == tag
) {
493 if (Error e
= (this->*AH
.routine
)(static_cast<AttrType
>(tag
)))
500 return Error::success();