1//===- AMDGPUELFObjectWriter.cpp - AMDGPU ELF Writer ----------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "AMDGPUFixupKinds.h"
10#include "AMDGPUMCTargetDesc.h"
11#include "MCTargetDesc/AMDGPUMCExpr.h"
12#include "llvm/MC/MCContext.h"
13#include "llvm/MC/MCELFObjectWriter.h"
14#include "llvm/MC/MCValue.h"
15
16using namespace llvm;
17
18namespace {
19
20class AMDGPUELFObjectWriter : public MCELFObjectTargetWriter {
21public:
22 AMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI, bool HasRelocationAddend);
23
24protected:
25 unsigned getRelocType(const MCFixup &, const MCValue &,
26 bool IsPCRel) const override;
27};
28
29
30} // end anonymous namespace
31
32AMDGPUELFObjectWriter::AMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI,
33 bool HasRelocationAddend)
34 : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_AMDGPU,
35 HasRelocationAddend) {}
36
37unsigned AMDGPUELFObjectWriter::getRelocType(const MCFixup &Fixup,
38 const MCValue &Target,
39 bool IsPCRel) const {
40 if (const auto *SymA = Target.getAddSym()) {
41 // SCRATCH_RSRC_DWORD[01] is a special global variable that represents
42 // the scratch buffer.
43 if (SymA->getName() == "SCRATCH_RSRC_DWORD0" ||
44 SymA->getName() == "SCRATCH_RSRC_DWORD1")
45 return ELF::R_AMDGPU_ABS32_LO;
46 }
47
48 switch (AMDGPUMCExpr::Specifier(Target.getSpecifier())) {
49 default:
50 break;
51 case AMDGPUMCExpr::S_GOTPCREL:
52 return ELF::R_AMDGPU_GOTPCREL;
53 case AMDGPUMCExpr::S_GOTPCREL32_LO:
54 return ELF::R_AMDGPU_GOTPCREL32_LO;
55 case AMDGPUMCExpr::S_GOTPCREL32_HI:
56 return ELF::R_AMDGPU_GOTPCREL32_HI;
57 case AMDGPUMCExpr::S_REL32_LO:
58 return ELF::R_AMDGPU_REL32_LO;
59 case AMDGPUMCExpr::S_REL32_HI:
60 return ELF::R_AMDGPU_REL32_HI;
61 case AMDGPUMCExpr::S_REL64:
62 return ELF::R_AMDGPU_REL64;
63 case AMDGPUMCExpr::S_ABS32_LO:
64 return ELF::R_AMDGPU_ABS32_LO;
65 case AMDGPUMCExpr::S_ABS32_HI:
66 return ELF::R_AMDGPU_ABS32_HI;
67 }
68
69 MCFixupKind Kind = Fixup.getKind();
70 switch (Kind) {
71 default: break;
72 case FK_PCRel_4:
73 return ELF::R_AMDGPU_REL32;
74 case FK_Data_4:
75 case FK_SecRel_4:
76 return IsPCRel ? ELF::R_AMDGPU_REL32 : ELF::R_AMDGPU_ABS32;
77 case FK_Data_8:
78 return IsPCRel ? ELF::R_AMDGPU_REL64 : ELF::R_AMDGPU_ABS64;
79 }
80
81 if (Fixup.getTargetKind() == AMDGPU::fixup_si_sopp_br) {
82 const auto *SymA = Target.getAddSym();
83 assert(SymA);
84
85 if (SymA->isUndefined()) {
86 reportError(L: Fixup.getLoc(),
87 Msg: Twine("undefined label '") + SymA->getName() + "'");
88 return ELF::R_AMDGPU_NONE;
89 }
90 return ELF::R_AMDGPU_REL16;
91 }
92
93 llvm_unreachable("unhandled relocation type");
94}
95
96std::unique_ptr<MCObjectTargetWriter>
97llvm::createAMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI,
98 bool HasRelocationAddend) {
99 return std::make_unique<AMDGPUELFObjectWriter>(args&: Is64Bit, args&: OSABI,
100 args&: HasRelocationAddend);
101}
102