171d5a254SDimitry Andric //===- AMDGPUELFObjectWriter.cpp - AMDGPU ELF Writer ----------------------===//
259d6cff9SDimitry Andric //
3e6d15924SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e6d15924SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e6d15924SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
659d6cff9SDimitry Andric //
759d6cff9SDimitry Andric //===----------------------------------------------------------------------===//
859d6cff9SDimitry Andric
9cfca06d7SDimitry Andric #include "AMDGPUFixupKinds.h"
1059d6cff9SDimitry Andric #include "AMDGPUMCTargetDesc.h"
11cfca06d7SDimitry Andric #include "llvm/MC/MCContext.h"
1259d6cff9SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h"
1371d5a254SDimitry Andric #include "llvm/MC/MCValue.h"
1459d6cff9SDimitry Andric
1559d6cff9SDimitry Andric using namespace llvm;
1659d6cff9SDimitry Andric
1759d6cff9SDimitry Andric namespace {
1859d6cff9SDimitry Andric
1959d6cff9SDimitry Andric class AMDGPUELFObjectWriter : public MCELFObjectTargetWriter {
2059d6cff9SDimitry Andric public:
214df029ccSDimitry Andric AMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI, bool HasRelocationAddend);
2271d5a254SDimitry Andric
2359d6cff9SDimitry Andric protected:
2401095a5dSDimitry Andric unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
2501095a5dSDimitry Andric const MCFixup &Fixup, bool IsPCRel) const override;
2659d6cff9SDimitry Andric };
2759d6cff9SDimitry Andric
2859d6cff9SDimitry Andric
2971d5a254SDimitry Andric } // end anonymous namespace
3059d6cff9SDimitry Andric
AMDGPUELFObjectWriter(bool Is64Bit,uint8_t OSABI,bool HasRelocationAddend)314df029ccSDimitry Andric AMDGPUELFObjectWriter::AMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI,
324df029ccSDimitry Andric bool HasRelocationAddend)
33044eb2f6SDimitry Andric : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_AMDGPU,
344df029ccSDimitry Andric HasRelocationAddend) {}
3559d6cff9SDimitry Andric
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const3601095a5dSDimitry Andric unsigned AMDGPUELFObjectWriter::getRelocType(MCContext &Ctx,
3701095a5dSDimitry Andric const MCValue &Target,
3801095a5dSDimitry Andric const MCFixup &Fixup,
3901095a5dSDimitry Andric bool IsPCRel) const {
40b915e9e0SDimitry Andric if (const auto *SymA = Target.getSymA()) {
4101095a5dSDimitry Andric // SCRATCH_RSRC_DWORD[01] is a special global variable that represents
4201095a5dSDimitry Andric // the scratch buffer.
43d8e91e46SDimitry Andric if (SymA->getSymbol().getName() == "SCRATCH_RSRC_DWORD0" ||
44d8e91e46SDimitry Andric SymA->getSymbol().getName() == "SCRATCH_RSRC_DWORD1")
4501095a5dSDimitry Andric return ELF::R_AMDGPU_ABS32_LO;
46b915e9e0SDimitry Andric }
4701095a5dSDimitry Andric
4801095a5dSDimitry Andric switch (Target.getAccessVariant()) {
4901095a5dSDimitry Andric default:
5001095a5dSDimitry Andric break;
5101095a5dSDimitry Andric case MCSymbolRefExpr::VK_GOTPCREL:
5201095a5dSDimitry Andric return ELF::R_AMDGPU_GOTPCREL;
53b915e9e0SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_LO:
54b915e9e0SDimitry Andric return ELF::R_AMDGPU_GOTPCREL32_LO;
55b915e9e0SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_HI:
56b915e9e0SDimitry Andric return ELF::R_AMDGPU_GOTPCREL32_HI;
57b915e9e0SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_REL32_LO:
58b915e9e0SDimitry Andric return ELF::R_AMDGPU_REL32_LO;
59b915e9e0SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_REL32_HI:
60b915e9e0SDimitry Andric return ELF::R_AMDGPU_REL32_HI;
61eb11fae6SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_REL64:
62eb11fae6SDimitry Andric return ELF::R_AMDGPU_REL64;
63b1c73532SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_ABS32_LO:
64b1c73532SDimitry Andric return ELF::R_AMDGPU_ABS32_LO;
65b1c73532SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_ABS32_HI:
66b1c73532SDimitry Andric return ELF::R_AMDGPU_ABS32_HI;
6701095a5dSDimitry Andric }
6801095a5dSDimitry Andric
69145449b1SDimitry Andric MCFixupKind Kind = Fixup.getKind();
70145449b1SDimitry Andric if (Kind >= FirstLiteralRelocationKind)
71145449b1SDimitry Andric return Kind - FirstLiteralRelocationKind;
72145449b1SDimitry Andric switch (Kind) {
7301095a5dSDimitry Andric default: break;
7401095a5dSDimitry Andric case FK_PCRel_4:
7501095a5dSDimitry Andric return ELF::R_AMDGPU_REL32;
76b915e9e0SDimitry Andric case FK_Data_4:
7701095a5dSDimitry Andric case FK_SecRel_4:
787fa27ce4SDimitry Andric return IsPCRel ? ELF::R_AMDGPU_REL32 : ELF::R_AMDGPU_ABS32;
79b915e9e0SDimitry Andric case FK_Data_8:
807fa27ce4SDimitry Andric return IsPCRel ? ELF::R_AMDGPU_REL64 : ELF::R_AMDGPU_ABS64;
8101095a5dSDimitry Andric }
8201095a5dSDimitry Andric
83cfca06d7SDimitry Andric if (Fixup.getTargetKind() == AMDGPU::fixup_si_sopp_br) {
84cfca06d7SDimitry Andric const auto *SymA = Target.getSymA();
85cfca06d7SDimitry Andric assert(SymA);
86cfca06d7SDimitry Andric
87344a3780SDimitry Andric if (SymA->getSymbol().isUndefined()) {
88344a3780SDimitry Andric Ctx.reportError(Fixup.getLoc(), Twine("undefined label '") +
89344a3780SDimitry Andric SymA->getSymbol().getName() + "'");
90cfca06d7SDimitry Andric return ELF::R_AMDGPU_NONE;
91cfca06d7SDimitry Andric }
92344a3780SDimitry Andric return ELF::R_AMDGPU_REL16;
93344a3780SDimitry Andric }
94cfca06d7SDimitry Andric
9501095a5dSDimitry Andric llvm_unreachable("unhandled relocation type");
9601095a5dSDimitry Andric }
9701095a5dSDimitry Andric
98eb11fae6SDimitry Andric std::unique_ptr<MCObjectTargetWriter>
createAMDGPUELFObjectWriter(bool Is64Bit,uint8_t OSABI,bool HasRelocationAddend)99044eb2f6SDimitry Andric llvm::createAMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI,
1004df029ccSDimitry Andric bool HasRelocationAddend) {
1011d5ae102SDimitry Andric return std::make_unique<AMDGPUELFObjectWriter>(Is64Bit, OSABI,
1024df029ccSDimitry Andric HasRelocationAddend);
10359d6cff9SDimitry Andric }
104