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 "llvm/BinaryFormat/ELF.h"
12#include "llvm/MC/MCContext.h"
13#include "llvm/MC/MCELFObjectWriter.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCFixup.h"
16#include "llvm/MC/MCObjectWriter.h"
17#include "llvm/MC/MCSymbol.h"
18#include "llvm/MC/MCValue.h"
19#include "llvm/Support/ErrorHandling.h"
20
21using namespace llvm;
22
23namespace {
24
25class AMDGPUELFObjectWriter : public MCELFObjectTargetWriter {
26public:
27  AMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI, bool HasRelocationAddend,
28                        uint8_t ABIVersion);
29
30protected:
31  unsigned getRelocType(MCContext &Ctx, const MCValue &Target,
32                        const MCFixup &Fixup, bool IsPCRel) const override;
33};
34
35
36} // end anonymous namespace
37
38AMDGPUELFObjectWriter::AMDGPUELFObjectWriter(bool Is64Bit,
39                                             uint8_t OSABI,
40                                             bool HasRelocationAddend,
41                                             uint8_t ABIVersion)
42  : MCELFObjectTargetWriter(Is64Bit, OSABI, ELF::EM_AMDGPU,
43                            HasRelocationAddend, ABIVersion) {}
44
45unsigned AMDGPUELFObjectWriter::getRelocType(MCContext &Ctx,
46                                             const MCValue &Target,
47                                             const MCFixup &Fixup,
48                                             bool IsPCRel) const {
49  if (const auto *SymA = Target.getSymA()) {
50    // SCRATCH_RSRC_DWORD[01] is a special global variable that represents
51    // the scratch buffer.
52    if (SymA->getSymbol().getName() == "SCRATCH_RSRC_DWORD0" ||
53        SymA->getSymbol().getName() == "SCRATCH_RSRC_DWORD1")
54      return ELF::R_AMDGPU_ABS32_LO;
55  }
56
57  switch (Target.getAccessVariant()) {
58  default:
59    break;
60  case MCSymbolRefExpr::VK_GOTPCREL:
61    return ELF::R_AMDGPU_GOTPCREL;
62  case MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_LO:
63    return ELF::R_AMDGPU_GOTPCREL32_LO;
64  case MCSymbolRefExpr::VK_AMDGPU_GOTPCREL32_HI:
65    return ELF::R_AMDGPU_GOTPCREL32_HI;
66  case MCSymbolRefExpr::VK_AMDGPU_REL32_LO:
67    return ELF::R_AMDGPU_REL32_LO;
68  case MCSymbolRefExpr::VK_AMDGPU_REL32_HI:
69    return ELF::R_AMDGPU_REL32_HI;
70  case MCSymbolRefExpr::VK_AMDGPU_REL64:
71    return ELF::R_AMDGPU_REL64;
72  }
73
74  switch (Fixup.getKind()) {
75  default: break;
76  case FK_PCRel_4:
77    return ELF::R_AMDGPU_REL32;
78  case FK_Data_4:
79  case FK_SecRel_4:
80    return ELF::R_AMDGPU_ABS32;
81  case FK_Data_8:
82    return ELF::R_AMDGPU_ABS64;
83  }
84
85  if (Fixup.getTargetKind() == AMDGPU::fixup_si_sopp_br) {
86    const auto *SymA = Target.getSymA();
87    assert(SymA);
88
89    Ctx.reportError(Fixup.getLoc(),
90                    Twine("undefined label '") + SymA->getSymbol().getName() + "'");
91    return ELF::R_AMDGPU_NONE;
92  }
93
94  llvm_unreachable("unhandled relocation type");
95}
96
97std::unique_ptr<MCObjectTargetWriter>
98llvm::createAMDGPUELFObjectWriter(bool Is64Bit, uint8_t OSABI,
99                                  bool HasRelocationAddend,
100                                  uint8_t ABIVersion) {
101  return std::make_unique<AMDGPUELFObjectWriter>(Is64Bit, OSABI,
102                                                  HasRelocationAddend,
103                                                  ABIVersion);
104}
105