Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Reapply "[RISCV] Support RISCV Atomics ABI attributes (#84597)" #90266

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

ilovepi
Copy link
Contributor

@ilovepi ilovepi commented Apr 26, 2024

This patch adds support for the atomic_abi attribute, specifid in
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#tag_riscv_atomic_abi-14-uleb128version.

The atomics_abi tag merging is conducted as follows:

UNKNOWN is safe to merge with all other values.
A6C is compatible with A6S, and results in the A6C ABI.
A6C is incompatible with A7, and results in an error.
A6S and A7 are compatible, and merging results in the A7 ABI.
Note: the A7 is not yet supported in either LLVM or in any current hardware,
and is therefore omitted from attribute generation in RISCVTargetStreamer.

This was previously reverted due to ld.bfd segfaulting w/ unknown riscv
attributes. This should reland once that has been addressed.

Created using spr 1.3.4
@llvmbot
Copy link
Collaborator

llvmbot commented Apr 26, 2024

@llvm/pr-subscribers-mc
@llvm/pr-subscribers-backend-risc-v
@llvm/pr-subscribers-lld-elf
@llvm/pr-subscribers-lld

@llvm/pr-subscribers-llvm-support

Author: Paul Kirth (ilovepi)

Changes

This patch adds support for the atomic_abi attribute, specifid in
https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#tag_riscv_atomic_abi-14-uleb128version.

The atomics_abi tag merging is conducted as follows:

UNKNOWN is safe to merge with all other values.
A6C is compatible with A6S, and results in the A6C ABI.
A6C is incompatible with A7, and results in an error.
A6S and A7 are compatible, and merging results in the A7 ABI.
Note: the A7 is not yet supported in either LLVM or in any current hardware,
and is therefore omitted from attribute generation in RISCVTargetStreamer.

This was previously reverted due to ld.bfd segfaulting w/ unknown riscv
attributes. This should reland once that has been addressed.


Full diff: https://github.com/llvm/llvm-project/pull/90266.diff

10 Files Affected:

  • (modified) lld/ELF/Arch/RISCV.cpp (+63)
  • (modified) lld/test/ELF/riscv-attributes.s (+202)
  • (modified) llvm/include/llvm/Support/RISCVAttributeParser.h (+1)
  • (modified) llvm/include/llvm/Support/RISCVAttributes.h (+13)
  • (modified) llvm/lib/Support/RISCVAttributeParser.cpp (+12-1)
  • (modified) llvm/lib/Support/RISCVAttributes.cpp (+1)
  • (modified) llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp (+7)
  • (modified) llvm/test/CodeGen/RISCV/attributes.ll (+9-1)
  • (modified) llvm/test/MC/RISCV/attribute.s (+3)
  • (modified) llvm/test/MC/RISCV/invalid-attribute.s (+3)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 20088d92bafa2f..7b9c9c6c6c3852 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1084,10 +1084,62 @@ static void mergeArch(RISCVISAInfo::OrderedExtensionMap &mergedExts,
   }
 }
 
