80 changes: 80 additions & 0 deletions lld/lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
//===- lib/ReaderWriter/ELF/AMDGPU/AMDGPUTargetHandler.h ------------------===//
//
// The LLVM Linker
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//

#ifndef AMDGPU_TARGET_HANDLER_H
#define AMDGPU_TARGET_HANDLER_H

#include "ELFFile.h"
#include "ELFReader.h"
#include "AMDGPURelocationHandler.h"
#include "TargetLayout.h"

namespace lld {
namespace elf {
class AMDGPULinkingContext;

class HSATextSection : public AtomSection<ELF64LE> {
public:
HSATextSection(const ELFLinkingContext &ctx);
};

/// \brief TargetLayout for AMDGPU
class AMDGPUTargetLayout final : public TargetLayout<ELF64LE> {
public:
AMDGPUTargetLayout(AMDGPULinkingContext &ctx) : TargetLayout(ctx) {}

void assignSectionsToSegments() override;

/// \brief Gets or creates a section.
AtomSection<ELF64LE> *
createSection(StringRef name, int32_t contentType,
DefinedAtom::ContentPermissions contentPermissions,
TargetLayout::SectionOrder sectionOrder) override {
if (name == ".text")
return new (_allocator) HSATextSection(_ctx);

if (name == ".note")
contentType = DefinedAtom::typeRONote;

return TargetLayout::createSection(name, contentType, contentPermissions,
sectionOrder);
}
};

/// \brief TargetHandler for AMDGPU
class AMDGPUTargetHandler final : public TargetHandler {
public:
AMDGPUTargetHandler(AMDGPULinkingContext &targetInfo);

const TargetRelocationHandler &getRelocationHandler() const override {
return *_relocationHandler;
}

std::unique_ptr<Reader> getObjReader() override {
return llvm::make_unique<ELFReader<ELFFile<ELF64LE>>>(_ctx);
}

std::unique_ptr<Reader> getDSOReader() override {
return llvm::make_unique<ELFReader<DynamicFile<ELF64LE>>>(_ctx);
}

std::unique_ptr<Writer> getWriter() override;

private:
AMDGPULinkingContext &_ctx;
std::unique_ptr<AMDGPUTargetLayout> _targetLayout;
std::unique_ptr<AMDGPUTargetRelocationHandler> _relocationHandler;
};

void finalizeAMDGPURuntimeAtomValues(AMDGPUTargetLayout &layout);

} // end namespace elf
} // end namespace lld

#endif
13 changes: 13 additions & 0 deletions lld/lib/ReaderWriter/ELF/AMDGPU/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
add_llvm_library(lldAMDGPUELFTarget
AMDGPUExecutableWriter.cpp
AMDGPULinkingContext.cpp
AMDGPURelocationHandler.cpp
AMDGPUSymbolTable.cpp
AMDGPUTargetHandler.cpp
LINK_LIBS
lldELF
lldReaderWriter
lldCore
LLVMObject
LLVMSupport
)
1 change: 1 addition & 0 deletions lld/lib/ReaderWriter/ELF/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,4 @@ add_subdirectory(Mips)
add_subdirectory(Hexagon)
add_subdirectory(AArch64)
add_subdirectory(ARM)
add_subdirectory(AMDGPU)
8 changes: 5 additions & 3 deletions lld/lib/ReaderWriter/ELF/ELFFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -196,12 +196,14 @@ template <class ELFT> class ELFFile : public SimpleFile {

/// Determines if the target wants to create an atom for a section that has no
/// symbol references.
bool handleSectionWithNoSymbols(const Elf_Shdr *shdr,
std::vector<const Elf_Sym *> &syms) const {
bool
handleSectionWithNoSymbols(const Elf_Shdr *shdr,
std::vector<const Elf_Sym *> &syms) const {
return shdr &&
(shdr->sh_type == llvm::ELF::SHT_PROGBITS ||
shdr->sh_type == llvm::ELF::SHT_INIT_ARRAY ||
shdr->sh_type == llvm::ELF::SHT_FINI_ARRAY) &&
shdr->sh_type == llvm::ELF::SHT_FINI_ARRAY ||
shdr->sh_type == llvm::ELF::SHT_NOTE) &&
syms.empty();
}

Expand Down
2 changes: 2 additions & 0 deletions lld/lib/ReaderWriter/ELF/ELFLinkingContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ uint16_t ELFLinkingContext::getOutputMachine() const {
return llvm::ELF::EM_AARCH64;
case llvm::Triple::arm:
return llvm::ELF::EM_ARM;
case llvm::Triple::amdgcn:
return llvm::ELF::EM_AMDGPU;
default:
llvm_unreachable("Unhandled arch");
}
Expand Down
53 changes: 53 additions & 0 deletions lld/test/elf/AMDGPU/hsa.test
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
# RUN: yaml2obj -format=elf %s > %t.obj
# RUN: lld -flavor gnu -target amdgcn--hsa %t.obj -o %t.exe --noinhibit-exec
# RUN: llvm-readobj -h -program-headers -s -symbols %t.exe | FileCheck %s

# CHECK: ElfHeader {
# CHECK: Ident {
# CHECK: Class: 64-bit (0x2)
# CHECK: DataEncoding: LittleEndian (0x1)
# CHECK: Machine: EM_AMDGPU (0xE0)


# CHECK: Section {
# CHECK: Name: .text
# CHECK: Type: SHT_PROGBITS (0x1)
# CHECK: Flags [ (0xC00007
# CHECK: SHF_ALLOC (0x2)
# CHECK: SHF_AMDGPU_HSA_AGENT (0x800000)
# CHECK: SHF_AMDGPU_HSA_CODE (0x400000)
# CHECK: SHF_EXECINSTR (0x4)
# CHECK: SHF_WRITE (0x1)
#
# CHECK: Symbol {
# CHECK: Name: kernel
# CHECK: Value: 0x0
# CHECK: Binding: Local (0x0)
# CHECK: Type: AMDGPU_HSA_KERNEL (0xA)

# CHECK: ProgramHeader {
# CHECK: Type: PT_AMDGPU_HSA_LOAD_CODE_AGENT (0x60000003)

---
FileHeader:
Class: ELFCLASS64
Data: ELFDATA2LSB
OSABI: ELFOSABI_GNU
Type: ET_REL
Machine: EM_AMDGPU
Sections:
- Name: .text
Type: SHT_PROGBITS
Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
AddressAlign: 0x0000000000000004
Content: ''
- Name: .note
Type: SHT_NOTE
AddressAlign: 0x0000000000000001
Content: '00'
Symbols:
Local:
- Name: kernel
Type: STT_GNU_IFUNC
Section: .text
...