LLVM 23.0.0git
CSKYAsmBackend.cpp
Go to the documentation of this file.
1//===-- CSKYAsmBackend.cpp - CSKY 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 "CSKYAsmBackend.h"
11#include "llvm/ADT/DenseMap.h"
12#include "llvm/MC/MCAssembler.h"
13#include "llvm/MC/MCContext.h"
15#include "llvm/MC/MCValue.h"
16#include "llvm/Support/Debug.h"
17
18#define DEBUG_TYPE "csky-asmbackend"
19
20using namespace llvm;
21
22std::unique_ptr<MCObjectTargetWriter>
26
28
30 {CSKY::Fixups::fixup_csky_addr32, {"fixup_csky_addr32", 0, 32, 0}},
31 {CSKY::Fixups::fixup_csky_addr_hi16, {"fixup_csky_addr_hi16", 0, 32, 0}},
32 {CSKY::Fixups::fixup_csky_addr_lo16, {"fixup_csky_addr_lo16", 0, 32, 0}},
34 {"fixup_csky_pcrel_imm16_scale2", 0, 32, 0}},
36 {"fixup_csky_pcrel_uimm16_scale4", 0, 32, 0}},
38 {"fixup_csky_pcrel_uimm8_scale4", 0, 32, 0}},
40 {"fixup_csky_pcrel_imm26_scale2", 0, 32, 0}},
42 {"fixup_csky_pcrel_imm18_scale2", 0, 32, 0}},
43 {CSKY::Fixups::fixup_csky_got32, {"fixup_csky_got32", 0, 32, 0}},
45 {"fixup_csky_got_imm18_scale4", 0, 32, 0}},
46 {CSKY::Fixups::fixup_csky_gotoff, {"fixup_csky_gotoff", 0, 32, 0}},
47 {CSKY::Fixups::fixup_csky_gotpc, {"fixup_csky_gotpc", 0, 32, 0}},
48 {CSKY::Fixups::fixup_csky_plt32, {"fixup_csky_plt32", 0, 32, 0}},
50 {"fixup_csky_plt_imm18_scale4", 0, 32, 0}},
52 {"fixup_csky_pcrel_imm10_scale2", 0, 16, 0}},
54 {"fixup_csky_pcrel_uimm7_scale4", 0, 16, 0}},
56 {"fixup_csky_doffset_imm18", 0, 18, 0}},
58 {"fixup_csky_doffset_imm18_scale2", 0, 18, 0}},
60 {"fixup_csky_doffset_imm18_scale4", 0, 18, 0}}};
61
63 "Not all fixup kinds added to Infos array");
64
65 if (mc::isRelocation(Kind))
66 return {};
67 if (Kind < FirstTargetFixupKind)
69 return Infos[Kind];
70}
71
73 MCContext &Ctx) {
74 switch (Fixup.getKind()) {
75 default:
76 llvm_unreachable("Unknown fixup kind!");
83 llvm_unreachable("Relocation should be unconditionally forced\n");
84 case FK_Data_1:
85 case FK_Data_2:
86 case FK_Data_4:
87 case FK_Data_8:
88 return Value;
90 return Value & 0xffffffff;
92 if (!isIntN(17, Value))
93 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
94 if (Value & 0x1)
95 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
96
97 return (Value >> 1) & 0xffff;
99 if (!isUIntN(18, Value))
100 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
101 if (Value & 0x3)
102 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
103
104 return (Value >> 2) & 0xffff;
106 if (!isIntN(27, Value))
107 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
108 if (Value & 0x1)
109 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
110
111 return (Value >> 1) & 0x3ffffff;
113 if (!isIntN(19, Value))
114 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
115 if (Value & 0x1)
116 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
117
118 return (Value >> 1) & 0x3ffff;
120 if (!isUIntN(10, Value))
121 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
122 if (Value & 0x3)
123 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
124
125 unsigned IMM4L = (Value >> 2) & 0xf;
126 unsigned IMM4H = (Value >> 6) & 0xf;
127
128 Value = (IMM4H << 21) | (IMM4L << 4);
129 return Value;
130 }
132 if (!isIntN(11, Value))
133 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
134 if (Value & 0x1)
135 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
136
137 return (Value >> 1) & 0x3ff;
139 if ((Value >> 2) > 0xfe)
140 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
141 if (Value & 0x3)
142 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
143
144 if ((Value >> 2) <= 0x7f) {
145 unsigned IMM5L = (Value >> 2) & 0x1f;
146 unsigned IMM2H = (Value >> 7) & 0x3;
147
148 Value = (1 << 12) | (IMM2H << 8) | IMM5L;
149 } else {
150 unsigned IMM5L = (~Value >> 2) & 0x1f;
151 unsigned IMM2H = (~Value >> 7) & 0x3;
152
153 Value = (IMM2H << 8) | IMM5L;
154 }
155
156 return Value;
157 }
158}
159
161 const MCFixup &Fixup,
162 const MCValue &,
164 bool Resolved) const {
165 // Return true if the symbol is unresolved.
166 if (!Resolved)
167 return true;
168
169 int64_t Offset = int64_t(Value);
170 switch (Fixup.getKind()) {
171 default:
172 return false;
180 return ((Value >> 2) > 0xfe) || (Value & 0x3);
181 }
182}
183
184std::optional<bool> CSKYAsmBackend::evaluateFixup(const MCFragment &F,
186 uint64_t &Value) {
187 // These forward-only constant pool load fixups compute displacement relative
188 // to AlignDown(PC, 4). Pre-seed Value with the low bits so the generic
189 // evaluateFixup effectively subtracts the aligned offset. Subtract Stretch
190 // to use the pre-Stretch (old) source offset, avoiding an epoch mismatch
191 // with the generic Stretch-adjusted displacement (see ARMAsmBackend).
192 switch (Fixup.getKind()) {
196 Value =
197 (Asm->getFragmentOffset(F) - Asm->getStretch() + Fixup.getOffset()) % 4;
198 }
199 return {};
200}
201
203 const MCValue &Target, uint8_t *Data,
204 uint64_t Value, bool IsResolved) {
205 if (IsResolved && shouldForceRelocation(Fixup, Target))
206 IsResolved = false;
207 maybeAddReloc(F, Fixup, Target, Value, IsResolved);
208
209 MCFixupKind Kind = Fixup.getKind();
210 if (mc::isRelocation(Kind))
211 return;
212 MCContext &Ctx = getContext();
214 if (!Value)
215 return; // Doesn't change encoding.
216 // Apply any target-specific value adjustments.
218
219 // Shift the value into position.
220 Value <<= Info.TargetOffset;
221
222 unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
223
224 assert(Fixup.getOffset() + NumBytes <= F.getSize() &&
225 "Invalid fixup offset!");
226
227 // For each byte of the fragment that the fixup touches, mask in the
228 // bits from the fixup value.
229 bool IsLittleEndian = (Endian == llvm::endianness::little);
230 bool IsInstFixup = (Kind >= FirstTargetFixupKind);
231
232 if (IsLittleEndian && IsInstFixup && (NumBytes == 4)) {
233 Data[0] |= uint8_t((Value >> 16) & 0xff);
234 Data[1] |= uint8_t((Value >> 24) & 0xff);
235 Data[2] |= uint8_t(Value & 0xff);
236 Data[3] |= uint8_t((Value >> 8) & 0xff);
237 } else {
238 for (unsigned I = 0; I != NumBytes; I++) {
239 unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I);
240 Data[Idx] |= uint8_t((Value >> (I * 8)) & 0xff);
241 }
242 }
243}
244
246 const MCSubtargetInfo &STI) const {
247 switch (Opcode) {
248 default:
249 return false;
250 case CSKY::JBR32:
251 case CSKY::JBT32:
252 case CSKY::JBF32:
253 case CSKY::JBSR32:
254 if (!STI.hasFeature(CSKY::Has2E3))
255 return false;
256 return true;
257 case CSKY::JBR16:
258 case CSKY::JBT16:
259 case CSKY::JBF16:
260 case CSKY::LRW16:
261 case CSKY::BR16:
262 return true;
263 }
264}
265
267 const MCValue &Target /*STI*/) {
268 if (Target.getSpecifier())
269 return true;
270 switch (Fixup.getKind()) {
271 default:
272 break;
276 return true;
277 }
278
279 return false;
280}
281
283 const MCSubtargetInfo &STI) const {
284 MCInst Res;
285
286 switch (Inst.getOpcode()) {
287 default:
288 LLVM_DEBUG(Inst.dump());
289 llvm_unreachable("Opcode not expected!");
290 case CSKY::LRW16:
291 Res.setOpcode(CSKY::LRW32);
292 Res.addOperand(Inst.getOperand(0));
293 Res.addOperand(Inst.getOperand(1));
294 break;
295 case CSKY::BR16:
296 Res.setOpcode(CSKY::BR32);
297 Res.addOperand(Inst.getOperand(0));
298 break;
299 case CSKY::JBSR32:
300 Res.setOpcode(CSKY::JSRI32);
301 Res.addOperand(Inst.getOperand(1));
302 break;
303 case CSKY::JBR32:
304 Res.setOpcode(CSKY::JMPI32);
305 Res.addOperand(Inst.getOperand(1));
306 break;
307 case CSKY::JBT32:
308 case CSKY::JBF32:
309 Res.setOpcode(Inst.getOpcode() == CSKY::JBT32 ? CSKY::JBT_E : CSKY::JBF_E);
310 Res.addOperand(Inst.getOperand(0));
311 Res.addOperand(Inst.getOperand(1));
312 Res.addOperand(Inst.getOperand(2));
313 break;
314 case CSKY::JBR16:
315 Res.setOpcode(CSKY::JBR32);
316 Res.addOperand(Inst.getOperand(0));
317 Res.addOperand(Inst.getOperand(1));
318 break;
319 case CSKY::JBT16:
320 case CSKY::JBF16:
321 // ck801
322 unsigned opcode;
323 if (STI.hasFeature(CSKY::HasE2))
324 opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT32 : CSKY::JBF32;
325 else
326 opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT_E : CSKY::JBF_E;
327
328 Res.setOpcode(opcode);
329 Res.addOperand(Inst.getOperand(0));
330 Res.addOperand(Inst.getOperand(1));
331 Res.addOperand(Inst.getOperand(2));
332 break;
333 }
334 Inst = std::move(Res);
335}
336
338 const MCSubtargetInfo *STI) const {
339 OS.write_zeros(Count);
340 return true;
341}
342
344 const MCSubtargetInfo &STI,
345 const MCRegisterInfo &MRI,
346 const MCTargetOptions &Options) {
347 return new CSKYAsmBackend(STI, Options);
348}
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!")
This file defines the DenseMap class.
static LVOptions Options
Definition LVOptions.cpp:25
#define F(x, y, z)
Definition MD5.cpp:54
#define I(x, y, z)
Definition MD5.cpp:57
#define T
PowerPC TLS Dynamic Call Fixup
#define LLVM_DEBUG(...)
Definition Debug.h:114
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory),...
Definition ArrayRef.h:40
bool shouldForceRelocation(const MCFixup &Fixup, const MCValue &Target)
MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const override
Get information on a fixup kind.
bool fixupNeedsRelaxationAdvanced(const MCFragment &, const MCFixup &, const MCValue &, uint64_t, bool) const override
Target specific predicate for whether a given fixup requires the associated instruction to be relaxed...
std::optional< bool > evaluateFixup(const MCFragment &, MCFixup &, MCValue &, uint64_t &) override
bool mayNeedRelaxation(unsigned Opcode, ArrayRef< MCOperand > Operands, const MCSubtargetInfo &STI) const override
Check whether the given instruction (encoded as Opcode+Operands) may need relaxation.
void applyFixup(const MCFragment &, const MCFixup &, const MCValue &Target, uint8_t *Data, uint64_t Value, bool IsResolved) override
void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override
Relax the instruction in the given fragment to the next wider instruction.
std::unique_ptr< MCObjectTargetWriter > createObjectTargetWriter() const override
bool writeNopData(raw_ostream &OS, uint64_t Count, const MCSubtargetInfo *STI) const override
Write an (optimal) nop sequence of Count bytes to the given output.
unsigned size() const
Definition DenseMap.h:110
Generic interface to target specific assembler backends.
const llvm::endianness Endian
virtual MCFixupKindInfo getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
MCAssembler * Asm
MCContext & getContext() const
void maybeAddReloc(const MCFragment &, const MCFixup &, const MCValue &, uint64_t &Value, bool IsResolved)
Context object for machine code objects.
Definition MCContext.h:83
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition MCFixup.h:61
Instances of this class represent a single low-level machine instruction.
Definition MCInst.h:188
unsigned getOpcode() const
Definition MCInst.h:202
LLVM_ABI void dump() const
Definition MCInst.cpp:112
void addOperand(const MCOperand Op)
Definition MCInst.h:215
void setOpcode(unsigned Op)
Definition MCInst.h:201
const MCOperand & getOperand(unsigned i) const
Definition MCInst.h:210
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
Target - Wrapper for Target specific information.
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.
#define llvm_unreachable(msg)
Marks that the current location is not supposed to be reachable.
@ fixup_csky_pcrel_imm10_scale2
@ fixup_csky_pcrel_uimm7_scale4
@ fixup_csky_doffset_imm18_scale2
@ fixup_csky_pcrel_imm16_scale2
@ fixup_csky_pcrel_imm18_scale2
@ fixup_csky_doffset_imm18_scale4
@ fixup_csky_pcrel_uimm16_scale4
@ fixup_csky_plt_imm18_scale4
@ fixup_csky_pcrel_imm26_scale2
@ fixup_csky_got_imm18_scale4
@ fixup_csky_pcrel_uimm8_scale4
@ fixup_csky_doffset_imm18
bool isRelocation(MCFixupKind FixupKind)
Definition MCFixup.h:130
This is an optimization pass for GlobalISel generic memory operations.
@ Offset
Definition DWP.cpp:532
MCAsmBackend * createCSKYAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
std::unique_ptr< MCObjectTargetWriter > createCSKYELFObjectWriter()
constexpr bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition MathExtras.h:243
uint16_t MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition MCFixup.h:22
constexpr uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition Alignment.h:144
FunctionAddr VTableAddr Count
Definition InstrProf.h:139
@ FirstTargetFixupKind
Definition MCFixup.h:44
@ 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
FunctionAddr VTableAddr uintptr_t uintptr_t Data
Definition InstrProf.h:221
constexpr bool isShiftedInt(int64_t x)
Checks if a signed integer is an N bit number shifted left by S.
Definition MathExtras.h:182
constexpr bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition MathExtras.h:248
Target independent information on a fixup kind.