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