1097a140dSpatrick //===- ARMAttributeParser.cpp - ARM Attribute Information Printer ---------===//
209467b48Spatrick //
309467b48Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
409467b48Spatrick // See https://llvm.org/LICENSE.txt for license information.
509467b48Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
609467b48Spatrick //
709467b48Spatrick //===----------------------------------------------------------------------===//
809467b48Spatrick 
909467b48Spatrick #include "llvm/Support/ARMAttributeParser.h"
1009467b48Spatrick #include "llvm/ADT/StringExtras.h"
11*d415bd75Srobert #include "llvm/Support/ARMBuildAttributes.h"
12097a140dSpatrick #include "llvm/Support/Errc.h"
1309467b48Spatrick #include "llvm/Support/ScopedPrinter.h"
14*d415bd75Srobert #include <optional>
1509467b48Spatrick 
1609467b48Spatrick using namespace llvm;
1709467b48Spatrick using namespace llvm::ARMBuildAttrs;
1809467b48Spatrick 
19097a140dSpatrick #define ATTRIBUTE_HANDLER(attr)                                                \
20097a140dSpatrick   { ARMBuildAttrs::attr, &ARMAttributeParser::attr }
2109467b48Spatrick 
22097a140dSpatrick const ARMAttributeParser::DisplayHandler ARMAttributeParser::displayRoutines[] =
23097a140dSpatrick     {
24097a140dSpatrick         {ARMBuildAttrs::CPU_raw_name, &ARMAttributeParser::stringAttribute},
25097a140dSpatrick         {ARMBuildAttrs::CPU_name, &ARMAttributeParser::stringAttribute},
2609467b48Spatrick         ATTRIBUTE_HANDLER(CPU_arch),
2709467b48Spatrick         ATTRIBUTE_HANDLER(CPU_arch_profile),
2809467b48Spatrick         ATTRIBUTE_HANDLER(ARM_ISA_use),
2909467b48Spatrick         ATTRIBUTE_HANDLER(THUMB_ISA_use),
3009467b48Spatrick         ATTRIBUTE_HANDLER(FP_arch),
3109467b48Spatrick         ATTRIBUTE_HANDLER(WMMX_arch),
3209467b48Spatrick         ATTRIBUTE_HANDLER(Advanced_SIMD_arch),
3309467b48Spatrick         ATTRIBUTE_HANDLER(MVE_arch),
3409467b48Spatrick         ATTRIBUTE_HANDLER(PCS_config),
3509467b48Spatrick         ATTRIBUTE_HANDLER(ABI_PCS_R9_use),
3609467b48Spatrick         ATTRIBUTE_HANDLER(ABI_PCS_RW_data),
3709467b48Spatrick         ATTRIBUTE_HANDLER(ABI_PCS_RO_data),
3809467b48Spatrick         ATTRIBUTE_HANDLER(ABI_PCS_GOT_use),
3909467b48Spatrick         ATTRIBUTE_HANDLER(ABI_PCS_wchar_t),
4009467b48Spatrick         ATTRIBUTE_HANDLER(ABI_FP_rounding),
4109467b48Spatrick         ATTRIBUTE_HANDLER(ABI_FP_denormal),
4209467b48Spatrick         ATTRIBUTE_HANDLER(ABI_FP_exceptions),
4309467b48Spatrick         ATTRIBUTE_HANDLER(ABI_FP_user_exceptions),
4409467b48Spatrick         ATTRIBUTE_HANDLER(ABI_FP_number_model),
4509467b48Spatrick         ATTRIBUTE_HANDLER(ABI_align_needed),
4609467b48Spatrick         ATTRIBUTE_HANDLER(ABI_align_preserved),
4709467b48Spatrick         ATTRIBUTE_HANDLER(ABI_enum_size),
4809467b48Spatrick         ATTRIBUTE_HANDLER(ABI_HardFP_use),
4909467b48Spatrick         ATTRIBUTE_HANDLER(ABI_VFP_args),
5009467b48Spatrick         ATTRIBUTE_HANDLER(ABI_WMMX_args),
5109467b48Spatrick         ATTRIBUTE_HANDLER(ABI_optimization_goals),
5209467b48Spatrick         ATTRIBUTE_HANDLER(ABI_FP_optimization_goals),
5309467b48Spatrick         ATTRIBUTE_HANDLER(compatibility),
5409467b48Spatrick         ATTRIBUTE_HANDLER(CPU_unaligned_access),
5509467b48Spatrick         ATTRIBUTE_HANDLER(FP_HP_extension),
5609467b48Spatrick         ATTRIBUTE_HANDLER(ABI_FP_16bit_format),
5709467b48Spatrick         ATTRIBUTE_HANDLER(MPextension_use),
5809467b48Spatrick         ATTRIBUTE_HANDLER(DIV_use),
5909467b48Spatrick         ATTRIBUTE_HANDLER(DSP_extension),
6009467b48Spatrick         ATTRIBUTE_HANDLER(T2EE_use),
6109467b48Spatrick         ATTRIBUTE_HANDLER(Virtualization_use),
62*d415bd75Srobert         ATTRIBUTE_HANDLER(PAC_extension),
63*d415bd75Srobert         ATTRIBUTE_HANDLER(BTI_extension),
64*d415bd75Srobert         ATTRIBUTE_HANDLER(PACRET_use),
65*d415bd75Srobert         ATTRIBUTE_HANDLER(BTI_use),
66097a140dSpatrick         ATTRIBUTE_HANDLER(nodefaults),
67*d415bd75Srobert         ATTRIBUTE_HANDLER(also_compatible_with),
6809467b48Spatrick };
6909467b48Spatrick 
7009467b48Spatrick #undef ATTRIBUTE_HANDLER
7109467b48Spatrick 
stringAttribute(AttrType tag)72097a140dSpatrick Error ARMAttributeParser::stringAttribute(AttrType tag) {
73097a140dSpatrick   StringRef tagName =
74*d415bd75Srobert       ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
75097a140dSpatrick   StringRef desc = de.getCStrRef(cursor);
76097a140dSpatrick 
77097a140dSpatrick   if (sw) {
78097a140dSpatrick     DictScope scope(*sw, "Attribute");
79097a140dSpatrick     sw->printNumber("Tag", tag);
80097a140dSpatrick     if (!tagName.empty())
81097a140dSpatrick       sw->printString("TagName", tagName);
82097a140dSpatrick     sw->printString("Value", desc);
83097a140dSpatrick   }
84097a140dSpatrick   return Error::success();
8509467b48Spatrick }
8609467b48Spatrick 
87*d415bd75Srobert static const char *CPU_arch_strings[] = {
88*d415bd75Srobert     "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ",
89*d415bd75Srobert     "ARM v6", "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M",
90*d415bd75Srobert     "ARM v6S-M", "ARM v7E-M", "ARM v8-A", "ARM v8-R", "ARM v8-M Baseline",
91*d415bd75Srobert     "ARM v8-M Mainline", nullptr, nullptr, nullptr, "ARM v8.1-M Mainline",
92*d415bd75Srobert     "ARM v9-A"};
93*d415bd75Srobert 
CPU_arch(AttrType tag)94097a140dSpatrick Error ARMAttributeParser::CPU_arch(AttrType tag) {
95*d415bd75Srobert   return parseStringAttribute("CPU_arch", tag, ArrayRef(CPU_arch_strings));
9609467b48Spatrick }
9709467b48Spatrick 
CPU_arch_profile(AttrType tag)98097a140dSpatrick Error ARMAttributeParser::CPU_arch_profile(AttrType tag) {
99097a140dSpatrick   uint64_t value = de.getULEB128(cursor);
10009467b48Spatrick 
101097a140dSpatrick   StringRef profile;
102097a140dSpatrick   switch (value) {
103097a140dSpatrick   default: profile = "Unknown"; break;
104097a140dSpatrick   case 'A': profile = "Application"; break;
105097a140dSpatrick   case 'R': profile = "Real-time"; break;
106097a140dSpatrick   case 'M': profile = "Microcontroller"; break;
107097a140dSpatrick   case 'S': profile = "Classic"; break;
108097a140dSpatrick   case 0: profile = "None"; break;
10909467b48Spatrick   }
11009467b48Spatrick 
111097a140dSpatrick   printAttribute(tag, value, profile);
112097a140dSpatrick   return Error::success();
11309467b48Spatrick }
11409467b48Spatrick 
ARM_ISA_use(AttrType tag)115097a140dSpatrick Error ARMAttributeParser::ARM_ISA_use(AttrType tag) {
116097a140dSpatrick   static const char *strings[] = {"Not Permitted", "Permitted"};
117*d415bd75Srobert   return parseStringAttribute("ARM_ISA_use", tag, ArrayRef(strings));
11809467b48Spatrick }
11909467b48Spatrick 
THUMB_ISA_use(AttrType tag)120097a140dSpatrick Error ARMAttributeParser::THUMB_ISA_use(AttrType tag) {
12173471bf0Spatrick   static const char *strings[] = {"Not Permitted", "Thumb-1", "Thumb-2", "Permitted"};
122*d415bd75Srobert   return parseStringAttribute("THUMB_ISA_use", tag, ArrayRef(strings));
12309467b48Spatrick }
12409467b48Spatrick 
FP_arch(AttrType tag)125097a140dSpatrick Error ARMAttributeParser::FP_arch(AttrType tag) {
126097a140dSpatrick   static const char *strings[] = {
127097a140dSpatrick       "Not Permitted", "VFPv1",     "VFPv2",      "VFPv3",         "VFPv3-D16",
128097a140dSpatrick       "VFPv4",         "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16"};
129*d415bd75Srobert   return parseStringAttribute("FP_arch", tag, ArrayRef(strings));
13009467b48Spatrick }
13109467b48Spatrick 
WMMX_arch(AttrType tag)132097a140dSpatrick Error ARMAttributeParser::WMMX_arch(AttrType tag) {
133097a140dSpatrick   static const char *strings[] = {"Not Permitted", "WMMXv1", "WMMXv2"};
134*d415bd75Srobert   return parseStringAttribute("WMMX_arch", tag, ArrayRef(strings));
13509467b48Spatrick }
13609467b48Spatrick 
Advanced_SIMD_arch(AttrType tag)137097a140dSpatrick Error ARMAttributeParser::Advanced_SIMD_arch(AttrType tag) {
138097a140dSpatrick   static const char *strings[] = {"Not Permitted", "NEONv1", "NEONv2+FMA",
139097a140dSpatrick                                   "ARMv8-a NEON", "ARMv8.1-a NEON"};
140*d415bd75Srobert   return parseStringAttribute("Advanced_SIMD_arch", tag, ArrayRef(strings));
14109467b48Spatrick }
14209467b48Spatrick 
MVE_arch(AttrType tag)143097a140dSpatrick Error ARMAttributeParser::MVE_arch(AttrType tag) {
144097a140dSpatrick   static const char *strings[] = {"Not Permitted", "MVE integer",
145097a140dSpatrick                                   "MVE integer and float"};
146*d415bd75Srobert   return parseStringAttribute("MVE_arch", tag, ArrayRef(strings));
14709467b48Spatrick }
14809467b48Spatrick 
PCS_config(AttrType tag)149097a140dSpatrick Error ARMAttributeParser::PCS_config(AttrType tag) {
150097a140dSpatrick   static const char *strings[] = {
15109467b48Spatrick     "None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004",
152097a140dSpatrick     "Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)"};
153*d415bd75Srobert   return parseStringAttribute("PCS_config", tag, ArrayRef(strings));
15409467b48Spatrick }
15509467b48Spatrick 
ABI_PCS_R9_use(AttrType tag)156097a140dSpatrick Error ARMAttributeParser::ABI_PCS_R9_use(AttrType tag) {
157097a140dSpatrick   static const char *strings[] = {"v6", "Static Base", "TLS", "Unused"};
158*d415bd75Srobert   return parseStringAttribute("ABI_PCS_R9_use", tag, ArrayRef(strings));
15909467b48Spatrick }
16009467b48Spatrick 
ABI_PCS_RW_data(AttrType tag)161097a140dSpatrick Error ARMAttributeParser::ABI_PCS_RW_data(AttrType tag) {
162097a140dSpatrick   static const char *strings[] = {"Absolute", "PC-relative", "SB-relative",
163097a140dSpatrick                                   "Not Permitted"};
164*d415bd75Srobert   return parseStringAttribute("ABI_PCS_RW_data", tag, ArrayRef(strings));
16509467b48Spatrick }
16609467b48Spatrick 
ABI_PCS_RO_data(AttrType tag)167097a140dSpatrick Error ARMAttributeParser::ABI_PCS_RO_data(AttrType tag) {
168097a140dSpatrick   static const char *strings[] = {"Absolute", "PC-relative", "Not Permitted"};
169*d415bd75Srobert   return parseStringAttribute("ABI_PCS_RO_data", tag, ArrayRef(strings));
17009467b48Spatrick }
17109467b48Spatrick 
ABI_PCS_GOT_use(AttrType tag)172097a140dSpatrick Error ARMAttributeParser::ABI_PCS_GOT_use(AttrType tag) {
173097a140dSpatrick   static const char *strings[] = {"Not Permitted", "Direct", "GOT-Indirect"};
174*d415bd75Srobert   return parseStringAttribute("ABI_PCS_GOT_use", tag, ArrayRef(strings));
17509467b48Spatrick }
17609467b48Spatrick 
ABI_PCS_wchar_t(AttrType tag)177097a140dSpatrick Error ARMAttributeParser::ABI_PCS_wchar_t(AttrType tag) {
178097a140dSpatrick   static const char *strings[] = {"Not Permitted", "Unknown", "2-byte",
179097a140dSpatrick                                   "Unknown", "4-byte"};
180*d415bd75Srobert   return parseStringAttribute("ABI_PCS_wchar_t", tag, ArrayRef(strings));
18109467b48Spatrick }
18209467b48Spatrick 
ABI_FP_rounding(AttrType tag)183097a140dSpatrick Error ARMAttributeParser::ABI_FP_rounding(AttrType tag) {
184097a140dSpatrick   static const char *strings[] = {"IEEE-754", "Runtime"};
185*d415bd75Srobert   return parseStringAttribute("ABI_FP_rounding", tag, ArrayRef(strings));
18609467b48Spatrick }
18709467b48Spatrick 
ABI_FP_denormal(AttrType tag)188097a140dSpatrick Error ARMAttributeParser::ABI_FP_denormal(AttrType tag) {
189097a140dSpatrick   static const char *strings[] = {"Unsupported", "IEEE-754", "Sign Only"};
190*d415bd75Srobert   return parseStringAttribute("ABI_FP_denormal", tag, ArrayRef(strings));
19109467b48Spatrick }
19209467b48Spatrick 
ABI_FP_exceptions(AttrType tag)193097a140dSpatrick Error ARMAttributeParser::ABI_FP_exceptions(AttrType tag) {
194097a140dSpatrick   static const char *strings[] = {"Not Permitted", "IEEE-754"};
195*d415bd75Srobert   return parseStringAttribute("ABI_FP_exceptions", tag, ArrayRef(strings));
196097a140dSpatrick }
ABI_FP_user_exceptions(AttrType tag)197097a140dSpatrick Error ARMAttributeParser::ABI_FP_user_exceptions(AttrType tag) {
198097a140dSpatrick   static const char *strings[] = {"Not Permitted", "IEEE-754"};
199*d415bd75Srobert   return parseStringAttribute("ABI_FP_user_exceptions", tag, ArrayRef(strings));
20009467b48Spatrick }
20109467b48Spatrick 
ABI_FP_number_model(AttrType tag)202097a140dSpatrick Error ARMAttributeParser::ABI_FP_number_model(AttrType tag) {
203097a140dSpatrick   static const char *strings[] = {"Not Permitted", "Finite Only", "RTABI",
204097a140dSpatrick                                   "IEEE-754"};
205*d415bd75Srobert   return parseStringAttribute("ABI_FP_number_model", tag, ArrayRef(strings));
20609467b48Spatrick }
20709467b48Spatrick 
ABI_align_needed(AttrType tag)208097a140dSpatrick Error ARMAttributeParser::ABI_align_needed(AttrType tag) {
209097a140dSpatrick   static const char *strings[] = {"Not Permitted", "8-byte alignment",
210097a140dSpatrick                                   "4-byte alignment", "Reserved"};
21109467b48Spatrick 
212097a140dSpatrick   uint64_t value = de.getULEB128(cursor);
21309467b48Spatrick 
214097a140dSpatrick   std::string description;
215*d415bd75Srobert   if (value < std::size(strings))
216097a140dSpatrick     description = strings[value];
217097a140dSpatrick   else if (value <= 12)
218097a140dSpatrick     description = "8-byte alignment, " + utostr(1ULL << value) +
219097a140dSpatrick                   "-byte extended alignment";
22009467b48Spatrick   else
221097a140dSpatrick     description = "Invalid";
22209467b48Spatrick 
223097a140dSpatrick   printAttribute(tag, value, description);
224097a140dSpatrick   return Error::success();
22509467b48Spatrick }
22609467b48Spatrick 
ABI_align_preserved(AttrType tag)227097a140dSpatrick Error ARMAttributeParser::ABI_align_preserved(AttrType tag) {
228097a140dSpatrick   static const char *strings[] = {"Not Required", "8-byte data alignment",
229097a140dSpatrick                                   "8-byte data and code alignment", "Reserved"};
23009467b48Spatrick 
231097a140dSpatrick   uint64_t value = de.getULEB128(cursor);
23209467b48Spatrick 
233097a140dSpatrick   std::string description;
234*d415bd75Srobert   if (value < std::size(strings))
235097a140dSpatrick     description = std::string(strings[value]);
236097a140dSpatrick   else if (value <= 12)
237097a140dSpatrick     description = std::string("8-byte stack alignment, ") +
238097a140dSpatrick                   utostr(1ULL << value) + std::string("-byte data alignment");
23909467b48Spatrick   else
240097a140dSpatrick     description = "Invalid";
24109467b48Spatrick 
242097a140dSpatrick   printAttribute(tag, value, description);
243097a140dSpatrick   return Error::success();
24409467b48Spatrick }
24509467b48Spatrick 
ABI_enum_size(AttrType tag)246097a140dSpatrick Error ARMAttributeParser::ABI_enum_size(AttrType tag) {
247097a140dSpatrick   static const char *strings[] = {"Not Permitted", "Packed", "Int32",
248097a140dSpatrick                                   "External Int32"};
249*d415bd75Srobert   return parseStringAttribute("ABI_enum_size", tag, ArrayRef(strings));
25009467b48Spatrick }
25109467b48Spatrick 
ABI_HardFP_use(AttrType tag)252097a140dSpatrick Error ARMAttributeParser::ABI_HardFP_use(AttrType tag) {
253097a140dSpatrick   static const char *strings[] = {"Tag_FP_arch", "Single-Precision", "Reserved",
254097a140dSpatrick                                   "Tag_FP_arch (deprecated)"};
255*d415bd75Srobert   return parseStringAttribute("ABI_HardFP_use", tag, ArrayRef(strings));
25609467b48Spatrick }
25709467b48Spatrick 
ABI_VFP_args(AttrType tag)258097a140dSpatrick Error ARMAttributeParser::ABI_VFP_args(AttrType tag) {
259097a140dSpatrick   static const char *strings[] = {"AAPCS", "AAPCS VFP", "Custom",
260097a140dSpatrick                                   "Not Permitted"};
261*d415bd75Srobert   return parseStringAttribute("ABI_VFP_args", tag, ArrayRef(strings));
26209467b48Spatrick }
26309467b48Spatrick 
ABI_WMMX_args(AttrType tag)264097a140dSpatrick Error ARMAttributeParser::ABI_WMMX_args(AttrType tag) {
265097a140dSpatrick   static const char *strings[] = {"AAPCS", "iWMMX", "Custom"};
266*d415bd75Srobert   return parseStringAttribute("ABI_WMMX_args", tag, ArrayRef(strings));
26709467b48Spatrick }
26809467b48Spatrick 
ABI_optimization_goals(AttrType tag)269097a140dSpatrick Error ARMAttributeParser::ABI_optimization_goals(AttrType tag) {
270097a140dSpatrick   static const char *strings[] = {
27109467b48Spatrick     "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Debugging",
27209467b48Spatrick     "Best Debugging"
27309467b48Spatrick   };
274*d415bd75Srobert   return parseStringAttribute("ABI_optimization_goals", tag, ArrayRef(strings));
27509467b48Spatrick }
27609467b48Spatrick 
ABI_FP_optimization_goals(AttrType tag)277097a140dSpatrick Error ARMAttributeParser::ABI_FP_optimization_goals(AttrType tag) {
278097a140dSpatrick   static const char *strings[] = {
279097a140dSpatrick       "None",     "Speed",        "Aggressive Speed", "Size", "Aggressive Size",
280097a140dSpatrick       "Accuracy", "Best Accuracy"};
281097a140dSpatrick   return parseStringAttribute("ABI_FP_optimization_goals", tag,
282*d415bd75Srobert                               ArrayRef(strings));
28309467b48Spatrick }
28409467b48Spatrick 
compatibility(AttrType tag)285097a140dSpatrick Error ARMAttributeParser::compatibility(AttrType tag) {
286097a140dSpatrick   uint64_t integer = de.getULEB128(cursor);
287097a140dSpatrick   StringRef string = de.getCStrRef(cursor);
28809467b48Spatrick 
289097a140dSpatrick   if (sw) {
290097a140dSpatrick     DictScope scope(*sw, "Attribute");
291097a140dSpatrick     sw->printNumber("Tag", tag);
292097a140dSpatrick     sw->startLine() << "Value: " << integer << ", " << string << '\n';
293097a140dSpatrick     sw->printString("TagName",
294097a140dSpatrick                     ELFAttrs::attrTypeAsString(tag, tagToStringMap,
295097a140dSpatrick                                                /*hasTagPrefix=*/false));
296097a140dSpatrick     switch (integer) {
29709467b48Spatrick     case 0:
298097a140dSpatrick       sw->printString("Description", StringRef("No Specific Requirements"));
29909467b48Spatrick       break;
30009467b48Spatrick     case 1:
301097a140dSpatrick       sw->printString("Description", StringRef("AEABI Conformant"));
30209467b48Spatrick       break;
30309467b48Spatrick     default:
304097a140dSpatrick       sw->printString("Description", StringRef("AEABI Non-Conformant"));
30509467b48Spatrick       break;
30609467b48Spatrick     }
30709467b48Spatrick   }
308097a140dSpatrick   return Error::success();
30909467b48Spatrick }
31009467b48Spatrick 
CPU_unaligned_access(AttrType tag)311097a140dSpatrick Error ARMAttributeParser::CPU_unaligned_access(AttrType tag) {
312097a140dSpatrick   static const char *strings[] = {"Not Permitted", "v6-style"};
313*d415bd75Srobert   return parseStringAttribute("CPU_unaligned_access", tag, ArrayRef(strings));
31409467b48Spatrick }
31509467b48Spatrick 
FP_HP_extension(AttrType tag)316097a140dSpatrick Error ARMAttributeParser::FP_HP_extension(AttrType tag) {
317097a140dSpatrick   static const char *strings[] = {"If Available", "Permitted"};
318*d415bd75Srobert   return parseStringAttribute("FP_HP_extension", tag, ArrayRef(strings));
31909467b48Spatrick }
32009467b48Spatrick 
ABI_FP_16bit_format(AttrType tag)321097a140dSpatrick Error ARMAttributeParser::ABI_FP_16bit_format(AttrType tag) {
322097a140dSpatrick   static const char *strings[] = {"Not Permitted", "IEEE-754", "VFPv3"};
323*d415bd75Srobert   return parseStringAttribute("ABI_FP_16bit_format", tag, ArrayRef(strings));
32409467b48Spatrick }
32509467b48Spatrick 
MPextension_use(AttrType tag)326097a140dSpatrick Error ARMAttributeParser::MPextension_use(AttrType tag) {
327097a140dSpatrick   static const char *strings[] = {"Not Permitted", "Permitted"};
328*d415bd75Srobert   return parseStringAttribute("MPextension_use", tag, ArrayRef(strings));
32909467b48Spatrick }
33009467b48Spatrick 
DIV_use(AttrType tag)331097a140dSpatrick Error ARMAttributeParser::DIV_use(AttrType tag) {
332097a140dSpatrick   static const char *strings[] = {"If Available", "Not Permitted", "Permitted"};
333*d415bd75Srobert   return parseStringAttribute("DIV_use", tag, ArrayRef(strings));
33409467b48Spatrick }
33509467b48Spatrick 
DSP_extension(AttrType tag)336097a140dSpatrick Error ARMAttributeParser::DSP_extension(AttrType tag) {
337097a140dSpatrick   static const char *strings[] = {"Not Permitted", "Permitted"};
338*d415bd75Srobert   return parseStringAttribute("DSP_extension", tag, ArrayRef(strings));
33909467b48Spatrick }
34009467b48Spatrick 
T2EE_use(AttrType tag)341097a140dSpatrick Error ARMAttributeParser::T2EE_use(AttrType tag) {
342097a140dSpatrick   static const char *strings[] = {"Not Permitted", "Permitted"};
343*d415bd75Srobert   return parseStringAttribute("T2EE_use", tag, ArrayRef(strings));
34409467b48Spatrick }
34509467b48Spatrick 
Virtualization_use(AttrType tag)346097a140dSpatrick Error ARMAttributeParser::Virtualization_use(AttrType tag) {
347097a140dSpatrick   static const char *strings[] = {"Not Permitted", "TrustZone",
348097a140dSpatrick                                   "Virtualization Extensions",
349097a140dSpatrick                                   "TrustZone + Virtualization Extensions"};
350*d415bd75Srobert   return parseStringAttribute("Virtualization_use", tag, ArrayRef(strings));
351*d415bd75Srobert }
352*d415bd75Srobert 
PAC_extension(ARMBuildAttrs::AttrType tag)353*d415bd75Srobert Error ARMAttributeParser::PAC_extension(ARMBuildAttrs::AttrType tag) {
354*d415bd75Srobert   static const char *strings[] = {"Not Permitted", "Permitted in NOP space",
355*d415bd75Srobert                                   "Permitted"};
356*d415bd75Srobert   return parseStringAttribute("PAC_extension", tag, ArrayRef(strings));
357*d415bd75Srobert }
358*d415bd75Srobert 
BTI_extension(ARMBuildAttrs::AttrType tag)359*d415bd75Srobert Error ARMAttributeParser::BTI_extension(ARMBuildAttrs::AttrType tag) {
360*d415bd75Srobert   static const char *strings[] = {"Not Permitted", "Permitted in NOP space",
361*d415bd75Srobert                                   "Permitted"};
362*d415bd75Srobert   return parseStringAttribute("BTI_extension", tag, ArrayRef(strings));
363*d415bd75Srobert }
364*d415bd75Srobert 
PACRET_use(ARMBuildAttrs::AttrType tag)365*d415bd75Srobert Error ARMAttributeParser::PACRET_use(ARMBuildAttrs::AttrType tag) {
366*d415bd75Srobert   static const char *strings[] = {"Not Used", "Used"};
367*d415bd75Srobert   return parseStringAttribute("PACRET_use", tag, ArrayRef(strings));
368*d415bd75Srobert }
369*d415bd75Srobert 
BTI_use(ARMBuildAttrs::AttrType tag)370*d415bd75Srobert Error ARMAttributeParser::BTI_use(ARMBuildAttrs::AttrType tag) {
371*d415bd75Srobert   static const char *strings[] = {"Not Used", "Used"};
372*d415bd75Srobert   return parseStringAttribute("BTI_use", tag, ArrayRef(strings));
37309467b48Spatrick }
37409467b48Spatrick 
nodefaults(AttrType tag)375097a140dSpatrick Error ARMAttributeParser::nodefaults(AttrType tag) {
376097a140dSpatrick   uint64_t value = de.getULEB128(cursor);
377097a140dSpatrick   printAttribute(tag, value, "Unspecified Tags UNDEFINED");
378097a140dSpatrick   return Error::success();
37909467b48Spatrick }
38009467b48Spatrick 
also_compatible_with(AttrType tag)381*d415bd75Srobert Error ARMAttributeParser::also_compatible_with(AttrType tag) {
382*d415bd75Srobert   // Parse value as a C string first in order to print it in escaped form later.
383*d415bd75Srobert   // Then, parse it again to catch errors or to pretty print if Tag_CPU_arch.
384*d415bd75Srobert   std::optional<Error> returnValue;
385*d415bd75Srobert 
386*d415bd75Srobert   SmallString<8> Description;
387*d415bd75Srobert   raw_svector_ostream DescStream(Description);
388*d415bd75Srobert 
389*d415bd75Srobert   uint64_t InitialOffset = cursor.tell();
390*d415bd75Srobert   StringRef RawStringValue = de.getCStrRef(cursor);
391*d415bd75Srobert   uint64_t FinalOffset = cursor.tell();
392*d415bd75Srobert   cursor.seek(InitialOffset);
393*d415bd75Srobert   uint64_t InnerTag = de.getULEB128(cursor);
394*d415bd75Srobert 
395*d415bd75Srobert   bool ValidInnerTag =
396*d415bd75Srobert       any_of(tagToStringMap, [InnerTag](const TagNameItem &Item) {
397*d415bd75Srobert         return Item.attr == InnerTag;
398*d415bd75Srobert       });
399*d415bd75Srobert 
400*d415bd75Srobert   if (!ValidInnerTag) {
401*d415bd75Srobert     returnValue =
402*d415bd75Srobert         createStringError(errc::argument_out_of_domain,
403*d415bd75Srobert                           Twine(InnerTag) + " is not a valid tag number");
404*d415bd75Srobert   } else {
405*d415bd75Srobert     switch (InnerTag) {
406*d415bd75Srobert     case ARMBuildAttrs::CPU_arch: {
407*d415bd75Srobert       uint64_t InnerValue = de.getULEB128(cursor);
408*d415bd75Srobert       auto strings = ArrayRef(CPU_arch_strings);
409*d415bd75Srobert       if (InnerValue >= strings.size()) {
410*d415bd75Srobert         returnValue = createStringError(
411*d415bd75Srobert             errc::argument_out_of_domain,
412*d415bd75Srobert             Twine(InnerValue) + " is not a valid " +
413*d415bd75Srobert                 ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) +
414*d415bd75Srobert                 " value");
415*d415bd75Srobert       } else {
416*d415bd75Srobert         DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
417*d415bd75Srobert                    << " = " << InnerValue;
418*d415bd75Srobert         if (strings[InnerValue])
419*d415bd75Srobert           DescStream << " (" << strings[InnerValue] << ')';
420*d415bd75Srobert       }
421*d415bd75Srobert       break;
422*d415bd75Srobert     }
423*d415bd75Srobert     case ARMBuildAttrs::also_compatible_with:
424*d415bd75Srobert       returnValue = createStringError(
425*d415bd75Srobert           errc::invalid_argument,
426*d415bd75Srobert           ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) +
427*d415bd75Srobert               " cannot be recursively defined");
428*d415bd75Srobert       break;
429*d415bd75Srobert     case ARMBuildAttrs::CPU_raw_name:
430*d415bd75Srobert     case ARMBuildAttrs::CPU_name:
431*d415bd75Srobert     case ARMBuildAttrs::compatibility:
432*d415bd75Srobert     case ARMBuildAttrs::conformance: {
433*d415bd75Srobert       StringRef InnerValue = de.getCStrRef(cursor);
434*d415bd75Srobert       DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
435*d415bd75Srobert                  << " = " << InnerValue;
436*d415bd75Srobert       break;
437*d415bd75Srobert     }
438*d415bd75Srobert     default: {
439*d415bd75Srobert       uint64_t InnerValue = de.getULEB128(cursor);
440*d415bd75Srobert       DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
441*d415bd75Srobert                  << " = " << InnerValue;
442*d415bd75Srobert     }
443*d415bd75Srobert     }
444*d415bd75Srobert   }
445*d415bd75Srobert 
446*d415bd75Srobert   setAttributeString(tag, RawStringValue);
447*d415bd75Srobert   if (sw) {
448*d415bd75Srobert     DictScope scope(*sw, "Attribute");
449*d415bd75Srobert     sw->printNumber("Tag", tag);
450*d415bd75Srobert     sw->printString("TagName",
451*d415bd75Srobert                     ELFAttrs::attrTypeAsString(tag, tagToStringMap, false));
452*d415bd75Srobert     sw->printStringEscaped("Value", RawStringValue);
453*d415bd75Srobert     if (!Description.empty()) {
454*d415bd75Srobert       sw->printString("Description", Description);
455*d415bd75Srobert     }
456*d415bd75Srobert   }
457*d415bd75Srobert 
458*d415bd75Srobert   cursor.seek(FinalOffset);
459*d415bd75Srobert 
460*d415bd75Srobert   return returnValue ? std::move(*returnValue) : Error::success();
461*d415bd75Srobert }
462*d415bd75Srobert 
handler(uint64_t tag,bool & handled)463097a140dSpatrick Error ARMAttributeParser::handler(uint64_t tag, bool &handled) {
464097a140dSpatrick   handled = false;
465*d415bd75Srobert   for (const auto &AH : displayRoutines) {
466*d415bd75Srobert     if (uint64_t(AH.attribute) == tag) {
467*d415bd75Srobert       if (Error e = (this->*AH.routine)(static_cast<AttrType>(tag)))
468097a140dSpatrick         return e;
469097a140dSpatrick       handled = true;
47009467b48Spatrick       break;
47109467b48Spatrick     }
47209467b48Spatrick   }
47309467b48Spatrick 
474097a140dSpatrick   return Error::success();
47509467b48Spatrick }
476