Index: ELF/Config.h =================================================================== --- ELF/Config.h +++ ELF/Config.h @@ -82,6 +82,7 @@ // Most fields are initialized by the driver. struct Configuration { uint8_t OSABI = 0; + uint8_t ABIVersion = 0; llvm::CachePruningPolicy ThinLTOCachePolicy; llvm::StringMap SectionStartMap; llvm::StringRef Chroot; Index: ELF/Driver.cpp =================================================================== --- ELF/Driver.cpp +++ ELF/Driver.cpp @@ -1165,6 +1165,7 @@ Config->EKind = F->EKind; Config->EMachine = F->EMachine; Config->OSABI = F->OSABI; + Config->ABIVersion = F->ABIVersion; Config->MipsN32Abi = Config->EMachine == EM_MIPS && isMipsN32Abi(F); return; } Index: ELF/InputFiles.h =================================================================== --- ELF/InputFiles.h +++ ELF/InputFiles.h @@ -103,6 +103,7 @@ ELFKind EKind = ELFNoneKind; uint16_t EMachine = llvm::ELF::EM_NONE; uint8_t OSABI = 0; + uint8_t ABIVersion = 0; // Cache for toString(). Only toString() should use this member. mutable std::string ToStringCache; Index: ELF/InputFiles.cpp =================================================================== --- ELF/InputFiles.cpp +++ ELF/InputFiles.cpp @@ -239,6 +239,7 @@ EMachine = getObj().getHeader()->e_machine; OSABI = getObj().getHeader()->e_ident[llvm::ELF::EI_OSABI]; + ABIVersion = getObj().getHeader()->e_ident[llvm::ELF::EI_ABIVERSION]; } template Index: ELF/SymbolTable.cpp =================================================================== --- ELF/SymbolTable.cpp +++ ELF/SymbolTable.cpp @@ -47,7 +47,8 @@ if (!F->isElf() && !isa(F)) return true; - if (F->EKind == Config->EKind && F->EMachine == Config->EMachine) { + if (F->EKind == Config->EKind && F->EMachine == Config->EMachine && + F->ABIVersion == Config->ABIVersion) { if (Config->EMachine != EM_MIPS) return true; if (isMipsN32Abi(F) == Config->MipsN32Abi) Index: ELF/Writer.cpp =================================================================== --- ELF/Writer.cpp +++ ELF/Writer.cpp @@ -2381,6 +2381,9 @@ } static uint8_t getAbiVersion() { + if (Config->ABIVersion) + return Config->ABIVersion; + // MIPS non-PIC executable gets ABI version 1. if (Config->EMachine == EM_MIPS && getELFType() == ET_EXEC && (Config->EFlags & (EF_MIPS_PIC | EF_MIPS_CPIC)) == EF_MIPS_CPIC) Index: test/ELF/amdgpu-abi-version-err.s =================================================================== --- /dev/null +++ test/ELF/amdgpu-abi-version-err.s @@ -0,0 +1,10 @@ +# REQUIRES: amdgpu +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx900 -filetype=obj %s -o %t-0.o +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx900 -mattr=-code-object-v3 -filetype=obj %s -o %t-1.o +# RUN: not ld.lld -shared %t-0.o %t-1 -o %t.so + +# CHECK: ld.lld: error: {{.*}}-1.o is incompatible with {{.*}}-0.o + +.text + s_nop 0x0 + s_endpgm Index: test/ELF/amdgpu-abi-version.s =================================================================== --- /dev/null +++ test/ELF/amdgpu-abi-version.s @@ -0,0 +1,11 @@ +# REQUIRES: amdgpu +# RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx900 -filetype=obj %s -o %t.o +# RUN: ld.lld -shared %t.o -o %t.so +# RUN: llvm-readobj -file-headers %t.so | FileCheck %s + +# CHECK: OS/ABI: AMDGPU_HSA (0x40) +# CHECK: ABIVersion: 1 + +.text + s_nop 0x0 + s_endpgm \ No newline at end of file