+static void mergeAtomic(DenseMap<unsigned, unsigned>::iterator it,
+                        const InputSectionBase *oldSection,
+                        const InputSectionBase *newSection, unsigned int oldTag,
+                        unsigned int newTag) {
+  using RISCVAttrs::RISCVAtomicAbiTag::AtomicABI;
+  // Same tags stay the same, and UNKNOWN is compatible with anything
+  if (oldTag == newTag || newTag == AtomicABI::UNKNOWN)
+    return;
+
+  switch (oldTag) {
+  case AtomicABI::UNKNOWN:
+    it->getSecond() = newTag;
+    return;
+  case AtomicABI::A6C:
+    switch (newTag) {
+    case AtomicABI::A6S:
+      it->getSecond() = AtomicABI::A6C;
+      return;
+    case AtomicABI::A7:
+      error(toString(oldSection) + " has atomic_abi=" + Twine(oldTag) +
+            " but " + toString(newSection) +
+            " has atomic_abi=" + Twine(newTag));
+      return;
+    };
+
+  case AtomicABI::A6S:
+    switch (newTag) {
+    case AtomicABI::A6C:
+      it->getSecond() = AtomicABI::A6C;
+      return;
+    case AtomicABI::A7:
+      it->getSecond() = AtomicABI::A7;
+      return;
+    };
+
+  case AtomicABI::A7:
+    switch (newTag) {
+    case AtomicABI::A6S:
+      it->getSecond() = AtomicABI::A7;
+      return;
+    case AtomicABI::A6C:
+      error(toString(oldSection) + " has atomic_abi=" + Twine(oldTag) +
+            " but " + toString(newSection) +
+            " has atomic_abi=" + Twine(newTag));
+      return;
+    };
+  default:
+    llvm_unreachable("unknown AtomicABI");
+  };
+}
+
 static RISCVAttributesSection *
 mergeAttributesSection(const SmallVector<InputSectionBase *, 0> &sections) {
   RISCVISAInfo::OrderedExtensionMap exts;
   const InputSectionBase *firstStackAlign = nullptr;
+  const InputSectionBase *firstAtomicAbi = nullptr;
   unsigned firstStackAlignValue = 0, xlen = 0;
   bool hasArch = false;
 
@@ -1134,6 +1186,17 @@ mergeAttributesSection(const SmallVector<InputSectionBase *, 0> &sections) {
       case RISCVAttrs::PRIV_SPEC_MINOR:
       case RISCVAttrs::PRIV_SPEC_REVISION:
         break;
+
+      case llvm::RISCVAttrs::AttrType::ATOMIC_ABI:
+        if (auto i = parser.getAttributeValue(tag.attr)) {
+          auto r = merged.intAttr.try_emplace(tag.attr, *i);
+          if (r.second) {
+            firstAtomicAbi = sec;
+          } else {
+            mergeAtomic(r.first, firstAtomicAbi, sec, r.first->getSecond(), *i);
+          }
+        }
+        continue;
       }
 
       // Fallback for deprecated priv_spec* and other unknown attributes: retain
diff --git a/lld/test/ELF/riscv-attributes.s b/lld/test/ELF/riscv-attributes.s
index d0ce0941269ec4..77c2c3cb263fd1 100644
--- a/lld/test/ELF/riscv-attributes.s
+++ b/lld/test/ELF/riscv-attributes.s
@@ -44,6 +44,39 @@
 # RUN: not ld.lld a.o b.o c.o diff_stack_align.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=STACK_ALIGN --implicit-check-not=error:
 # STACK_ALIGN: error: diff_stack_align.o:(.riscv.attributes) has stack_align=32 but a.o:(.riscv.attributes) has stack_align=16
 
+## merging atomic_abi values for A6C and A7 lead to an error.
+# RUN: llvm-mc -filetype=obj -triple=riscv64  atomic_abi_A6C.s -o atomic_abi_A6C.o
+# RUN: llvm-mc -filetype=obj -triple=riscv64  atomic_abi_A7.s -o atomic_abi_A7.o
+# RUN: not ld.lld atomic_abi_A6C.o atomic_abi_A7.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ATOMIC_ABI_ERROR --implicit-check-not=error:
+# ATOMIC_ABI_ERROR: error: atomic_abi_A6C.o:(.riscv.attributes) has atomic_abi=1 but atomic_abi_A7.o:(.riscv.attributes) has atomic_abi=3
+
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64  atomic_abi_A6S.s -o atomic_abi_A6S.o
+# RUN: ld.lld atomic_abi_A6S.o atomic_abi_A6C.o -o atomic_abi_A6C_A6S
+# RUN: llvm-readobj -A atomic_abi_A6C_A6S | FileCheck %s --check-prefix=A6C_A6S
+
+# RUN: ld.lld atomic_abi_A6S.o atomic_abi_A7.o -o atomic_abi_A6S_A7
+# RUN: llvm-readobj -A atomic_abi_A6S_A7 | FileCheck %s --check-prefix=A6S_A7
+
+# RUN: llvm-mc -filetype=obj -triple=riscv64  atomic_abi_unknown.s -o atomic_abi_unknown.o
+# RUN: ld.lld atomic_abi_unknown.o atomic_abi_A6C.o -o atomic_abi_A6C_unknown
+# RUN: llvm-readobj -A atomic_abi_A6C_unknown | FileCheck %s --check-prefixes=UNKNOWN_A6C
+
+# RUN: ld.lld atomic_abi_unknown.o diff_stack_align.o -o atomic_abi_none_unknown
+# RUN: llvm-readobj -A atomic_abi_none_unknown | FileCheck %s --check-prefixes=UNKNOWN_NONE
+
+# RUN: ld.lld diff_stack_align.o atomic_abi_A6C.o -o atomic_abi_A6C_none
+# RUN: llvm-readobj -A atomic_abi_A6C_none | FileCheck %s --check-prefixes=NONE_A6C
+
+# RUN: ld.lld atomic_abi_unknown.o atomic_abi_A6S.o -o atomic_abi_A6S_unknown
+# RUN: llvm-readobj -A atomic_abi_A6S_unknown | FileCheck %s --check-prefix=UNKNOWN_A6S
+
+# RUN: ld.lld atomic_abi_unknown.o atomic_abi_A7.o -o atomic_abi_A7_unknown
+# RUN: llvm-readobj -A atomic_abi_A7_unknown | FileCheck %s --check-prefix=UNKNOWN_A7
+
+# RUN: ld.lld diff_stack_align.o atomic_abi_A7.o -o atomic_abi_A7_none
+# RUN: llvm-readobj -A atomic_abi_A7_none | FileCheck %s --check-prefix=NONE_A7
+
 ## The deprecated priv_spec is not handled as GNU ld does.
 ## Differing priv_spec attributes lead to an absent attribute.
 # RUN: llvm-mc -filetype=obj -triple=riscv64 diff_priv_spec.s -o diff_priv_spec.o
@@ -286,6 +319,175 @@
 .attribute priv_spec, 3
 .attribute priv_spec_minor, 3
 
+#--- atomic_abi_unknown.s
+.attribute atomic_abi, 0
+
+#--- atomic_abi_A6C.s
+.attribute atomic_abi, 1
+
+#--- atomic_abi_A6S.s
+.attribute atomic_abi, 2
+
+#--- atomic_abi_A7.s
+.attribute atomic_abi, 3
+
+#      UNKNOWN_NONE: BuildAttributes {
+# UNKNOWN_NONE-NEXT:   FormatVersion: 0x41
+# UNKNOWN_NONE-NEXT:   Section 1 {
+# UNKNOWN_NONE-NEXT:     SectionLength: 17
+# UNKNOWN_NONE-NEXT:     Vendor: riscv
+# UNKNOWN_NONE-NEXT:     Tag: Tag_File (0x1)
+# UNKNOWN_NONE-NEXT:     Size: 7
+# UNKNOWN_NONE-NEXT:     FileAttributes {
+# UNKNOWN_NONE-NEXT:       Attribute {
+# UNKNOWN_NONE-NEXT:         Tag: 4
+# UNKNOWN_NONE-NEXT:         Value: 32
+# UNKNOWN_NONE-NEXT:         TagName: stack_align
+# UNKNOWN_NONE-NEXT:         Description: Stack alignment is 32-bytes
+# UNKNOWN_NONE-NEXT:       }
+# UNKNOWN_NONE-NEXT:     }
+# UNKNOWN_NONE-NEXT:   }
+# UNKNOWN_NONE-NEXT: }
+
+#      NONE_A6C: BuildAttributes {
+# NONE_A6C-NEXT:   FormatVersion: 0x41
+# NONE_A6C-NEXT:   Section 1 {
+# NONE_A6C-NEXT:     SectionLength: 19
+# NONE_A6C-NEXT:     Vendor: riscv
+# NONE_A6C-NEXT:     Tag: Tag_File (0x1)
+# NONE_A6C-NEXT:     Size: 9
+# NONE_A6C-NEXT:     FileAttributes {
+# NONE_A6C-NEXT:       Attribute {
+# NONE_A6C-NEXT:         Tag: 14
+# NONE_A6C-NEXT:         Value: 1
+# NONE_A6C-NEXT:         TagName: atomic_abi
+# NONE_A6C-NEXT:         Description: Atomic ABI is 1
+# NONE_A6C-NEXT:       }
+# NONE_A6C-NEXT:       Attribute {
+# NONE_A6C-NEXT:         Tag: 4
+# NONE_A6C-NEXT:         Value: 32
+# NONE_A6C-NEXT:         TagName: stack_align
+# NONE_A6C-NEXT:         Description: Stack alignment is 32-bytes
+# NONE_A6C-NEXT:       }
+# NONE_A6C-NEXT:     }
+# NONE_A6C-NEXT:   }
+# NONE_A6C-NEXT: }
+
+#      UNKNOWN_A6C: BuildAttributes {
+# UNKNOWN_A6C-NEXT:   FormatVersion: 0x41
+# UNKNOWN_A6C-NEXT:   Section 1 {
+# UNKNOWN_A6C-NEXT:     SectionLength: 17
+# UNKNOWN_A6C-NEXT:     Vendor: riscv
+# UNKNOWN_A6C-NEXT:     Tag: Tag_File (0x1)
+# UNKNOWN_A6C-NEXT:     Size: 7
+# UNKNOWN_A6C-NEXT:     FileAttributes {
+# UNKNOWN_A6C-NEXT:       Attribute {
+# UNKNOWN_A6C-NEXT:         Tag: 14
+# UNKNOWN_A6C-NEXT:         Value: 1
+# UNKNOWN_A6C-NEXT:         TagName: atomic_abi
+# UNKNOWN_A6C-NEXT:         Description: Atomic ABI is 1
+# UNKNOWN_A6C-NEXT:       }
+# UNKNOWN_A6C-NEXT:     }
+# UNKNOWN_A6C-NEXT:   }
+# UNKNOWN_A6C-NEXT: }
+
+#      UNKNOWN_A6S: BuildAttributes {
+# UNKNOWN_A6S-NEXT:   FormatVersion: 0x41
+# UNKNOWN_A6S-NEXT:   Section 1 {
+# UNKNOWN_A6S-NEXT:     SectionLength:
+# UNKNOWN_A6S-NEXT:     Vendor: riscv
+# UNKNOWN_A6S-NEXT:     Tag: Tag_File (0x1)
+# UNKNOWN_A6S-NEXT:     Size: 7
+# UNKNOWN_A6S-NEXT:     FileAttributes {
+# UNKNOWN_A6S-NEXT:       Attribute {
+# UNKNOWN_A6S-NEXT:         Tag: 14
+# UNKNOWN_A6S-NEXT:         Value: 2
+# UNKNOWN_A6S-NEXT:         TagName: atomic_abi
+# UNKNOWN_A6S-NEXT:         Description: Atomic ABI is 2
+# UNKNOWN_A6S-NEXT:       }
+# UNKNOWN_A6S-NEXT:     }
+# UNKNOWN_A6S-NEXT:   }
+# UNKNOWN_A6S-NEXT: }
+
+#      NONE_A7: BuildAttributes {
+# NONE_A7-NEXT:   FormatVersion: 0x41
+# NONE_A7-NEXT:   Section 1 {
+# NONE_A7-NEXT:     SectionLength: 19
+# NONE_A7-NEXT:     Vendor: riscv
+# NONE_A7-NEXT:     Tag: Tag_File (0x1)
+# NONE_A7-NEXT:     Size: 9
+# NONE_A7-NEXT:     FileAttributes {
+# NONE_A7-NEXT:       Attribute {
+# NONE_A7-NEXT:         Tag: 14
+# NONE_A7-NEXT:         Value: 3
+# NONE_A7-NEXT:         TagName: atomic_abi
+# NONE_A7-NEXT:         Description: Atomic ABI is 3
+# NONE_A7-NEXT:       }
+# NONE_A7-NEXT:       Attribute {
+# NONE_A7-NEXT:         Tag: 4
+# NONE_A7-NEXT:         Value: 32
+# NONE_A7-NEXT:         TagName: stack_align
+# NONE_A7-NEXT:         Description: Stack alignment is 32-bytes
+# NONE_A7-NEXT:       }
+# NONE_A7-NEXT:     }
+# NONE_A7-NEXT:   }
+# NONE_A7-NEXT: }
+
+
+#      UNKNOWN_A7: BuildAttributes {
+# UNKNOWN_A7-NEXT:   FormatVersion: 0x41
+# UNKNOWN_A7-NEXT:   Section 1 {
+# UNKNOWN_A7-NEXT:     SectionLength: 17
+# UNKNOWN_A7-NEXT:     Vendor: riscv
+# UNKNOWN_A7-NEXT:     Tag: Tag_File (0x1)
+# UNKNOWN_A7-NEXT:     Size: 7
+# UNKNOWN_A7-NEXT:     FileAttributes {
+# UNKNOWN_A7-NEXT:       Attribute {
+# UNKNOWN_A7-NEXT:         Tag: 14
+# UNKNOWN_A7-NEXT:         Value: 3
+# UNKNOWN_A7-NEXT:         TagName: atomic_abi
+# UNKNOWN_A7-NEXT:         Description: Atomic ABI is 3
+# UNKNOWN_A7-NEXT:       }
+# UNKNOWN_A7-NEXT:     }
+# UNKNOWN_A7-NEXT:   }
+# UNKNOWN_A7-NEXT: }
+
+#      A6C_A6S: BuildAttributes {
+# A6C_A6S-NEXT:   FormatVersion: 0x41
+# A6C_A6S-NEXT:   Section 1 {
+# A6C_A6S-NEXT:     SectionLength: 17
+# A6C_A6S-NEXT:     Vendor: riscv
+# A6C_A6S-NEXT:     Tag: Tag_File (0x1)
+# A6C_A6S-NEXT:     Size: 7
+# A6C_A6S-NEXT:     FileAttributes {
+# A6C_A6S-NEXT:       Attribute {
+# A6C_A6S-NEXT:         Tag: 14
+# A6C_A6S-NEXT:         Value: 1
+# A6C_A6S-NEXT:         TagName: atomic_abi
+# A6C_A6S-NEXT:         Description: Atomic ABI is 1
+# A6C_A6S-NEXT:       }
+# A6C_A6S-NEXT:     }
+# A6C_A6S-NEXT:   }
+# A6C_A6S-NEXT: }
+
+#      A6S_A7: BuildAttributes {
+# A6S_A7-NEXT:   FormatVersion: 0x41
+# A6S_A7-NEXT:   Section 1 {
+# A6S_A7-NEXT:     SectionLength: 17
+# A6S_A7-NEXT:     Vendor: riscv
+# A6S_A7-NEXT:     Tag: Tag_File (0x1)
+# A6S_A7-NEXT:     Size: 7
+# A6S_A7-NEXT:     FileAttributes {
+# A6S_A7-NEXT:       Attribute {
+# A6S_A7-NEXT:         Tag: 14
+# A6S_A7-NEXT:         Value: 3
+# A6S_A7-NEXT:         TagName: atomic_abi
+# A6S_A7-NEXT:         Description: Atomic ABI is 3
+# A6S_A7-NEXT:       }
+# A6S_A7-NEXT:     }
+# A6S_A7-NEXT:   }
+# A6S_A7-NEXT: }
+
 #--- unknown13.s
 .attribute 13, "0"
 #--- unknown13a.s
diff --git a/llvm/include/llvm/Support/RISCVAttributeParser.h b/llvm/include/llvm/Support/RISCVAttributeParser.h
index 305adffbe851e7..9f295504de959e 100644
--- a/llvm/include/llvm/Support/RISCVAttributeParser.h
+++ b/llvm/include/llvm/Support/RISCVAttributeParser.h
@@ -24,6 +24,7 @@ class RISCVAttributeParser : public ELFAttributeParser {
 
   Error unalignedAccess(unsigned tag);
   Error stackAlign(unsigned tag);
+  Error atomicAbi(unsigned tag);
 
 public:
   RISCVAttributeParser(ScopedPrinter *sw)
diff --git a/llvm/include/llvm/Support/RISCVAttributes.h b/llvm/include/llvm/Support/RISCVAttributes.h
index 18f5a84d21f250..5def890a727355 100644
--- a/llvm/include/llvm/Support/RISCVAttributes.h
+++ b/llvm/include/llvm/Support/RISCVAttributes.h
@@ -32,8 +32,21 @@ enum AttrType : unsigned {
   PRIV_SPEC = 8,
   PRIV_SPEC_MINOR = 10,
   PRIV_SPEC_REVISION = 12,
+  ATOMIC_ABI = 14,
 };
 
+namespace RISCVAtomicAbiTag {
+enum AtomicABI : unsigned {
+  // Values for Tag_RISCV_atomic_abi
+  // Defined at
+  // https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#tag_riscv_atomic_abi-14-uleb128version
+  UNKNOWN = 0,
+  A6C = 1,
+  A6S = 2,
+  A7 = 3,
+};
+} // namespace RISCVAtomicAbiTag
+
 enum { NOT_ALLOWED = 0, ALLOWED = 1 };
 
 } // namespace RISCVAttrs
diff --git a/llvm/lib/Support/RISCVAttributeParser.cpp b/llvm/lib/Support/RISCVAttributeParser.cpp
index 7ce4b6ab161cd3..19c5a0e06903f6 100644
--- a/llvm/lib/Support/RISCVAttributeParser.cpp
+++ b/llvm/lib/Support/RISCVAttributeParser.cpp
@@ -36,7 +36,18 @@ const RISCVAttributeParser::DisplayHandler
         {
             RISCVAttrs::UNALIGNED_ACCESS,
             &RISCVAttributeParser::unalignedAccess,
-        }};
+        },
+        {
+            RISCVAttrs::ATOMIC_ABI,
+            &RISCVAttributeParser::atomicAbi,
+        },
+};
+
+Error RISCVAttributeParser::atomicAbi(unsigned Tag) {
+  uint64_t Value = de.getULEB128(cursor);
+  printAttribute(Tag, Value, "Atomic ABI is " + utostr(Value));
+  return Error::success();
+}
 
 Error RISCVAttributeParser::unalignedAccess(unsigned tag) {
   static const char *strings[] = {"No unaligned access", "Unaligned access"};
diff --git a/llvm/lib/Support/RISCVAttributes.cpp b/llvm/lib/Support/RISCVAttributes.cpp
index 9e629760d3d842..dc70d65acba063 100644
--- a/llvm/lib/Support/RISCVAttributes.cpp
+++ b/llvm/lib/Support/RISCVAttributes.cpp
@@ -18,6 +18,7 @@ static constexpr TagNameItem tagData[] = {
     {PRIV_SPEC, "Tag_priv_spec"},
     {PRIV_SPEC_MINOR, "Tag_priv_spec_minor"},
     {PRIV_SPEC_REVISION, "Tag_priv_spec_revision"},
+    {ATOMIC_ABI, "Tag_atomic_abi"},
 };
 
 constexpr TagNameMap RISCVAttributeTags{tagData};
diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
index 0f92e9ed6a64d3..6f5f12cc72862d 100644
--- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
+++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVTargetStreamer.cpp
@@ -75,6 +75,13 @@ void RISCVTargetStreamer::emitTargetAttributes(const MCSubtargetInfo &STI,
     auto &ISAInfo = *ParseResult;
     emitTextAttribute(RISCVAttrs::ARCH, ISAInfo->toString());
   }
+
+  if (STI.hasFeature(RISCV::FeatureStdExtA)) {
+    unsigned AtomicABITag = STI.hasFeature(RISCV::FeatureTrailingSeqCstFence)
+                                ? RISCVAttrs::RISCVAtomicAbiTag::AtomicABI::A6S
+                                : RISCVAttrs::RISCVAtomicAbiTag::AtomicABI::A6C;
+    emitAttribute(RISCVAttrs::ATOMIC_ABI, AtomicABITag);
+  }
 }
 
 // This part is for ascii assembly output
