LLVM 17.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/MCAsmLayout.h"
13#include "llvm/MC/MCAssembler.h"
14#include "llvm/MC/MCContext.h"
17#include "llvm/Support/Debug.h"
18
19#define DEBUG_TYPE "csky-asmbackend"
20
21using namespace llvm;
22
23std::unique_ptr<MCObjectTargetWriter>
26}
27
28const MCFixupKindInfo &
30
32 {CSKY::Fixups::fixup_csky_addr32, {"fixup_csky_addr32", 0, 32, 0}},
33 {CSKY::Fixups::fixup_csky_addr_hi16, {"fixup_csky_addr_hi16", 0, 32, 0}},
34 {CSKY::Fixups::fixup_csky_addr_lo16, {"fixup_csky_addr_lo16", 0, 32, 0}},
36 {"fixup_csky_pcrel_imm16_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
38 {"fixup_csky_pcrel_uimm16_scale4", 0, 32,
42 {"fixup_csky_pcrel_uimm8_scale4", 0, 32,
46 {"fixup_csky_pcrel_imm26_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
48 {"fixup_csky_pcrel_imm18_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
49 {CSKY::Fixups::fixup_csky_got32, {"fixup_csky_got32", 0, 32, 0}},
51 {"fixup_csky_got_imm18_scale4", 0, 32, 0}},
52 {CSKY::Fixups::fixup_csky_gotoff, {"fixup_csky_gotoff", 0, 32, 0}},
54 {"fixup_csky_gotpc", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
55 {CSKY::Fixups::fixup_csky_plt32, {"fixup_csky_plt32", 0, 32, 0}},
57 {"fixup_csky_plt_imm18_scale4", 0, 32, 0}},
59 {"fixup_csky_pcrel_imm10_scale2", 0, 16, MCFixupKindInfo::FKF_IsPCRel}},
61 {"fixup_csky_pcrel_uimm7_scale4", 0, 16,
65 {"fixup_csky_doffset_imm18", 0, 18, 0}},
67 {"fixup_csky_doffset_imm18_scale2", 0, 18, 0}},
69 {"fixup_csky_doffset_imm18_scale4", 0, 18, 0}}};
70
72 "Not all fixup kinds added to Infos array");
73
75 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
76 "Invalid kind!");
77
78 return Infos[Kind];
79 } else if (Kind < FirstTargetFixupKind) {
81 } else {
83 }
84}
85
87 MCContext &Ctx) {
88 switch (Fixup.getTargetKind()) {
89 default:
90 llvm_unreachable("Unknown fixup kind!");
97 llvm_unreachable("Relocation should be unconditionally forced\n");
98 case FK_Data_1:
99 case FK_Data_2:
100 case FK_Data_4:
101 case FK_Data_8:
102 return Value;
104 return Value & 0xffffffff;
106 if (!isIntN(17, 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) & 0xffff;
113 if (!isUIntN(18, Value))
114 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
115 if (Value & 0x3)
116 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
117
118 return (Value >> 2) & 0xffff;
120 if (!isIntN(27, Value))
121 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
122 if (Value & 0x1)
123 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
124
125 return (Value >> 1) & 0x3ffffff;
127 if (!isIntN(19, Value))
128 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
129 if (Value & 0x1)
130 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
131
132 return (Value >> 1) & 0x3ffff;
134 if (!isUIntN(10, Value))
135 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
136 if (Value & 0x3)
137 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
138
139 unsigned IMM4L = (Value >> 2) & 0xf;
140 unsigned IMM4H = (Value >> 6) & 0xf;
141
142 Value = (IMM4H << 21) | (IMM4L << 4);
143 return Value;
144 }
146 if (!isIntN(11, Value))
147 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
148 if (Value & 0x1)
149 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
150
151 return (Value >> 1) & 0x3ff;
153 if ((Value >> 2) > 0xfe)
154 Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
155 if (Value & 0x3)
156 Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
157
158 if ((Value >> 2) <= 0x7f) {
159 unsigned IMM5L = (Value >> 2) & 0x1f;
160 unsigned IMM2H = (Value >> 7) & 0x3;
161
162 Value = (1 << 12) | (IMM2H << 8) | IMM5L;
163 } else {
164 unsigned IMM5L = (~Value >> 2) & 0x1f;
165 unsigned IMM2H = (~Value >> 7) & 0x3;
166
167 Value = (IMM2H << 8) | IMM5L;
168 }
169
170 return Value;
171 }
172}
173
175 bool Resolved, uint64_t Value,
176 const MCRelaxableFragment *DF,
177 const MCAsmLayout &Layout,
178 const bool WasForced) const {
179 // Return true if the symbol is actually unresolved.
180 // Resolved could be always false when shouldForceRelocation return true.
181 // We use !WasForced to indicate that the symbol is unresolved and not forced
182 // by shouldForceRelocation.
183 if (!Resolved && !WasForced)
184 return true;
185
186 int64_t Offset = int64_t(Value);
187 switch (Fixup.getTargetKind()) {
188 default:
189 return false;
191 return !isShiftedInt<10, 1>(Offset);
193 return !isShiftedInt<16, 1>(Offset);
195 return !isShiftedInt<26, 1>(Offset);
197 return ((Value >> 2) > 0xfe) || (Value & 0x3);
198 }
199}
200
202 const MCValue &Target,
204 bool IsResolved,
205 const MCSubtargetInfo *STI) const {
206 MCFixupKind Kind = Fixup.getKind();
207 if (Kind >= FirstLiteralRelocationKind)
208 return;
209 MCContext &Ctx = Asm.getContext();
211 if (!Value)
212 return; // Doesn't change encoding.
213 // Apply any target-specific value adjustments.
215
216 // Shift the value into position.
217 Value <<= Info.TargetOffset;
218
219 unsigned Offset = Fixup.getOffset();
220 unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
221
222 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
223
224 // For each byte of the fragment that the fixup touches, mask in the
225 // bits from the fixup value.
226 bool IsLittleEndian = (Endian == support::little);
227 bool IsInstFixup = (Kind >= FirstTargetFixupKind);
228
229 if (IsLittleEndian && IsInstFixup && (NumBytes == 4)) {
230 Data[Offset + 0] |= uint8_t((Value >> 16) & 0xff);
231 Data[Offset + 1] |= uint8_t((Value >> 24) & 0xff);
232 Data[Offset + 2] |= uint8_t(Value & 0xff);
233 Data[Offset + 3] |= uint8_t((Value >> 8) & 0xff);
234 } else {
235 for (unsigned I = 0; I != NumBytes; I++) {
236 unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I);
237 Data[Offset + Idx] |= uint8_t((Value >> (I * 8)) & 0xff);
238 }
239 }
240}
241
243 const MCSubtargetInfo &STI) const {
244 switch (Inst.getOpcode()) {
245 default:
246 return false;
247 case CSKY::JBR32:
248 case CSKY::JBT32:
249 case CSKY::JBF32:
250 case CSKY::JBSR32:
251 if (!STI.hasFeature(CSKY::Has2E3))
252 return false;
253 return true;
254 case CSKY::JBR16:
255 case CSKY::JBT16:
256 case CSKY::JBF16:
257 case CSKY::LRW16:
258 case CSKY::BR16:
259 return true;
260 }
261}
262
264 const MCFixup &Fixup,
265 const MCValue &Target) {
266 if (Fixup.getKind() >= FirstLiteralRelocationKind)
267 return true;
268 switch (Fixup.getTargetKind()) {
269 default:
270 break;
280 return true;
281 }
282
283 return false;
284}
285
287 const MCRelaxableFragment *DF,
288 const MCAsmLayout &Layout) const {
289 return false;
290}
291
293 const MCSubtargetInfo &STI) const {
294 MCInst Res;
295
296 switch (Inst.getOpcode()) {
297 default:
298 LLVM_DEBUG(Inst.dump());
299 llvm_unreachable("Opcode not expected!");
300 case CSKY::LRW16:
301 Res.setOpcode(CSKY::LRW32);
302 Res.addOperand(Inst.getOperand(0));
303 Res.addOperand(Inst.getOperand(1));
304 break;
305 case CSKY::BR16:
306 Res.setOpcode(CSKY::BR32);
307 Res.addOperand(Inst.getOperand(0));
308 break;
309 case CSKY::JBSR32:
310 Res.setOpcode(CSKY::JSRI32);
311 Res.addOperand(Inst.getOperand(1));
312 break;
313 case CSKY::JBR32:
314 Res.setOpcode(CSKY::JMPI32);
315 Res.addOperand(Inst.getOperand(1));
316 break;
317 case CSKY::JBT32:
318 case CSKY::JBF32:
319 Res.setOpcode(Inst.getOpcode() == CSKY::JBT32 ? CSKY::JBT_E : CSKY::JBF_E);
320 Res.addOperand(Inst.getOperand(0));
321 Res.addOperand(Inst.getOperand(1));
322 Res.addOperand(Inst.getOperand(2));
323 break;
324 case CSKY::JBR16:
325 Res.setOpcode(CSKY::JBR32);
326 Res.addOperand(Inst.getOperand(0));
327 Res.addOperand(Inst.getOperand(1));
328 break;
329 case CSKY::JBT16:
330 case CSKY::JBF16:
331 // ck801
332 unsigned opcode;
333 if (STI.hasFeature(CSKY::HasE2))
334 opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT32 : CSKY::JBF32;
335 else
336 opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT_E : CSKY::JBF_E;
337
338 Res.setOpcode(opcode);
339 Res.addOperand(Inst.getOperand(0));
340 Res.addOperand(Inst.getOperand(1));
341 Res.addOperand(Inst.getOperand(2));
342 break;
343 }
344 Inst = std::move(Res);
345}
346
348 const MCSubtargetInfo *STI) const {
349 OS.write_zeros(Count);
350 return true;
351}
352
354 const MCSubtargetInfo &STI,
355 const MCRegisterInfo &MRI,
356 const MCTargetOptions &Options) {
357 return new CSKYAsmBackend(STI, Options);
358}
unsigned const MachineRegisterInfo * MRI
static uint64_t adjustFixupValue(const MCFixup &Fixup, const MCValue &Target, uint64_t Value, MCContext &Ctx, const Triple &TheTriple, bool IsResolved)
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
#define LLVM_DEBUG(X)
Definition: Debug.h:101
static RegisterPass< DebugifyFunctionPass > DF("debugify-function", "Attach debug info to a function")
This file defines the DenseMap class.
static LVOptions Options
Definition: LVOptions.cpp:25
#define I(x, y, z)
Definition: MD5.cpp:58
PowerPC TLS Dynamic Call Fixup
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
raw_pwrite_stream & OS
bool fixupNeedsRelaxationAdvanced(const MCFixup &Fixup, bool Resolved, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout, const bool WasForced) const override
Target specific predicate for whether a given fixup requires the associated instruction to be relaxed...
const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const override
Get information on a fixup kind.
bool mayNeedRelaxation(const MCInst &Inst, const MCSubtargetInfo &STI) const override
Check whether the given instruction may need relaxation.
void applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target, MutableArrayRef< char > Data, uint64_t Value, bool IsResolved, const MCSubtargetInfo *STI) const override
Apply the Value for given Fixup into the provided data fragment, at the offset specified by the fixup...
bool shouldForceRelocation(const MCAssembler &Asm, const MCFixup &Fixup, const MCValue &Target) override
Hook to check if a relocation is needed for some target specific reason.
bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value, const MCRelaxableFragment *DF, const MCAsmLayout &Layout) const override
Simple predicate for targets where !Resolved implies requiring relaxation.
void relaxInstruction(MCInst &Inst, const MCSubtargetInfo &STI) const override
Relax the instruction in the given fragment to the next wider instruction.
unsigned int getNumFixupKinds() const override
Get the number of target specific fixup kinds.
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:99
Generic interface to target specific assembler backends.
Definition: MCAsmBackend.h:42
virtual const MCFixupKindInfo & getFixupKindInfo(MCFixupKind Kind) const
Get information on a fixup kind.
const support::endianness Endian
Definition: MCAsmBackend.h:51
Encapsulates the layout of an assembly file at a particular point in time.
Definition: MCAsmLayout.h:28
Context object for machine code objects.
Definition: MCContext.h:76
void reportError(SMLoc L, const Twine &Msg)
Definition: MCContext.cpp:1055
Encode information on a single operation to perform on a byte sequence (e.g., an encoded instruction)...
Definition: MCFixup.h:71
Instances of this class represent a single low-level machine instruction.
Definition: MCInst.h:184
unsigned getOpcode() const
Definition: MCInst.h:198
void dump() const
Definition: MCInst.cpp:104
void addOperand(const MCOperand Op)
Definition: MCInst.h:210
void setOpcode(unsigned Op)
Definition: MCInst.h:197
const MCOperand & getOperand(unsigned i) const
Definition: MCInst.h:206
MCRegisterInfo base class - We assume that the target defines a static array of MCRegisterDesc object...
A relaxable fragment holds on to its MCInst, since it may need to be relaxed during the assembler lay...
Definition: MCFragment.h:270
Generic base class for all target subtargets.
bool hasFeature(unsigned Feature) const
This represents an "assembler immediate".
Definition: MCValue.h:36
MutableArrayRef - Represent a mutable reference to an array (0 or more elements consecutively in memo...
Definition: ArrayRef.h:305
Target - Wrapper for Target specific information.
LLVM Value Representation.
Definition: Value.h:74
This class implements an extremely fast bulk output stream that can only output to a stream.
Definition: raw_ostream.h:52
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_addr_hi16
@ fixup_csky_addr_lo16
@ fixup_csky_doffset_imm18
This is an optimization pass for GlobalISel generic memory operations.
Definition: AddressRanges.h:18
@ Offset
Definition: DWP.cpp:440
bool isUIntN(unsigned N, uint64_t x)
Checks if an unsigned integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:256
MCAsmBackend * createCSKYAsmBackend(const Target &T, const MCSubtargetInfo &STI, const MCRegisterInfo &MRI, const MCTargetOptions &Options)
std::unique_ptr< MCObjectTargetWriter > createCSKYELFObjectWriter()
MCFixupKind
Extensible enumeration to represent the type of a fixup.
Definition: MCFixup.h:21
@ FirstTargetFixupKind
Definition: MCFixup.h:45
@ FirstLiteralRelocationKind
The range [FirstLiteralRelocationKind, MaxTargetFixupKind) is used for relocations coming from ....
Definition: MCFixup.h:50
@ FK_Data_8
A eight-byte fixup.
Definition: MCFixup.h:26
@ FK_Data_1
A one-byte fixup.
Definition: MCFixup.h:23
@ FK_Data_4
A four-byte fixup.
Definition: MCFixup.h:25
@ FK_NONE
A no-op fixup.
Definition: MCFixup.h:22
@ FK_Data_2
A two-byte fixup.
Definition: MCFixup.h:24
bool isIntN(unsigned N, int64_t x)
Checks if an signed integer fits into the given (dynamic) bit width.
Definition: MathExtras.h:261
uint64_t alignTo(uint64_t Size, Align A)
Returns a multiple of A needed to store Size bytes.
Definition: Alignment.h:155
Target independent information on a fixup kind.
@ FKF_IsAlignedDownTo32Bits
Should this fixup kind force a 4-byte aligned effective PC value?
@ FKF_IsPCRel
Is this fixup kind PCrelative? This is used by the assembler backend to evaluate fixup values in a ta...