LLVM 24.0.0git
SparcAsmBackend.cpp
Go to the documentation of this file.
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
14#include "llvm/MC/MCExpr.h"
17#include "llvm/MC/MCValue.h"
20
21using namespace llvm;
22
23static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
24 switch (Kind) {
25 default:
26 assert(uint16_t(Kind) < FirstTargetFixupKind && "Unknown fixup kind!");
27 return Value;
28 case FK_Data_1:
29 case FK_Data_2:
30 case FK_Data_4:
31 case FK_Data_8:
32 return Value;
33
35 return (Value >> 2) & 0x3fffffff;
36
37 case ELF::R_SPARC_WDISP22:
38 return (Value >> 2) & 0x3fffff;
39
40 case ELF::R_SPARC_WDISP19:
41 return (Value >> 2) & 0x7ffff;
42
43 case ELF::R_SPARC_WDISP16: {
44 // A.3 Branch on Integer Register with Prediction (BPr)
45 // Inst{21-20} = d16hi;
46 // Inst{13-0} = d16lo;
47 unsigned d16hi = (Value >> 16) & 0x3;
48 unsigned d16lo = (Value >> 2) & 0x3fff;
49 return (d16hi << 20) | d16lo;
50 }
51
52 case ELF::R_SPARC_WDISP10: {
53 // FIXME this really should be an error reporting check.
54 assert((Value & 0x3) == 0);
55
56 // 7.17 Compare and Branch
57 // Inst{20-19} = d10hi;
58 // Inst{12-5} = d10lo;
59 unsigned d10hi = (Value >> 10) & 0x3;
60 unsigned d10lo = (Value >> 2) & 0xff;
61 return (d10hi << 19) | (d10lo << 5);
62 }
63
64 case ELF::R_SPARC_HIX22:
65 return (~Value >> 10) & 0x3fffff;
66
67 // In PIC mode the parser may map %hi to PC22/GOT22. An operand that folds to
68 // an absolute value emits no relocation and needs the %hi encoding.
69 case ELF::R_SPARC_PC22:
70 case ELF::R_SPARC_HI22:
71 case ELF::R_SPARC_GOT22:
72 case ELF::R_SPARC_LM22:
73 return (Value >> 10) & 0x3fffff;
74
76 return Value & 0x1fff;
77
78 case ELF::R_SPARC_5:
79 return Value & 0x1f;
80
81 case ELF::R_SPARC_LOX10:
82 return (Value & 0x3ff) | 0x1c00;
83
84 case ELF::R_SPARC_PC10:
85 case ELF::R_SPARC_LO10:
86 case ELF::R_SPARC_GOT10:
87 return Value & 0x3ff;
88
89 case ELF::R_SPARC_H44:
90 return (Value >> 22) & 0x3fffff;
91 case ELF::R_SPARC_M44:
92 return (Value >> 12) & 0x3ff;
93 case ELF::R_SPARC_L44:
94 return Value & 0xfff;
95
96 case ELF::R_SPARC_HH22:
97 return (Value >> 42) & 0x3fffff;
98 case ELF::R_SPARC_HM10:
99 return (Value >> 32) & 0x3ff;
100 }
101}
102
103/// getFixupKindNumBytes - The number of bytes the fixup may change.
104static unsigned getFixupKindNumBytes(unsigned Kind) {
105 switch (Kind) {
106 default:
107 return 4;
108 case FK_Data_1:
109 return 1;
110 case FK_Data_2:
111 return 2;
112 case FK_Data_8:
113 return 8;
114 }
115}
116
117namespace {
118class SparcAsmBackend : public MCAsmBackend {
119protected:
120 bool Is64Bit;
121 bool IsV8Plus;
122
123public:
124 SparcAsmBackend(const MCSubtargetInfo &STI)
125 : MCAsmBackend(STI.getTargetTriple().isLittleEndian()
126 ? llvm::endianness::little
127 : llvm::endianness::big),
128 Is64Bit(STI.getTargetTriple().isArch64Bit()),
129 IsV8Plus(STI.hasFeature(Sparc::FeatureV8Plus)) {}
130
131 std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
132 MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
133 void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
134 uint8_t *Data, uint64_t Value, bool IsResolved) override;
135
136 bool writeNopData(raw_ostream &OS, uint64_t Count,
137 const MCSubtargetInfo *STI) const override {
138
139 // If the count is not 4-byte aligned, we must be writing data into the
140 // text section (otherwise we have unaligned instructions, and thus have
141 // far bigger problems), so just write zeros instead.
142 OS.write_zeros(Count % 4);
143
144 uint64_t NumNops = Count / 4;
145 for (uint64_t i = 0; i != NumNops; ++i)
146 support::endian::write<uint32_t>(OS, 0x01000000, Endian);
147
148 return true;
149 }
150};
151
152class ELFSparcAsmBackend : public SparcAsmBackend {
153 Triple::OSType OSType;
154
155public:
156 ELFSparcAsmBackend(const MCSubtargetInfo &STI, Triple::OSType OSType)
157 : SparcAsmBackend(STI), OSType(OSType) {}
158
159 std::unique_ptr<MCObjectTargetWriter>
160 createObjectTargetWriter() const override {
161 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(OSType);
162 return createSparcELFObjectWriter(Is64Bit, IsV8Plus, OSABI);
163 }
164};
165} // end anonymous namespace
166
167std::optional<MCFixupKind> SparcAsmBackend::getFixupKind(StringRef Name) const {
168 unsigned Type;
169 Type = llvm::StringSwitch<unsigned>(Name)
170#define ELF_RELOC(X, Y) .Case(#X, Y)
171#include "llvm/BinaryFormat/ELFRelocs/Sparc.def"
172#undef ELF_RELOC
173 .Case("BFD_RELOC_NONE", ELF::R_SPARC_NONE)
174 .Case("BFD_RELOC_8", ELF::R_SPARC_8)
175 .Case("BFD_RELOC_16", ELF::R_SPARC_16)
176 .Case("BFD_RELOC_32", ELF::R_SPARC_32)
177 .Case("BFD_RELOC_64", ELF::R_SPARC_64)
178 .Default(-1u);
179 if (Type == -1u)
180 return std::nullopt;
181 return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
182}
183
184MCFixupKindInfo SparcAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
185 // clang-format off
186 const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = {
187 // name offset bits flags
188 {"fixup_sparc_call30", 2, 30, 0},
189 {"fixup_sparc_13", 19, 13, 0},
190 };
191
192 const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {
193 // name offset bits flags
194 {"fixup_sparc_call30", 0, 30, 0},
195 {"fixup_sparc_13", 0, 13, 0},
196 };
197 // clang-format on
198
199 if (!mc::isRelocation(Kind)) {
200 if (Kind < FirstTargetFixupKind)
203 "Invalid kind!");
204 if (Endian == llvm::endianness::little)
205 return InfosLE[Kind - FirstTargetFixupKind];
206
207 return InfosBE[Kind - FirstTargetFixupKind];
208 }
209
210 MCFixupKindInfo Info{};
211 switch (uint16_t(Kind)) {
212 case ELF::R_SPARC_PC10:
213 Info = {"", 22, 10, 0};
214 break;
215 case ELF::R_SPARC_PC22:
216 Info = {"", 10, 22, 0};
217 break;
218 case ELF::R_SPARC_WDISP10:
219 Info = {"", 0, 32, 0};
220 break;
221 case ELF::R_SPARC_WDISP16:
222 Info = {"", 0, 32, 0};
223 break;
224 case ELF::R_SPARC_WDISP19:
225 Info = {"", 13, 19, 0};
226 break;
227 case ELF::R_SPARC_WDISP22:
228 Info = {"", 10, 22, 0};
229 break;
230
231 case ELF::R_SPARC_HI22:
232 Info = {"", 10, 22, 0};
233 break;
234 case ELF::R_SPARC_LO10:
235 Info = {"", 22, 10, 0};
236 break;
237 case ELF::R_SPARC_HH22:
238 Info = {"", 10, 22, 0};
239 break;
240 case ELF::R_SPARC_HM10:
241 Info = {"", 22, 10, 0};
242 break;
243 case ELF::R_SPARC_LM22:
244 Info = {"", 10, 22, 0};
245 break;
246 case ELF::R_SPARC_HIX22:
247 Info = {"", 10, 22, 0};
248 break;
249 case ELF::R_SPARC_LOX10:
250 Info = {"", 19, 13, 0};
251 break;
252 }
253 if (Endian == llvm::endianness::little)
254 Info.TargetOffset = 32 - Info.TargetOffset - Info.TargetSize;
255 return Info;
256}
257
258void SparcAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
259 const MCValue &Target, uint8_t *Data,
260 uint64_t Value, bool IsResolved) {
261 maybeAddReloc(F, Fixup, Target, Value, IsResolved);
262 if (!IsResolved)
263 return;
264 Value = adjustFixupValue(Fixup.getKind(), Value);
265
266 unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
267 // For each byte of the fragment that the fixup touches, mask in the
268 // bits from the fixup value.
269 for (unsigned i = 0; i != NumBytes; ++i) {
270 unsigned Idx = Endian == llvm::endianness::little ? i : (NumBytes - 1) - i;
271 Data[Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
272 }
273}
274
276 const MCSubtargetInfo &STI,
277 const MCRegisterInfo &MRI,
278 const MCTargetOptions &Options) {
279 return new ELFSparcAsmBackend(STI, STI.getTargetTriple().getOS());
280}
static unsigned getFixupKindNumBytes(unsigned Kind)
The number of bytes the fixup may change.
static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, uint64_t Value, MCContext &Ctx, const Triple &TheTriple, bool IsResolved)
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
static LVOptions Options
Definition LVOptions.cpp:25
static bool hasFeature(StringRef Feature, const FeatureBitset &FeatureBits, ArrayRef< SubtargetFeatureKV > ProcFeatures)
#define F(x, y, z)
Definition MD5.cpp:54
#define T
PowerPC TLS Dynamic Call Fixup
static unsigned adjustFixupValue(unsigned Kind, uint64_t Value)
static unsigned getFixupKindNumBytes(unsigned Kind)
getFixupKindNumBytes - The number of bytes the fixup may change.
This file implements the StringSwitch template, which mimics a switch() statement whose cases are str...
Generic interface to target specific assembler backends.
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
const Triple & getTargetTriple() const
Represent a constant reference to a string, i.e.
Definition StringRef.h:56
Target - Wrapper for Target specific information.
OSType getOS() const
Get the parsed operating system type of this triple.
Definition Triple.h:521
LLVM Value Representation.
Definition Value.h:75
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert 'NumZeros' nulls.
@ fixup_sparc_13
fixup_sparc_13 - 13-bit fixup
VE::Fixups getFixupKind(uint8_t S)
bool isRelocation(MCFixupKind FixupKind)
Definition MCFixup.h:130
void write(void *memory, value_type value, endianness endian)
Write a value to memory with a particular endianness.
Definition Endian.h:82
This is an optimization pass for GlobalISel generic memory operations.
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Value
Definition InstrProf.h:143
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition MCFixup.h:22
std::unique_ptr< MCObjectTargetWriter > createSparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, uint8_t OSABI)
@ FirstTargetFixupKind
Definition MCFixup.h:44
@ FirstLiteralRelocationKind
Definition MCFixup.h:29
@ FK_Data_8
A eight-byte fixup.
Definition MCFixup.h:37
@ FK_Data_1
A one-byte fixup.
Definition MCFixup.h:34
@ FK_Data_4
A four-byte fixup.
Definition MCFixup.h:36
@ FK_Data_2
A two-byte fixup.
Definition MCFixup.h:35
RelativeUniformCounterPtr ValuesPtrExpr VTableAddr Count
Definition InstrProf.h:145
MCAsmBackend * createSparcAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
endianness
Definition bit.h:71