Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/contrib/llvm-project/llvm/lib/Target/Sparc/MCTargetDesc/SparcAsmBackend.cpp
35294 views
1
//===-- SparcAsmBackend.cpp - Sparc Assembler Backend ---------------------===//
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 "MCTargetDesc/SparcFixupKinds.h"
10
#include "MCTargetDesc/SparcMCTargetDesc.h"
11
#include "llvm/ADT/StringSwitch.h"
12
#include "llvm/MC/MCAsmBackend.h"
13
#include "llvm/MC/MCELFObjectWriter.h"
14
#include "llvm/MC/MCExpr.h"
15
#include "llvm/MC/MCFixupKindInfo.h"
16
#include "llvm/MC/MCObjectWriter.h"
17
#include "llvm/MC/MCSubtargetInfo.h"
18
#include "llvm/MC/MCValue.h"
19
#include "llvm/MC/TargetRegistry.h"
20
#include "llvm/Support/EndianStream.h"
21
22
using namespace llvm;
23
24
static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
25
switch (Kind) {
26
default:
27
llvm_unreachable("Unknown fixup kind!");
28
case FK_Data_1:
29
case FK_Data_2:
30
case FK_Data_4:
31
case FK_Data_8:
32
return Value;
33
34
case Sparc::fixup_sparc_wplt30:
35
case Sparc::fixup_sparc_call30:
36
return (Value >> 2) & 0x3fffffff;
37
38
case Sparc::fixup_sparc_br22:
39
return (Value >> 2) & 0x3fffff;
40
41
case Sparc::fixup_sparc_br19:
42
return (Value >> 2) & 0x7ffff;
43
44
case Sparc::fixup_sparc_br16: {
45
// A.3 Branch on Integer Register with Prediction (BPr)
46
// Inst{21-20} = d16hi;
47
// Inst{13-0} = d16lo;
48
unsigned d16hi = (Value >> 16) & 0x3;
49
unsigned d16lo = (Value >> 2) & 0x3fff;
50
return (d16hi << 20) | d16lo;
51
}
52
53
case Sparc::fixup_sparc_hix22:
54
return (~Value >> 10) & 0x3fffff;
55
56
case Sparc::fixup_sparc_pc22:
57
case Sparc::fixup_sparc_got22:
58
case Sparc::fixup_sparc_tls_gd_hi22:
59
case Sparc::fixup_sparc_tls_ldm_hi22:
60
case Sparc::fixup_sparc_tls_ie_hi22:
61
case Sparc::fixup_sparc_hi22:
62
case Sparc::fixup_sparc_lm:
63
return (Value >> 10) & 0x3fffff;
64
65
case Sparc::fixup_sparc_got13:
66
case Sparc::fixup_sparc_13:
67
return Value & 0x1fff;
68
69
case Sparc::fixup_sparc_lox10:
70
return (Value & 0x3ff) | 0x1c00;
71
72
case Sparc::fixup_sparc_pc10:
73
case Sparc::fixup_sparc_got10:
74
case Sparc::fixup_sparc_tls_gd_lo10:
75
case Sparc::fixup_sparc_tls_ldm_lo10:
76
case Sparc::fixup_sparc_tls_ie_lo10:
77
case Sparc::fixup_sparc_lo10:
78
return Value & 0x3ff;
79
80
case Sparc::fixup_sparc_h44:
81
return (Value >> 22) & 0x3fffff;
82
83
case Sparc::fixup_sparc_m44:
84
return (Value >> 12) & 0x3ff;
85
86
case Sparc::fixup_sparc_l44:
87
return Value & 0xfff;
88
89
case Sparc::fixup_sparc_hh:
90
return (Value >> 42) & 0x3fffff;
91
92
case Sparc::fixup_sparc_hm:
93
return (Value >> 32) & 0x3ff;
94
95
case Sparc::fixup_sparc_tls_ldo_hix22:
96
case Sparc::fixup_sparc_tls_le_hix22:
97
case Sparc::fixup_sparc_tls_ldo_lox10:
98
case Sparc::fixup_sparc_tls_le_lox10:
99
assert(Value == 0 && "Sparc TLS relocs expect zero Value");
100
return 0;
101
102
case Sparc::fixup_sparc_tls_gd_add:
103
case Sparc::fixup_sparc_tls_gd_call:
104
case Sparc::fixup_sparc_tls_ldm_add:
105
case Sparc::fixup_sparc_tls_ldm_call:
106
case Sparc::fixup_sparc_tls_ldo_add:
107
case Sparc::fixup_sparc_tls_ie_ld:
108
case Sparc::fixup_sparc_tls_ie_ldx:
109
case Sparc::fixup_sparc_tls_ie_add:
110
case Sparc::fixup_sparc_gotdata_lox10:
111
case Sparc::fixup_sparc_gotdata_hix22:
112
case Sparc::fixup_sparc_gotdata_op:
113
return 0;
114
}
115
}
116
117
/// getFixupKindNumBytes - The number of bytes the fixup may change.
118
static unsigned getFixupKindNumBytes(unsigned Kind) {
119
switch (Kind) {
120
default:
121
return 4;
122
case FK_Data_1:
123
return 1;
124
case FK_Data_2:
125
return 2;
126
case FK_Data_8:
127
return 8;
128
}
129
}
130
131
namespace {
132
class SparcAsmBackend : public MCAsmBackend {
133
protected:
134
bool Is64Bit;
135
bool HasV9;
136
137
public:
138
SparcAsmBackend(const MCSubtargetInfo &STI)
139
: MCAsmBackend(STI.getTargetTriple().isLittleEndian()
140
? llvm::endianness::little
141
: llvm::endianness::big),
142
Is64Bit(STI.getTargetTriple().isArch64Bit()),
143
HasV9(STI.hasFeature(Sparc::FeatureV9)) {}
144
145
unsigned getNumFixupKinds() const override {
146
return Sparc::NumTargetFixupKinds;
147
}
148
149
std::optional<MCFixupKind> getFixupKind(StringRef Name) const override {
150
unsigned Type;
151
Type = llvm::StringSwitch<unsigned>(Name)
152
#define ELF_RELOC(X, Y) .Case(#X, Y)
153
#include "llvm/BinaryFormat/ELFRelocs/Sparc.def"
154
#undef ELF_RELOC
155
.Case("BFD_RELOC_NONE", ELF::R_SPARC_NONE)
156
.Case("BFD_RELOC_8", ELF::R_SPARC_8)
157
.Case("BFD_RELOC_16", ELF::R_SPARC_16)
158
.Case("BFD_RELOC_32", ELF::R_SPARC_32)
159
.Case("BFD_RELOC_64", ELF::R_SPARC_64)
160
.Default(-1u);
161
if (Type == -1u)
162
return std::nullopt;
163
return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
164
}
165
166
const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override {
167
const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = {
168
// name offset bits flags
169
{ "fixup_sparc_call30", 2, 30, MCFixupKindInfo::FKF_IsPCRel },
170
{ "fixup_sparc_br22", 10, 22, MCFixupKindInfo::FKF_IsPCRel },
171
{ "fixup_sparc_br19", 13, 19, MCFixupKindInfo::FKF_IsPCRel },
172
{ "fixup_sparc_br16", 0, 32, MCFixupKindInfo::FKF_IsPCRel },
173
{ "fixup_sparc_13", 19, 13, 0 },
174
{ "fixup_sparc_hi22", 10, 22, 0 },
175
{ "fixup_sparc_lo10", 22, 10, 0 },
176
{ "fixup_sparc_h44", 10, 22, 0 },
177
{ "fixup_sparc_m44", 22, 10, 0 },
178
{ "fixup_sparc_l44", 20, 12, 0 },
179
{ "fixup_sparc_hh", 10, 22, 0 },
180
{ "fixup_sparc_hm", 22, 10, 0 },
181
{ "fixup_sparc_lm", 10, 22, 0 },
182
{ "fixup_sparc_pc22", 10, 22, MCFixupKindInfo::FKF_IsPCRel },
183
{ "fixup_sparc_pc10", 22, 10, MCFixupKindInfo::FKF_IsPCRel },
184
{ "fixup_sparc_got22", 10, 22, 0 },
185
{ "fixup_sparc_got10", 22, 10, 0 },
186
{ "fixup_sparc_got13", 19, 13, 0 },
187
{ "fixup_sparc_wplt30", 2, 30, MCFixupKindInfo::FKF_IsPCRel },
188
{ "fixup_sparc_tls_gd_hi22", 10, 22, 0 },
189
{ "fixup_sparc_tls_gd_lo10", 22, 10, 0 },
190
{ "fixup_sparc_tls_gd_add", 0, 0, 0 },
191
{ "fixup_sparc_tls_gd_call", 0, 0, 0 },
192
{ "fixup_sparc_tls_ldm_hi22", 10, 22, 0 },
193
{ "fixup_sparc_tls_ldm_lo10", 22, 10, 0 },
194
{ "fixup_sparc_tls_ldm_add", 0, 0, 0 },
195
{ "fixup_sparc_tls_ldm_call", 0, 0, 0 },
196
{ "fixup_sparc_tls_ldo_hix22", 10, 22, 0 },
197
{ "fixup_sparc_tls_ldo_lox10", 22, 10, 0 },
198
{ "fixup_sparc_tls_ldo_add", 0, 0, 0 },
199
{ "fixup_sparc_tls_ie_hi22", 10, 22, 0 },
200
{ "fixup_sparc_tls_ie_lo10", 22, 10, 0 },
201
{ "fixup_sparc_tls_ie_ld", 0, 0, 0 },
202
{ "fixup_sparc_tls_ie_ldx", 0, 0, 0 },
203
{ "fixup_sparc_tls_ie_add", 0, 0, 0 },
204
{ "fixup_sparc_tls_le_hix22", 0, 0, 0 },
205
{ "fixup_sparc_tls_le_lox10", 0, 0, 0 },
206
{ "fixup_sparc_hix22", 10, 22, 0 },
207
{ "fixup_sparc_lox10", 19, 13, 0 },
208
{ "fixup_sparc_gotdata_hix22", 0, 0, 0 },
209
{ "fixup_sparc_gotdata_lox10", 0, 0, 0 },
210
{ "fixup_sparc_gotdata_op", 0, 0, 0 },
211
};
212
213
const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {
214
// name offset bits flags
215
{ "fixup_sparc_call30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
216
{ "fixup_sparc_br22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
217
{ "fixup_sparc_br19", 0, 19, MCFixupKindInfo::FKF_IsPCRel },
218
{ "fixup_sparc_br16", 32, 0, MCFixupKindInfo::FKF_IsPCRel },
219
{ "fixup_sparc_13", 0, 13, 0 },
220
{ "fixup_sparc_hi22", 0, 22, 0 },
221
{ "fixup_sparc_lo10", 0, 10, 0 },
222
{ "fixup_sparc_h44", 0, 22, 0 },
223
{ "fixup_sparc_m44", 0, 10, 0 },
224
{ "fixup_sparc_l44", 0, 12, 0 },
225
{ "fixup_sparc_hh", 0, 22, 0 },
226
{ "fixup_sparc_hm", 0, 10, 0 },
227
{ "fixup_sparc_lm", 0, 22, 0 },
228
{ "fixup_sparc_pc22", 0, 22, MCFixupKindInfo::FKF_IsPCRel },
229
{ "fixup_sparc_pc10", 0, 10, MCFixupKindInfo::FKF_IsPCRel },
230
{ "fixup_sparc_got22", 0, 22, 0 },
231
{ "fixup_sparc_got10", 0, 10, 0 },
232
{ "fixup_sparc_got13", 0, 13, 0 },
233
{ "fixup_sparc_wplt30", 0, 30, MCFixupKindInfo::FKF_IsPCRel },
234
{ "fixup_sparc_tls_gd_hi22", 0, 22, 0 },
235
{ "fixup_sparc_tls_gd_lo10", 0, 10, 0 },
236
{ "fixup_sparc_tls_gd_add", 0, 0, 0 },
237
{ "fixup_sparc_tls_gd_call", 0, 0, 0 },
238
{ "fixup_sparc_tls_ldm_hi22", 0, 22, 0 },
239
{ "fixup_sparc_tls_ldm_lo10", 0, 10, 0 },
240
{ "fixup_sparc_tls_ldm_add", 0, 0, 0 },
241
{ "fixup_sparc_tls_ldm_call", 0, 0, 0 },
242
{ "fixup_sparc_tls_ldo_hix22", 0, 22, 0 },
243
{ "fixup_sparc_tls_ldo_lox10", 0, 10, 0 },
244
{ "fixup_sparc_tls_ldo_add", 0, 0, 0 },
245
{ "fixup_sparc_tls_ie_hi22", 0, 22, 0 },
246
{ "fixup_sparc_tls_ie_lo10", 0, 10, 0 },
247
{ "fixup_sparc_tls_ie_ld", 0, 0, 0 },
248
{ "fixup_sparc_tls_ie_ldx", 0, 0, 0 },
249
{ "fixup_sparc_tls_ie_add", 0, 0, 0 },
250
{ "fixup_sparc_tls_le_hix22", 0, 0, 0 },
251
{ "fixup_sparc_tls_le_lox10", 0, 0, 0 },
252
{ "fixup_sparc_hix22", 0, 22, 0 },
253
{ "fixup_sparc_lox10", 0, 13, 0 },
254
{ "fixup_sparc_gotdata_hix22", 0, 0, 0 },
255
{ "fixup_sparc_gotdata_lox10", 0, 0, 0 },
256
{ "fixup_sparc_gotdata_op", 0, 0, 0 },
257
};
258
259
// Fixup kinds from .reloc directive are like R_SPARC_NONE. They do
260
// not require any extra processing.
261
if (Kind >= FirstLiteralRelocationKind)
262
return MCAsmBackend::getFixupKindInfo(FK_NONE);
263
264
if (Kind < FirstTargetFixupKind)
265
return MCAsmBackend::getFixupKindInfo(Kind);
266
267
assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
268
"Invalid kind!");
269
if (Endian == llvm::endianness::little)
270
return InfosLE[Kind - FirstTargetFixupKind];
271
272
return InfosBE[Kind - FirstTargetFixupKind];
273
}
274
275
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup,
276
const MCValue &Target,
277
const MCSubtargetInfo *STI) override {
278
if (Fixup.getKind() >= FirstLiteralRelocationKind)
279
return true;
280
switch ((Sparc::Fixups)Fixup.getKind()) {
281
default:
282
return false;
283
case Sparc::fixup_sparc_wplt30:
284
if (Target.getSymA()->getSymbol().isTemporary())
285
return false;
286
[[fallthrough]];
287
case Sparc::fixup_sparc_tls_gd_hi22:
288
case Sparc::fixup_sparc_tls_gd_lo10:
289
case Sparc::fixup_sparc_tls_gd_add:
290
case Sparc::fixup_sparc_tls_gd_call:
291
case Sparc::fixup_sparc_tls_ldm_hi22:
292
case Sparc::fixup_sparc_tls_ldm_lo10:
293
case Sparc::fixup_sparc_tls_ldm_add:
294
case Sparc::fixup_sparc_tls_ldm_call:
295
case Sparc::fixup_sparc_tls_ldo_hix22:
296
case Sparc::fixup_sparc_tls_ldo_lox10:
297
case Sparc::fixup_sparc_tls_ldo_add:
298
case Sparc::fixup_sparc_tls_ie_hi22:
299
case Sparc::fixup_sparc_tls_ie_lo10:
300
case Sparc::fixup_sparc_tls_ie_ld:
301
case Sparc::fixup_sparc_tls_ie_ldx:
302
case Sparc::fixup_sparc_tls_ie_add:
303
case Sparc::fixup_sparc_tls_le_hix22:
304
case Sparc::fixup_sparc_tls_le_lox10:
305
return true;
306
}
307
}
308
309
void relaxInstruction(MCInst &Inst,
310
const MCSubtargetInfo &STI) const override {
311
// FIXME.
312
llvm_unreachable("relaxInstruction() unimplemented");
313
}
314
315
bool writeNopData(raw_ostream &OS, uint64_t Count,
316
const MCSubtargetInfo *STI) const override {
317
318
// If the count is not 4-byte aligned, we must be writing data into the
319
// text section (otherwise we have unaligned instructions, and thus have
320
// far bigger problems), so just write zeros instead.
321
OS.write_zeros(Count % 4);
322
323
uint64_t NumNops = Count / 4;
324
for (uint64_t i = 0; i != NumNops; ++i)
325
support::endian::write<uint32_t>(OS, 0x01000000, Endian);
326
327
return true;
328
}
329
};
330
331
class ELFSparcAsmBackend : public SparcAsmBackend {
332
Triple::OSType OSType;
333
public:
334
ELFSparcAsmBackend(const MCSubtargetInfo &STI, Triple::OSType OSType)
335
: SparcAsmBackend(STI), OSType(OSType) {}
336
337
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
338
const MCValue &Target, MutableArrayRef<char> Data,
339
uint64_t Value, bool IsResolved,
340
const MCSubtargetInfo *STI) const override {
341
342
if (Fixup.getKind() >= FirstLiteralRelocationKind)
343
return;
344
Value = adjustFixupValue(Fixup.getKind(), Value);
345
if (!Value) return; // Doesn't change encoding.
346
347
unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
348
unsigned Offset = Fixup.getOffset();
349
// For each byte of the fragment that the fixup touches, mask in the bits
350
// from the fixup value. The Value has been "split up" into the
351
// appropriate bitfields above.
352
for (unsigned i = 0; i != NumBytes; ++i) {
353
unsigned Idx =
354
Endian == llvm::endianness::little ? i : (NumBytes - 1) - i;
355
Data[Offset + Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
356
}
357
}
358
359
std::unique_ptr<MCObjectTargetWriter>
360
createObjectTargetWriter() const override {
361
uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
362
return createSparcELFObjectWriter(Is64Bit, HasV9, OSABI);
363
}
364
};
365
366
} // end anonymous namespace
367
368
MCAsmBackend *llvm::createSparcAsmBackend(const Target &T,
369
const MCSubtargetInfo &STI,
370
const MCRegisterInfo &MRI,
371
const MCTargetOptions &Options) {
372
return new ELFSparcAsmBackend(STI, STI.getTargetTriple().getOS());
373
}
374
375