diff --git a/llvm/test/CodeGen/RISCV/attributes.ll b/llvm/test/CodeGen/RISCV/attributes.ll
index 141d5ea4182892..1aff3e8b83f401 100644
--- a/llvm/test/CodeGen/RISCV/attributes.ll
+++ b/llvm/test/CodeGen/RISCV/attributes.ll
@@ -129,7 +129,8 @@
 ; RUN: llc -mtriple=riscv64 -mattr=+m %s -o - | FileCheck --check-prefixes=CHECK,RV64M %s
 ; RUN: llc -mtriple=riscv64 -mattr=+zmmul %s -o - | FileCheck --check-prefixes=CHECK,RV64ZMMUL %s
 ; RUN: llc -mtriple=riscv64 -mattr=+m,+zmmul %s -o - | FileCheck --check-prefixes=CHECK,RV64MZMMUL %s
-; RUN: llc -mtriple=riscv64 -mattr=+a %s -o - | FileCheck --check-prefixes=CHECK,RV64A %s
+; RUN: llc -mtriple=riscv64 -mattr=+a %s -o - | FileCheck --check-prefixes=CHECK,RV64A,A6C %s
+; RUN: llc -mtriple=riscv64 -mattr=+a,+seq-cst-trailing-fence %s -o - | FileCheck --check-prefixes=CHECK,RV64A,A6S %s
 ; RUN: llc -mtriple=riscv64 -mattr=+f %s -o - | FileCheck --check-prefixes=CHECK,RV64F %s
 ; RUN: llc -mtriple=riscv64 -mattr=+d %s -o - | FileCheck --check-prefixes=CHECK,RV64D %s
 ; RUN: llc -mtriple=riscv64 -mattr=+c %s -o - | FileCheck --check-prefixes=CHECK,RV64C %s
