Index: lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp =================================================================== --- lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp +++ lib/Target/AMDGPU/AMDGPUAsmPrinter.cpp @@ -132,6 +132,19 @@ } void AMDGPUAsmPrinter::EmitEndOfAsmFile(Module &M) { + if (TM.getTargetTriple().getArch() != Triple::amdgcn) + return; + + // Emit ISA Version (NT_AMD_AMDGPU_ISA). + getTargetStreamer().EmitISAVersion(IsaInfo::getIsaVersionString(getSTI())); + + // Emit HSA Metadata (NT_AMD_AMDGPU_HSA_METADATA). + if (TM.getTargetTriple().getOS() == Triple::AMDHSA) { + HSAMetadataStream.end(); + getTargetStreamer().EmitHSAMetadata(HSAMetadataStream.getHSAMetadata()); + } + + // Emit PAL Metadata (NT_AMD_AMDGPU_PAL_METADATA). if (TM.getTargetTriple().getOS() == Triple::AMDPAL) { // Copy the PAL metadata from the map where we collected it into a vector, // then write it as a .note. @@ -142,12 +155,6 @@ } getTargetStreamer().EmitPALMetadata(PALMetadataVector); } - - if (TM.getTargetTriple().getOS() != Triple::AMDHSA) - return; - - HSAMetadataStream.end(); - getTargetStreamer().EmitHSAMetadata(HSAMetadataStream.getHSAMetadata()); } bool AMDGPUAsmPrinter::isBlockOnlyReachableByFallthrough( Index: lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp =================================================================== --- lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp +++ lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp @@ -833,6 +833,7 @@ bool subtargetHasRegister(const MCRegisterInfo &MRI, unsigned RegNo) const; bool ParseDirectiveAMDGPUHsaKernel(); + bool ParseDirectiveISAVersion(); bool ParseDirectiveHSAMetadata(); bool ParseDirectivePALMetadata(); @@ -2453,6 +2454,22 @@ return false; } +bool AMDGPUAsmParser::ParseDirectiveISAVersion() { + auto ISAVersionFromASM = getLexer().getTok().getStringContents(); + auto ISAVersionFromSTI = IsaInfo::getIsaVersionString(&getSTI()); + + if (ISAVersionFromASM != ISAVersionFromSTI) { + return Error(getParser().getTok().getLoc(), + ".amd_amdgpu_isa directive does not match triple and/or mcpu " + "arguments specified through the command line"); + } + + getTargetStreamer().EmitISAVersion(ISAVersionFromSTI); + Lex(); + + return false; +} + bool AMDGPUAsmParser::ParseDirectiveHSAMetadata() { std::string HSAMetadataString; raw_string_ostream YamlStream(HSAMetadataString); @@ -2528,6 +2545,9 @@ if (IDVal == ".amdgpu_hsa_kernel") return ParseDirectiveAMDGPUHsaKernel(); + if (IDVal == ".amd_amdgpu_isa") + return ParseDirectiveISAVersion(); + if (IDVal == AMDGPU::HSAMD::AssemblerDirectiveBegin) return ParseDirectiveHSAMetadata(); Index: lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h =================================================================== --- lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h +++ lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.h @@ -12,6 +12,7 @@ #include "AMDKernelCodeT.h" #include "llvm/MC/MCStreamer.h" +#include "llvm/MC/MCSubtargetInfo.h" #include "llvm/Support/AMDGPUMetadata.h" namespace llvm { @@ -30,7 +31,8 @@ MCContext &getContext() const { return Streamer.getContext(); } public: - AMDGPUTargetStreamer(MCStreamer &S); + AMDGPUTargetStreamer(MCStreamer &S) : MCTargetStreamer(S) {} + virtual void EmitDirectiveHSACodeObjectVersion(uint32_t Major, uint32_t Minor) = 0; @@ -44,6 +46,9 @@ virtual void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) = 0; /// \returns True on success, false on failure. + virtual bool EmitISAVersion(StringRef IsaVersionString) = 0; + + /// \returns True on success, false on failure. virtual bool EmitHSAMetadata(StringRef HSAMetadataString); /// \returns True on success, false on failure. @@ -69,6 +74,9 @@ void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override; /// \returns True on success, false on failure. + bool EmitISAVersion(StringRef IsaVersionString) override; + + /// \returns True on success, false on failure. bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) override; /// \returns True on success, false on failure. @@ -98,6 +106,9 @@ void EmitAMDGPUSymbolType(StringRef SymbolName, unsigned Type) override; /// \returns True on success, false on failure. + bool EmitISAVersion(StringRef IsaVersionString) override; + + /// \returns True on success, false on failure. bool EmitHSAMetadata(const AMDGPU::HSAMD::Metadata &HSAMetadata) override; /// \returns True on success, false on failure. Index: lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp =================================================================== --- lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp +++ lib/Target/AMDGPU/MCTargetDesc/AMDGPUTargetStreamer.cpp @@ -39,9 +39,6 @@ // AMDGPUTargetStreamer //===----------------------------------------------------------------------===// -AMDGPUTargetStreamer::AMDGPUTargetStreamer(MCStreamer &S) - : MCTargetStreamer(S) {} - bool AMDGPUTargetStreamer::EmitHSAMetadata(StringRef HSAMetadataString) { HSAMD::Metadata HSAMetadata; if (auto Error = HSAMD::fromString(HSAMetadataString, HSAMetadata)) @@ -94,6 +91,11 @@ } } +bool AMDGPUTargetAsmStreamer::EmitISAVersion(StringRef IsaVersionString) { + OS << "\t.amd_amdgpu_isa \"" << IsaVersionString << "\"\n"; + return true; +} + bool AMDGPUTargetAsmStreamer::EmitHSAMetadata( const AMDGPU::HSAMD::Metadata &HSAMetadata) { std::string HSAMetadataString; @@ -208,6 +210,28 @@ Symbol->setType(ELF::STT_AMDGPU_HSA_KERNEL); } +bool AMDGPUTargetELFStreamer::EmitISAVersion(StringRef IsaVersionString) { + // Create two labels to mark the beginning and end of the desc field + // and a MCExpr to calculate the size of the desc field. + auto &Context = getContext(); + auto *DescBegin = Context.createTempSymbol(); + auto *DescEnd = Context.createTempSymbol(); + auto *DescSZ = MCBinaryExpr::createSub( + MCSymbolRefExpr::create(DescEnd, Context), + MCSymbolRefExpr::create(DescBegin, Context), Context); + + EmitAMDGPUNote( + DescSZ, + ELF::NT_AMD_AMDGPU_ISA, + [&](MCELFStreamer &OS) { + OS.EmitLabel(DescBegin); + OS.EmitBytes(IsaVersionString); + OS.EmitLabel(DescEnd); + } + ); + return true; +} + bool AMDGPUTargetELFStreamer::EmitHSAMetadata( const AMDGPU::HSAMD::Metadata &HSAMetadata) { std::string HSAMetadataString; Index: lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h =================================================================== --- lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h +++ lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.h @@ -19,6 +19,7 @@ #include "llvm/Support/Compiler.h" #include "llvm/Support/ErrorHandling.h" #include +#include #include namespace llvm { @@ -54,6 +55,9 @@ /// \returns Isa version for given subtarget \p Features. IsaVersion getIsaVersion(const FeatureBitset &Features); +/// \returns Isa version string for given subtarget \p STI. +std::string getIsaVersionString(const MCSubtargetInfo *STI); + /// \returns Wavefront size for given subtarget \p Features. unsigned getWavefrontSize(const FeatureBitset &Features); Index: lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp =================================================================== --- lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp +++ lib/Target/AMDGPU/Utils/AMDGPUBaseInfo.cpp @@ -147,6 +147,25 @@ return {7, 0, 0}; } +std::string getIsaVersionString(const MCSubtargetInfo *STI) { + auto TargetTriple = STI->getTargetTriple(); + auto ISAVersion = IsaInfo::getIsaVersion(STI->getFeatureBits()); + + std::string ISAVersionString; + raw_string_ostream ISAVersionStream(ISAVersionString); + + ISAVersionStream << TargetTriple.getArchName() << '-' + << TargetTriple.getVendorName() << '-' + << TargetTriple.getOSName() << '-' + << TargetTriple.getEnvironmentName() << '-' + << "gfx" + << ISAVersion.Major + << ISAVersion.Minor + << ISAVersion.Stepping; + ISAVersionStream.flush(); + return ISAVersionString; +} + unsigned getWavefrontSize(const FeatureBitset &Features) { if (Features.test(FeatureWavefrontSize16)) return 16; Index: test/CodeGen/AMDGPU/elf-notes.ll =================================================================== --- /dev/null +++ test/CodeGen/AMDGPU/elf-notes.ll @@ -0,0 +1,25 @@ +; RUN: llc -march=r600 < %s | FileCheck --check-prefix=R600 %s +; RUN: llc -mtriple=amdgcn-amd-unknown -mcpu=gfx800 < %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-UNK --check-prefix=GFX800 %s +; RUN: llc -mtriple=amdgcn-amd-unknown -mcpu=iceland < %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-UNK --check-prefix=GFX800 %s +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=gfx800 < %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-HSA --check-prefix=GFX800 %s +; RUN: llc -mtriple=amdgcn-amd-amdhsa -mcpu=iceland < %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-HSA --check-prefix=GFX800 %s +; RUN: llc -mtriple=amdgcn-amd-amdpal -mcpu=gfx800 < %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-PAL --check-prefix=GFX800 %s +; RUN: llc -mtriple=amdgcn-amd-amdpal -mcpu=iceland < %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-PAL --check-prefix=GFX800 %s + +; R600-NOT: .amd_amdgpu_isa +; R600-NOT: .amd_amdgpu_hsa_metadata +; R600-NOT: .amd_amdgpu_hsa_metadata + +; OSABI-UNK: .amd_amdgpu_isa "amdgcn-amd-unknown--gfx800" +; OSABI-UNK-NOT: .amd_amdgpu_hsa_metadata +; OSABI-UNK-NOT: .amd_amdgpu_pal_metadata + +; OSABI-HSA: .amd_amdgpu_isa "amdgcn-amd-amdhsa--gfx800" +; OSABI-HSA: .amd_amdgpu_hsa_metadata + +; OSABI-PAL: .amd_amdgpu_isa "amdgcn-amd-amdpal--gfx800" +; OSABI-PAL: .amd_amdgpu_pal_metadata + +define amdgpu_kernel void @elf_notes() { + ret void +} Index: test/MC/AMDGPU/isa-version-hsa.s =================================================================== --- /dev/null +++ test/MC/AMDGPU/isa-version-hsa.s @@ -0,0 +1,14 @@ +// RUN: not llvm-mc -triple amdgcn-amd-unknown -mcpu=gfx800 %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-UNK-ERR --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-unknown -mcpu=iceland %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-UNK-ERR --check-prefix=GFX800 %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx800 %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-HSA --check-prefix=GFX800 %s +// RUN: llvm-mc -triple amdgcn-amd-amdhsa -mcpu=iceland %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-HSA --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx803 %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-HSA-ERR --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-amdpal -mcpu=gfx800 %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-PAL-ERR --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-amdpal -mcpu=iceland %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-PAL-ERR --check-prefix=GFX800 %s + + +// OSABI-HSA: .amd_amdgpu_isa "amdgcn-amd-amdhsa--gfx800" +// OSABI-UNK-ERR: error: .amd_amdgpu_isa directive does not match triple and/or mcpu arguments specified through the command line +// OSABI-HSA-ERR: error: .amd_amdgpu_isa directive does not match triple and/or mcpu arguments specified through the command line +// OSABI-PAL-ERR: error: .amd_amdgpu_isa directive does not match triple and/or mcpu arguments specified through the command line +.amd_amdgpu_isa "amdgcn-amd-amdhsa--gfx800" Index: test/MC/AMDGPU/isa-version-pal.s =================================================================== --- /dev/null +++ test/MC/AMDGPU/isa-version-pal.s @@ -0,0 +1,13 @@ +// RUN: not llvm-mc -triple amdgcn-amd-unknown -mcpu=gfx800 %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-UNK-ERR --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-unknown -mcpu=iceland %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-UNK-ERR --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx800 %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-HSA-ERR --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-amdhsa -mcpu=iceland %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-HSA-ERR --check-prefix=GFX800 %s +// RUN: llvm-mc -triple amdgcn-amd-amdpal -mcpu=gfx800 %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-PAL --check-prefix=GFX800 %s +// RUN: llvm-mc -triple amdgcn-amd-amdpal -mcpu=iceland %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-PAL --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-unknown -mcpu=gfx803 %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-UNK-ERR --check-prefix=GFX800 %s + +// OSABI-PAL: .amd_amdgpu_isa "amdgcn-amd-amdpal--gfx800" +// OSABI-UNK-ERR: error: .amd_amdgpu_isa directive does not match triple and/or mcpu arguments specified through the command line +// OSABI-HSA-ERR: error: .amd_amdgpu_isa directive does not match triple and/or mcpu arguments specified through the command line +// OSABI-PAL-ERR: error: .amd_amdgpu_isa directive does not match triple and/or mcpu arguments specified through the command line +.amd_amdgpu_isa "amdgcn-amd-amdpal--gfx800" Index: test/MC/AMDGPU/isa-version-unk.s =================================================================== --- /dev/null +++ test/MC/AMDGPU/isa-version-unk.s @@ -0,0 +1,14 @@ +// RUN: llvm-mc -triple amdgcn-amd-unknown -mcpu=gfx800 %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-UNK --check-prefix=GFX800 %s +// RUN: llvm-mc -triple amdgcn-amd-unknown -mcpu=iceland %s | FileCheck --check-prefix=GCN --check-prefix=OSABI-UNK --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-unknown -mcpu=gfx803 %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-UNK-ERR --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-amdhsa -mcpu=gfx800 %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-HSA-ERR --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-amdhsa -mcpu=iceland %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-HSA-ERR --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-amdpal -mcpu=gfx800 %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-PAL-ERR --check-prefix=GFX800 %s +// RUN: not llvm-mc -triple amdgcn-amd-amdpal -mcpu=iceland %s 2>&1 | FileCheck --check-prefix=GCN --check-prefix=OSABI-PAL-ERR --check-prefix=GFX800 %s + + +// OSABI-UNK: .amd_amdgpu_isa "amdgcn-amd-unknown--gfx800" +// OSABI-UNK-ERR: error: .amd_amdgpu_isa directive does not match triple and/or mcpu arguments specified through the command line +// OSABI-HSA-ERR: error: .amd_amdgpu_isa directive does not match triple and/or mcpu arguments specified through the command line +// OSABI-PAL-ERR: error: .amd_amdgpu_isa directive does not match triple and/or mcpu arguments specified through the command line +.amd_amdgpu_isa "amdgcn-amd-unknown--gfx800"