diff --git a/llvm/include/llvm/Support/ARMAttributeParser.h b/llvm/include/llvm/Support/ARMAttributeParser.h --- a/llvm/include/llvm/Support/ARMAttributeParser.h +++ b/llvm/include/llvm/Support/ARMAttributeParser.h @@ -70,6 +70,7 @@ Error PACRET_use(ARMBuildAttrs::AttrType tag); Error BTI_use(ARMBuildAttrs::AttrType tag); Error nodefaults(ARMBuildAttrs::AttrType tag); + Error also_compatible_with(ARMBuildAttrs::AttrType tag); public: ARMAttributeParser(ScopedPrinter *sw) diff --git a/llvm/lib/Support/ARMAttributeParser.cpp b/llvm/lib/Support/ARMAttributeParser.cpp --- a/llvm/lib/Support/ARMAttributeParser.cpp +++ b/llvm/lib/Support/ARMAttributeParser.cpp @@ -9,6 +9,8 @@ #include "llvm/Support/ARMAttributeParser.h" #include "llvm/ADT/STLArrayExtras.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/ARMBuildAttributes.h" +#include "llvm/Support/Errc.h" #include "llvm/Support/ScopedPrinter.h" using namespace llvm; @@ -62,6 +64,7 @@ ATTRIBUTE_HANDLER(PACRET_use), ATTRIBUTE_HANDLER(BTI_use), ATTRIBUTE_HANDLER(nodefaults), + ATTRIBUTE_HANDLER(also_compatible_with), }; #undef ATTRIBUTE_HANDLER @@ -81,15 +84,15 @@ return Error::success(); } +static const char *CPU_arch_strings[] = { + "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", + "ARM v6", "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", + "ARM v6S-M", "ARM v7E-M", "ARM v8-A", "ARM v8-R", "ARM v8-M Baseline", + "ARM v8-M Mainline", nullptr, nullptr, nullptr, "ARM v8.1-M Mainline", + "ARM v9-A"}; + Error ARMAttributeParser::CPU_arch(AttrType tag) { - static const char *strings[] = { - "Pre-v4", "ARM v4", "ARM v4T", "ARM v5T", "ARM v5TE", "ARM v5TEJ", "ARM v6", - "ARM v6KZ", "ARM v6T2", "ARM v6K", "ARM v7", "ARM v6-M", "ARM v6S-M", - "ARM v7E-M", "ARM v8-A", "ARM v8-R", - "ARM v8-M Baseline", "ARM v8-M Mainline", nullptr, nullptr, nullptr, - "ARM v8.1-M Mainline", "ARM v9-A" - }; - return parseStringAttribute("CPU_arch", tag, makeArrayRef(strings)); + return parseStringAttribute("CPU_arch", tag, makeArrayRef(CPU_arch_strings)); } Error ARMAttributeParser::CPU_arch_profile(AttrType tag) { @@ -380,6 +383,65 @@ return Error::success(); } +Error ARMAttributeParser::also_compatible_with(AttrType tag) { + // Parse value as a C string first in order to print it in escaped form later. + // Then, parse it again to catch errors or to pretty print if Tag_CPU_arch. + uint64_t InitialOffset = cursor.tell(); + StringRef RawStringValue = de.getCStrRef(cursor); + uint64_t FinalOffset = cursor.tell(); + StringRef Description; + + auto PrintAndRestoreCursorState = [&]() { + DictScope scope(*sw, "Attribute"); + sw->printNumber("Tag", tag); + sw->printString("TagName", + ELFAttrs::attrTypeAsString(tag, tagToStringMap, false)); + sw->printString("Value", encodeAttrTagValuePair(RawStringValue)); + if (!Description.empty()) { + sw->printString("Description", Description); + } + cursor.seek(FinalOffset); + }; + + cursor.seek(InitialOffset); + uint64_t InnerTag = de.getULEB128(cursor); + + bool ValidInnerTag = + any_of(tagToStringMap, [InnerTag](const TagNameItem &Item) { + return Item.attr == InnerTag; + }); + + if (!ValidInnerTag) { + PrintAndRestoreCursorState(); + return createStringError(errc::argument_out_of_domain, + Twine(InnerTag) + " is not a valid tag number"); + } + + if (InnerTag == ARMBuildAttrs::also_compatible_with) { + PrintAndRestoreCursorState(); + return createStringError( + errc::invalid_argument, + ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) + + " cannot be recursively defined"); + } else if (InnerTag == ARMBuildAttrs::CPU_arch) { + uint64_t InnerValue = de.getULEB128(cursor); + auto strings = makeArrayRef(CPU_arch_strings); + if (InnerValue >= strings.size()) { + PrintAndRestoreCursorState(); + return createStringError( + errc::argument_out_of_domain, + Twine(InnerValue) + " is not a valid " + + ELFAttrs::attrTypeAsString(InnerTag, tagToStringMap) + + " value"); + } else + Description = strings[InnerValue]; + } + + PrintAndRestoreCursorState(); + + return Error::success(); +} + Error ARMAttributeParser::handler(uint64_t tag, bool &handled) { handled = false; for (unsigned AHI = 0, AHE = array_lengthof(displayRoutines); AHI != AHE; diff --git a/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_arch.s b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_arch.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_arch.s @@ -0,0 +1,6 @@ +@ RUN: llvm-mc -triple arm -filetype obj -o - %s | \ +@ RUN: llvm-readobj -A - 2>&1 | \ +@ RUN: FileCheck %s --check-prefix=CHECK-WARNING + +.eabi_attribute Tag_also_compatible_with, "\006\143" +@ CHECK-WARNING: 99 is not a valid Tag_CPU_arch value diff --git a/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_tag.s b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_tag.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-invalid_tag.s @@ -0,0 +1,6 @@ +@ RUN: llvm-mc -triple arm -filetype obj -o - %s | \ +@ RUN: llvm-readobj -A - 2>&1 | \ +@ RUN: FileCheck %s --check-prefix=CHECK-WARNING + +.eabi_attribute Tag_also_compatible_with, "\074\001" +@ CHECK-WARNING: 60 is not a valid tag number diff --git a/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-recursive.s b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-recursive.s new file mode 100644 --- /dev/null +++ b/llvm/test/MC/ARM/directive-eabi_attribute-also_compatible_with-recursive.s @@ -0,0 +1,6 @@ +@ RUN: llvm-mc -triple arm -filetype obj -o - %s | \ +@ RUN: llvm-readobj -A - 2>&1 | \ +@ RUN: FileCheck %s --check-prefix=CHECK-WARNING + +.eabi_attribute Tag_also_compatible_with, "\101\006\017" +@ CHECK-WARNING: Tag_also_compatible_with cannot be recursively defined diff --git a/llvm/test/MC/ARM/directive-eabi_attribute.s b/llvm/test/MC/ARM/directive-eabi_attribute.s --- a/llvm/test/MC/ARM/directive-eabi_attribute.s +++ b/llvm/test/MC/ARM/directive-eabi_attribute.s @@ -234,13 +234,11 @@ @ CHECK-OBJ-NEXT: TagName: nodefaults @ CHECK-OBJ-NEXT: Description: Unspecified Tags UNDEFINED .eabi_attribute Tag_also_compatible_with, "\006\017" -@ The value for Tag_also_compatible_with should be a pair of a tag (ULEB128) + -@ a value (ULEB128 + null or NTBS). llvm-readobj doesn't now how to process -@ this yet, so we use the encoded value explicitly here. @ CHECK: .eabi_attribute 65, "\006\017" @ CHECK-OBJ: Tag: 65 @ CHECK-OBJ-NEXT: TagName: also_compatible_with -@ CHECK-OBJ-NEXT: Value: +@ CHECK-OBJ-NEXT: Value: \006\017 +@ CHECK-OBJ-NEXT: Description: ARM v8-R .eabi_attribute Tag_T2EE_use, 0 @ CHECK: .eabi_attribute 66, 0 @ CHECK-OBJ: Tag: 66