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