10b57cec5SDimitry Andric //===- AMDGPUELFObjectWriter.cpp - AMDGPU ELF Writer ----------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric
95ffd83dbSDimitry Andric #include "AMDGPUFixupKinds.h"
100b57cec5SDimitry Andric #include "AMDGPUMCTargetDesc.h"
115ffd83dbSDimitry Andric #include "llvm/MC/MCContext.h"
120b57cec5SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
140b57cec5SDimitry Andric
150b57cec5SDimitry Andric using namespace llvm;
160b57cec5SDimitry Andric
170b57cec5SDimitry Andric namespace {
180b57cec5SDimitry Andric
190b57cec5SDimitry Andric class AMDGPUELFObjectWriter : public MCELFObjectTargetWriter {
200b57cec5SDimitry Andric public:
21*7a6dacacSDimitry Andric AMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI, bool HasRelocationAddend);
220b57cec5SDimitry Andric
230b57cec5SDimitry Andric protected:
240b57cec5SDimitry Andric unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
250b57cec5SDimitry Andric const MCFixup &Fixup, bool IsPCRel) const override;
260b57cec5SDimitry Andric };
270b57cec5SDimitry Andric
280b57cec5SDimitry Andric
290b57cec5SDimitry Andric } // end anonymous namespace
300b57cec5SDimitry Andric
AMDGPUELFObjectWriter(bool Is64Bit,uint8_t OSABI,bool HasRelocationAddend)31*7a6dacacSDimitry Andric AMDGPUELFObjectWriter::AMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI,
32*7a6dacacSDimitry Andric bool HasRelocationAddend)
330b57cec5SDimitry Andric : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_AMDGPU,
34*7a6dacacSDimitry Andric HasRelocationAddend) {}
350b57cec5SDimitry Andric
getRelocType(MCContext & Ctx,const MCValue & Target,const MCFixup & Fixup,bool IsPCRel) const360b57cec5SDimitry Andric unsigned AMDGPUELFObjectWriter::getRelocType(MCContext &Ctx,
370b57cec5SDimitry Andric const MCValue &Target,
380b57cec5SDimitry Andric const MCFixup &Fixup,
390b57cec5SDimitry Andric bool IsPCRel) const {
400b57cec5SDimitry Andric if (const auto *SymA = Target.getSymA()) {
410b57cec5SDimitry Andric // SCRATCH_RSRC_DWORD[01] is a special global variable that represents
420b57cec5SDimitry Andric // the scratch buffer.
430b57cec5SDimitry Andric if (SymA->getSymbol().getName() == "SCRATCH_RSRC_DWORD0" ||
440b57cec5SDimitry Andric SymA->getSymbol().getName() == "SCRATCH_RSRC_DWORD1")
450b57cec5SDimitry Andric return ELF::R_AMDGPU_ABS32_LO;
460b57cec5SDimitry Andric }
470b57cec5SDimitry Andric
480b57cec5SDimitry Andric switch (Target.getAccessVariant()) {
490b57cec5SDimitry Andric default:
500b57cec5SDimitry Andric break;
510b57cec5SDimitry Andric case MCSymbolRefExpr::VK_GOTPCREL:
520b57cec5SDimitry Andric return ELF::R_AMDGPU_GOTPCREL;
530b57cec5SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_LO:
540b57cec5SDimitry Andric return ELF::R_AMDGPU_GOTPCREL32_LO;
550b57cec5SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_HI:
560b57cec5SDimitry Andric return ELF::R_AMDGPU_GOTPCREL32_HI;
570b57cec5SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_REL32_LO:
580b57cec5SDimitry Andric return ELF::R_AMDGPU_REL32_LO;
590b57cec5SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_REL32_HI:
600b57cec5SDimitry Andric return ELF::R_AMDGPU_REL32_HI;
610b57cec5SDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_REL64:
620b57cec5SDimitry Andric return ELF::R_AMDGPU_REL64;
635f757f3fSDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_ABS32_LO:
645f757f3fSDimitry Andric return ELF::R_AMDGPU_ABS32_LO;
655f757f3fSDimitry Andric case MCSymbolRefExpr::VK_AMDGPU_ABS32_HI:
665f757f3fSDimitry Andric return ELF::R_AMDGPU_ABS32_HI;
670b57cec5SDimitry Andric }
680b57cec5SDimitry Andric
6981ad6265SDimitry Andric MCFixupKind Kind = Fixup.getKind();
7081ad6265SDimitry Andric if (Kind >= FirstLiteralRelocationKind)
7181ad6265SDimitry Andric return Kind - FirstLiteralRelocationKind;
7281ad6265SDimitry Andric switch (Kind) {
730b57cec5SDimitry Andric default: break;
740b57cec5SDimitry Andric case FK_PCRel_4:
750b57cec5SDimitry Andric return ELF::R_AMDGPU_REL32;
760b57cec5SDimitry Andric case FK_Data_4:
770b57cec5SDimitry Andric case FK_SecRel_4:
7806c3fb27SDimitry Andric return IsPCRel ? ELF::R_AMDGPU_REL32 : ELF::R_AMDGPU_ABS32;
790b57cec5SDimitry Andric case FK_Data_8:
8006c3fb27SDimitry Andric return IsPCRel ? ELF::R_AMDGPU_REL64 : ELF::R_AMDGPU_ABS64;
810b57cec5SDimitry Andric }
820b57cec5SDimitry Andric
835ffd83dbSDimitry Andric if (Fixup.getTargetKind() == AMDGPU::fixup_si_sopp_br) {
845ffd83dbSDimitry Andric const auto *SymA = Target.getSymA();
855ffd83dbSDimitry Andric assert(SymA);
865ffd83dbSDimitry Andric
87fe6060f1SDimitry Andric if (SymA->getSymbol().isUndefined()) {
88fe6060f1SDimitry Andric Ctx.reportError(Fixup.getLoc(), Twine("undefined label '") +
89fe6060f1SDimitry Andric SymA->getSymbol().getName() + "'");
905ffd83dbSDimitry Andric return ELF::R_AMDGPU_NONE;
915ffd83dbSDimitry Andric }
92fe6060f1SDimitry Andric return ELF::R_AMDGPU_REL16;
93fe6060f1SDimitry Andric }
945ffd83dbSDimitry Andric
950b57cec5SDimitry Andric llvm_unreachable("unhandled relocation type");
960b57cec5SDimitry Andric }
970b57cec5SDimitry Andric
980b57cec5SDimitry Andric std::unique_ptr<MCObjectTargetWriter>
createAMDGPUELFObjectWriter(bool Is64Bit,uint8_t OSABI,bool HasRelocationAddend)990b57cec5SDimitry Andric llvm::createAMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI,
100*7a6dacacSDimitry Andric bool HasRelocationAddend) {
1018bcb0991SDimitry Andric return std::make_unique<AMDGPUELFObjectWriter>(Is64Bit, OSABI,
102*7a6dacacSDimitry Andric HasRelocationAddend);
1030b57cec5SDimitry Andric }
104