LLVM 22.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 case ELF::R_SPARC_PC22:
68 case ELF::R_SPARC_HI22:
69 case ELF::R_SPARC_LM22:
70 return (Value >> 10) & 0x3fffff;
71
73 return Value & 0x1fff;
74
75 case ELF::R_SPARC_5:
76 return Value & 0x1f;
77
78 case ELF::R_SPARC_LOX10:
79 return (Value & 0x3ff) | 0x1c00;
80
81 case ELF::R_SPARC_PC10:
82 case ELF::R_SPARC_LO10:
83 return Value & 0x3ff;
84
85 case ELF::R_SPARC_H44:
86 return (Value >> 22) & 0x3fffff;
87 case ELF::R_SPARC_M44:
88 return (Value >> 12) & 0x3ff;
89 case ELF::R_SPARC_L44:
90 return Value & 0xfff;
91
92 case ELF::R_SPARC_HH22:
93 return (Value >> 42) & 0x3fffff;
94 case ELF::R_SPARC_HM10:
95 return (Value >> 32) & 0x3ff;
96 }
97}
98
99/// getFixupKindNumBytes - The number of bytes the fixup may change.
100static unsigned getFixupKindNumBytes(unsigned Kind) {
101 switch (Kind) {
102 default:
103 return 4;
104 case FK_Data_1:
105 return 1;
106 case FK_Data_2:
107 return 2;
108 case FK_Data_8:
109 return 8;
110 }
111}
112
113namespace {
114class SparcAsmBackend : public MCAsmBackend {
115protected:
116 bool Is64Bit;
117 bool IsV8Plus;
118
119public:
120 SparcAsmBackend(const MCSubtargetInfo &STI)
121 : MCAsmBackend(STI.getTargetTriple().isLittleEndian()
123 : llvm::endianness::big),
124 Is64Bit(STI.getTargetTriple().isArch64Bit()),
125 IsV8Plus(STI.hasFeature(Sparc::FeatureV8Plus)) {}
126
127 std::optional<MCFixupKind> getFixupKind(StringRef Name) const override;
128 MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override;
129 void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target,
130 uint8_t *Data, uint64_t Value, bool IsResolved) override;
131
132 bool writeNopData(raw_ostream &OS, uint64_t Count,
133 const MCSubtargetInfo *STI) const override {
134
135 // If the count is not 4-byte aligned, we must be writing data into the
136 // text section (otherwise we have unaligned instructions, and thus have
137 // far bigger problems), so just write zeros instead.
138 OS.write_zeros(Count % 4);
139
140 uint64_t NumNops = Count / 4;
141 for (uint64_t i = 0; i != NumNops; ++i)
142 support::endian::write<uint32_t>(OS, 0x01000000, Endian);
143
144 return true;
145 }
146};
147
148class ELFSparcAsmBackend : public SparcAsmBackend {
149 Triple::OSType OSType;
150
151public:
152 ELFSparcAsmBackend(const MCSubtargetInfo &STI, Triple::OSType OSType)
153 : SparcAsmBackend(STI), OSType(OSType) {}
154
155 std::unique_ptr<MCObjectTargetWriter>
156 createObjectTargetWriter() const override {
158 return createSparcELFObjectWriter(Is64Bit, IsV8Plus, OSABI);
159 }
160};
161} // end anonymous namespace
162
163std::optional<MCFixupKind> SparcAsmBackend::getFixupKind(StringRef Name) const {
164 unsigned Type;
166#define ELF_RELOC(X, Y) .Case(#X, Y)
167#include "llvm/BinaryFormat/ELFRelocs/Sparc.def"
168#undef ELF_RELOC
169 .Case("BFD_RELOC_NONE", ELF::R_SPARC_NONE)
170 .Case("BFD_RELOC_8", ELF::R_SPARC_8)
171 .Case("BFD_RELOC_16", ELF::R_SPARC_16)
172 .Case("BFD_RELOC_32", ELF::R_SPARC_32)
173 .Case("BFD_RELOC_64", ELF::R_SPARC_64)
174 .Default(-1u);
175 if (Type == -1u)
176 return std::nullopt;
177 return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
178}
179
180MCFixupKindInfo SparcAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
181 // clang-format off
182 const static MCFixupKindInfo InfosBE[Sparc::NumTargetFixupKinds] = {
183 // name offset bits flags
184 {"fixup_sparc_call30", 2, 30, 0},
185 {"fixup_sparc_13", 19, 13, 0},
186 };
187
188 const static MCFixupKindInfo InfosLE[Sparc::NumTargetFixupKinds] = {
189 // name offset bits flags
190 {"fixup_sparc_call30", 0, 30, 0},
191 {"fixup_sparc_13", 0, 13, 0},
192 };
193 // clang-format on
194
195 if (!mc::isRelocation(Kind)) {
196 if (Kind < FirstTargetFixupKind)
199 "Invalid kind!");
200 if (Endian == llvm::endianness::little)
201 return InfosLE[Kind - FirstTargetFixupKind];
202
203 return InfosBE[Kind - FirstTargetFixupKind];
204 }
205
207 switch (uint16_t(Kind)) {
208 case ELF::R_SPARC_PC10:
209 Info = {"", 22, 10, 0};
210 break;
211 case ELF::R_SPARC_PC22:
212 Info = {"", 10, 22, 0};
213 break;
214 case ELF::R_SPARC_WDISP10:
215 Info = {"", 0, 32, 0};
216 break;
217 case ELF::R_SPARC_WDISP16:
218 Info = {"", 0, 32, 0};
219 break;
220 case ELF::R_SPARC_WDISP19:
221 Info = {"", 13, 19, 0};
222 break;
223 case ELF::R_SPARC_WDISP22:
224 Info = {"", 10, 22, 0};
225 break;
226
227 case ELF::R_SPARC_HI22:
228 Info = {"", 10, 22, 0};
229 break;
230 case ELF::R_SPARC_LO10:
231 Info = {"", 22, 10, 0};
232 break;
233 case ELF::R_SPARC_HH22:
234 Info = {"", 10, 22, 0};
235 break;
236 case ELF::R_SPARC_HM10:
237 Info = {"", 22, 10, 0};
238 break;
239 case ELF::R_SPARC_LM22:
240 Info = {"", 10, 22, 0};
241 break;
242 case ELF::R_SPARC_HIX22:
243 Info = {"", 10, 22, 0};
244 break;
245 case ELF::R_SPARC_LOX10:
246 Info = {"", 19, 13, 0};
247 break;
248 }
249 if (Endian == llvm::endianness::little)
250 Info.TargetOffset = 32 - Info.TargetOffset - Info.TargetSize;
251 return Info;
252}
253
254void SparcAsmBackend::applyFixup(const MCFragment &F, const MCFixup &Fixup,
255 const MCValue &Target, uint8_t *Data,
256 uint64_t Value, bool IsResolved) {
257 maybeAddReloc(F, Fixup, Target, Value, IsResolved);
258 if (!IsResolved)
259 return;
260 Value = adjustFixupValue(Fixup.getKind(), Value);
261
262 unsigned NumBytes = getFixupKindNumBytes(Fixup.getKind());
263 // For each byte of the fragment that the fixup touches, mask in the
264 // bits from the fixup value.
265 for (unsigned i = 0; i != NumBytes; ++i) {
266 unsigned Idx = Endian == llvm::endianness::little ? i : (NumBytes - 1) - i;
267 Data[Idx] |= uint8_t((Value >> (i * 8)) & 0xff);
268 }
269}
270
272 const MCSubtargetInfo &STI,
273 const MCRegisterInfo &MRI,
274 const MCTargetOptions &Options) {
275 return new ELFSparcAsmBackend(STI, STI.getTargetTriple().getOS());
276}
unsigned const MachineRegisterInfo * MRI
assert(UImm &&(UImm !=~static_cast< T >(0)) &&"Invalid immediate!")
Analysis containing CSE Info
Definition: CSEInfo.cpp:27
Returns the sub type a function will return at a given Idx Should correspond to the result type of an ExtractValue instruction executed with just that one unsigned Idx
std::string Name
static LVOptions Options
Definition: LVOptions.cpp:25
#define F(x, y, z)
Definition: MD5.cpp:55
PowerPC TLS Dynamic Call Fixup
endianness Endian
raw_pwrite_stream & OS
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.
Definition: MCAsmBackend.h:55
virtual bool writeNopData(raw_ostream &OS, uint64_t Count, const MCSubtargetInfo *STI) const =0
Write an (optimal) nop sequence of Count bytes to the given output.
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
virtual std::optional< MCFixupKind > getFixupKind(StringRef Name) const
Map a relocation name used in .reloc to a fixup kind.
virtual void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target, uint8_t *Data, uint64_t Value, bool IsResolved)=0
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:61
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
StringRef - Represent a constant reference to a string, i.e.
Definition: StringRef.h:55
A switch()-like statement whose cases are string literals.
Definition: StringSwitch.h:43
StringSwitch & Case(StringLiteral S, T Value)
Definition: StringSwitch.h:68
R Default(T Value)
Definition: StringSwitch.h:177
Target - Wrapper for Target specific information.
OSType getOS() const
Get the parsed operating system type of this triple.
Definition: Triple.h:418
The instances of the Type class are immutable: once they are created, they are never changed.
Definition: Type.h:45
LLVM Value Representation.
Definition: Value.h:75
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:53
raw_ostream & write_zeros(unsigned NumZeros)
write_zeros - Insert 'NumZeros' nulls.
@ fixup_sparc_13
fixup_sparc_13 - 13-bit fixup
bool isRelocation(MCFixupKind FixupKind)
Definition: MCFixup.h:130
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ 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
std::unique_ptr< MCObjectTargetWriter > createSparcELFObjectWriter(bool Is64Bit, bool IsV8Plus, uint8_t OSABI)
MCAsmBackend * createSparcAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
endianness
Definition: bit.h:71
Target independent information on a fixup kind.
Definition: MCAsmBackend.h:38