AMDGPU.cpp revision 360784
1//===- AMDGPU.cpp ---------------------------------------------------------===//
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 "InputFiles.h"
10#include "Symbols.h"
11#include "Target.h"
12#include "lld/Common/ErrorHandler.h"
13#include "llvm/Object/ELF.h"
14#include "llvm/Support/Endian.h"
15
16using namespace llvm;
17using namespace llvm::object;
18using namespace llvm::support::endian;
19using namespace llvm::ELF;
20
21namespace lld {
22namespace elf {
23
24namespace {
25class AMDGPU final : public TargetInfo {
26public:
27  AMDGPU();
28  uint32_t calcEFlags() const override;
29  void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
30  RelExpr getRelExpr(RelType type, const Symbol &s,
31                     const uint8_t *loc) const override;
32  RelType getDynRel(RelType type) const override;
33};
34} // namespace
35
36AMDGPU::AMDGPU() {
37  relativeRel = R_AMDGPU_RELATIVE64;
38  gotRel = R_AMDGPU_ABS64;
39  noneRel = R_AMDGPU_NONE;
40  symbolicRel = R_AMDGPU_ABS64;
41}
42
43static uint32_t getEFlags(InputFile *file) {
44  return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader()->e_flags;
45}
46
47uint32_t AMDGPU::calcEFlags() const {
48  assert(!objectFiles.empty());
49  uint32_t ret = getEFlags(objectFiles[0]);
50
51  // Verify that all input files have the same e_flags.
52  for (InputFile *f : makeArrayRef(objectFiles).slice(1)) {
53    if (ret == getEFlags(f))
54      continue;
55    error("incompatible e_flags: " + toString(f));
56    return 0;
57  }
58  return ret;
59}
60
61void AMDGPU::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
62  switch (type) {
63  case R_AMDGPU_ABS32:
64  case R_AMDGPU_GOTPCREL:
65  case R_AMDGPU_GOTPCREL32_LO:
66  case R_AMDGPU_REL32:
67  case R_AMDGPU_REL32_LO:
68    write32le(loc, val);
69    break;
70  case R_AMDGPU_ABS64:
71  case R_AMDGPU_REL64:
72    write64le(loc, val);
73    break;
74  case R_AMDGPU_GOTPCREL32_HI:
75  case R_AMDGPU_REL32_HI:
76    write32le(loc, val >> 32);
77    break;
78  default:
79    llvm_unreachable("unknown relocation");
80  }
81}
82
83RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s,
84                           const uint8_t *loc) const {
85  switch (type) {
86  case R_AMDGPU_ABS32:
87  case R_AMDGPU_ABS64:
88    return R_ABS;
89  case R_AMDGPU_REL32:
90  case R_AMDGPU_REL32_LO:
91  case R_AMDGPU_REL32_HI:
92  case R_AMDGPU_REL64:
93    return R_PC;
94  case R_AMDGPU_GOTPCREL:
95  case R_AMDGPU_GOTPCREL32_LO:
96  case R_AMDGPU_GOTPCREL32_HI:
97    return R_GOT_PC;
98  default:
99    error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
100          ") against symbol " + toString(s));
101    return R_NONE;
102  }
103}
104
105RelType AMDGPU::getDynRel(RelType type) const {
106  if (type == R_AMDGPU_ABS64)
107    return type;
108  return R_AMDGPU_NONE;
109}
110
111TargetInfo *getAMDGPUTargetInfo() {
112  static AMDGPU target;
113  return &target;
114}
115
116} // namespace elf
117} // namespace lld
118