@@ -516,3 +517,10 @@ define i32 @addi(i32 %a) {
   %1 = add i32 %a, 1
   ret i32 %1
 }
+
+define i8 @atomic_load_i8_seq_cst(ptr %a) nounwind {
+  %1 = load atomic i8, ptr %a seq_cst, align 1
+  ret i8 %1
+; A6S: .attribute 14, 2
+; A6C: .attribute 14, 1
+}
diff --git a/llvm/test/MC/RISCV/attribute.s b/llvm/test/MC/RISCV/attribute.s
index 56f0cb1daf176f..75b9c65ed1cc2f 100644
--- a/llvm/test/MC/RISCV/attribute.s
+++ b/llvm/test/MC/RISCV/attribute.s
@@ -24,3 +24,6 @@
 
 .attribute priv_spec_revision, 0
 # CHECK: attribute      12, 0
+
+.attribute atomic_abi, 0
+# CHECK: attribute      14, 0
diff --git a/llvm/test/MC/RISCV/invalid-attribute.s b/llvm/test/MC/RISCV/invalid-attribute.s
index 1d732af83cda35..2ebf7ddc9aff85 100644
--- a/llvm/test/MC/RISCV/invalid-attribute.s
+++ b/llvm/test/MC/RISCV/invalid-attribute.s
@@ -33,3 +33,6 @@
 
 .attribute arch, 30
 # CHECK: [[@LINE-1]]:18: error: expected string constant
