xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
15f757f3fSDimitry Andric //===-- RISCVAsmBackend.cpp - RISC-V Assembler Backend --------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "RISCVAsmBackend.h"
100b57cec5SDimitry Andric #include "RISCVMCExpr.h"
110b57cec5SDimitry Andric #include "llvm/ADT/APInt.h"
12fe6060f1SDimitry Andric #include "llvm/MC/MCAsmInfo.h"
130b57cec5SDimitry Andric #include "llvm/MC/MCAssembler.h"
140b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
150b57cec5SDimitry Andric #include "llvm/MC/MCDirectives.h"
160b57cec5SDimitry Andric #include "llvm/MC/MCELFObjectWriter.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
190b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCValue.h"
215f757f3fSDimitry Andric #include "llvm/Support/CommandLine.h"
22fe6060f1SDimitry Andric #include "llvm/Support/Endian.h"
23fe6060f1SDimitry Andric #include "llvm/Support/EndianStream.h"
240b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
25fe6060f1SDimitry Andric #include "llvm/Support/LEB128.h"
260b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
270b57cec5SDimitry Andric 
280b57cec5SDimitry Andric using namespace llvm;
290b57cec5SDimitry Andric 
305f757f3fSDimitry Andric static cl::opt<bool> RelaxBranches("riscv-asm-relax-branches", cl::init(true),
315f757f3fSDimitry Andric                                    cl::Hidden);
325f757f3fSDimitry Andric // Temporary workaround for old linkers that do not support ULEB128 relocations,
335f757f3fSDimitry Andric // which are abused by DWARF v5 DW_LLE_offset_pair/DW_RLE_offset_pair
345f757f3fSDimitry Andric // implemented in Clang/LLVM.
355f757f3fSDimitry Andric static cl::opt<bool> ULEB128Reloc(
365f757f3fSDimitry Andric     "riscv-uleb128-reloc", cl::init(true), cl::Hidden,
375f757f3fSDimitry Andric     cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate"));
385f757f3fSDimitry Andric 
39bdd1243dSDimitry Andric std::optional<MCFixupKind> RISCVAsmBackend::getFixupKind(StringRef Name) const {
405ffd83dbSDimitry Andric   if (STI.getTargetTriple().isOSBinFormatELF()) {
415ffd83dbSDimitry Andric     unsigned Type;
425ffd83dbSDimitry Andric     Type = llvm::StringSwitch<unsigned>(Name)
435ffd83dbSDimitry Andric #define ELF_RELOC(X, Y) .Case(#X, Y)
445ffd83dbSDimitry Andric #include "llvm/BinaryFormat/ELFRelocs/RISCV.def"
455ffd83dbSDimitry Andric #undef ELF_RELOC
46fe6060f1SDimitry Andric                .Case("BFD_RELOC_NONE", ELF::R_RISCV_NONE)
47fe6060f1SDimitry Andric                .Case("BFD_RELOC_32", ELF::R_RISCV_32)
48fe6060f1SDimitry Andric                .Case("BFD_RELOC_64", ELF::R_RISCV_64)
495ffd83dbSDimitry Andric                .Default(-1u);
505ffd83dbSDimitry Andric     if (Type != -1u)
515ffd83dbSDimitry Andric       return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);
525ffd83dbSDimitry Andric   }
53bdd1243dSDimitry Andric   return std::nullopt;
545ffd83dbSDimitry Andric }
555ffd83dbSDimitry Andric 
565ffd83dbSDimitry Andric const MCFixupKindInfo &
575ffd83dbSDimitry Andric RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
585ffd83dbSDimitry Andric   const static MCFixupKindInfo Infos[] = {
595ffd83dbSDimitry Andric       // This table *must* be in the order that the fixup_* kinds are defined in
605ffd83dbSDimitry Andric       // RISCVFixupKinds.h.
615ffd83dbSDimitry Andric       //
625ffd83dbSDimitry Andric       // name                      offset bits  flags
635ffd83dbSDimitry Andric       {"fixup_riscv_hi20", 12, 20, 0},
645ffd83dbSDimitry Andric       {"fixup_riscv_lo12_i", 20, 12, 0},
6506c3fb27SDimitry Andric       {"fixup_riscv_12_i", 20, 12, 0},
665ffd83dbSDimitry Andric       {"fixup_riscv_lo12_s", 0, 32, 0},
675ffd83dbSDimitry Andric       {"fixup_riscv_pcrel_hi20", 12, 20,
685ffd83dbSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},
695ffd83dbSDimitry Andric       {"fixup_riscv_pcrel_lo12_i", 20, 12,
705ffd83dbSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},
715ffd83dbSDimitry Andric       {"fixup_riscv_pcrel_lo12_s", 0, 32,
725ffd83dbSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},
735ffd83dbSDimitry Andric       {"fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel},
745ffd83dbSDimitry Andric       {"fixup_riscv_tprel_hi20", 12, 20, 0},
755ffd83dbSDimitry Andric       {"fixup_riscv_tprel_lo12_i", 20, 12, 0},
765ffd83dbSDimitry Andric       {"fixup_riscv_tprel_lo12_s", 0, 32, 0},
775ffd83dbSDimitry Andric       {"fixup_riscv_tprel_add", 0, 0, 0},
785ffd83dbSDimitry Andric       {"fixup_riscv_tls_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel},
795ffd83dbSDimitry Andric       {"fixup_riscv_tls_gd_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel},
805ffd83dbSDimitry Andric       {"fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel},
815ffd83dbSDimitry Andric       {"fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},
825ffd83dbSDimitry Andric       {"fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel},
835ffd83dbSDimitry Andric       {"fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel},
845ffd83dbSDimitry Andric       {"fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
855ffd83dbSDimitry Andric       {"fixup_riscv_call_plt", 0, 64, MCFixupKindInfo::FKF_IsPCRel},
865ffd83dbSDimitry Andric       {"fixup_riscv_relax", 0, 0, 0},
87fe6060f1SDimitry Andric       {"fixup_riscv_align", 0, 0, 0},
887a6dacacSDimitry Andric 
897a6dacacSDimitry Andric       {"fixup_riscv_tlsdesc_hi20", 12, 20,
907a6dacacSDimitry Andric        MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},
917a6dacacSDimitry Andric       {"fixup_riscv_tlsdesc_load_lo12", 20, 12, 0},
927a6dacacSDimitry Andric       {"fixup_riscv_tlsdesc_add_lo12", 20, 12, 0},
937a6dacacSDimitry Andric       {"fixup_riscv_tlsdesc_call", 0, 0, 0},
94fe6060f1SDimitry Andric   };
95bdd1243dSDimitry Andric   static_assert((std::size(Infos)) == RISCV::NumTargetFixupKinds,
965ffd83dbSDimitry Andric                 "Not all fixup kinds added to Infos array");
975ffd83dbSDimitry Andric 
985ffd83dbSDimitry Andric   // Fixup kinds from .reloc directive are like R_RISCV_NONE. They
995ffd83dbSDimitry Andric   // do not require any extra processing.
1005ffd83dbSDimitry Andric   if (Kind >= FirstLiteralRelocationKind)
1015ffd83dbSDimitry Andric     return MCAsmBackend::getFixupKindInfo(FK_NONE);
1025ffd83dbSDimitry Andric 
1035ffd83dbSDimitry Andric   if (Kind < FirstTargetFixupKind)
1045ffd83dbSDimitry Andric     return MCAsmBackend::getFixupKindInfo(Kind);
1055ffd83dbSDimitry Andric 
1065ffd83dbSDimitry Andric   assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
1075ffd83dbSDimitry Andric          "Invalid kind!");
1085ffd83dbSDimitry Andric   return Infos[Kind - FirstTargetFixupKind];
1095ffd83dbSDimitry Andric }
1105ffd83dbSDimitry Andric 
1110b57cec5SDimitry Andric // If linker relaxation is enabled, or the relax option had previously been
1120b57cec5SDimitry Andric // enabled, always emit relocations even if the fixup can be resolved. This is
1130b57cec5SDimitry Andric // necessary for correctness as offsets may change during relaxation.
1140b57cec5SDimitry Andric bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
1150b57cec5SDimitry Andric                                             const MCFixup &Fixup,
1165f757f3fSDimitry Andric                                             const MCValue &Target,
1175f757f3fSDimitry Andric                                             const MCSubtargetInfo *STI) {
1185ffd83dbSDimitry Andric   if (Fixup.getKind() >= FirstLiteralRelocationKind)
1195ffd83dbSDimitry Andric     return true;
1208bcb0991SDimitry Andric   switch (Fixup.getTargetKind()) {
1210b57cec5SDimitry Andric   default:
1220b57cec5SDimitry Andric     break;
1230b57cec5SDimitry Andric   case FK_Data_1:
1240b57cec5SDimitry Andric   case FK_Data_2:
1250b57cec5SDimitry Andric   case FK_Data_4:
1260b57cec5SDimitry Andric   case FK_Data_8:
1275f757f3fSDimitry Andric   case FK_Data_leb128:
1280b57cec5SDimitry Andric     if (Target.isAbsolute())
1290b57cec5SDimitry Andric       return false;
1300b57cec5SDimitry Andric     break;
1310b57cec5SDimitry Andric   case RISCV::fixup_riscv_got_hi20:
1320b57cec5SDimitry Andric   case RISCV::fixup_riscv_tls_got_hi20:
1330b57cec5SDimitry Andric   case RISCV::fixup_riscv_tls_gd_hi20:
1347a6dacacSDimitry Andric   case RISCV::fixup_riscv_tlsdesc_hi20:
1350b57cec5SDimitry Andric     return true;
1360b57cec5SDimitry Andric   }
1370b57cec5SDimitry Andric 
1385f757f3fSDimitry Andric   return STI->hasFeature(RISCV::FeatureRelax) || ForceRelocs;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
141*0fca6ea1SDimitry Andric bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(
142*0fca6ea1SDimitry Andric     const MCAssembler &Asm, const MCFixup &Fixup, bool Resolved, uint64_t Value,
143*0fca6ea1SDimitry Andric     const MCRelaxableFragment *DF, const bool WasForced) const {
1445f757f3fSDimitry Andric   if (!RelaxBranches)
1455f757f3fSDimitry Andric     return false;
1465f757f3fSDimitry Andric 
14706c3fb27SDimitry Andric   int64_t Offset = int64_t(Value);
14806c3fb27SDimitry Andric   unsigned Kind = Fixup.getTargetKind();
14906c3fb27SDimitry Andric 
1500b57cec5SDimitry Andric   // Return true if the symbol is actually unresolved.
1510b57cec5SDimitry Andric   // Resolved could be always false when shouldForceRelocation return true.
1520b57cec5SDimitry Andric   // We use !WasForced to indicate that the symbol is unresolved and not forced
1530b57cec5SDimitry Andric   // by shouldForceRelocation.
1540b57cec5SDimitry Andric   if (!Resolved && !WasForced)
1550b57cec5SDimitry Andric     return true;
1560b57cec5SDimitry Andric 
15706c3fb27SDimitry Andric   switch (Kind) {
1580b57cec5SDimitry Andric   default:
1590b57cec5SDimitry Andric     return false;
1600b57cec5SDimitry Andric   case RISCV::fixup_riscv_rvc_branch:
1610b57cec5SDimitry Andric     // For compressed branch instructions the immediate must be
1620b57cec5SDimitry Andric     // in the range [-256, 254].
1630b57cec5SDimitry Andric     return Offset > 254 || Offset < -256;
1640b57cec5SDimitry Andric   case RISCV::fixup_riscv_rvc_jump:
1650b57cec5SDimitry Andric     // For compressed jump instructions the immediate must be
1660b57cec5SDimitry Andric     // in the range [-2048, 2046].
1670b57cec5SDimitry Andric     return Offset > 2046 || Offset < -2048;
1685f757f3fSDimitry Andric   case RISCV::fixup_riscv_branch:
1695f757f3fSDimitry Andric     // For conditional branch instructions the immediate must be
1705f757f3fSDimitry Andric     // in the range [-4096, 4095].
1715f757f3fSDimitry Andric     return !isInt<13>(Offset);
1720b57cec5SDimitry Andric   }
1730b57cec5SDimitry Andric }
1740b57cec5SDimitry Andric 
1755ffd83dbSDimitry Andric void RISCVAsmBackend::relaxInstruction(MCInst &Inst,
1765ffd83dbSDimitry Andric                                        const MCSubtargetInfo &STI) const {
1775ffd83dbSDimitry Andric   MCInst Res;
1780b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
1790b57cec5SDimitry Andric   default:
1800b57cec5SDimitry Andric     llvm_unreachable("Opcode not expected!");
1810b57cec5SDimitry Andric   case RISCV::C_BEQZ:
1820b57cec5SDimitry Andric   case RISCV::C_BNEZ:
1830b57cec5SDimitry Andric   case RISCV::C_J:
18406c3fb27SDimitry Andric   case RISCV::C_JAL: {
185*0fca6ea1SDimitry Andric     [[maybe_unused]] bool Success = RISCVRVC::uncompress(Res, Inst, STI);
186bdd1243dSDimitry Andric     assert(Success && "Can't uncompress instruction");
1870b57cec5SDimitry Andric     break;
1880b57cec5SDimitry Andric   }
18906c3fb27SDimitry Andric   case RISCV::BEQ:
19006c3fb27SDimitry Andric   case RISCV::BNE:
19106c3fb27SDimitry Andric   case RISCV::BLT:
19206c3fb27SDimitry Andric   case RISCV::BGE:
19306c3fb27SDimitry Andric   case RISCV::BLTU:
19406c3fb27SDimitry Andric   case RISCV::BGEU:
19506c3fb27SDimitry Andric     Res.setOpcode(getRelaxedOpcode(Inst.getOpcode()));
19606c3fb27SDimitry Andric     Res.addOperand(Inst.getOperand(0));
19706c3fb27SDimitry Andric     Res.addOperand(Inst.getOperand(1));
19806c3fb27SDimitry Andric     Res.addOperand(Inst.getOperand(2));
19906c3fb27SDimitry Andric     break;
20006c3fb27SDimitry Andric   }
2015ffd83dbSDimitry Andric   Inst = std::move(Res);
2020b57cec5SDimitry Andric }
2030b57cec5SDimitry Andric 
204*0fca6ea1SDimitry Andric bool RISCVAsmBackend::relaxDwarfLineAddr(const MCAssembler &Asm,
205*0fca6ea1SDimitry Andric                                          MCDwarfLineAddrFragment &DF,
206fe6060f1SDimitry Andric                                          bool &WasRelaxed) const {
207*0fca6ea1SDimitry Andric   MCContext &C = Asm.getContext();
208fe6060f1SDimitry Andric 
209fe6060f1SDimitry Andric   int64_t LineDelta = DF.getLineDelta();
210fe6060f1SDimitry Andric   const MCExpr &AddrDelta = DF.getAddrDelta();
211fe6060f1SDimitry Andric   SmallVectorImpl<char> &Data = DF.getContents();
212fe6060f1SDimitry Andric   SmallVectorImpl<MCFixup> &Fixups = DF.getFixups();
213fe6060f1SDimitry Andric   size_t OldSize = Data.size();
214fe6060f1SDimitry Andric 
215fe6060f1SDimitry Andric   int64_t Value;
216*0fca6ea1SDimitry Andric   [[maybe_unused]] bool IsAbsolute =
217*0fca6ea1SDimitry Andric       AddrDelta.evaluateKnownAbsolute(Value, Asm);
218fe6060f1SDimitry Andric   assert(IsAbsolute && "CFA with invalid expression");
219fe6060f1SDimitry Andric 
220fe6060f1SDimitry Andric   Data.clear();
221fe6060f1SDimitry Andric   Fixups.clear();
222fe6060f1SDimitry Andric   raw_svector_ostream OS(Data);
223fe6060f1SDimitry Andric 
224fe6060f1SDimitry Andric   // INT64_MAX is a signal that this is actually a DW_LNE_end_sequence.
225fe6060f1SDimitry Andric   if (LineDelta != INT64_MAX) {
226fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_LNS_advance_line);
227fe6060f1SDimitry Andric     encodeSLEB128(LineDelta, OS);
228fe6060f1SDimitry Andric   }
229fe6060f1SDimitry Andric 
230fe6060f1SDimitry Andric   unsigned Offset;
23106c3fb27SDimitry Andric   std::pair<MCFixupKind, MCFixupKind> Fixup;
232fe6060f1SDimitry Andric 
233fe6060f1SDimitry Andric   // According to the DWARF specification, the `DW_LNS_fixed_advance_pc` opcode
234fe6060f1SDimitry Andric   // takes a single unsigned half (unencoded) operand. The maximum encodable
235fe6060f1SDimitry Andric   // value is therefore 65535.  Set a conservative upper bound for relaxation.
236fe6060f1SDimitry Andric   if (Value > 60000) {
237fe6060f1SDimitry Andric     unsigned PtrSize = C.getAsmInfo()->getCodePointerSize();
238fe6060f1SDimitry Andric 
239fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_LNS_extended_op);
240fe6060f1SDimitry Andric     encodeULEB128(PtrSize + 1, OS);
241fe6060f1SDimitry Andric 
242fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_LNE_set_address);
243fe6060f1SDimitry Andric     Offset = OS.tell();
24406c3fb27SDimitry Andric     assert((PtrSize == 4 || PtrSize == 8) && "Unexpected pointer size");
24506c3fb27SDimitry Andric     Fixup = RISCV::getRelocPairForSize(PtrSize);
246fe6060f1SDimitry Andric     OS.write_zeros(PtrSize);
247fe6060f1SDimitry Andric   } else {
248fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);
249fe6060f1SDimitry Andric     Offset = OS.tell();
25006c3fb27SDimitry Andric     Fixup = RISCV::getRelocPairForSize(2);
2515f757f3fSDimitry Andric     support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
252fe6060f1SDimitry Andric   }
253fe6060f1SDimitry Andric 
254fe6060f1SDimitry Andric   const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
25506c3fb27SDimitry Andric   Fixups.push_back(MCFixup::create(Offset, MBE.getLHS(), std::get<0>(Fixup)));
25606c3fb27SDimitry Andric   Fixups.push_back(MCFixup::create(Offset, MBE.getRHS(), std::get<1>(Fixup)));
257fe6060f1SDimitry Andric 
258fe6060f1SDimitry Andric   if (LineDelta == INT64_MAX) {
259fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_LNS_extended_op);
260fe6060f1SDimitry Andric     OS << uint8_t(1);
261fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_LNE_end_sequence);
262fe6060f1SDimitry Andric   } else {
263fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_LNS_copy);
264fe6060f1SDimitry Andric   }
265fe6060f1SDimitry Andric 
266fe6060f1SDimitry Andric   WasRelaxed = OldSize != Data.size();
267fe6060f1SDimitry Andric   return true;
268fe6060f1SDimitry Andric }
269fe6060f1SDimitry Andric 
270*0fca6ea1SDimitry Andric bool RISCVAsmBackend::relaxDwarfCFA(const MCAssembler &Asm,
271*0fca6ea1SDimitry Andric                                     MCDwarfCallFrameFragment &DF,
272fe6060f1SDimitry Andric                                     bool &WasRelaxed) const {
273fe6060f1SDimitry Andric   const MCExpr &AddrDelta = DF.getAddrDelta();
274fe6060f1SDimitry Andric   SmallVectorImpl<char> &Data = DF.getContents();
275fe6060f1SDimitry Andric   SmallVectorImpl<MCFixup> &Fixups = DF.getFixups();
276fe6060f1SDimitry Andric   size_t OldSize = Data.size();
277fe6060f1SDimitry Andric 
278fe6060f1SDimitry Andric   int64_t Value;
279*0fca6ea1SDimitry Andric   if (AddrDelta.evaluateAsAbsolute(Value, Asm))
28006c3fb27SDimitry Andric     return false;
281*0fca6ea1SDimitry Andric   [[maybe_unused]] bool IsAbsolute =
282*0fca6ea1SDimitry Andric       AddrDelta.evaluateKnownAbsolute(Value, Asm);
283fe6060f1SDimitry Andric   assert(IsAbsolute && "CFA with invalid expression");
284fe6060f1SDimitry Andric 
285fe6060f1SDimitry Andric   Data.clear();
286fe6060f1SDimitry Andric   Fixups.clear();
287fe6060f1SDimitry Andric   raw_svector_ostream OS(Data);
288fe6060f1SDimitry Andric 
289*0fca6ea1SDimitry Andric   assert(Asm.getContext().getAsmInfo()->getMinInstAlignment() == 1 &&
290fe6060f1SDimitry Andric          "expected 1-byte alignment");
291fe6060f1SDimitry Andric   if (Value == 0) {
292fe6060f1SDimitry Andric     WasRelaxed = OldSize != Data.size();
293fe6060f1SDimitry Andric     return true;
294fe6060f1SDimitry Andric   }
295fe6060f1SDimitry Andric 
296fe6060f1SDimitry Andric   auto AddFixups = [&Fixups, &AddrDelta](unsigned Offset,
297fe6060f1SDimitry Andric                                          std::pair<unsigned, unsigned> Fixup) {
298fe6060f1SDimitry Andric     const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);
2995f757f3fSDimitry Andric     Fixups.push_back(
3005f757f3fSDimitry Andric         MCFixup::create(Offset, MBE.getLHS(),
3015f757f3fSDimitry Andric                         static_cast<MCFixupKind>(FirstLiteralRelocationKind +
3025f757f3fSDimitry Andric                                                  std::get<0>(Fixup))));
3035f757f3fSDimitry Andric     Fixups.push_back(
3045f757f3fSDimitry Andric         MCFixup::create(Offset, MBE.getRHS(),
3055f757f3fSDimitry Andric                         static_cast<MCFixupKind>(FirstLiteralRelocationKind +
3065f757f3fSDimitry Andric                                                  std::get<1>(Fixup))));
307fe6060f1SDimitry Andric   };
308fe6060f1SDimitry Andric 
309fe6060f1SDimitry Andric   if (isUIntN(6, Value)) {
310fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_CFA_advance_loc);
3115f757f3fSDimitry Andric     AddFixups(0, {ELF::R_RISCV_SET6, ELF::R_RISCV_SUB6});
312fe6060f1SDimitry Andric   } else if (isUInt<8>(Value)) {
313fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_CFA_advance_loc1);
3145f757f3fSDimitry Andric     support::endian::write<uint8_t>(OS, 0, llvm::endianness::little);
3155f757f3fSDimitry Andric     AddFixups(1, {ELF::R_RISCV_SET8, ELF::R_RISCV_SUB8});
316fe6060f1SDimitry Andric   } else if (isUInt<16>(Value)) {
317fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_CFA_advance_loc2);
3185f757f3fSDimitry Andric     support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);
3195f757f3fSDimitry Andric     AddFixups(1, {ELF::R_RISCV_SET16, ELF::R_RISCV_SUB16});
320fe6060f1SDimitry Andric   } else if (isUInt<32>(Value)) {
321fe6060f1SDimitry Andric     OS << uint8_t(dwarf::DW_CFA_advance_loc4);
3225f757f3fSDimitry Andric     support::endian::write<uint32_t>(OS, 0, llvm::endianness::little);
3235f757f3fSDimitry Andric     AddFixups(1, {ELF::R_RISCV_SET32, ELF::R_RISCV_SUB32});
324fe6060f1SDimitry Andric   } else {
325fe6060f1SDimitry Andric     llvm_unreachable("unsupported CFA encoding");
326fe6060f1SDimitry Andric   }
327fe6060f1SDimitry Andric 
328fe6060f1SDimitry Andric   WasRelaxed = OldSize != Data.size();
329fe6060f1SDimitry Andric   return true;
330fe6060f1SDimitry Andric }
331fe6060f1SDimitry Andric 
332*0fca6ea1SDimitry Andric std::pair<bool, bool> RISCVAsmBackend::relaxLEB128(const MCAssembler &Asm,
333*0fca6ea1SDimitry Andric                                                    MCLEBFragment &LF,
3345f757f3fSDimitry Andric                                                    int64_t &Value) const {
3355f757f3fSDimitry Andric   if (LF.isSigned())
3361db9f3b2SDimitry Andric     return std::make_pair(false, false);
3375f757f3fSDimitry Andric   const MCExpr &Expr = LF.getValue();
3385f757f3fSDimitry Andric   if (ULEB128Reloc) {
3395f757f3fSDimitry Andric     LF.getFixups().push_back(
3405f757f3fSDimitry Andric         MCFixup::create(0, &Expr, FK_Data_leb128, Expr.getLoc()));
3415f757f3fSDimitry Andric   }
342*0fca6ea1SDimitry Andric   return std::make_pair(Expr.evaluateKnownAbsolute(Value, Asm), false);
3435f757f3fSDimitry Andric }
3445f757f3fSDimitry Andric 
3450b57cec5SDimitry Andric // Given a compressed control flow instruction this function returns
3460b57cec5SDimitry Andric // the expanded instruction.
3470b57cec5SDimitry Andric unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {
3480b57cec5SDimitry Andric   switch (Op) {
3490b57cec5SDimitry Andric   default:
3500b57cec5SDimitry Andric     return Op;
3510b57cec5SDimitry Andric   case RISCV::C_BEQZ:
3520b57cec5SDimitry Andric     return RISCV::BEQ;
3530b57cec5SDimitry Andric   case RISCV::C_BNEZ:
3540b57cec5SDimitry Andric     return RISCV::BNE;
3550b57cec5SDimitry Andric   case RISCV::C_J:
3560b57cec5SDimitry Andric   case RISCV::C_JAL: // fall through.
3570b57cec5SDimitry Andric     return RISCV::JAL;
35806c3fb27SDimitry Andric   case RISCV::BEQ:
35906c3fb27SDimitry Andric     return RISCV::PseudoLongBEQ;
36006c3fb27SDimitry Andric   case RISCV::BNE:
36106c3fb27SDimitry Andric     return RISCV::PseudoLongBNE;
36206c3fb27SDimitry Andric   case RISCV::BLT:
36306c3fb27SDimitry Andric     return RISCV::PseudoLongBLT;
36406c3fb27SDimitry Andric   case RISCV::BGE:
36506c3fb27SDimitry Andric     return RISCV::PseudoLongBGE;
36606c3fb27SDimitry Andric   case RISCV::BLTU:
36706c3fb27SDimitry Andric     return RISCV::PseudoLongBLTU;
36806c3fb27SDimitry Andric   case RISCV::BGEU:
36906c3fb27SDimitry Andric     return RISCV::PseudoLongBGEU;
3700b57cec5SDimitry Andric   }
3710b57cec5SDimitry Andric }
3720b57cec5SDimitry Andric 
3730b57cec5SDimitry Andric bool RISCVAsmBackend::mayNeedRelaxation(const MCInst &Inst,
3740b57cec5SDimitry Andric                                         const MCSubtargetInfo &STI) const {
3750b57cec5SDimitry Andric   return getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode();
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric 
378349cc55cSDimitry Andric bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
379349cc55cSDimitry Andric                                    const MCSubtargetInfo *STI) const {
380bdd1243dSDimitry Andric   // We mostly follow binutils' convention here: align to even boundary with a
381bdd1243dSDimitry Andric   // 0-fill padding.  We emit up to 1 2-byte nop, though we use c.nop if RVC is
382bdd1243dSDimitry Andric   // enabled or 0-fill otherwise.  The remainder is now padded with 4-byte nops.
3830b57cec5SDimitry Andric 
384bdd1243dSDimitry Andric   // Instructions always are at even addresses.  We must be in a data area or
385bdd1243dSDimitry Andric   // be unaligned due to some other reason.
386bdd1243dSDimitry Andric   if (Count % 2) {
387bdd1243dSDimitry Andric     OS.write("\0", 1);
388bdd1243dSDimitry Andric     Count -= 1;
389bdd1243dSDimitry Andric   }
390bdd1243dSDimitry Andric 
39106c3fb27SDimitry Andric   bool UseCompressedNop = STI->hasFeature(RISCV::FeatureStdExtC) ||
39206c3fb27SDimitry Andric                           STI->hasFeature(RISCV::FeatureStdExtZca);
393bdd1243dSDimitry Andric   // The canonical nop on RVC is c.nop.
394bdd1243dSDimitry Andric   if (Count % 4 == 2) {
39506c3fb27SDimitry Andric     OS.write(UseCompressedNop ? "\x01\0" : "\0\0", 2);
396bdd1243dSDimitry Andric     Count -= 2;
397bdd1243dSDimitry Andric   }
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric   // The canonical nop on RISC-V is addi x0, x0, 0.
4000b57cec5SDimitry Andric   for (; Count >= 4; Count -= 4)
4010b57cec5SDimitry Andric     OS.write("\x13\0\0\0", 4);
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric   return true;
4040b57cec5SDimitry Andric }
4050b57cec5SDimitry Andric 
4060b57cec5SDimitry Andric static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
4070b57cec5SDimitry Andric                                  MCContext &Ctx) {
4088bcb0991SDimitry Andric   switch (Fixup.getTargetKind()) {
4090b57cec5SDimitry Andric   default:
4100b57cec5SDimitry Andric     llvm_unreachable("Unknown fixup kind!");
4110b57cec5SDimitry Andric   case RISCV::fixup_riscv_got_hi20:
4120b57cec5SDimitry Andric   case RISCV::fixup_riscv_tls_got_hi20:
4130b57cec5SDimitry Andric   case RISCV::fixup_riscv_tls_gd_hi20:
4147a6dacacSDimitry Andric   case RISCV::fixup_riscv_tlsdesc_hi20:
4150b57cec5SDimitry Andric     llvm_unreachable("Relocation should be unconditionally forced\n");
4160b57cec5SDimitry Andric   case FK_Data_1:
4170b57cec5SDimitry Andric   case FK_Data_2:
4180b57cec5SDimitry Andric   case FK_Data_4:
4190b57cec5SDimitry Andric   case FK_Data_8:
4205f757f3fSDimitry Andric   case FK_Data_leb128:
4210b57cec5SDimitry Andric     return Value;
4220b57cec5SDimitry Andric   case RISCV::fixup_riscv_lo12_i:
4230b57cec5SDimitry Andric   case RISCV::fixup_riscv_pcrel_lo12_i:
4240b57cec5SDimitry Andric   case RISCV::fixup_riscv_tprel_lo12_i:
4257a6dacacSDimitry Andric   case RISCV::fixup_riscv_tlsdesc_load_lo12:
4260b57cec5SDimitry Andric     return Value & 0xfff;
42706c3fb27SDimitry Andric   case RISCV::fixup_riscv_12_i:
42806c3fb27SDimitry Andric     if (!isInt<12>(Value)) {
42906c3fb27SDimitry Andric       Ctx.reportError(Fixup.getLoc(),
43006c3fb27SDimitry Andric                       "operand must be a constant 12-bit integer");
43106c3fb27SDimitry Andric     }
43206c3fb27SDimitry Andric     return Value & 0xfff;
4330b57cec5SDimitry Andric   case RISCV::fixup_riscv_lo12_s:
4340b57cec5SDimitry Andric   case RISCV::fixup_riscv_pcrel_lo12_s:
4350b57cec5SDimitry Andric   case RISCV::fixup_riscv_tprel_lo12_s:
4360b57cec5SDimitry Andric     return (((Value >> 5) & 0x7f) << 25) | ((Value & 0x1f) << 7);
4370b57cec5SDimitry Andric   case RISCV::fixup_riscv_hi20:
4380b57cec5SDimitry Andric   case RISCV::fixup_riscv_pcrel_hi20:
4390b57cec5SDimitry Andric   case RISCV::fixup_riscv_tprel_hi20:
4400b57cec5SDimitry Andric     // Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.
4410b57cec5SDimitry Andric     return ((Value + 0x800) >> 12) & 0xfffff;
4420b57cec5SDimitry Andric   case RISCV::fixup_riscv_jal: {
4430b57cec5SDimitry Andric     if (!isInt<21>(Value))
4440b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
4450b57cec5SDimitry Andric     if (Value & 0x1)
4460b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
4470b57cec5SDimitry Andric     // Need to produce imm[19|10:1|11|19:12] from the 21-bit Value.
4480b57cec5SDimitry Andric     unsigned Sbit = (Value >> 20) & 0x1;
4490b57cec5SDimitry Andric     unsigned Hi8 = (Value >> 12) & 0xff;
4500b57cec5SDimitry Andric     unsigned Mid1 = (Value >> 11) & 0x1;
4510b57cec5SDimitry Andric     unsigned Lo10 = (Value >> 1) & 0x3ff;
4520b57cec5SDimitry Andric     // Inst{31} = Sbit;
4530b57cec5SDimitry Andric     // Inst{30-21} = Lo10;
4540b57cec5SDimitry Andric     // Inst{20} = Mid1;
4550b57cec5SDimitry Andric     // Inst{19-12} = Hi8;
4560b57cec5SDimitry Andric     Value = (Sbit << 19) | (Lo10 << 9) | (Mid1 << 8) | Hi8;
4570b57cec5SDimitry Andric     return Value;
4580b57cec5SDimitry Andric   }
4590b57cec5SDimitry Andric   case RISCV::fixup_riscv_branch: {
4600b57cec5SDimitry Andric     if (!isInt<13>(Value))
4610b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
4620b57cec5SDimitry Andric     if (Value & 0x1)
4630b57cec5SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");
4640b57cec5SDimitry Andric     // Need to extract imm[12], imm[10:5], imm[4:1], imm[11] from the 13-bit
4650b57cec5SDimitry Andric     // Value.
4660b57cec5SDimitry Andric     unsigned Sbit = (Value >> 12) & 0x1;
4670b57cec5SDimitry Andric     unsigned Hi1 = (Value >> 11) & 0x1;
4680b57cec5SDimitry Andric     unsigned Mid6 = (Value >> 5) & 0x3f;
4690b57cec5SDimitry Andric     unsigned Lo4 = (Value >> 1) & 0xf;
4700b57cec5SDimitry Andric     // Inst{31} = Sbit;
4710b57cec5SDimitry Andric     // Inst{30-25} = Mid6;
4720b57cec5SDimitry Andric     // Inst{11-8} = Lo4;
4730b57cec5SDimitry Andric     // Inst{7} = Hi1;
4740b57cec5SDimitry Andric     Value = (Sbit << 31) | (Mid6 << 25) | (Lo4 << 8) | (Hi1 << 7);
4750b57cec5SDimitry Andric     return Value;
4760b57cec5SDimitry Andric   }
4770b57cec5SDimitry Andric   case RISCV::fixup_riscv_call:
4780b57cec5SDimitry Andric   case RISCV::fixup_riscv_call_plt: {
4790b57cec5SDimitry Andric     // Jalr will add UpperImm with the sign-extended 12-bit LowerImm,
4800b57cec5SDimitry Andric     // we need to add 0x800ULL before extract upper bits to reflect the
4810b57cec5SDimitry Andric     // effect of the sign extension.
4820b57cec5SDimitry Andric     uint64_t UpperImm = (Value + 0x800ULL) & 0xfffff000ULL;
4830b57cec5SDimitry Andric     uint64_t LowerImm = Value & 0xfffULL;
4840b57cec5SDimitry Andric     return UpperImm | ((LowerImm << 20) << 32);
4850b57cec5SDimitry Andric   }
4860b57cec5SDimitry Andric   case RISCV::fixup_riscv_rvc_jump: {
4875f757f3fSDimitry Andric     if (!isInt<12>(Value))
4885f757f3fSDimitry Andric       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
4890b57cec5SDimitry Andric     // Need to produce offset[11|4|9:8|10|6|7|3:1|5] from the 11-bit Value.
4900b57cec5SDimitry Andric     unsigned Bit11  = (Value >> 11) & 0x1;
4910b57cec5SDimitry Andric     unsigned Bit4   = (Value >> 4) & 0x1;
4920b57cec5SDimitry Andric     unsigned Bit9_8 = (Value >> 8) & 0x3;
4930b57cec5SDimitry Andric     unsigned Bit10  = (Value >> 10) & 0x1;
4940b57cec5SDimitry Andric     unsigned Bit6   = (Value >> 6) & 0x1;
4950b57cec5SDimitry Andric     unsigned Bit7   = (Value >> 7) & 0x1;
4960b57cec5SDimitry Andric     unsigned Bit3_1 = (Value >> 1) & 0x7;
4970b57cec5SDimitry Andric     unsigned Bit5   = (Value >> 5) & 0x1;
4980b57cec5SDimitry Andric     Value = (Bit11 << 10) | (Bit4 << 9) | (Bit9_8 << 7) | (Bit10 << 6) |
4990b57cec5SDimitry Andric             (Bit6 << 5) | (Bit7 << 4) | (Bit3_1 << 1) | Bit5;
5000b57cec5SDimitry Andric     return Value;
5010b57cec5SDimitry Andric   }
5020b57cec5SDimitry Andric   case RISCV::fixup_riscv_rvc_branch: {
5035f757f3fSDimitry Andric     if (!isInt<9>(Value))
5045f757f3fSDimitry Andric       Ctx.reportError(Fixup.getLoc(), "fixup value out of range");
5050b57cec5SDimitry Andric     // Need to produce offset[8|4:3], [reg 3 bit], offset[7:6|2:1|5]
5060b57cec5SDimitry Andric     unsigned Bit8   = (Value >> 8) & 0x1;
5070b57cec5SDimitry Andric     unsigned Bit7_6 = (Value >> 6) & 0x3;
5080b57cec5SDimitry Andric     unsigned Bit5   = (Value >> 5) & 0x1;
5090b57cec5SDimitry Andric     unsigned Bit4_3 = (Value >> 3) & 0x3;
5100b57cec5SDimitry Andric     unsigned Bit2_1 = (Value >> 1) & 0x3;
5110b57cec5SDimitry Andric     Value = (Bit8 << 12) | (Bit4_3 << 10) | (Bit7_6 << 5) | (Bit2_1 << 3) |
5120b57cec5SDimitry Andric             (Bit5 << 2);
5130b57cec5SDimitry Andric     return Value;
5140b57cec5SDimitry Andric   }
5150b57cec5SDimitry Andric 
5160b57cec5SDimitry Andric   }
5170b57cec5SDimitry Andric }
5180b57cec5SDimitry Andric 
519*0fca6ea1SDimitry Andric bool RISCVAsmBackend::evaluateTargetFixup(const MCAssembler &Asm,
520*0fca6ea1SDimitry Andric                                           const MCFixup &Fixup,
521*0fca6ea1SDimitry Andric                                           const MCFragment *DF,
522*0fca6ea1SDimitry Andric                                           const MCValue &Target,
523*0fca6ea1SDimitry Andric                                           const MCSubtargetInfo *STI,
5245f757f3fSDimitry Andric                                           uint64_t &Value, bool &WasForced) {
52555e4f9d5SDimitry Andric   const MCFixup *AUIPCFixup;
52655e4f9d5SDimitry Andric   const MCFragment *AUIPCDF;
52755e4f9d5SDimitry Andric   MCValue AUIPCTarget;
52855e4f9d5SDimitry Andric   switch (Fixup.getTargetKind()) {
52955e4f9d5SDimitry Andric   default:
53055e4f9d5SDimitry Andric     llvm_unreachable("Unexpected fixup kind!");
5317a6dacacSDimitry Andric   case RISCV::fixup_riscv_tlsdesc_hi20:
53255e4f9d5SDimitry Andric   case RISCV::fixup_riscv_pcrel_hi20:
53355e4f9d5SDimitry Andric     AUIPCFixup = &Fixup;
53455e4f9d5SDimitry Andric     AUIPCDF = DF;
53555e4f9d5SDimitry Andric     AUIPCTarget = Target;
53655e4f9d5SDimitry Andric     break;
53755e4f9d5SDimitry Andric   case RISCV::fixup_riscv_pcrel_lo12_i:
53855e4f9d5SDimitry Andric   case RISCV::fixup_riscv_pcrel_lo12_s: {
53955e4f9d5SDimitry Andric     AUIPCFixup = cast<RISCVMCExpr>(Fixup.getValue())->getPCRelHiFixup(&AUIPCDF);
54055e4f9d5SDimitry Andric     if (!AUIPCFixup) {
54155e4f9d5SDimitry Andric       Asm.getContext().reportError(Fixup.getLoc(),
54255e4f9d5SDimitry Andric                                    "could not find corresponding %pcrel_hi");
54355e4f9d5SDimitry Andric       return true;
54455e4f9d5SDimitry Andric     }
54555e4f9d5SDimitry Andric 
54655e4f9d5SDimitry Andric     // MCAssembler::evaluateFixup will emit an error for this case when it sees
54755e4f9d5SDimitry Andric     // the %pcrel_hi, so don't duplicate it when also seeing the %pcrel_lo.
54855e4f9d5SDimitry Andric     const MCExpr *AUIPCExpr = AUIPCFixup->getValue();
549*0fca6ea1SDimitry Andric     if (!AUIPCExpr->evaluateAsRelocatable(AUIPCTarget, &Asm, AUIPCFixup))
55055e4f9d5SDimitry Andric       return true;
55155e4f9d5SDimitry Andric     break;
55255e4f9d5SDimitry Andric   }
55355e4f9d5SDimitry Andric   }
55455e4f9d5SDimitry Andric 
55555e4f9d5SDimitry Andric   if (!AUIPCTarget.getSymA() || AUIPCTarget.getSymB())
55655e4f9d5SDimitry Andric     return false;
55755e4f9d5SDimitry Andric 
55855e4f9d5SDimitry Andric   const MCSymbolRefExpr *A = AUIPCTarget.getSymA();
55955e4f9d5SDimitry Andric   const MCSymbol &SA = A->getSymbol();
56055e4f9d5SDimitry Andric   if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined())
56155e4f9d5SDimitry Andric     return false;
56255e4f9d5SDimitry Andric 
563*0fca6ea1SDimitry Andric   bool IsResolved = Asm.getWriter().isSymbolRefDifferenceFullyResolvedImpl(
56455e4f9d5SDimitry Andric       Asm, SA, *AUIPCDF, false, true);
56555e4f9d5SDimitry Andric   if (!IsResolved)
56655e4f9d5SDimitry Andric     return false;
56755e4f9d5SDimitry Andric 
568*0fca6ea1SDimitry Andric   Value = Asm.getSymbolOffset(SA) + AUIPCTarget.getConstant();
569*0fca6ea1SDimitry Andric   Value -= Asm.getFragmentOffset(*AUIPCDF) + AUIPCFixup->getOffset();
57055e4f9d5SDimitry Andric 
5715f757f3fSDimitry Andric   if (shouldForceRelocation(Asm, *AUIPCFixup, AUIPCTarget, STI)) {
57255e4f9d5SDimitry Andric     WasForced = true;
57355e4f9d5SDimitry Andric     return false;
57455e4f9d5SDimitry Andric   }
57555e4f9d5SDimitry Andric 
57655e4f9d5SDimitry Andric   return true;
57755e4f9d5SDimitry Andric }
57855e4f9d5SDimitry Andric 
579*0fca6ea1SDimitry Andric bool RISCVAsmBackend::handleAddSubRelocations(const MCAssembler &Asm,
58006c3fb27SDimitry Andric                                               const MCFragment &F,
58106c3fb27SDimitry Andric                                               const MCFixup &Fixup,
58206c3fb27SDimitry Andric                                               const MCValue &Target,
58306c3fb27SDimitry Andric                                               uint64_t &FixedValue) const {
58406c3fb27SDimitry Andric   uint64_t FixedValueA, FixedValueB;
58506c3fb27SDimitry Andric   unsigned TA = 0, TB = 0;
58606c3fb27SDimitry Andric   switch (Fixup.getKind()) {
58706c3fb27SDimitry Andric   case llvm::FK_Data_1:
58806c3fb27SDimitry Andric     TA = ELF::R_RISCV_ADD8;
58906c3fb27SDimitry Andric     TB = ELF::R_RISCV_SUB8;
59006c3fb27SDimitry Andric     break;
59106c3fb27SDimitry Andric   case llvm::FK_Data_2:
59206c3fb27SDimitry Andric     TA = ELF::R_RISCV_ADD16;
59306c3fb27SDimitry Andric     TB = ELF::R_RISCV_SUB16;
59406c3fb27SDimitry Andric     break;
59506c3fb27SDimitry Andric   case llvm::FK_Data_4:
59606c3fb27SDimitry Andric     TA = ELF::R_RISCV_ADD32;
59706c3fb27SDimitry Andric     TB = ELF::R_RISCV_SUB32;
59806c3fb27SDimitry Andric     break;
59906c3fb27SDimitry Andric   case llvm::FK_Data_8:
60006c3fb27SDimitry Andric     TA = ELF::R_RISCV_ADD64;
60106c3fb27SDimitry Andric     TB = ELF::R_RISCV_SUB64;
60206c3fb27SDimitry Andric     break;
6035f757f3fSDimitry Andric   case llvm::FK_Data_leb128:
6045f757f3fSDimitry Andric     TA = ELF::R_RISCV_SET_ULEB128;
6055f757f3fSDimitry Andric     TB = ELF::R_RISCV_SUB_ULEB128;
6065f757f3fSDimitry Andric     break;
60706c3fb27SDimitry Andric   default:
60806c3fb27SDimitry Andric     llvm_unreachable("unsupported fixup size");
60906c3fb27SDimitry Andric   }
61006c3fb27SDimitry Andric   MCValue A = MCValue::get(Target.getSymA(), nullptr, Target.getConstant());
61106c3fb27SDimitry Andric   MCValue B = MCValue::get(Target.getSymB());
61206c3fb27SDimitry Andric   auto FA = MCFixup::create(
61306c3fb27SDimitry Andric       Fixup.getOffset(), nullptr,
61406c3fb27SDimitry Andric       static_cast<MCFixupKind>(FirstLiteralRelocationKind + TA));
61506c3fb27SDimitry Andric   auto FB = MCFixup::create(
61606c3fb27SDimitry Andric       Fixup.getOffset(), nullptr,
61706c3fb27SDimitry Andric       static_cast<MCFixupKind>(FirstLiteralRelocationKind + TB));
618*0fca6ea1SDimitry Andric   auto &Assembler = const_cast<MCAssembler &>(Asm);
619*0fca6ea1SDimitry Andric   Asm.getWriter().recordRelocation(Assembler, &F, FA, A, FixedValueA);
620*0fca6ea1SDimitry Andric   Asm.getWriter().recordRelocation(Assembler, &F, FB, B, FixedValueB);
62106c3fb27SDimitry Andric   FixedValue = FixedValueA - FixedValueB;
62206c3fb27SDimitry Andric   return true;
62306c3fb27SDimitry Andric }
62406c3fb27SDimitry Andric 
6250b57cec5SDimitry Andric void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
6260b57cec5SDimitry Andric                                  const MCValue &Target,
6270b57cec5SDimitry Andric                                  MutableArrayRef<char> Data, uint64_t Value,
6280b57cec5SDimitry Andric                                  bool IsResolved,
6290b57cec5SDimitry Andric                                  const MCSubtargetInfo *STI) const {
6305ffd83dbSDimitry Andric   MCFixupKind Kind = Fixup.getKind();
6315ffd83dbSDimitry Andric   if (Kind >= FirstLiteralRelocationKind)
6325ffd83dbSDimitry Andric     return;
6330b57cec5SDimitry Andric   MCContext &Ctx = Asm.getContext();
6345ffd83dbSDimitry Andric   MCFixupKindInfo Info = getFixupKindInfo(Kind);
6350b57cec5SDimitry Andric   if (!Value)
6360b57cec5SDimitry Andric     return; // Doesn't change encoding.
6370b57cec5SDimitry Andric   // Apply any target-specific value adjustments.
6380b57cec5SDimitry Andric   Value = adjustFixupValue(Fixup, Value, Ctx);
6390b57cec5SDimitry Andric 
6400b57cec5SDimitry Andric   // Shift the value into position.
6410b57cec5SDimitry Andric   Value <<= Info.TargetOffset;
6420b57cec5SDimitry Andric 
6430b57cec5SDimitry Andric   unsigned Offset = Fixup.getOffset();
6440b57cec5SDimitry Andric   unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
6450b57cec5SDimitry Andric 
6460b57cec5SDimitry Andric   assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
6470b57cec5SDimitry Andric 
6480b57cec5SDimitry Andric   // For each byte of the fragment that the fixup touches, mask in the
6490b57cec5SDimitry Andric   // bits from the fixup value.
6500b57cec5SDimitry Andric   for (unsigned i = 0; i != NumBytes; ++i) {
6510b57cec5SDimitry Andric     Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);
6520b57cec5SDimitry Andric   }
6530b57cec5SDimitry Andric }
6540b57cec5SDimitry Andric 
6550b57cec5SDimitry Andric // Linker relaxation may change code size. We have to insert Nops
6560b57cec5SDimitry Andric // for .align directive when linker relaxation enabled. So then Linker
6570b57cec5SDimitry Andric // could satisfy alignment by removing Nops.
6580b57cec5SDimitry Andric // The function return the total Nops Size we need to insert.
6590b57cec5SDimitry Andric bool RISCVAsmBackend::shouldInsertExtraNopBytesForCodeAlign(
6600b57cec5SDimitry Andric     const MCAlignFragment &AF, unsigned &Size) {
6610b57cec5SDimitry Andric   // Calculate Nops Size only when linker relaxation enabled.
6623a9a9c0cSDimitry Andric   const MCSubtargetInfo *STI = AF.getSubtargetInfo();
66306c3fb27SDimitry Andric   if (!STI->hasFeature(RISCV::FeatureRelax))
6640b57cec5SDimitry Andric     return false;
6650b57cec5SDimitry Andric 
66606c3fb27SDimitry Andric   bool UseCompressedNop = STI->hasFeature(RISCV::FeatureStdExtC) ||
66706c3fb27SDimitry Andric                           STI->hasFeature(RISCV::FeatureStdExtZca);
668bdd1243dSDimitry Andric   unsigned MinNopLen = UseCompressedNop ? 2 : 4;
6690b57cec5SDimitry Andric 
6700b57cec5SDimitry Andric   if (AF.getAlignment() <= MinNopLen) {
6710b57cec5SDimitry Andric     return false;
6720b57cec5SDimitry Andric   } else {
67381ad6265SDimitry Andric     Size = AF.getAlignment().value() - MinNopLen;
6740b57cec5SDimitry Andric     return true;
6750b57cec5SDimitry Andric   }
6760b57cec5SDimitry Andric }
6770b57cec5SDimitry Andric 
6780b57cec5SDimitry Andric // We need to insert R_RISCV_ALIGN relocation type to indicate the
6790b57cec5SDimitry Andric // position of Nops and the total bytes of the Nops have been inserted
6800b57cec5SDimitry Andric // when linker relaxation enabled.
6810b57cec5SDimitry Andric // The function insert fixup_riscv_align fixup which eventually will
6820b57cec5SDimitry Andric // transfer to R_RISCV_ALIGN relocation type.
6830b57cec5SDimitry Andric bool RISCVAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm,
6840b57cec5SDimitry Andric                                                     MCAlignFragment &AF) {
6850b57cec5SDimitry Andric   // Insert the fixup only when linker relaxation enabled.
6863a9a9c0cSDimitry Andric   const MCSubtargetInfo *STI = AF.getSubtargetInfo();
68706c3fb27SDimitry Andric   if (!STI->hasFeature(RISCV::FeatureRelax))
6880b57cec5SDimitry Andric     return false;
6890b57cec5SDimitry Andric 
6900b57cec5SDimitry Andric   // Calculate total Nops we need to insert. If there are none to insert
6910b57cec5SDimitry Andric   // then simply return.
6920b57cec5SDimitry Andric   unsigned Count;
6930b57cec5SDimitry Andric   if (!shouldInsertExtraNopBytesForCodeAlign(AF, Count) || (Count == 0))
6940b57cec5SDimitry Andric     return false;
6950b57cec5SDimitry Andric 
6960b57cec5SDimitry Andric   MCContext &Ctx = Asm.getContext();
6970b57cec5SDimitry Andric   const MCExpr *Dummy = MCConstantExpr::create(0, Ctx);
6980b57cec5SDimitry Andric   // Create fixup_riscv_align fixup.
6990b57cec5SDimitry Andric   MCFixup Fixup =
7000b57cec5SDimitry Andric       MCFixup::create(0, Dummy, MCFixupKind(RISCV::fixup_riscv_align), SMLoc());
7010b57cec5SDimitry Andric 
7020b57cec5SDimitry Andric   uint64_t FixedValue = 0;
7030b57cec5SDimitry Andric   MCValue NopBytes = MCValue::get(Count);
7040b57cec5SDimitry Andric 
705*0fca6ea1SDimitry Andric   Asm.getWriter().recordRelocation(Asm, &AF, Fixup, NopBytes, FixedValue);
7060b57cec5SDimitry Andric 
7070b57cec5SDimitry Andric   return true;
7080b57cec5SDimitry Andric }
7090b57cec5SDimitry Andric 
7100b57cec5SDimitry Andric std::unique_ptr<MCObjectTargetWriter>
7110b57cec5SDimitry Andric RISCVAsmBackend::createObjectTargetWriter() const {
7120b57cec5SDimitry Andric   return createRISCVELFObjectWriter(OSABI, Is64Bit);
7130b57cec5SDimitry Andric }
7140b57cec5SDimitry Andric 
7150b57cec5SDimitry Andric MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T,
7160b57cec5SDimitry Andric                                           const MCSubtargetInfo &STI,
7170b57cec5SDimitry Andric                                           const MCRegisterInfo &MRI,
7180b57cec5SDimitry Andric                                           const MCTargetOptions &Options) {
7190b57cec5SDimitry Andric   const Triple &TT = STI.getTargetTriple();
7200b57cec5SDimitry Andric   uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());
7210b57cec5SDimitry Andric   return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options);
7220b57cec5SDimitry Andric }
723