[llvm] ba9caf9 - [Arm] Fix parsing and emission of Tag_also_compatible_with eabi attribute

Lucas Prates via llvm-commits llvm-commits at lists.llvm.org
Mon Aug 1 05:28:08 PDT 2022


Author: Lucas Prates
Date: 2022-08-01T13:28:01+01:00
New Revision: ba9caf91708abb052e22982d2665abb50e9759cb

URL: https://github.com/llvm/llvm-project/commit/ba9caf91708abb052e22982d2665abb50e9759cb
DIFF: https://github.com/llvm/llvm-project/commit/ba9caf91708abb052e22982d2665abb50e9759cb.diff

LOG: [Arm] Fix parsing and emission of Tag_also_compatible_with eabi attribute

According to the ABI for the Arm Architecture, the value for the
Tag_also_compatible_with eabi attribute is represented by an NTBS entry.
This string value, in turn, is composed of a pair of tag+value encoded
in one of two formats:
- ULEB128: tag, ULEB128: value, 0.
- ULEB128: tag, NBTS: data.
(See [[ https://github.com/ARM-software/abi-aa/blob/60a8eb8c55e999d74dac5e368fc9d7e36e38dda4/addenda32/addenda32.rst#3373secondary-compatibility-tag | section 3.3.7.3 on the Addenda to, and Errata in, the ABI for the Arm Architecture ]].)

Currently the Arm assembly parser and streamer ignore the encoding of
the attribute's NTBS value, which can result in incorrect attributes
being emitted in both assembly and object file outputs.

This patch fixes these issues by properly handing the value's encoding.
An update to llvm-readobj to properly handle the attribute's value will be
covered by a separate patch.

Patch by Victor Campos and Lucas Prates.

Reviewed By: vhscampos

Differential Revision: https://reviews.llvm.org/D129500

Added: 
    

Modified: 
    llvm/include/llvm/Support/ARMBuildAttributes.h
    llvm/lib/Support/ARMBuildAttrs.cpp
    llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
    llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
    llvm/test/CodeGen/ARM/build-attributes-encoding.s
    llvm/test/MC/ARM/directive-eabi_attribute.s

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/ARMBuildAttributes.h b/llvm/include/llvm/Support/ARMBuildAttributes.h
index 35f8992ca9329..1965beed29273 100644
--- a/llvm/include/llvm/Support/ARMBuildAttributes.h
+++ b/llvm/include/llvm/Support/ARMBuildAttributes.h
@@ -263,6 +263,8 @@ enum {
   PACRETUsed = 1
 };
 
+std::string encodeAttrTagValuePair(StringRef OriginalString);
+
 } // namespace ARMBuildAttrs
 } // namespace llvm
 

diff  --git a/llvm/lib/Support/ARMBuildAttrs.cpp b/llvm/lib/Support/ARMBuildAttrs.cpp
index 815cfc62a4b0e..c39013659a275 100644
--- a/llvm/lib/Support/ARMBuildAttrs.cpp
+++ b/llvm/lib/Support/ARMBuildAttrs.cpp
@@ -7,6 +7,11 @@
 //===----------------------------------------------------------------------===//
 
 #include "llvm/Support/ARMBuildAttributes.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/LEB128.h"
+#include <iomanip>
+#include <sstream>
 
 using namespace llvm;
 
@@ -71,3 +76,39 @@ constexpr TagNameMap ARMAttributeTags{tagData};
 const TagNameMap &llvm::ARMBuildAttrs::getARMAttributeTags() {
   return ARMAttributeTags;
 }
+
+static std::string getEncodedULEB128AsText(const uint8_t *Value,
+                                           unsigned Size) {
+  std::stringstream SS;
+  for (unsigned i = 0; i < Size; ++i) {
+    SS << "\\" << std::setfill('0') << std::setw(3) << std::oct
+       << int(Value[i]);
+  }
+  return SS.str();
+}
+
+std::string
+llvm::ARMBuildAttrs::encodeAttrTagValuePair(StringRef OriginalString) {
+  auto BytesBegin = reinterpret_cast<const uint8_t *>(OriginalString.data());
+  auto BytesEnd = BytesBegin + OriginalString.size();
+
+  unsigned N = 0;
+  const char *Error = nullptr;
+  unsigned Tag = decodeULEB128(BytesBegin, &N, BytesEnd, &Error);
+  if (Error)
+    report_fatal_error("Could not decode Tag value: " + Twine(Error));
+
+  std::string EncodedPair = getEncodedULEB128AsText(BytesBegin, N);
+  switch (Tag) {
+  case ARMBuildAttrs::CPU_raw_name:
+  case ARMBuildAttrs::CPU_name:
+  case ARMBuildAttrs::compatibility:
+  case ARMBuildAttrs::conformance:
+    EncodedPair += OriginalString.substr(N);
+    break;
+  default:
+    EncodedPair +=
+        getEncodedULEB128AsText(BytesBegin + N, OriginalString.size() - N);
+  }
+  return EncodedPair;
+}

diff  --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
index b725ea3a84e5d..a68f7f1519b7d 100644
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -11439,12 +11439,20 @@ bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
       return true;
   }
 