+
+.attribute atomic_abi, "16"
+# CHECK: [[@LINE-1]]:24: error: expected numeric constant

@ilovepi
Copy link
Contributor Author

ilovepi commented Apr 26, 2024

Note, I'm not sure what the time table for this to reland is.

@ilovepi
Copy link
Contributor Author

ilovepi commented Apr 26, 2024

Seems like @MaskRay reported the bfd bug quite a while ago. https://sourceware.org/bugzilla/show_bug.cgi?id=29823

@MaskRay
Copy link
Member

MaskRay commented Apr 29, 2024

Seems like @MaskRay reported the bfd bug quite a while ago. sourceware.org/bugzilla/show_bug.cgi?id=29823

Hopefully @Nelson1225 can take a look.


As we add more build attributes, llvm-readelf -A riscv64.o starts to resemble a typical AArch32 relocatable file with over 10 attributes.
This might not be ideal for everyone, and I haven't found another architecture doing this.

The GNU ld error suggests the atomic attribute should be opt-in.
This allows groups who find these attributes useful to enable them explicitly.

On the LLVM side, we can have a cl::opt<bool> option to control whether such attributes should be emitted.
We can replace this with a driver option after we gain more experience and agree with GCC.
It is possible that we will eventually go the AArch32 way and a typical relocatable file will contain 10+ attributes, but that's probably not the immediate focus.

