Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/lld/ELF/Arch/AMDGPU.cpp
34878 views
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/BinaryFormat/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
using namespace lld;
21
using namespace lld::elf;
22
23
namespace {
24
class AMDGPU final : public TargetInfo {
25
private:
26
uint32_t calcEFlagsV3() const;
27
uint32_t calcEFlagsV4() const;
28
uint32_t calcEFlagsV6() const;
29
30
public:
31
AMDGPU();
32
uint32_t calcEFlags() const override;
33
void relocate(uint8_t *loc, const Relocation &rel,
34
uint64_t val) const override;
35
RelExpr getRelExpr(RelType type, const Symbol &s,
36
const uint8_t *loc) const override;
37
RelType getDynRel(RelType type) const override;
38
int64_t getImplicitAddend(const uint8_t *buf, RelType type) const override;
39
};
40
} // namespace
41
42
AMDGPU::AMDGPU() {
43
relativeRel = R_AMDGPU_RELATIVE64;
44
gotRel = R_AMDGPU_ABS64;
45
symbolicRel = R_AMDGPU_ABS64;
46
}
47
48
static uint32_t getEFlags(InputFile *file) {
49
return cast<ObjFile<ELF64LE>>(file)->getObj().getHeader().e_flags;
50
}
51
52
uint32_t AMDGPU::calcEFlagsV3() const {
53
uint32_t ret = getEFlags(ctx.objectFiles[0]);
54
55
// Verify that all input files have the same e_flags.
56
for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) {
57
if (ret == getEFlags(f))
58
continue;
59
error("incompatible e_flags: " + toString(f));
60
return 0;
61
}
62
return ret;
63
}
64
65
uint32_t AMDGPU::calcEFlagsV4() const {
66
uint32_t retMach = getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_MACH;
67
uint32_t retXnack =
68
getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_FEATURE_XNACK_V4;
69
uint32_t retSramEcc =
70
getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_FEATURE_SRAMECC_V4;
71
72
// Verify that all input files have compatible e_flags (same mach, all
73
// features in the same category are either ANY, ANY and ON, or ANY and OFF).
74
for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) {
75
if (retMach != (getEFlags(f) & EF_AMDGPU_MACH)) {
76
error("incompatible mach: " + toString(f));
77
return 0;
78
}
79
80
if (retXnack == EF_AMDGPU_FEATURE_XNACK_UNSUPPORTED_V4 ||
81
(retXnack != EF_AMDGPU_FEATURE_XNACK_ANY_V4 &&
82
(getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4)
83
!= EF_AMDGPU_FEATURE_XNACK_ANY_V4)) {
84
if (retXnack != (getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4)) {
85
error("incompatible xnack: " + toString(f));
86
return 0;
87
}
88
} else {
89
if (retXnack == EF_AMDGPU_FEATURE_XNACK_ANY_V4)
90
retXnack = getEFlags(f) & EF_AMDGPU_FEATURE_XNACK_V4;
91
}
92
93
if (retSramEcc == EF_AMDGPU_FEATURE_SRAMECC_UNSUPPORTED_V4 ||
94
(retSramEcc != EF_AMDGPU_FEATURE_SRAMECC_ANY_V4 &&
95
(getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4) !=
96
EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)) {
97
if (retSramEcc != (getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4)) {
98
error("incompatible sramecc: " + toString(f));
99
return 0;
100
}
101
} else {
102
if (retSramEcc == EF_AMDGPU_FEATURE_SRAMECC_ANY_V4)
103
retSramEcc = getEFlags(f) & EF_AMDGPU_FEATURE_SRAMECC_V4;
104
}
105
}
106
107
return retMach | retXnack | retSramEcc;
108
}
109
110
uint32_t AMDGPU::calcEFlagsV6() const {
111
uint32_t flags = calcEFlagsV4();
112
113
uint32_t genericVersion =
114
getEFlags(ctx.objectFiles[0]) & EF_AMDGPU_GENERIC_VERSION;
115
116
// Verify that all input files have compatible generic version.
117
for (InputFile *f : ArrayRef(ctx.objectFiles).slice(1)) {
118
if (genericVersion != (getEFlags(f) & EF_AMDGPU_GENERIC_VERSION)) {
119
error("incompatible generic version: " + toString(f));
120
return 0;
121
}
122
}
123
124
flags |= genericVersion;
125
return flags;
126
}
127
128
uint32_t AMDGPU::calcEFlags() const {
129
if (ctx.objectFiles.empty())
130
return 0;
131
132
uint8_t abiVersion = cast<ObjFile<ELF64LE>>(ctx.objectFiles[0])
133
->getObj()
134
.getHeader()
135
.e_ident[EI_ABIVERSION];
136
switch (abiVersion) {
137
case ELFABIVERSION_AMDGPU_HSA_V2:
138
case ELFABIVERSION_AMDGPU_HSA_V3:
139
return calcEFlagsV3();
140
case ELFABIVERSION_AMDGPU_HSA_V4:
141
case ELFABIVERSION_AMDGPU_HSA_V5:
142
return calcEFlagsV4();
143
case ELFABIVERSION_AMDGPU_HSA_V6:
144
return calcEFlagsV6();
145
default:
146
error("unknown abi version: " + Twine(abiVersion));
147
return 0;
148
}
149
}
150
151
void AMDGPU::relocate(uint8_t *loc, const Relocation &rel, uint64_t val) const {
152
switch (rel.type) {
153
case R_AMDGPU_ABS32:
154
case R_AMDGPU_GOTPCREL:
155
case R_AMDGPU_GOTPCREL32_LO:
156
case R_AMDGPU_REL32:
157
case R_AMDGPU_REL32_LO:
158
write32le(loc, val);
159
break;
160
case R_AMDGPU_ABS64:
161
case R_AMDGPU_REL64:
162
write64le(loc, val);
163
break;
164
case R_AMDGPU_GOTPCREL32_HI:
165
case R_AMDGPU_REL32_HI:
166
write32le(loc, val >> 32);
167
break;
168
case R_AMDGPU_REL16: {
169
int64_t simm = (static_cast<int64_t>(val) - 4) / 4;
170
checkInt(loc, simm, 16, rel);
171
write16le(loc, simm);
172
break;
173
}
174
default:
175
llvm_unreachable("unknown relocation");
176
}
177
}
178
179
RelExpr AMDGPU::getRelExpr(RelType type, const Symbol &s,
180
const uint8_t *loc) const {
181
switch (type) {
182
case R_AMDGPU_ABS32:
183
case R_AMDGPU_ABS64:
184
return R_ABS;
185
case R_AMDGPU_REL32:
186
case R_AMDGPU_REL32_LO:
187
case R_AMDGPU_REL32_HI:
188
case R_AMDGPU_REL64:
189
case R_AMDGPU_REL16:
190
return R_PC;
191
case R_AMDGPU_GOTPCREL:
192
case R_AMDGPU_GOTPCREL32_LO:
193
case R_AMDGPU_GOTPCREL32_HI:
194
return R_GOT_PC;
195
default:
196
error(getErrorLocation(loc) + "unknown relocation (" + Twine(type) +
197
") against symbol " + toString(s));
198
return R_NONE;
199
}
200
}
201
202
RelType AMDGPU::getDynRel(RelType type) const {
203
if (type == R_AMDGPU_ABS64)
204
return type;
205
return R_AMDGPU_NONE;
206
}
207
208
int64_t AMDGPU::getImplicitAddend(const uint8_t *buf, RelType type) const {
209
switch (type) {
210
case R_AMDGPU_NONE:
211
return 0;
212
case R_AMDGPU_ABS64:
213
case R_AMDGPU_RELATIVE64:
214
return read64(buf);
215
default:
216
internalLinkerError(getErrorLocation(buf),
217
"cannot read addend for relocation " + toString(type));
218
return 0;
219
}
220
}
221
222
TargetInfo *elf::getAMDGPUTargetInfo() {
223
static AMDGPU target;
224
return &target;
225
}
226
227