+  std::string EscapedValue;
   if (IsStringValue) {
     if (Parser.getTok().isNot(AsmToken::String))
       return Error(Parser.getTok().getLoc(), "bad string constant");
 
-    StringValue = Parser.getTok().getStringContents();
-    Parser.Lex();
+    if (Tag == ARMBuildAttrs::also_compatible_with) {
+      if (Parser.parseEscapedString(EscapedValue))
+        return Error(Parser.getTok().getLoc(), "bad escaped string constant");
+
+      StringValue = EscapedValue;
+    } else {
+      StringValue = Parser.getTok().getStringContents();
+      Parser.Lex();
+    }
   }
 
   if (Parser.parseEOL())

diff  --git a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
index d74da27fbc4f1..24ffa0c0703fc 100644
--- a/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
+++ b/llvm/lib/Target/ARM/MCTargetDesc/ARMELFStreamer.cpp
@@ -202,7 +202,12 @@ void ARMTargetAsmStreamer::emitTextAttribute(unsigned Attribute,
     OS << "\t.cpu\t" << String.lower();
     break;
   default:
-    OS << "\t.eabi_attribute\t" << Attribute << ", \"" << String << "\"";
+    OS << "\t.eabi_attribute\t" << Attribute << ", \"";
+    if (Attribute == ARMBuildAttrs::also_compatible_with)
+      OS << ARMBuildAttrs::encodeAttrTagValuePair(String);
+    else
+      OS << String;
+    OS << "\"";
     if (IsVerboseAsm) {
       StringRef Name = ELFAttrs::attrTypeAsString(
           Attribute, ARMBuildAttrs::getARMAttributeTags());

diff  --git a/llvm/test/CodeGen/ARM/build-attributes-encoding.s b/llvm/test/CodeGen/ARM/build-attributes-encoding.s
index 1ba607c5bbc1c..8de3758c0bb4d 100644
--- a/llvm/test/CodeGen/ARM/build-attributes-encoding.s
+++ b/llvm/test/CodeGen/ARM/build-attributes-encoding.s
@@ -63,6 +63,9 @@
 // Tag_BTI_extension (=52)
 .eabi_attribute 52, 0
 
+// Tag_also_compatible_with (=65)
+.eabi_attribute 65, "\006\017"
+
 // Tag_BTI_use (=74)
 .eabi_attribute 74, 0
 
@@ -86,16 +89,16 @@
 // CHECK-NEXT:    ]
 // CHECK-NEXT:    Address: 0x0
 // CHECK-NEXT:    Offset: 0x34
-// CHECK-NEXT:    Size: 81
+// CHECK-NEXT:    Size: 85
 // CHECK-NEXT:    Link: 0
 // CHECK-NEXT:    Info: 0
 // CHECK-NEXT:    AddressAlignment: 1
 // CHECK-NEXT:    EntrySize: 0
 // CHECK-NEXT:    SectionData (
-// CHECK-NEXT:      0000: 41500000 00616561 62690001 46000000  |AP...aeabi..F...|
+// CHECK-NEXT:      0000: 41540000 00616561 62690001 4A000000  |AT...aeabi..J...|
 // CHECK-NEXT:      0010: 05636F72 7465782D 61380006 0A074108  |.cortex-a8....A.|
 // CHECK-NEXT:      0020: 0109020A 030C0214 01150117 01180119  |................|
 // CHECK-NEXT:      0030: 011B001C 0124012A 012C022E 01320034  |.....$.*.,...2.4|
-// CHECK-NEXT:      0040: 0044034A 004C006E A0018101 3100FA01  |.D.J.L.n....1...|
-// CHECK-NEXT:      0050: 01                                   |.|
+// CHECK-NEXT:      0040: 0041060F 0044034A 004C006E A0018101  |.A...D.J.L.n....|
+// CHECK-NEXT:      0050: 3100FA01 01                          |1....|
 // CHECK-NEXT:    )

diff  --git a/llvm/test/MC/ARM/directive-eabi_attribute.s b/llvm/test/MC/ARM/directive-eabi_attribute.s
index 7722f52f54592..fd2719ec9642a 100644
--- a/llvm/test/MC/ARM/directive-eabi_attribute.s
+++ b/llvm/test/MC/ARM/directive-eabi_attribute.s
@@ -233,11 +233,14 @@
 @ CHECK-OBJ-NEXT:   Value: 0
 @ CHECK-OBJ-NEXT:   TagName: nodefaults
 @ CHECK-OBJ-NEXT:   Description: Unspecified Tags UNDEFINED
-	.eabi_attribute Tag_also_compatible_with, "gnu"
-@ CHECK: .eabi_attribute 65, "gnu"
+	.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: gnu
+@ CHECK-OBJ-NEXT:   Value:
 	.eabi_attribute Tag_T2EE_use, 0
 @ CHECK: .eabi_attribute 66, 0
 @ CHECK-OBJ:        Tag: 66


        


More information about the llvm-commits mailing list