1320021Sdim//===- AMDGPU.cpp ---------------------------------------------------------===//
2320021Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6320021Sdim//
7320021Sdim//===----------------------------------------------------------------------===//
8320021Sdim
9320021Sdim#include "InputFiles.h"
10320021Sdim#include "Symbols.h"
11320021Sdim#include "Target.h"
12327952Sdim#include "lld/Common/ErrorHandler.h"
13320021Sdim#include "llvm/Object/ELF.h"
14320021Sdim#include "llvm/Support/Endian.h"
15320021Sdim
16320021Sdimusing namespace llvm;
17320021Sdimusing namespace llvm::object;
18320021Sdimusing namespace llvm::support::endian;
19320021Sdimusing namespace llvm::ELF;
20320021Sdim
21360784Sdimnamespace lld {
22360784Sdimnamespace elf {
23360784Sdim
24320021Sdimnamespace {
25320021Sdimclass AMDGPU final : public TargetInfo {
26320021Sdimpublic:
27320021Sdim  AMDGPU();
28327952Sdim  uint32_t calcEFlags() const override;
29353358Sdim  void relocateOne(uint8_t *loc, RelType type, uint64_t val) const override;
30353358Sdim  RelExpr getRelExpr(RelType type, const Symbol &s,
31353358Sdim                     const uint8_t *loc) const override;
32353358Sdim  RelType getDynRel(RelType type) const override;
33320021Sdim};
34320021Sdim} // namespace
35320021Sdim
36320021SdimAMDGPU::AMDGPU() {
37353358Sdim  relativeRel = R_AMDGPU_RELATIVE64;
38353358Sdim  gotRel = R_AMDGPU_ABS64;
39353358Sdim  noneRel = R_AMDGPU_NONE;
40353358Sdim  symbolicRel = R_AMDGPU_ABS64;
41320021Sdim}
42320021Sdim
43353358Sdimstatic uint32_t getEFlags(InputFile *file) {
44353358Sdim  return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader()->e_flags;
45327952Sdim}
46327952Sdim
47327952Sdimuint32_t AMDGPU::calcEFlags() const {
48353358Sdim  assert(!objectFiles.empty());
49353358Sdim  uint32_t ret = getEFlags(objectFiles[0]);
50327952Sdim
51327952Sdim  // Verify that all input files have the same e_flags.
52353358Sdim  for (InputFile *f : makeArrayRef(objectFiles).slice(1)) {
53353358Sdim    if (ret == getEFlags(f))
54327952Sdim      continue;
55353358Sdim    error("incompatible e_flags: " + toString(f));
56327952Sdim    return 0;
57327952Sdim  }
58353358Sdim  return ret;
59327952Sdim}
60327952Sdim
61353358Sdimvoid AMDGPU::relocateOne(uint8_t *loc, RelType type, uint64_t val) const {
62353358Sdim  switch (type) {
63320021Sdim  case R_AMDGPU_ABS32:
64320021Sdim  case R_AMDGPU_GOTPCREL:
65320021Sdim  case R_AMDGPU_GOTPCREL32_LO:
66320021Sdim  case R_AMDGPU_REL32:
67320021Sdim  case R_AMDGPU_REL32_LO:
68353358Sdim    write32le(loc, val);
69320021Sdim    break;
70320021Sdim  case R_AMDGPU_ABS64:
71341825Sdim  case R_AMDGPU_REL64:
72353358Sdim    write64le(loc, val);
73320021Sdim    break;
74320021Sdim  case R_AMDGPU_GOTPCREL32_HI:
75320021Sdim  case R_AMDGPU_REL32_HI:
76353358Sdim    write32le(loc, val >> 32);
77320021Sdim    break;
78320021Sdim  default:
79353358Sdim    llvm_unreachable("unknown relocation");
80320021Sdim  }
81320021Sdim}
82320021Sdim
83353358SdimRelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s,
84353358Sdim                           const uint8_t *loc) const {
85353358Sdim  switch (type) {
86320021Sdim  case R_AMDGPU_ABS32:
87320021Sdim  case R_AMDGPU_ABS64:
88320021Sdim    return R_ABS;
89320021Sdim  case R_AMDGPU_REL32:
90320021Sdim  case R_AMDGPU_REL32_LO:
91320021Sdim  case R_AMDGPU_REL32_HI:
92341825Sdim  case R_AMDGPU_REL64:
93320021Sdim    return R_PC;
94320021Sdim  case R_AMDGPU_GOTPCREL:
95320021Sdim  case R_AMDGPU_GOTPCREL32_LO:
96320021Sdim  case R_AMDGPU_GOTPCREL32_HI:
97320021Sdim    return R_GOT_PC;
98320021Sdim  default:
99353358Sdim    error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
100353358Sdim          ") against symbol " + toString(s));
101353358Sdim    return R_NONE;
102320021Sdim  }
103320021Sdim}
104320021Sdim
105353358SdimRelType AMDGPU::getDynRel(RelType type) const {
106353358Sdim  if (type == R_AMDGPU_ABS64)
107353358Sdim    return type;
108353358Sdim  return R_AMDGPU_NONE;
109353358Sdim}
110353358Sdim
111360784SdimTargetInfo *getAMDGPUTargetInfo() {
112353358Sdim  static AMDGPU target;
113353358Sdim  return &target;
114320397Sdim}
115360784Sdim
116360784Sdim} // namespace elf
117360784Sdim} // namespace lld
118