Skip to content

[lld] Support merging RISC-V Atomics ABI attributes #97347

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

Conversation

ilovepi
Copy link
Contributor

@ilovepi ilovepi commented Jul 1, 2024

This patch adds support for merging 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,
to LLD.

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.

LLD support was split from #90266

ilovepi added 2 commits July 1, 2024 13:55
Created using spr 1.3.4
@llvmbot
Copy link
Member

llvmbot commented Jul 1, 2024

@llvm/pr-subscribers-lld

@llvm/pr-subscribers-lld-elf

Author: Paul Kirth (ilovepi)

Changes

This patch adds support for merging 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,
to LLD.

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.

LLD support was split from #90266


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

2 Files Affected:

  • (modified) lld/ELF/Arch/RISCV.cpp (+78)
  • (modified) lld/test/ELF/riscv-attributes.s (+203)
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index e4d63250135e0..aa11aaa61a532 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1084,10 +1084,76 @@ static void mergeArch(RISCVISAUtils::OrderedExtensionMap &mergedExts,
   }
 }
 
+static void mergeAtomic(DenseMap<unsigned, unsigned>::iterator it,
+                        const InputSectionBase *oldSection,
+                        const InputSectionBase *newSection,
+                        RISCVAttrs::RISCVAtomicAbiTag oldTag,
+                        RISCVAttrs::RISCVAtomicAbiTag newTag) {
+  using RISCVAttrs::RISCVAtomicAbiTag;
+  // Same tags stay the same, and UNKNOWN is compatible with anything
+  if (oldTag == newTag || newTag == RISCVAtomicAbiTag::UNKNOWN)
+    return;
+
+  auto reportAbiError = [&]() {
+    errorOrWarn("atomic abi mismatch for " + oldSection->name + "\n>>> " +
+                toString(oldSection) +
+                ": atomic_abi=" + Twine(static_cast<unsigned>(oldTag)) +
+                "\n>>> " + toString(newSection) +
+                ": atomic_abi=" + Twine(static_cast<unsigned>(newTag)));
+  };
+
+  switch (static_cast<RISCVAtomicAbiTag>(oldTag)) {
+  case RISCVAtomicAbiTag::UNKNOWN:
+    it->getSecond() = static_cast<unsigned>(newTag);
+    return;
+  case RISCVAtomicAbiTag::A6C:
+    switch (newTag) {
+    case RISCVAtomicAbiTag::A6S:
+      it->getSecond() = static_cast<unsigned>(RISCVAtomicAbiTag::A6C);
+      return;
+    case RISCVAtomicAbiTag::A7:
+      reportAbiError();
+      return;
+    case RISCVAttrs::RISCVAtomicAbiTag::UNKNOWN:
+    case RISCVAttrs::RISCVAtomicAbiTag::A6C:
+      return;
+    };
+
+  case RISCVAtomicAbiTag::A6S:
+    switch (newTag) {
+    case RISCVAtomicAbiTag::A6C:
+      it->getSecond() = static_cast<unsigned>(RISCVAtomicAbiTag::A6C);
+      return;
+    case RISCVAtomicAbiTag::A7:
+      it->getSecond() = static_cast<unsigned>(RISCVAtomicAbiTag::A7);
+      return;
+    case RISCVAttrs::RISCVAtomicAbiTag::UNKNOWN:
+    case RISCVAttrs::RISCVAtomicAbiTag::A6S:
+      return;
+    };
+
+  case RISCVAtomicAbiTag::A7:
+    switch (newTag) {
+    case RISCVAtomicAbiTag::A6S:
+      it->getSecond() = static_cast<unsigned>(RISCVAtomicAbiTag::A7);
+      return;
+    case RISCVAtomicAbiTag::A6C:
+      reportAbiError();
+      return;
+    case RISCVAttrs::RISCVAtomicAbiTag::UNKNOWN:
+    case RISCVAttrs::RISCVAtomicAbiTag::A7:
+      return;
+    };
+  };
+  llvm_unreachable("unknown AtomicABI");
+}
+
 static RISCVAttributesSection *
 mergeAttributesSection(const SmallVector<InputSectionBase *, 0> &sections) {
+  using RISCVAttrs::RISCVAtomicAbiTag;
   RISCVISAUtils::OrderedExtensionMap exts;
   const InputSectionBase *firstStackAlign = nullptr;
+  const InputSectionBase *firstAtomicAbi = nullptr;
   unsigned firstStackAlignValue = 0, xlen = 0;
   bool hasArch = false;
 
@@ -1134,6 +1200,18 @@ 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,
+                        static_cast<RISCVAtomicAbiTag>(r.first->getSecond()),
+                        static_cast<RISCVAtomicAbiTag>(*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 68534d0fb6b75..38b0fe8e7797e 100644
--- a/lld/test/ELF/riscv-attributes.s
+++ b/lld/test/ELF/riscv-attributes.s
@@ -44,6 +44,40 @@
 # 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
 
+## RISC-V tag merging for atomic_abi values 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 mismatch for .riscv.attributes
+# ATOMIC_ABI_ERROR-NEXT: >>> atomic_abi_A6C.o:(.riscv.attributes): atomic_abi=1
+# ATOMIC_ABI_ERROR-NEXT: >>> atomic_abi_A7.o:(.riscv.attributes): 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 +320,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

ilovepi added 4 commits July 1, 2024 13:59
Created using spr 1.3.4

[skip ci]
Created using spr 1.3.4
Created using spr 1.3.4

[skip ci]
Created using spr 1.3.4
": atomic_abi=" + Twine(static_cast<unsigned>(newTag)));
};

switch (static_cast<RISCVAtomicAbiTag>(oldTag)) {
Copy link
Member

Choose a reason for hiding this comment

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

unneeded cast?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

yes. Looks like I missed one. Thanks.

return;
};
};
llvm_unreachable("unknown AtomicABI");
Copy link
Member

Choose a reason for hiding this comment

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

If a potentially-corrupted object file may contain an unknown tag, it's inappropriate to use unreachable.

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, fair point. I'll update w/ an error instead.

ilovepi added 3 commits July 2, 2024 08:23
Created using spr 1.3.4

[skip ci]
Created using spr 1.3.4
Created using spr 1.3.4
@MaskRay
Copy link
Member

MaskRay commented Jul 3, 2024

[RISCV][lld] ...

I usually omit [RISCV] when the title already contains RISC-V or RISCV...

hokein and others added 2 commits July 8, 2024 13:22
Created using spr 1.3.4

[skip ci]
Created using spr 1.3.4
@ilovepi ilovepi changed the title [RISCV][lld] Support merging RISC-V Atomics ABI attributes [lld] Support merging RISC-V Atomics ABI attributes Jul 8, 2024
@ilovepi ilovepi changed the base branch from users/ilovepi/spr/main.riscvlld-support-merging-risc-v-atomics-abi-attributes to main July 8, 2024 20:24
@ilovepi ilovepi merged commit 526dbc1 into main Jul 8, 2024
5 of 7 checks passed
@ilovepi ilovepi deleted the users/ilovepi/spr/riscvlld-support-merging-risc-v-atomics-abi-attributes branch July 8, 2024 20:25
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.

4 participants