diff --git a/lld/ELF/Arch/AMDGPU.cpp b/lld/ELF/Arch/AMDGPU.cpp index 4f4ce0094bbfd3..c765d6e083002c 100644 --- a/lld/ELF/Arch/AMDGPU.cpp +++ b/lld/ELF/Arch/AMDGPU.cpp @@ -22,6 +22,10 @@ using namespace lld::elf; namespace { class AMDGPU final : public TargetInfo { +private: + uint32_t calcEFlagsV3() const; + uint32_t calcEFlagsV4() const; + public: AMDGPU(); uint32_t calcEFlags() const override; @@ -44,8 +48,7 @@ static uint32_t getEFlags(InputFile *file) { return cast>(file)->getObj().getHeader().e_flags; } -uint32_t AMDGPU::calcEFlags() const { - assert(!objectFiles.empty()); +uint32_t AMDGPU::calcEFlagsV3() const { uint32_t ret = getEFlags(objectFiles[0]); // Verify that all input files have the same e_flags. @@ -58,6 +61,67 @@ uint32_t AMDGPU::calcEFlags() const { return ret; } +uint32_t AMDGPU::calcEFlagsV4() const { + uint32_t retMach = getEFlags(objectFiles[0]) & EF_AMDGPU_MACH; + uint32_t retXnack = getEFlags(objectFiles[0]) & EF_AMDGPU_FEATURE_XNACK_V4; + uint32_t retSramEcc = + getEFlags(objectFiles[0]) & EF_AMDGPU_FEATURE_SRAMECC_V4; + + // Verify that all input files have compatible e_flags (same mach, all + // features in the same category are either ANY, ANY and ON, or ANY and OFF). + for (InputFile *f : makeArrayRef(objectFiles).slice(1)) { + if (retMach != (getEFlags(f) & EF_AMDGPU_MACH)) { + error("incompatible mach: " + toString(f)); + return 0; + } + + if (retXnack == EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 || + (retXnack != EF_AMDGPU_FEATURE_XNACK_ANY_V4 && + (getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4) + != EF_AMDGPU_FEATURE_XNACK_ANY_V4)) { + if (retXnack != (getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4)) { + error("incompatible xnack: " + toString(f)); + return 0; + } + } else { + if (retXnack == EF_AMDGPU_FEATURE_XNACK_ANY_V4) + retXnack = getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4; + } + + if (retSramEcc == EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 || + (retSramEcc != EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 && + (getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4) != + EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)) { + if (retSramEcc != (getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4)) { + error("incompatible sramecc: " + toString(f)); + return 0; + } + } else { + if (retSramEcc == EF_AMDGPU_FEATURE_SRAMECC_ANY_V4) + retSramEcc = getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4; + } + } + + return retMach | retXnack | retSramEcc; +} + +uint32_t AMDGPU::calcEFlags() const { + assert(!objectFiles.empty()); + + uint8_t abiVersion = cast>(objectFiles[0])->getObj() + .getHeader().e_ident[EI_ABIVERSION]; + switch (abiVersion) { + case ELFABIVERSION_AMDGPU_HSA_V2: + case ELFABIVERSION_AMDGPU_HSA_V3: + return calcEFlagsV3(); + case ELFABIVERSION_AMDGPU_HSA_V4: + return calcEFlagsV4(); + default: + error("unknown abi version: " + Twine(abiVersion)); + return 0; + } +} + void AMDGPU::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const { switch (rel.type) { case R_AMDGPU_ABS32: diff --git a/lld/test/ELF/amdgpu-tid.s b/lld/test/ELF/amdgpu-tid.s new file mode 100644 index 00000000000000..6623443a4541d7 --- /dev/null +++ b/lld/test/ELF/amdgpu-tid.s @@ -0,0 +1,45 @@ +# REQUIRES: amdgpu + +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx906 -mattr=-xnack --amdhsa-code-object-version=4 -filetype=obj %s -o %t-xnack-off0.o +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx906 -mattr=-xnack --amdhsa-code-object-version=4 -filetype=obj %s -o %t-xnack-off1.o +# RUN: ld.lld -shared %t-xnack-off0.o %t-xnack-off1.o -o %t-xnack-off2.so +# RUN: llvm-readobj --file-headers %t-xnack-off2.so | FileCheck --check-prefix=XNACK-OFF %s + +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx906 -mattr=+xnack --amdhsa-code-object-version=4 -filetype=obj %s -o %t-xnack-on0.o +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx906 -mattr=+xnack --amdhsa-code-object-version=4 -filetype=obj %s -o %t-xnack-on1.o +# RUN: ld.lld -shared %t-xnack-on0.o %t-xnack-on1.o -o %t-xnack-on2.so +# RUN: llvm-readobj --file-headers %t-xnack-on2.so | FileCheck --check-prefix=XNACK-ON %s + +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx906 --amdhsa-code-object-version=4 -filetype=obj %s -o %t-xnack-any.o +# RUN: ld.lld -shared %t-xnack-off0.o %t-xnack-any.o -o %t-xnack-off3.so +# RUN: llvm-readobj --file-headers %t-xnack-off3.so | FileCheck --check-prefix=XNACK-OFF %s +# RUN: ld.lld -shared %t-xnack-on0.o %t-xnack-any.o -o %t-xnack-on3.so +# RUN: llvm-readobj --file-headers %t-xnack-on3.so | FileCheck --check-prefix=XNACK-ON %s + +# RUN: not ld.lld -shared %t-xnack-off0.o %t-xnack-on0.o -o /dev/null 2>&1 | FileCheck --check-prefix=XNACK-INCOMPATIBLE %s + +# XNACK-OFF: EF_AMDGPU_FEATURE_XNACK_OFF_V4 (0x200) +# XNACK-ON: EF_AMDGPU_FEATURE_XNACK_ON_V4 (0x300) +# XNACK-INCOMPATIBLE: incompatible xnack: + +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx906 -mattr=-sramecc --amdhsa-code-object-version=4 -filetype=obj %s -o %t-sramecc-off0.o +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx906 -mattr=-sramecc --amdhsa-code-object-version=4 -filetype=obj %s -o %t-sramecc-off1.o +# RUN: ld.lld -shared %t-sramecc-off0.o %t-sramecc-off1.o -o %t-sramecc-off2.so +# RUN: llvm-readobj --file-headers %t-sramecc-off2.so | FileCheck --check-prefix=SRAMECC-OFF %s + +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx906 -mattr=+sramecc --amdhsa-code-object-version=4 -filetype=obj %s -o %t-sramecc-on0.o +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx906 -mattr=+sramecc --amdhsa-code-object-version=4 -filetype=obj %s -o %t-sramecc-on1.o +# RUN: ld.lld -shared %t-sramecc-on0.o %t-sramecc-on1.o -o %t-sramecc-on2.so +# RUN: llvm-readobj --file-headers %t-sramecc-on2.so | FileCheck --check-prefix=SRAMECC-ON %s + +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx906 --amdhsa-code-object-version=4 -filetype=obj %s -o %t-sramecc-any.o +# RUN: ld.lld -shared %t-sramecc-off0.o %t-sramecc-any.o -o %t-sramecc-off3.so +# RUN: llvm-readobj --file-headers %t-sramecc-off3.so | FileCheck --check-prefix=SRAMECC-OFF %s +# RUN: ld.lld -shared %t-sramecc-on0.o %t-sramecc-any.o -o %t-sramecc-on3.so +# RUN: llvm-readobj --file-headers %t-sramecc-on3.so | FileCheck --check-prefix=SRAMECC-ON %s + +# RUN: not ld.lld -shared %t-sramecc-off0.o %t-sramecc-on0.o -o /dev/null 2>&1 | FileCheck --check-prefix=SRAMECC-INCOMPATIBLE %s + +# SRAMECC-OFF: EF_AMDGPU_FEATURE_SRAMECC_OFF_V4 (0x800) +# SRAMECC-ON: EF_AMDGPU_FEATURE_SRAMECC_ON_V4 (0xC00) +# SRAMECC-INCOMPATIBLE: incompatible sramecc: