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