xref: /freebsd/contrib/llvm-project/llvm/lib/Support/ARMAttributeParser.cpp (revision bdd1243df58e60e85101c09001d9812a789b6bc4)
15ffd83dbSDimitry Andric //===- ARMAttributeParser.cpp - ARM Attribute Information Printer ---------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/Support/ARMAttributeParser.h"
100b57cec5SDimitry Andric #include "llvm/ADT/StringExtras.h"
11*bdd1243dSDimitry Andric #include "llvm/Support/ARMBuildAttributes.h"
12*bdd1243dSDimitry Andric #include "llvm/Support/Errc.h"
130b57cec5SDimitry Andric #include "llvm/Support/ScopedPrinter.h"
14*bdd1243dSDimitry Andric #include <optional>
150b57cec5SDimitry Andric 
160b57cec5SDimitry Andric using namespace llvm;
170b57cec5SDimitry Andric using namespace llvm::ARMBuildAttrs;
180b57cec5SDimitry Andric 
195ffd83dbSDimitry Andric #define ATTRIBUTE_HANDLER(attr)                                                \
205ffd83dbSDimitry Andric   { ARMBuildAttrs::attr, &ARMAttributeParser::attr }
210b57cec5SDimitry Andric 
225ffd83dbSDimitry Andric const ARMAttributeParser::DisplayHandler ARMAttributeParser::displayRoutines[] =
235ffd83dbSDimitry Andric     {
245ffd83dbSDimitry Andric         {ARMBuildAttrs::CPU_raw_name, &ARMAttributeParser::stringAttribute},
255ffd83dbSDimitry Andric         {ARMBuildAttrs::CPU_name, &ARMAttributeParser::stringAttribute},
260b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(CPU_arch),
270b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(CPU_arch_profile),
280b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ARM_ISA_use),
290b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(THUMB_ISA_use),
300b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(FP_arch),
310b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(WMMX_arch),
320b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(Advanced_SIMD_arch),
330b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(MVE_arch),
340b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(PCS_config),
350b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_PCS_R9_use),
360b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_PCS_RW_data),
370b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_PCS_RO_data),
380b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_PCS_GOT_use),
390b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_PCS_wchar_t),
400b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_FP_rounding),
410b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_FP_denormal),
420b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_FP_exceptions),
430b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_FP_user_exceptions),
440b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_FP_number_model),
450b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_align_needed),
460b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_align_preserved),
470b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_enum_size),
480b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_HardFP_use),
490b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_VFP_args),
500b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_WMMX_args),
510b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_optimization_goals),
520b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_FP_optimization_goals),
530b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(compatibility),
540b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(CPU_unaligned_access),
550b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(FP_HP_extension),
560b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(ABI_FP_16bit_format),
570b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(MPextension_use),
580b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(DIV_use),
590b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(DSP_extension),
600b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(T2EE_use),
610b57cec5SDimitry Andric         ATTRIBUTE_HANDLER(Virtualization_use),
624824e7fdSDimitry Andric         ATTRIBUTE_HANDLER(PAC_extension),
634824e7fdSDimitry Andric         ATTRIBUTE_HANDLER(BTI_extension),
644824e7fdSDimitry Andric         ATTRIBUTE_HANDLER(PACRET_use),
654824e7fdSDimitry Andric         ATTRIBUTE_HANDLER(BTI_use),
665ffd83dbSDimitry Andric         ATTRIBUTE_HANDLER(nodefaults),
67*bdd1243dSDimitry Andric         ATTRIBUTE_HANDLER(also_compatible_with),
680b57cec5SDimitry Andric };
690b57cec5SDimitry Andric 
700b57cec5SDimitry Andric #undef ATTRIBUTE_HANDLER
710b57cec5SDimitry Andric 
stringAttribute(AttrType tag)725ffd83dbSDimitry Andric Error ARMAttributeParser::stringAttribute(AttrType tag) {
735ffd83dbSDimitry Andric   StringRef tagName =
7404eeddc0SDimitry Andric       ELFAttrs::attrTypeAsString(tag, tagToStringMap, /*hasTagPrefix=*/false);
755ffd83dbSDimitry Andric   StringRef desc = de.getCStrRef(cursor);
765ffd83dbSDimitry Andric 
775ffd83dbSDimitry Andric   if (sw) {
785ffd83dbSDimitry Andric     DictScope scope(*sw, "Attribute");
795ffd83dbSDimitry Andric     sw->printNumber("Tag", tag);
805ffd83dbSDimitry Andric     if (!tagName.empty())
815ffd83dbSDimitry Andric       sw->printString("TagName", tagName);
825ffd83dbSDimitry Andric     sw->printString("Value", desc);
835ffd83dbSDimitry Andric   }
845ffd83dbSDimitry Andric   return Error::success();
850b57cec5SDimitry Andric }
860b57cec5SDimitry Andric 
87*bdd1243dSDimitry Andric static const char *CPU_arch_strings[] = {
88*bdd1243dSDimitry Andric     "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ",
89*bdd1243dSDimitry Andric     "ARM v6", "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M",
90*bdd1243dSDimitry Andric     "ARM v6S-M", "ARM v7E-M", "ARM v8-A", "ARM v8-R", "ARM v8-M Baseline",
91*bdd1243dSDimitry Andric     "ARM v8-M Mainline", nullptr, nullptr, nullptr, "ARM v8.1-M Mainline",
92*bdd1243dSDimitry Andric     "ARM v9-A"};
93*bdd1243dSDimitry Andric 
CPU_arch(AttrType tag)945ffd83dbSDimitry Andric Error ARMAttributeParser::CPU_arch(AttrType tag) {
95*bdd1243dSDimitry Andric   return parseStringAttribute("CPU_arch", tag, ArrayRef(CPU_arch_strings));
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric 
CPU_arch_profile(AttrType tag)985ffd83dbSDimitry Andric Error ARMAttributeParser::CPU_arch_profile(AttrType tag) {
995ffd83dbSDimitry Andric   uint64_t value = de.getULEB128(cursor);
1000b57cec5SDimitry Andric 
1015ffd83dbSDimitry Andric   StringRef profile;
1025ffd83dbSDimitry Andric   switch (value) {
1035ffd83dbSDimitry Andric   default: profile = "Unknown"; break;
1045ffd83dbSDimitry Andric   case 'A': profile = "Application"; break;
1055ffd83dbSDimitry Andric   case 'R': profile = "Real-time"; break;
1065ffd83dbSDimitry Andric   case 'M': profile = "Microcontroller"; break;
1075ffd83dbSDimitry Andric   case 'S': profile = "Classic"; break;
1085ffd83dbSDimitry Andric   case 0: profile = "None"; break;
1090b57cec5SDimitry Andric   }
1100b57cec5SDimitry Andric 
1115ffd83dbSDimitry Andric   printAttribute(tag, value, profile);
1125ffd83dbSDimitry Andric   return Error::success();
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
ARM_ISA_use(AttrType tag)1155ffd83dbSDimitry Andric Error ARMAttributeParser::ARM_ISA_use(AttrType tag) {
1165ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "Permitted"};
117*bdd1243dSDimitry Andric   return parseStringAttribute("ARM_ISA_use", tag, ArrayRef(strings));
1180b57cec5SDimitry Andric }
1190b57cec5SDimitry Andric 
THUMB_ISA_use(AttrType tag)1205ffd83dbSDimitry Andric Error ARMAttributeParser::THUMB_ISA_use(AttrType tag) {
121e8d8bef9SDimitry Andric   static const char *strings[] = {"Not Permitted", "Thumb-1", "Thumb-2", "Permitted"};
122*bdd1243dSDimitry Andric   return parseStringAttribute("THUMB_ISA_use", tag, ArrayRef(strings));
1230b57cec5SDimitry Andric }
1240b57cec5SDimitry Andric 
FP_arch(AttrType tag)1255ffd83dbSDimitry Andric Error ARMAttributeParser::FP_arch(AttrType tag) {
1265ffd83dbSDimitry Andric   static const char *strings[] = {
1275ffd83dbSDimitry Andric       "Not Permitted", "VFPv1",     "VFPv2",      "VFPv3",         "VFPv3-D16",
1285ffd83dbSDimitry Andric       "VFPv4",         "VFPv4-D16", "ARMv8-a FP", "ARMv8-a FP-D16"};
129*bdd1243dSDimitry Andric   return parseStringAttribute("FP_arch", tag, ArrayRef(strings));
1300b57cec5SDimitry Andric }
1310b57cec5SDimitry Andric 
WMMX_arch(AttrType tag)1325ffd83dbSDimitry Andric Error ARMAttributeParser::WMMX_arch(AttrType tag) {
1335ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "WMMXv1", "WMMXv2"};
134*bdd1243dSDimitry Andric   return parseStringAttribute("WMMX_arch", tag, ArrayRef(strings));
1350b57cec5SDimitry Andric }
1360b57cec5SDimitry Andric 
Advanced_SIMD_arch(AttrType tag)1375ffd83dbSDimitry Andric Error ARMAttributeParser::Advanced_SIMD_arch(AttrType tag) {
1385ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "NEONv1", "NEONv2+FMA",
1395ffd83dbSDimitry Andric                                   "ARMv8-a NEON", "ARMv8.1-a NEON"};
140*bdd1243dSDimitry Andric   return parseStringAttribute("Advanced_SIMD_arch", tag, ArrayRef(strings));
1410b57cec5SDimitry Andric }
1420b57cec5SDimitry Andric 
MVE_arch(AttrType tag)1435ffd83dbSDimitry Andric Error ARMAttributeParser::MVE_arch(AttrType tag) {
1445ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "MVE integer",
1455ffd83dbSDimitry Andric                                   "MVE integer and float"};
146*bdd1243dSDimitry Andric   return parseStringAttribute("MVE_arch", tag, ArrayRef(strings));
1470b57cec5SDimitry Andric }
1480b57cec5SDimitry Andric 
PCS_config(AttrType tag)1495ffd83dbSDimitry Andric Error ARMAttributeParser::PCS_config(AttrType tag) {
1505ffd83dbSDimitry Andric   static const char *strings[] = {
1510b57cec5SDimitry Andric     "None", "Bare Platform", "Linux Application", "Linux DSO", "Palm OS 2004",
1525ffd83dbSDimitry Andric     "Reserved (Palm OS)", "Symbian OS 2004", "Reserved (Symbian OS)"};
153*bdd1243dSDimitry Andric   return parseStringAttribute("PCS_config", tag, ArrayRef(strings));
1540b57cec5SDimitry Andric }
1550b57cec5SDimitry Andric 
ABI_PCS_R9_use(AttrType tag)1565ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_PCS_R9_use(AttrType tag) {
1575ffd83dbSDimitry Andric   static const char *strings[] = {"v6", "Static Base", "TLS", "Unused"};
158*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_PCS_R9_use", tag, ArrayRef(strings));
1590b57cec5SDimitry Andric }
1600b57cec5SDimitry Andric 
ABI_PCS_RW_data(AttrType tag)1615ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_PCS_RW_data(AttrType tag) {
1625ffd83dbSDimitry Andric   static const char *strings[] = {"Absolute", "PC-relative", "SB-relative",
1635ffd83dbSDimitry Andric                                   "Not Permitted"};
164*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_PCS_RW_data", tag, ArrayRef(strings));
1650b57cec5SDimitry Andric }
1660b57cec5SDimitry Andric 
ABI_PCS_RO_data(AttrType tag)1675ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_PCS_RO_data(AttrType tag) {
1685ffd83dbSDimitry Andric   static const char *strings[] = {"Absolute", "PC-relative", "Not Permitted"};
169*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_PCS_RO_data", tag, ArrayRef(strings));
1700b57cec5SDimitry Andric }
1710b57cec5SDimitry Andric 
ABI_PCS_GOT_use(AttrType tag)1725ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_PCS_GOT_use(AttrType tag) {
1735ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "Direct", "GOT-Indirect"};
174*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_PCS_GOT_use", tag, ArrayRef(strings));
1750b57cec5SDimitry Andric }
1760b57cec5SDimitry Andric 
ABI_PCS_wchar_t(AttrType tag)1775ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_PCS_wchar_t(AttrType tag) {
1785ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "Unknown", "2-byte",
1795ffd83dbSDimitry Andric                                   "Unknown", "4-byte"};
180*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_PCS_wchar_t", tag, ArrayRef(strings));
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric 
ABI_FP_rounding(AttrType tag)1835ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_FP_rounding(AttrType tag) {
1845ffd83dbSDimitry Andric   static const char *strings[] = {"IEEE-754", "Runtime"};
185*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_FP_rounding", tag, ArrayRef(strings));
1860b57cec5SDimitry Andric }
1870b57cec5SDimitry Andric 
ABI_FP_denormal(AttrType tag)1885ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_FP_denormal(AttrType tag) {
1895ffd83dbSDimitry Andric   static const char *strings[] = {"Unsupported", "IEEE-754", "Sign Only"};
190*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_FP_denormal", tag, ArrayRef(strings));
1910b57cec5SDimitry Andric }
1920b57cec5SDimitry Andric 
ABI_FP_exceptions(AttrType tag)1935ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_FP_exceptions(AttrType tag) {
1945ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "IEEE-754"};
195*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_FP_exceptions", tag, ArrayRef(strings));
1965ffd83dbSDimitry Andric }
ABI_FP_user_exceptions(AttrType tag)1975ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_FP_user_exceptions(AttrType tag) {
1985ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "IEEE-754"};
199*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_FP_user_exceptions", tag, ArrayRef(strings));
2000b57cec5SDimitry Andric }
2010b57cec5SDimitry Andric 
ABI_FP_number_model(AttrType tag)2025ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_FP_number_model(AttrType tag) {
2035ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "Finite Only", "RTABI",
2045ffd83dbSDimitry Andric                                   "IEEE-754"};
205*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_FP_number_model", tag, ArrayRef(strings));
2060b57cec5SDimitry Andric }
2070b57cec5SDimitry Andric 
ABI_align_needed(AttrType tag)2085ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_align_needed(AttrType tag) {
2095ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "8-byte alignment",
2105ffd83dbSDimitry Andric                                   "4-byte alignment", "Reserved"};
2110b57cec5SDimitry Andric 
2125ffd83dbSDimitry Andric   uint64_t value = de.getULEB128(cursor);
2130b57cec5SDimitry Andric 
2145ffd83dbSDimitry Andric   std::string description;
215*bdd1243dSDimitry Andric   if (value < std::size(strings))
2165ffd83dbSDimitry Andric     description = strings[value];
2175ffd83dbSDimitry Andric   else if (value <= 12)
2185ffd83dbSDimitry Andric     description = "8-byte alignment, " + utostr(1ULL << value) +
2195ffd83dbSDimitry Andric                   "-byte extended alignment";
2200b57cec5SDimitry Andric   else
2215ffd83dbSDimitry Andric     description = "Invalid";
2220b57cec5SDimitry Andric 
2235ffd83dbSDimitry Andric   printAttribute(tag, value, description);
2245ffd83dbSDimitry Andric   return Error::success();
2250b57cec5SDimitry Andric }
2260b57cec5SDimitry Andric 
ABI_align_preserved(AttrType tag)2275ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_align_preserved(AttrType tag) {
2285ffd83dbSDimitry Andric   static const char *strings[] = {"Not Required", "8-byte data alignment",
2295ffd83dbSDimitry Andric                                   "8-byte data and code alignment", "Reserved"};
2300b57cec5SDimitry Andric 
2315ffd83dbSDimitry Andric   uint64_t value = de.getULEB128(cursor);
2320b57cec5SDimitry Andric 
2335ffd83dbSDimitry Andric   std::string description;
234*bdd1243dSDimitry Andric   if (value < std::size(strings))
2355ffd83dbSDimitry Andric     description = std::string(strings[value]);
2365ffd83dbSDimitry Andric   else if (value <= 12)
2375ffd83dbSDimitry Andric     description = std::string("8-byte stack alignment, ") +
2385ffd83dbSDimitry Andric                   utostr(1ULL << value) + std::string("-byte data alignment");
2390b57cec5SDimitry Andric   else
2405ffd83dbSDimitry Andric     description = "Invalid";
2410b57cec5SDimitry Andric 
2425ffd83dbSDimitry Andric   printAttribute(tag, value, description);
2435ffd83dbSDimitry Andric   return Error::success();
2440b57cec5SDimitry Andric }
2450b57cec5SDimitry Andric 
ABI_enum_size(AttrType tag)2465ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_enum_size(AttrType tag) {
2475ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "Packed", "Int32",
2485ffd83dbSDimitry Andric                                   "External Int32"};
249*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_enum_size", tag, ArrayRef(strings));
2500b57cec5SDimitry Andric }
2510b57cec5SDimitry Andric 
ABI_HardFP_use(AttrType tag)2525ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_HardFP_use(AttrType tag) {
2535ffd83dbSDimitry Andric   static const char *strings[] = {"Tag_FP_arch", "Single-Precision", "Reserved",
2545ffd83dbSDimitry Andric                                   "Tag_FP_arch (deprecated)"};
255*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_HardFP_use", tag, ArrayRef(strings));
2560b57cec5SDimitry Andric }
2570b57cec5SDimitry Andric 
ABI_VFP_args(AttrType tag)2585ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_VFP_args(AttrType tag) {
2595ffd83dbSDimitry Andric   static const char *strings[] = {"AAPCS", "AAPCS VFP", "Custom",
2605ffd83dbSDimitry Andric                                   "Not Permitted"};
261*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_VFP_args", tag, ArrayRef(strings));
2620b57cec5SDimitry Andric }
2630b57cec5SDimitry Andric 
ABI_WMMX_args(AttrType tag)2645ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_WMMX_args(AttrType tag) {
2655ffd83dbSDimitry Andric   static const char *strings[] = {"AAPCS", "iWMMX", "Custom"};
266*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_WMMX_args", tag, ArrayRef(strings));
2670b57cec5SDimitry Andric }
2680b57cec5SDimitry Andric 
ABI_optimization_goals(AttrType tag)2695ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_optimization_goals(AttrType tag) {
2705ffd83dbSDimitry Andric   static const char *strings[] = {
2710b57cec5SDimitry Andric     "None", "Speed", "Aggressive Speed", "Size", "Aggressive Size", "Debugging",
2720b57cec5SDimitry Andric     "Best Debugging"
2730b57cec5SDimitry Andric   };
274*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_optimization_goals", tag, ArrayRef(strings));
2750b57cec5SDimitry Andric }
2760b57cec5SDimitry Andric 
ABI_FP_optimization_goals(AttrType tag)2775ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_FP_optimization_goals(AttrType tag) {
2785ffd83dbSDimitry Andric   static const char *strings[] = {
2795ffd83dbSDimitry Andric       "None",     "Speed",        "Aggressive Speed", "Size", "Aggressive Size",
2805ffd83dbSDimitry Andric       "Accuracy", "Best Accuracy"};
2815ffd83dbSDimitry Andric   return parseStringAttribute("ABI_FP_optimization_goals", tag,
282*bdd1243dSDimitry Andric                               ArrayRef(strings));
2830b57cec5SDimitry Andric }
2840b57cec5SDimitry Andric 
compatibility(AttrType tag)2855ffd83dbSDimitry Andric Error ARMAttributeParser::compatibility(AttrType tag) {
2865ffd83dbSDimitry Andric   uint64_t integer = de.getULEB128(cursor);
2875ffd83dbSDimitry Andric   StringRef string = de.getCStrRef(cursor);
2880b57cec5SDimitry Andric 
2895ffd83dbSDimitry Andric   if (sw) {
2905ffd83dbSDimitry Andric     DictScope scope(*sw, "Attribute");
2915ffd83dbSDimitry Andric     sw->printNumber("Tag", tag);
2925ffd83dbSDimitry Andric     sw->startLine() << "Value: " << integer << ", " << string << '\n';
2935ffd83dbSDimitry Andric     sw->printString("TagName",
2945ffd83dbSDimitry Andric                     ELFAttrs::attrTypeAsString(tag, tagToStringMap,
2955ffd83dbSDimitry Andric                                                /*hasTagPrefix=*/false));
2965ffd83dbSDimitry Andric     switch (integer) {
2970b57cec5SDimitry Andric     case 0:
2985ffd83dbSDimitry Andric       sw->printString("Description", StringRef("No Specific Requirements"));
2990b57cec5SDimitry Andric       break;
3000b57cec5SDimitry Andric     case 1:
3015ffd83dbSDimitry Andric       sw->printString("Description", StringRef("AEABI Conformant"));
3020b57cec5SDimitry Andric       break;
3030b57cec5SDimitry Andric     default:
3045ffd83dbSDimitry Andric       sw->printString("Description", StringRef("AEABI Non-Conformant"));
3050b57cec5SDimitry Andric       break;
3060b57cec5SDimitry Andric     }
3070b57cec5SDimitry Andric   }
3085ffd83dbSDimitry Andric   return Error::success();
3090b57cec5SDimitry Andric }
3100b57cec5SDimitry Andric 
CPU_unaligned_access(AttrType tag)3115ffd83dbSDimitry Andric Error ARMAttributeParser::CPU_unaligned_access(AttrType tag) {
3125ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "v6-style"};
313*bdd1243dSDimitry Andric   return parseStringAttribute("CPU_unaligned_access", tag, ArrayRef(strings));
3140b57cec5SDimitry Andric }
3150b57cec5SDimitry Andric 
FP_HP_extension(AttrType tag)3165ffd83dbSDimitry Andric Error ARMAttributeParser::FP_HP_extension(AttrType tag) {
3175ffd83dbSDimitry Andric   static const char *strings[] = {"If Available", "Permitted"};
318*bdd1243dSDimitry Andric   return parseStringAttribute("FP_HP_extension", tag, ArrayRef(strings));
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric 
ABI_FP_16bit_format(AttrType tag)3215ffd83dbSDimitry Andric Error ARMAttributeParser::ABI_FP_16bit_format(AttrType tag) {
3225ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "IEEE-754", "VFPv3"};
323*bdd1243dSDimitry Andric   return parseStringAttribute("ABI_FP_16bit_format", tag, ArrayRef(strings));
3240b57cec5SDimitry Andric }
3250b57cec5SDimitry Andric 
MPextension_use(AttrType tag)3265ffd83dbSDimitry Andric Error ARMAttributeParser::MPextension_use(AttrType tag) {
3275ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "Permitted"};
328*bdd1243dSDimitry Andric   return parseStringAttribute("MPextension_use", tag, ArrayRef(strings));
3290b57cec5SDimitry Andric }
3300b57cec5SDimitry Andric 
DIV_use(AttrType tag)3315ffd83dbSDimitry Andric Error ARMAttributeParser::DIV_use(AttrType tag) {
3325ffd83dbSDimitry Andric   static const char *strings[] = {"If Available", "Not Permitted", "Permitted"};
333*bdd1243dSDimitry Andric   return parseStringAttribute("DIV_use", tag, ArrayRef(strings));
3340b57cec5SDimitry Andric }
3350b57cec5SDimitry Andric 
DSP_extension(AttrType tag)3365ffd83dbSDimitry Andric Error ARMAttributeParser::DSP_extension(AttrType tag) {
3375ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "Permitted"};
338*bdd1243dSDimitry Andric   return parseStringAttribute("DSP_extension", tag, ArrayRef(strings));
3390b57cec5SDimitry Andric }
3400b57cec5SDimitry Andric 
T2EE_use(AttrType tag)3415ffd83dbSDimitry Andric Error ARMAttributeParser::T2EE_use(AttrType tag) {
3425ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "Permitted"};
343*bdd1243dSDimitry Andric   return parseStringAttribute("T2EE_use", tag, ArrayRef(strings));
3440b57cec5SDimitry Andric }
3450b57cec5SDimitry Andric 
Virtualization_use(AttrType tag)3465ffd83dbSDimitry Andric Error ARMAttributeParser::Virtualization_use(AttrType tag) {
3475ffd83dbSDimitry Andric   static const char *strings[] = {"Not Permitted", "TrustZone",
3485ffd83dbSDimitry Andric                                   "Virtualization Extensions",
3495ffd83dbSDimitry Andric                                   "TrustZone + Virtualization Extensions"};
350*bdd1243dSDimitry Andric   return parseStringAttribute("Virtualization_use", tag, ArrayRef(strings));
3510b57cec5SDimitry Andric }
3520b57cec5SDimitry Andric 
PAC_extension(ARMBuildAttrs::AttrType tag)3534824e7fdSDimitry Andric Error ARMAttributeParser::PAC_extension(ARMBuildAttrs::AttrType tag) {
3544824e7fdSDimitry Andric   static const char *strings[] = {"Not Permitted", "Permitted in NOP space",
3554824e7fdSDimitry Andric                                   "Permitted"};
356*bdd1243dSDimitry Andric   return parseStringAttribute("PAC_extension", tag, ArrayRef(strings));
3574824e7fdSDimitry Andric }
3584824e7fdSDimitry Andric 
BTI_extension(ARMBuildAttrs::AttrType tag)3594824e7fdSDimitry Andric Error ARMAttributeParser::BTI_extension(ARMBuildAttrs::AttrType tag) {
3604824e7fdSDimitry Andric   static const char *strings[] = {"Not Permitted", "Permitted in NOP space",
3614824e7fdSDimitry Andric                                   "Permitted"};
362*bdd1243dSDimitry Andric   return parseStringAttribute("BTI_extension", tag, ArrayRef(strings));
3634824e7fdSDimitry Andric }
3644824e7fdSDimitry Andric 
PACRET_use(ARMBuildAttrs::AttrType tag)3654824e7fdSDimitry Andric Error ARMAttributeParser::PACRET_use(ARMBuildAttrs::AttrType tag) {
3664824e7fdSDimitry Andric   static const char *strings[] = {"Not Used", "Used"};
367*bdd1243dSDimitry Andric   return parseStringAttribute("PACRET_use", tag, ArrayRef(strings));
3684824e7fdSDimitry Andric }
3694824e7fdSDimitry Andric 
BTI_use(ARMBuildAttrs::AttrType tag)3704824e7fdSDimitry Andric Error ARMAttributeParser::BTI_use(ARMBuildAttrs::AttrType tag) {
3714824e7fdSDimitry Andric   static const char *strings[] = {"Not Used", "Used"};
372*bdd1243dSDimitry Andric   return parseStringAttribute("BTI_use", tag, ArrayRef(strings));
3734824e7fdSDimitry Andric }
3744824e7fdSDimitry Andric 
nodefaults(AttrType tag)3755ffd83dbSDimitry Andric Error ARMAttributeParser::nodefaults(AttrType tag) {
3765ffd83dbSDimitry Andric   uint64_t value = de.getULEB128(cursor);
3775ffd83dbSDimitry Andric   printAttribute(tag, value, "Unspecified Tags UNDEFINED");
3785ffd83dbSDimitry Andric   return Error::success();
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric 
also_compatible_with(AttrType tag)381*bdd1243dSDimitry Andric Error ARMAttributeParser::also_compatible_with(AttrType tag) {
382*bdd1243dSDimitry Andric   // Parse value as a C string first in order to print it in escaped form later.
383*bdd1243dSDimitry Andric   // Then, parse it again to catch errors or to pretty print if Tag_CPU_arch.
384*bdd1243dSDimitry Andric   std::optional<Error> returnValue;
385*bdd1243dSDimitry Andric 
386*bdd1243dSDimitry Andric   SmallString<8> Description;
387*bdd1243dSDimitry Andric   raw_svector_ostream DescStream(Description);
388*bdd1243dSDimitry Andric 
389*bdd1243dSDimitry Andric   uint64_t InitialOffset = cursor.tell();
390*bdd1243dSDimitry Andric   StringRef RawStringValue = de.getCStrRef(cursor);
391*bdd1243dSDimitry Andric   uint64_t FinalOffset = cursor.tell();
392*bdd1243dSDimitry Andric   cursor.seek(InitialOffset);
393*bdd1243dSDimitry Andric   uint64_t InnerTag = de.getULEB128(cursor);
394*bdd1243dSDimitry Andric 
395*bdd1243dSDimitry Andric   bool ValidInnerTag =
396*bdd1243dSDimitry Andric       any_of(tagToStringMap, [InnerTag](const TagNameItem &Item) {
397*bdd1243dSDimitry Andric         return Item.attr == InnerTag;
398*bdd1243dSDimitry Andric       });
399*bdd1243dSDimitry Andric 
400*bdd1243dSDimitry Andric   if (!ValidInnerTag) {
401*bdd1243dSDimitry Andric     returnValue =
402*bdd1243dSDimitry Andric         createStringError(errc::argument_out_of_domain,
403*bdd1243dSDimitry Andric                           Twine(InnerTag) + " is not a valid tag number");
404*bdd1243dSDimitry Andric   } else {
405*bdd1243dSDimitry Andric     switch (InnerTag) {
406*bdd1243dSDimitry Andric     case ARMBuildAttrs::CPU_arch: {
407*bdd1243dSDimitry Andric       uint64_t InnerValue = de.getULEB128(cursor);
408*bdd1243dSDimitry Andric       auto strings = ArrayRef(CPU_arch_strings);
409*bdd1243dSDimitry Andric       if (InnerValue >= strings.size()) {
410*bdd1243dSDimitry Andric         returnValue = createStringError(
411*bdd1243dSDimitry Andric             errc::argument_out_of_domain,
412*bdd1243dSDimitry Andric             Twine(InnerValue) + " is not a valid " +
413*bdd1243dSDimitry Andric                 ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) +
414*bdd1243dSDimitry Andric                 " value");
415*bdd1243dSDimitry Andric       } else {
416*bdd1243dSDimitry Andric         DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
417*bdd1243dSDimitry Andric                    << " = " << InnerValue;
418*bdd1243dSDimitry Andric         if (strings[InnerValue])
419*bdd1243dSDimitry Andric           DescStream << " (" << strings[InnerValue] << ')';
420*bdd1243dSDimitry Andric       }
421*bdd1243dSDimitry Andric       break;
422*bdd1243dSDimitry Andric     }
423*bdd1243dSDimitry Andric     case ARMBuildAttrs::also_compatible_with:
424*bdd1243dSDimitry Andric       returnValue = createStringError(
425*bdd1243dSDimitry Andric           errc::invalid_argument,
426*bdd1243dSDimitry Andric           ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) +
427*bdd1243dSDimitry Andric               " cannot be recursively defined");
428*bdd1243dSDimitry Andric       break;
429*bdd1243dSDimitry Andric     case ARMBuildAttrs::CPU_raw_name:
430*bdd1243dSDimitry Andric     case ARMBuildAttrs::CPU_name:
431*bdd1243dSDimitry Andric     case ARMBuildAttrs::compatibility:
432*bdd1243dSDimitry Andric     case ARMBuildAttrs::conformance: {
433*bdd1243dSDimitry Andric       StringRef InnerValue = de.getCStrRef(cursor);
434*bdd1243dSDimitry Andric       DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
435*bdd1243dSDimitry Andric                  << " = " << InnerValue;
436*bdd1243dSDimitry Andric       break;
437*bdd1243dSDimitry Andric     }
438*bdd1243dSDimitry Andric     default: {
439*bdd1243dSDimitry Andric       uint64_t InnerValue = de.getULEB128(cursor);
440*bdd1243dSDimitry Andric       DescStream << ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap)
441*bdd1243dSDimitry Andric                  << " = " << InnerValue;
442*bdd1243dSDimitry Andric     }
443*bdd1243dSDimitry Andric     }
444*bdd1243dSDimitry Andric   }
445*bdd1243dSDimitry Andric 
446*bdd1243dSDimitry Andric   setAttributeString(tag, RawStringValue);
447*bdd1243dSDimitry Andric   if (sw) {
448*bdd1243dSDimitry Andric     DictScope scope(*sw, "Attribute");
449*bdd1243dSDimitry Andric     sw->printNumber("Tag", tag);
450*bdd1243dSDimitry Andric     sw->printString("TagName",
451*bdd1243dSDimitry Andric                     ELFAttrs::attrTypeAsString(tag, tagToStringMap, false));
452*bdd1243dSDimitry Andric     sw->printStringEscaped("Value", RawStringValue);
453*bdd1243dSDimitry Andric     if (!Description.empty()) {
454*bdd1243dSDimitry Andric       sw->printString("Description", Description);
455*bdd1243dSDimitry Andric     }
456*bdd1243dSDimitry Andric   }
457*bdd1243dSDimitry Andric 
458*bdd1243dSDimitry Andric   cursor.seek(FinalOffset);
459*bdd1243dSDimitry Andric 
460*bdd1243dSDimitry Andric   return returnValue ? std::move(*returnValue) : Error::success();
461*bdd1243dSDimitry Andric }
462*bdd1243dSDimitry Andric 
handler(uint64_t tag,bool & handled)4635ffd83dbSDimitry Andric Error ARMAttributeParser::handler(uint64_t tag, bool &handled) {
4645ffd83dbSDimitry Andric   handled = false;
465*bdd1243dSDimitry Andric   for (const auto &AH : displayRoutines) {
466*bdd1243dSDimitry Andric     if (uint64_t(AH.attribute) == tag) {
467*bdd1243dSDimitry Andric       if (Error e = (this->*AH.routine)(static_cast<AttrType>(tag)))
4685ffd83dbSDimitry Andric         return e;
4695ffd83dbSDimitry Andric       handled = true;
4700b57cec5SDimitry Andric       break;
4710b57cec5SDimitry Andric     }
4720b57cec5SDimitry Andric   }
4730b57cec5SDimitry Andric 
4745ffd83dbSDimitry Andric   return Error::success();
4750b57cec5SDimitry Andric }
476