[lld] 526dbc1 - [lld] Support merging RISC-V Atomics ABI attributes (#97347)
via llvm-commits
llvm-commits at lists.llvm.org
Mon Jul 8 13:25:43 PDT 2024
Author: Paul Kirth
Date: 2024-07-08T13:25:40-07:00
New Revision: 526dbc1b933d111db1e564631690914580e7e429
URL: https://github.com/llvm/llvm-project/commit/526dbc1b933d111db1e564631690914580e7e429
DIFF: https://github.com/llvm/llvm-project/commit/526dbc1b933d111db1e564631690914580e7e429.diff
LOG: [lld] Support merging RISC-V Atomics ABI attributes (#97347)
This patch adds support for merging the atomic_abi attribute, specified
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
https://github.com/llvm/llvm-project/pull/90266
Added:
Modified:
lld/ELF/Arch/RISCV.cpp
lld/test/ELF/riscv-attributes.s
Removed:
################################################################################
diff --git a/lld/ELF/Arch/RISCV.cpp b/lld/ELF/Arch/RISCV.cpp
index 281567e372298..07a1b63be8051 100644
--- a/lld/ELF/Arch/RISCV.cpp
+++ b/lld/ELF/Arch/RISCV.cpp
@@ -1084,10 +1084,94 @@ 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)));
+ };
+
+ auto reportUnknownAbiError = [](const InputSectionBase *section,
+ RISCVAtomicAbiTag tag) {
+ switch (tag) {
+ case RISCVAtomicAbiTag::UNKNOWN:
+ case RISCVAtomicAbiTag::A6C:
+ case RISCVAtomicAbiTag::A6S:
+ case RISCVAtomicAbiTag::A7:
+ return;
+ };
+ errorOrWarn("unknown atomic abi for " + section->name + "\n>>> " +
+ toString(section) +
+ ": atomic_abi=" + Twine(static_cast<unsigned>(tag)));
+ };
+ switch (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;
+ };
+ };
+
+ // If we get here, then we have an invalid tag, so report it.
+ // Putting these checks at the end allows us to only do these checks when we
+ // need to, since this is expected to be a rare occurrence.
+ reportUnknownAbiError(oldSection, oldTag);
+ reportUnknownAbiError(newSection, newTag);
+}
+
static RISCVAttributesSection *
mergeAttributesSection(const SmallVector<InputSectionBase *, 0> §ions) {
+ using RISCVAttrs::RISCVAtomicAbiTag;
RISCVISAUtils::OrderedExtensionMap exts;
const InputSectionBase *firstStackAlign = nullptr;
+ const InputSectionBase *firstAtomicAbi = nullptr;
unsigned firstStackAlignValue = 0, xlen = 0;
bool hasArch = false;
@@ -1136,7 +1220,15 @@ mergeAttributesSection(const SmallVector<InputSectionBase *, 0> §ions) {
break;
case RISCVAttrs::AttrType::ATOMIC_ABI:
- // TODO: Handle ATOMIC_ABI tag merging
+ 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;
}
diff --git a/lld/test/ELF/riscv-attributes.s b/lld/test/ELF/riscv-attributes.s
index 68534d0fb6b75..057223c18418e 100644
--- a/lld/test/ELF/riscv-attributes.s
+++ b/lld/test/ELF/riscv-attributes.s
@@ -44,6 +44,46 @@
# 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
+
+## RISC-V tag merging for atomic_abi values A6C and invalid lead to an error.
+# RUN: llvm-mc -filetype=obj -triple=riscv64 atomic_abi_invalid.s -o atomic_abi_invalid.o
+# RUN: not ld.lld atomic_abi_A6C.o atomic_abi_invalid.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=ATOMIC_ABI_INVALID --implicit-check-not=error:
+# ATOMIC_ABI_INVALID: error: unknown atomic abi for .riscv.attributes
+# ATOMIC_ABI_INVALID-NEXT: >>> atomic_abi_invalid.o:(.riscv.attributes): atomic_abi=42
+
+# 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 +326,178 @@
.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
+
+#--- atomic_abi_invalid.s
+.attribute atomic_abi, 42
+
+# 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
More information about the llvm-commits
mailing list