if (auto i = parser.getAttributeValue(tag.attr)) {
auto r = merged.intAttr.try_emplace(tag.attr, *i);
if (r.second) {
firstAtomicAbi = sec;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no braces for one-line single statements

see other comments in #84597

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I missed that. Thanks.

Copy link
Member

@MaskRay MaskRay left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

.

@ilovepi
Copy link
Contributor Author

ilovepi commented Apr 30, 2024

Seems like @MaskRay reported the bfd bug quite a while ago. sourceware.org/bugzilla/show_bug.cgi?id=29823

Hopefully @Nelson1225 can take a look.

As we add more build attributes, llvm-readelf -A riscv64.o starts to resemble a typical AArch32 relocatable file with over 10 attributes. This might not be ideal for everyone, and I haven't found another architecture doing this.

The GNU ld error suggests the atomic attribute should be opt-in. This allows groups who find these attributes useful to enable them explicitly.

I'm not sure I follow, are you refering to the current ToT GNU ld behavior or the segfault reported? Second, the psABI isn't ambiguous about the requirement here https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#tag_riscv_atomic_abi-14-uleb128version, and the merge policy is clearly spelled out

Merge policy
 The linker should report errors if object files with incompatible atomics ABIs are merged; the compatibility rules for atomic ABIs can be found in the compatibility column in the following table.

The wording there doesn't sound optional to me.

On the LLVM side, we can have a cl::opt<bool> option to control whether such attributes should be emitted.

I don't think this is very practical. CL opts are probably not enough, and tend to cause issues, particularly when they don't get forwarded to the linker correctly in LTO builds.

We can replace this with a driver option after we gain more experience and agree with GCC. It is possible that we will eventually go the AArch32 way and a typical relocatable file will contain 10+ attributes, but that's probably not the immediate focus.

I'm not aware of any reason we need to maintain strict compatibility w/ GCC at all points in time, when we're all supposed to be implementing the same spec. Note: I'm not saying we shouldn't maintain compatibility at all, but I don't see why Clang can't be leading the way here. Also, whether we emit attributes or not, doesn't seem to be the kind of thing you should control w/ a driver option if its mandated by the ABI you're targeting.

Lastly, I'd like to emphasize, enabling the correct Atomics ABI has been blocked on this feature for a long time. This is required for Android and other systems that do not want to maintain any compatibility with the old/broken A6C ABI, since A6C and A7 are completely incompatible.

Created using spr 1.3.4
Created using spr 1.3.4
Copy link

github-actions bot commented May 2, 2024

✅ With the latest revision this PR passed the C/C++ code formatter.

@asb
Copy link
Contributor

asb commented May 9, 2024

I don't think this is very practical. CL opts are probably not enough, and tend to cause issues, particularly when they don't get forwarded to the linker correctly in LTO builds.

I think one reason we'd go with this route is it would make it easy for people to have a downstream patch that flips the default, while having the logic upstream and at least minimally tested. Not ideal, but it's a pattern we've followed before.

Anyway, let's discuss a path forwards in the call today. I agree we could go overboard on maintaining strict compatibility at all times, but the segfault with what was until recently the most current ld release is fairly user hostile. There aren't any great solutions here I think, we just have to find the least-worst :/

Created using spr 1.3.4
@ilovepi
Copy link
Contributor Author

ilovepi commented May 22, 2024

Ping. Are we happy w/ this as an -mattr, or should it be guarded by another kind of flag?

@asb
Copy link
Contributor

asb commented May 23, 2024

Ping. Are we happy w/ this as an -mattr, or should it be guarded by another kind of flag?

Sorry, I'd missed the update somehow. I'd actually been thinking a cl::opt flag (much like AArch64 has aarch64-mark-bti-property). I'd say the +abi-attr/FeatureAbiAttributes is confusingly named as well, as it controls only the atomics ABI attributes rather than all of them.

Unless anyone else feels differently I'd think the cl::opt is most consistent with how we usually do this (and easy to pass through from clang with -mllvm). The precise name doesn't matter much, as long as it's clear it relates to RISC-V atomic abi attribute / tags in some way I promise I won't bikeshed beyond that!

@ilovepi
Copy link
Contributor Author

ilovepi commented May 23, 2024

Ping. Are we happy w/ this as an -mattr, or should it be guarded by another kind of flag?

Sorry, I'd missed the update somehow. I'd actually been thinking a cl::opt flag (much like AArch64 has aarch64-mark-bti-property). I'd say the +abi-attr/FeatureAbiAttributes is confusingly named as well, as it controls only the atomics ABI attributes rather than all of them.

Unless anyone else feels differently I'd think the cl::opt is most consistent with how we usually do this (and easy to pass through from clang with -mllvm). The precise name doesn't matter much, as long as it's clear it relates to atomic abi attribute / tags in some way I promise I won't bikeshed beyond that!

Sounds good. I’ll try to send an update later today.

@MaskRay
Copy link
Member

MaskRay commented May 28, 2024

Seems like @MaskRay reported the bfd bug quite a while ago. sourceware.org/bugzilla/show_bug.cgi?id=29823

Hopefully @Nelson1225 can take a look.

As we add more build attributes, llvm-readelf -A riscv64.o starts to resemble a typical AArch32 relocatable file with over 10 attributes. This might not be ideal for everyone, and I haven't found another architecture doing this.

The GNU ld error suggests the atomic attribute should be opt-in. This allows groups who find these attributes useful to enable them explicitly.

I'm not sure I follow, are you refering to the current ToT GNU ld behavior or the segfault reported? Second, the psABI isn't ambiguous about the requirement here https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/master/riscv-elf.adoc#tag_riscv_atomic_abi-14-uleb128version, and the merge policy is clearly spelled out

The trend of liberally including attributes in .riscv.attributes raises concerns.
While specific attributes can be helpful, overabundance similar to aarch32's style could lead to clutter and maintenance challenges.
Removing now-unnecessary attributes might become difficult due to some users favoring stronger compatibility.

I'll likely be more concerned if a future linker option is proposed to suppress incompatibility errors.

Merge policy
 The linker should report errors if object files with incompatible atomics ABIs are merged; the compatibility rules for atomic ABIs can be found in the compatibility column in the following table.

The wording there doesn't sound optional to me.

I don't think we should read too much from the use of "should" here. This requirement level is probably between "should" and "may".
It should certainly be fine for a linker to ignore .riscv.attributes completely.

RFC2119

3. SHOULD   This word, or the adjective "RECOMMENDED", mean that there
   may exist valid reasons in particular circumstances to ignore a
   particular item, but the full implications must be understood and
   carefully weighed before choosing a different course.

On the LLVM side, we can have a cl::opt<bool> option to control whether such attributes should be emitted.

I don't think this is very practical. CL opts are probably not enough, and tend to cause issues, particularly when they don't get forwarded to the linker correctly in LTO builds.

Using cl::opt<bool> looks good to me.
The LTO status is not a practical issue. Many codegen options are not recorded in LLVM IR, and it's possibly inpractical to record every one (a lot don't even have clear merge policy).

We can replace this with a driver option after we gain more experience and agree with GCC. It is possible that we will eventually go the AArch32 way and a typical relocatable file will contain 10+ attributes, but that's probably not the immediate focus.

I'm not aware of any reason we need to maintain strict compatibility w/ GCC at all points in time, when we're all supposed to be implementing the same spec. Note: I'm not saying we shouldn't maintain compatibility at all, but I don't see why Clang can't be leading the way here. Also, whether we emit attributes or not, doesn't seem to be the kind of thing you should control w/ a driver option if its mandated by the ABI you're targeting.

Lastly, I'd like to emphasize, enabling the correct Atomics ABI has been blocked on this feature for a long time. This is required for Android and other systems that do not want to maintain any compatibility with the old/broken A6C ABI, since A6C and A7 are completely incompatible.

A cl::opt looks good to me. By using an internal option cl::opt<bool>, we don't commit to the stability of the option.
It could be named, though we probably won't without a good reason. Users need to be ready to change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

4 participants