1 //===-- RISCVAsmBackend.cpp - RISCV Assembler Backend ---------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "RISCVAsmBackend.h"
10 #include "RISCVMCExpr.h"
11 #include "llvm/ADT/APInt.h"
12 #include "llvm/MC/MCAsmLayout.h"
13 #include "llvm/MC/MCAssembler.h"
14 #include "llvm/MC/MCContext.h"
15 #include "llvm/MC/MCDirectives.h"
16 #include "llvm/MC/MCELFObjectWriter.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCObjectWriter.h"
19 #include "llvm/MC/MCSymbol.h"
20 #include "llvm/MC/MCValue.h"
21 #include "llvm/Support/ErrorHandling.h"
22 #include "llvm/Support/raw_ostream.h"
26 // If linker relaxation is enabled, or the relax option had previously been
27 // enabled, always emit relocations even if the fixup can be resolved. This is
28 // necessary for correctness as offsets may change during relaxation.
29 bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
31 const MCValue &Target) {
32 switch (Fixup.getTargetKind()) {
39 if (Target.isAbsolute())
42 case RISCV::fixup_riscv_got_hi20:
43 case RISCV::fixup_riscv_tls_got_hi20:
44 case RISCV::fixup_riscv_tls_gd_hi20:
48 return STI.getFeatureBits()[RISCV::FeatureRelax] || ForceRelocs;
51 bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup,
54 const MCRelaxableFragment *DF,
55 const MCAsmLayout &Layout,
56 const bool WasForced) const {
57 // Return true if the symbol is actually unresolved.
58 // Resolved could be always false when shouldForceRelocation return true.
59 // We use !WasForced to indicate that the symbol is unresolved and not forced
60 // by shouldForceRelocation.
61 if (!Resolved && !WasForced)
64 int64_t Offset = int64_t(Value);
65 switch (Fixup.getTargetKind()) {
68 case RISCV::fixup_riscv_rvc_branch:
69 // For compressed branch instructions the immediate must be
70 // in the range [-256, 254].
71 return Offset > 254 || Offset < -256;
72 case RISCV::fixup_riscv_rvc_jump:
73 // For compressed jump instructions the immediate must be
74 // in the range [-2048, 2046].
75 return Offset > 2046 || Offset < -2048;
79 void RISCVAsmBackend::relaxInstruction(const MCInst &Inst,
80 const MCSubtargetInfo &STI,
82 // TODO: replace this with call to auto generated uncompressinstr() function.
83 switch (Inst.getOpcode()) {
85 llvm_unreachable("Opcode not expected!");
87 // c.beqz $rs1, $imm -> beq $rs1, X0, $imm.
88 Res.setOpcode(RISCV::BEQ);
89 Res.addOperand(Inst.getOperand(0));
90 Res.addOperand(MCOperand::createReg(RISCV::X0));
91 Res.addOperand(Inst.getOperand(1));
94 // c.bnez $rs1, $imm -> bne $rs1, X0, $imm.
95 Res.setOpcode(RISCV::BNE);
96 Res.addOperand(Inst.getOperand(0));
97 Res.addOperand(MCOperand::createReg(RISCV::X0));
98 Res.addOperand(Inst.getOperand(1));
101 // c.j $imm -> jal X0, $imm.
102 Res.setOpcode(RISCV::JAL);
103 Res.addOperand(MCOperand::createReg(RISCV::X0));
104 Res.addOperand(Inst.getOperand(0));
107 // c.jal $imm -> jal X1, $imm.
108 Res.setOpcode(RISCV::JAL);
109 Res.addOperand(MCOperand::createReg(RISCV::X1));
110 Res.addOperand(Inst.getOperand(0));
115 // Given a compressed control flow instruction this function returns
116 // the expanded instruction.
117 unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {
126 case RISCV::C_JAL: // fall through.
131 bool RISCVAsmBackend::mayNeedRelaxation(const MCInst &Inst,
132 const MCSubtargetInfo &STI) const {
133 return getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode();
136 bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
137 bool HasStdExtC = STI.getFeatureBits()[RISCV::FeatureStdExtC];
138 unsigned MinNopLen = HasStdExtC ? 2 : 4;
140 if ((Count % MinNopLen) != 0)
143 // The canonical nop on RISC-V is addi x0, x0, 0.
144 for (; Count >= 4; Count -= 4)
145 OS.write("\x13\0\0\0", 4);
147 // The canonical nop on RVC is c.nop.
148 if (Count && HasStdExtC)
149 OS.write("\x01\0", 2);
154 static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
156 switch (Fixup.getTargetKind()) {
158 llvm_unreachable("Unknown fixup kind!");
159 case RISCV::fixup_riscv_got_hi20:
160 case RISCV::fixup_riscv_tls_got_hi20:
161 case RISCV::fixup_riscv_tls_gd_hi20:
162 llvm_unreachable("Relocation should be unconditionally forced\n");
169 case RISCV::fixup_riscv_lo12_i:
170 case RISCV::fixup_riscv_pcrel_lo12_i:
171 case RISCV::fixup_riscv_tprel_lo12_i:
172 return Value & 0xfff;
173 case RISCV::fixup_riscv_lo12_s:
174 case RISCV::fixup_riscv_pcrel_lo12_s:
175 case RISCV::fixup_riscv_tprel_lo12_s:
176 return (((Value >> 5) & 0x7f) << 25) | ((Value & 0x1f) << 7);
177 case RISCV::fixup_riscv_hi20:
178 case RISCV::fixup_riscv_pcrel_hi20:
179 case RISCV::fixup_riscv_tprel_hi20:
180 // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
181 return ((Value + 0x800) >> 12) & 0xfffff;
182 case RISCV::fixup_riscv_jal: {
183 if (!isInt<21>(Value))
184 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
186 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
187 // Need to produce imm[19|10:1|11|19:12] from the 21-bit Value.
188 unsigned Sbit = (Value >> 20) & 0x1;
189 unsigned Hi8 = (Value >> 12) & 0xff;
190 unsigned Mid1 = (Value >> 11) & 0x1;
191 unsigned Lo10 = (Value >> 1) & 0x3ff;
193 // Inst{30-21} = Lo10;
195 // Inst{19-12} = Hi8;
196 Value = (Sbit << 19) | (Lo10 << 9) | (Mid1 << 8) | Hi8;
199 case RISCV::fixup_riscv_branch: {
200 if (!isInt<13>(Value))
201 Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
203 Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
204 // Need to extract imm[12], imm[10:5], imm[4:1], imm[11] from the 13-bit
206 unsigned Sbit = (Value >> 12) & 0x1;
207 unsigned Hi1 = (Value >> 11) & 0x1;
208 unsigned Mid6 = (Value >> 5) & 0x3f;
209 unsigned Lo4 = (Value >> 1) & 0xf;
211 // Inst{30-25} = Mid6;
214 Value = (Sbit << 31) | (Mid6 << 25) | (Lo4 << 8) | (Hi1 << 7);
217 case RISCV::fixup_riscv_call:
218 case RISCV::fixup_riscv_call_plt: {
219 // Jalr will add UpperImm with the sign-extended 12-bit LowerImm,
220 // we need to add 0x800ULL before extract upper bits to reflect the
221 // effect of the sign extension.
222 uint64_t UpperImm = (Value + 0x800ULL) & 0xfffff000ULL;
223 uint64_t LowerImm = Value & 0xfffULL;
224 return UpperImm | ((LowerImm << 20) << 32);
226 case RISCV::fixup_riscv_rvc_jump: {
227 // Need to produce offset[11|4|9:8|10|6|7|3:1|5] from the 11-bit Value.
228 unsigned Bit11 = (Value >> 11) & 0x1;
229 unsigned Bit4 = (Value >> 4) & 0x1;
230 unsigned Bit9_8 = (Value >> 8) & 0x3;
231 unsigned Bit10 = (Value >> 10) & 0x1;
232 unsigned Bit6 = (Value >> 6) & 0x1;
233 unsigned Bit7 = (Value >> 7) & 0x1;
234 unsigned Bit3_1 = (Value >> 1) & 0x7;
235 unsigned Bit5 = (Value >> 5) & 0x1;
236 Value = (Bit11 << 10) | (Bit4 << 9) | (Bit9_8 << 7) | (Bit10 << 6) |
237 (Bit6 << 5) | (Bit7 << 4) | (Bit3_1 << 1) | Bit5;
240 case RISCV::fixup_riscv_rvc_branch: {
241 // Need to produce offset[8|4:3], [reg 3 bit], offset[7:6|2:1|5]
242 unsigned Bit8 = (Value >> 8) & 0x1;
243 unsigned Bit7_6 = (Value >> 6) & 0x3;
244 unsigned Bit5 = (Value >> 5) & 0x1;
245 unsigned Bit4_3 = (Value >> 3) & 0x3;
246 unsigned Bit2_1 = (Value >> 1) & 0x3;
247 Value = (Bit8 << 12) | (Bit4_3 << 10) | (Bit7_6 << 5) | (Bit2_1 << 3) |
255 bool RISCVAsmBackend::evaluateTargetFixup(
256 const MCAssembler &Asm, const MCAsmLayout &Layout, const MCFixup &Fixup,
257 const MCFragment *DF, const MCValue &Target, uint64_t &Value,
259 const MCFixup *AUIPCFixup;
260 const MCFragment *AUIPCDF;
262 switch (Fixup.getTargetKind()) {
264 llvm_unreachable("Unexpected fixup kind!");
265 case RISCV::fixup_riscv_pcrel_hi20:
268 AUIPCTarget = Target;
270 case RISCV::fixup_riscv_pcrel_lo12_i:
271 case RISCV::fixup_riscv_pcrel_lo12_s: {
272 AUIPCFixup = cast<RISCVMCExpr>(Fixup.getValue())->getPCRelHiFixup(&AUIPCDF);
274 Asm.getContext().reportError(Fixup.getLoc(),
275 "could not find corresponding %pcrel_hi");
279 // MCAssembler::evaluateFixup will emit an error for this case when it sees
280 // the %pcrel_hi, so don't duplicate it when also seeing the %pcrel_lo.
281 const MCExpr *AUIPCExpr = AUIPCFixup->getValue();
282 if (!AUIPCExpr->evaluateAsRelocatable(AUIPCTarget, &Layout, AUIPCFixup))
288 if (!AUIPCTarget.getSymA() || AUIPCTarget.getSymB())
291 const MCSymbolRefExpr *A = AUIPCTarget.getSymA();
292 const MCSymbol &SA = A->getSymbol();
293 if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined())
296 auto *Writer = Asm.getWriterPtr();
300 bool IsResolved = Writer->isSymbolRefDifferenceFullyResolvedImpl(
301 Asm, SA, *AUIPCDF, false, true);
305 Value = Layout.getSymbolOffset(SA) + AUIPCTarget.getConstant();
306 Value -= Layout.getFragmentOffset(AUIPCDF) + AUIPCFixup->getOffset();
308 if (shouldForceRelocation(Asm, *AUIPCFixup, AUIPCTarget)) {
316 void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
317 const MCValue &Target,
318 MutableArrayRef<char> Data, uint64_t Value,
320 const MCSubtargetInfo *STI) const {
321 MCContext &Ctx = Asm.getContext();
322 MCFixupKindInfo Info = getFixupKindInfo(Fixup.getKind());
324 return; // Doesn't change encoding.
325 // Apply any target-specific value adjustments.
326 Value = adjustFixupValue(Fixup, Value, Ctx);
328 // Shift the value into position.
329 Value <<= Info.TargetOffset;
331 unsigned Offset = Fixup.getOffset();
332 unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
334 assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
336 // For each byte of the fragment that the fixup touches, mask in the
337 // bits from the fixup value.
338 for (unsigned i = 0; i != NumBytes; ++i) {
339 Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
343 // Linker relaxation may change code size. We have to insert Nops
344 // for .align directive when linker relaxation enabled. So then Linker
345 // could satisfy alignment by removing Nops.
346 // The function return the total Nops Size we need to insert.
347 bool RISCVAsmBackend::shouldInsertExtraNopBytesForCodeAlign(
348 const MCAlignFragment &AF, unsigned &Size) {
349 // Calculate Nops Size only when linker relaxation enabled.
350 if (!STI.getFeatureBits()[RISCV::FeatureRelax])
353 bool HasStdExtC = STI.getFeatureBits()[RISCV::FeatureStdExtC];
354 unsigned MinNopLen = HasStdExtC ? 2 : 4;
356 if (AF.getAlignment() <= MinNopLen) {
359 Size = AF.getAlignment() - MinNopLen;
364 // We need to insert R_RISCV_ALIGN relocation type to indicate the
365 // position of Nops and the total bytes of the Nops have been inserted
366 // when linker relaxation enabled.
367 // The function insert fixup_riscv_align fixup which eventually will
368 // transfer to R_RISCV_ALIGN relocation type.
369 bool RISCVAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm,
370 const MCAsmLayout &Layout,
371 MCAlignFragment &AF) {
372 // Insert the fixup only when linker relaxation enabled.
373 if (!STI.getFeatureBits()[RISCV::FeatureRelax])
376 // Calculate total Nops we need to insert. If there are none to insert
377 // then simply return.
379 if (!shouldInsertExtraNopBytesForCodeAlign(AF, Count) || (Count == 0))
382 MCContext &Ctx = Asm.getContext();
383 const MCExpr *Dummy = MCConstantExpr::create(0, Ctx);
384 // Create fixup_riscv_align fixup.
386 MCFixup::create(0, Dummy, MCFixupKind(RISCV::fixup_riscv_align), SMLoc());
388 uint64_t FixedValue = 0;
389 MCValue NopBytes = MCValue::get(Count);
391 Asm.getWriter().recordRelocation(Asm, Layout, &AF, Fixup, NopBytes,
397 std::unique_ptr<MCObjectTargetWriter>
398 RISCVAsmBackend::createObjectTargetWriter() const {
399 return createRISCVELFObjectWriter(OSABI, Is64Bit);
402 MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T,
403 const MCSubtargetInfo &STI,
404 const MCRegisterInfo &MRI,
405 const MCTargetOptions &Options) {
406 const Triple &TT = STI.getTargetTriple();
407 uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
408 return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options);