Path: blob/main/contrib/llvm-project/llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
35294 views
//===-- RISCVAsmBackend.cpp - RISC-V Assembler Backend --------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "RISCVAsmBackend.h"9#include "RISCVMCExpr.h"10#include "llvm/ADT/APInt.h"11#include "llvm/MC/MCAsmInfo.h"12#include "llvm/MC/MCAssembler.h"13#include "llvm/MC/MCContext.h"14#include "llvm/MC/MCDirectives.h"15#include "llvm/MC/MCELFObjectWriter.h"16#include "llvm/MC/MCExpr.h"17#include "llvm/MC/MCObjectWriter.h"18#include "llvm/MC/MCSymbol.h"19#include "llvm/MC/MCValue.h"20#include "llvm/Support/CommandLine.h"21#include "llvm/Support/Endian.h"22#include "llvm/Support/EndianStream.h"23#include "llvm/Support/ErrorHandling.h"24#include "llvm/Support/LEB128.h"25#include "llvm/Support/raw_ostream.h"2627using namespace llvm;2829static cl::opt<bool> RelaxBranches("riscv-asm-relax-branches", cl::init(true),30cl::Hidden);31// Temporary workaround for old linkers that do not support ULEB128 relocations,32// which are abused by DWARF v5 DW_LLE_offset_pair/DW_RLE_offset_pair33// implemented in Clang/LLVM.34static cl::opt<bool> ULEB128Reloc(35"riscv-uleb128-reloc", cl::init(true), cl::Hidden,36cl::desc("Emit R_RISCV_SET_ULEB128/E_RISCV_SUB_ULEB128 if appropriate"));3738std::optional<MCFixupKind> RISCVAsmBackend::getFixupKind(StringRef Name) const {39if (STI.getTargetTriple().isOSBinFormatELF()) {40unsigned Type;41Type = llvm::StringSwitch<unsigned>(Name)42#define ELF_RELOC(X, Y) .Case(#X, Y)43#include "llvm/BinaryFormat/ELFRelocs/RISCV.def"44#undef ELF_RELOC45.Case("BFD_RELOC_NONE", ELF::R_RISCV_NONE)46.Case("BFD_RELOC_32", ELF::R_RISCV_32)47.Case("BFD_RELOC_64", ELF::R_RISCV_64)48.Default(-1u);49if (Type != -1u)50return static_cast<MCFixupKind>(FirstLiteralRelocationKind + Type);51}52return std::nullopt;53}5455const MCFixupKindInfo &56RISCVAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {57const static MCFixupKindInfo Infos[] = {58// This table *must* be in the order that the fixup_* kinds are defined in59// RISCVFixupKinds.h.60//61// name offset bits flags62{"fixup_riscv_hi20", 12, 20, 0},63{"fixup_riscv_lo12_i", 20, 12, 0},64{"fixup_riscv_12_i", 20, 12, 0},65{"fixup_riscv_lo12_s", 0, 32, 0},66{"fixup_riscv_pcrel_hi20", 12, 20,67MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},68{"fixup_riscv_pcrel_lo12_i", 20, 12,69MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},70{"fixup_riscv_pcrel_lo12_s", 0, 32,71MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},72{"fixup_riscv_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel},73{"fixup_riscv_tprel_hi20", 12, 20, 0},74{"fixup_riscv_tprel_lo12_i", 20, 12, 0},75{"fixup_riscv_tprel_lo12_s", 0, 32, 0},76{"fixup_riscv_tprel_add", 0, 0, 0},77{"fixup_riscv_tls_got_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel},78{"fixup_riscv_tls_gd_hi20", 12, 20, MCFixupKindInfo::FKF_IsPCRel},79{"fixup_riscv_jal", 12, 20, MCFixupKindInfo::FKF_IsPCRel},80{"fixup_riscv_branch", 0, 32, MCFixupKindInfo::FKF_IsPCRel},81{"fixup_riscv_rvc_jump", 2, 11, MCFixupKindInfo::FKF_IsPCRel},82{"fixup_riscv_rvc_branch", 0, 16, MCFixupKindInfo::FKF_IsPCRel},83{"fixup_riscv_call", 0, 64, MCFixupKindInfo::FKF_IsPCRel},84{"fixup_riscv_call_plt", 0, 64, MCFixupKindInfo::FKF_IsPCRel},85{"fixup_riscv_relax", 0, 0, 0},86{"fixup_riscv_align", 0, 0, 0},8788{"fixup_riscv_tlsdesc_hi20", 12, 20,89MCFixupKindInfo::FKF_IsPCRel | MCFixupKindInfo::FKF_IsTarget},90{"fixup_riscv_tlsdesc_load_lo12", 20, 12, 0},91{"fixup_riscv_tlsdesc_add_lo12", 20, 12, 0},92{"fixup_riscv_tlsdesc_call", 0, 0, 0},93};94static_assert((std::size(Infos)) == RISCV::NumTargetFixupKinds,95"Not all fixup kinds added to Infos array");9697// Fixup kinds from .reloc directive are like R_RISCV_NONE. They98// do not require any extra processing.99if (Kind >= FirstLiteralRelocationKind)100return MCAsmBackend::getFixupKindInfo(FK_NONE);101102if (Kind < FirstTargetFixupKind)103return MCAsmBackend::getFixupKindInfo(Kind);104105assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&106"Invalid kind!");107return Infos[Kind - FirstTargetFixupKind];108}109110// If linker relaxation is enabled, or the relax option had previously been111// enabled, always emit relocations even if the fixup can be resolved. This is112// necessary for correctness as offsets may change during relaxation.113bool RISCVAsmBackend::shouldForceRelocation(const MCAssembler &Asm,114const MCFixup &Fixup,115const MCValue &Target,116const MCSubtargetInfo *STI) {117if (Fixup.getKind() >= FirstLiteralRelocationKind)118return true;119switch (Fixup.getTargetKind()) {120default:121break;122case FK_Data_1:123case FK_Data_2:124case FK_Data_4:125case FK_Data_8:126case FK_Data_leb128:127if (Target.isAbsolute())128return false;129break;130case RISCV::fixup_riscv_got_hi20:131case RISCV::fixup_riscv_tls_got_hi20:132case RISCV::fixup_riscv_tls_gd_hi20:133case RISCV::fixup_riscv_tlsdesc_hi20:134return true;135}136137return STI->hasFeature(RISCV::FeatureRelax) || ForceRelocs;138}139140bool RISCVAsmBackend::fixupNeedsRelaxationAdvanced(141const MCAssembler &Asm, const MCFixup &Fixup, bool Resolved, uint64_t Value,142const MCRelaxableFragment *DF, const bool WasForced) const {143if (!RelaxBranches)144return false;145146int64_t Offset = int64_t(Value);147unsigned Kind = Fixup.getTargetKind();148149// Return true if the symbol is actually unresolved.150// Resolved could be always false when shouldForceRelocation return true.151// We use !WasForced to indicate that the symbol is unresolved and not forced152// by shouldForceRelocation.153if (!Resolved && !WasForced)154return true;155156switch (Kind) {157default:158return false;159case RISCV::fixup_riscv_rvc_branch:160// For compressed branch instructions the immediate must be161// in the range [-256, 254].162return Offset > 254 || Offset < -256;163case RISCV::fixup_riscv_rvc_jump:164// For compressed jump instructions the immediate must be165// in the range [-2048, 2046].166return Offset > 2046 || Offset < -2048;167case RISCV::fixup_riscv_branch:168// For conditional branch instructions the immediate must be169// in the range [-4096, 4095].170return !isInt<13>(Offset);171}172}173174void RISCVAsmBackend::relaxInstruction(MCInst &Inst,175const MCSubtargetInfo &STI) const {176MCInst Res;177switch (Inst.getOpcode()) {178default:179llvm_unreachable("Opcode not expected!");180case RISCV::C_BEQZ:181case RISCV::C_BNEZ:182case RISCV::C_J:183case RISCV::C_JAL: {184[[maybe_unused]] bool Success = RISCVRVC::uncompress(Res, Inst, STI);185assert(Success && "Can't uncompress instruction");186break;187}188case RISCV::BEQ:189case RISCV::BNE:190case RISCV::BLT:191case RISCV::BGE:192case RISCV::BLTU:193case RISCV::BGEU:194Res.setOpcode(getRelaxedOpcode(Inst.getOpcode()));195Res.addOperand(Inst.getOperand(0));196Res.addOperand(Inst.getOperand(1));197Res.addOperand(Inst.getOperand(2));198break;199}200Inst = std::move(Res);201}202203bool RISCVAsmBackend::relaxDwarfLineAddr(const MCAssembler &Asm,204MCDwarfLineAddrFragment &DF,205bool &WasRelaxed) const {206MCContext &C = Asm.getContext();207208int64_t LineDelta = DF.getLineDelta();209const MCExpr &AddrDelta = DF.getAddrDelta();210SmallVectorImpl<char> &Data = DF.getContents();211SmallVectorImpl<MCFixup> &Fixups = DF.getFixups();212size_t OldSize = Data.size();213214int64_t Value;215[[maybe_unused]] bool IsAbsolute =216AddrDelta.evaluateKnownAbsolute(Value, Asm);217assert(IsAbsolute && "CFA with invalid expression");218219Data.clear();220Fixups.clear();221raw_svector_ostream OS(Data);222223// INT64_MAX is a signal that this is actually a DW_LNE_end_sequence.224if (LineDelta != INT64_MAX) {225OS << uint8_t(dwarf::DW_LNS_advance_line);226encodeSLEB128(LineDelta, OS);227}228229unsigned Offset;230std::pair<MCFixupKind, MCFixupKind> Fixup;231232// According to the DWARF specification, the `DW_LNS_fixed_advance_pc` opcode233// takes a single unsigned half (unencoded) operand. The maximum encodable234// value is therefore 65535. Set a conservative upper bound for relaxation.235if (Value > 60000) {236unsigned PtrSize = C.getAsmInfo()->getCodePointerSize();237238OS << uint8_t(dwarf::DW_LNS_extended_op);239encodeULEB128(PtrSize + 1, OS);240241OS << uint8_t(dwarf::DW_LNE_set_address);242Offset = OS.tell();243assert((PtrSize == 4 || PtrSize == 8) && "Unexpected pointer size");244Fixup = RISCV::getRelocPairForSize(PtrSize);245OS.write_zeros(PtrSize);246} else {247OS << uint8_t(dwarf::DW_LNS_fixed_advance_pc);248Offset = OS.tell();249Fixup = RISCV::getRelocPairForSize(2);250support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);251}252253const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);254Fixups.push_back(MCFixup::create(Offset, MBE.getLHS(), std::get<0>(Fixup)));255Fixups.push_back(MCFixup::create(Offset, MBE.getRHS(), std::get<1>(Fixup)));256257if (LineDelta == INT64_MAX) {258OS << uint8_t(dwarf::DW_LNS_extended_op);259OS << uint8_t(1);260OS << uint8_t(dwarf::DW_LNE_end_sequence);261} else {262OS << uint8_t(dwarf::DW_LNS_copy);263}264265WasRelaxed = OldSize != Data.size();266return true;267}268269bool RISCVAsmBackend::relaxDwarfCFA(const MCAssembler &Asm,270MCDwarfCallFrameFragment &DF,271bool &WasRelaxed) const {272const MCExpr &AddrDelta = DF.getAddrDelta();273SmallVectorImpl<char> &Data = DF.getContents();274SmallVectorImpl<MCFixup> &Fixups = DF.getFixups();275size_t OldSize = Data.size();276277int64_t Value;278if (AddrDelta.evaluateAsAbsolute(Value, Asm))279return false;280[[maybe_unused]] bool IsAbsolute =281AddrDelta.evaluateKnownAbsolute(Value, Asm);282assert(IsAbsolute && "CFA with invalid expression");283284Data.clear();285Fixups.clear();286raw_svector_ostream OS(Data);287288assert(Asm.getContext().getAsmInfo()->getMinInstAlignment() == 1 &&289"expected 1-byte alignment");290if (Value == 0) {291WasRelaxed = OldSize != Data.size();292return true;293}294295auto AddFixups = [&Fixups, &AddrDelta](unsigned Offset,296std::pair<unsigned, unsigned> Fixup) {297const MCBinaryExpr &MBE = cast<MCBinaryExpr>(AddrDelta);298Fixups.push_back(299MCFixup::create(Offset, MBE.getLHS(),300static_cast<MCFixupKind>(FirstLiteralRelocationKind +301std::get<0>(Fixup))));302Fixups.push_back(303MCFixup::create(Offset, MBE.getRHS(),304static_cast<MCFixupKind>(FirstLiteralRelocationKind +305std::get<1>(Fixup))));306};307308if (isUIntN(6, Value)) {309OS << uint8_t(dwarf::DW_CFA_advance_loc);310AddFixups(0, {ELF::R_RISCV_SET6, ELF::R_RISCV_SUB6});311} else if (isUInt<8>(Value)) {312OS << uint8_t(dwarf::DW_CFA_advance_loc1);313support::endian::write<uint8_t>(OS, 0, llvm::endianness::little);314AddFixups(1, {ELF::R_RISCV_SET8, ELF::R_RISCV_SUB8});315} else if (isUInt<16>(Value)) {316OS << uint8_t(dwarf::DW_CFA_advance_loc2);317support::endian::write<uint16_t>(OS, 0, llvm::endianness::little);318AddFixups(1, {ELF::R_RISCV_SET16, ELF::R_RISCV_SUB16});319} else if (isUInt<32>(Value)) {320OS << uint8_t(dwarf::DW_CFA_advance_loc4);321support::endian::write<uint32_t>(OS, 0, llvm::endianness::little);322AddFixups(1, {ELF::R_RISCV_SET32, ELF::R_RISCV_SUB32});323} else {324llvm_unreachable("unsupported CFA encoding");325}326327WasRelaxed = OldSize != Data.size();328return true;329}330331std::pair<bool, bool> RISCVAsmBackend::relaxLEB128(const MCAssembler &Asm,332MCLEBFragment &LF,333int64_t &Value) const {334if (LF.isSigned())335return std::make_pair(false, false);336const MCExpr &Expr = LF.getValue();337if (ULEB128Reloc) {338LF.getFixups().push_back(339MCFixup::create(0, &Expr, FK_Data_leb128, Expr.getLoc()));340}341return std::make_pair(Expr.evaluateKnownAbsolute(Value, Asm), false);342}343344// Given a compressed control flow instruction this function returns345// the expanded instruction.346unsigned RISCVAsmBackend::getRelaxedOpcode(unsigned Op) const {347switch (Op) {348default:349return Op;350case RISCV::C_BEQZ:351return RISCV::BEQ;352case RISCV::C_BNEZ:353return RISCV::BNE;354case RISCV::C_J:355case RISCV::C_JAL: // fall through.356return RISCV::JAL;357case RISCV::BEQ:358return RISCV::PseudoLongBEQ;359case RISCV::BNE:360return RISCV::PseudoLongBNE;361case RISCV::BLT:362return RISCV::PseudoLongBLT;363case RISCV::BGE:364return RISCV::PseudoLongBGE;365case RISCV::BLTU:366return RISCV::PseudoLongBLTU;367case RISCV::BGEU:368return RISCV::PseudoLongBGEU;369}370}371372bool RISCVAsmBackend::mayNeedRelaxation(const MCInst &Inst,373const MCSubtargetInfo &STI) const {374return getRelaxedOpcode(Inst.getOpcode()) != Inst.getOpcode();375}376377bool RISCVAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,378const MCSubtargetInfo *STI) const {379// We mostly follow binutils' convention here: align to even boundary with a380// 0-fill padding. We emit up to 1 2-byte nop, though we use c.nop if RVC is381// enabled or 0-fill otherwise. The remainder is now padded with 4-byte nops.382383// Instructions always are at even addresses. We must be in a data area or384// be unaligned due to some other reason.385if (Count % 2) {386OS.write("\0", 1);387Count -= 1;388}389390bool UseCompressedNop = STI->hasFeature(RISCV::FeatureStdExtC) ||391STI->hasFeature(RISCV::FeatureStdExtZca);392// The canonical nop on RVC is c.nop.393if (Count % 4 == 2) {394OS.write(UseCompressedNop ? "\x01\0" : "\0\0", 2);395Count -= 2;396}397398// The canonical nop on RISC-V is addi x0, x0, 0.399for (; Count >= 4; Count -= 4)400OS.write("\x13\0\0\0", 4);401402return true;403}404405static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,406MCContext &Ctx) {407switch (Fixup.getTargetKind()) {408default:409llvm_unreachable("Unknown fixup kind!");410case RISCV::fixup_riscv_got_hi20:411case RISCV::fixup_riscv_tls_got_hi20:412case RISCV::fixup_riscv_tls_gd_hi20:413case RISCV::fixup_riscv_tlsdesc_hi20:414llvm_unreachable("Relocation should be unconditionally forced\n");415case FK_Data_1:416case FK_Data_2:417case FK_Data_4:418case FK_Data_8:419case FK_Data_leb128:420return Value;421case RISCV::fixup_riscv_lo12_i:422case RISCV::fixup_riscv_pcrel_lo12_i:423case RISCV::fixup_riscv_tprel_lo12_i:424case RISCV::fixup_riscv_tlsdesc_load_lo12:425return Value & 0xfff;426case RISCV::fixup_riscv_12_i:427if (!isInt<12>(Value)) {428Ctx.reportError(Fixup.getLoc(),429"operand must be a constant 12-bit integer");430}431return Value & 0xfff;432case RISCV::fixup_riscv_lo12_s:433case RISCV::fixup_riscv_pcrel_lo12_s:434case RISCV::fixup_riscv_tprel_lo12_s:435return (((Value >> 5) & 0x7f) << 25) | ((Value & 0x1f) << 7);436case RISCV::fixup_riscv_hi20:437case RISCV::fixup_riscv_pcrel_hi20:438case RISCV::fixup_riscv_tprel_hi20:439// Add 1 if bit 11 is 1, to compensate for low 12 bits being negative.440return ((Value + 0x800) >> 12) & 0xfffff;441case RISCV::fixup_riscv_jal: {442if (!isInt<21>(Value))443Ctx.reportError(Fixup.getLoc(), "fixup value out of range");444if (Value & 0x1)445Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");446// Need to produce imm[19|10:1|11|19:12] from the 21-bit Value.447unsigned Sbit = (Value >> 20) & 0x1;448unsigned Hi8 = (Value >> 12) & 0xff;449unsigned Mid1 = (Value >> 11) & 0x1;450unsigned Lo10 = (Value >> 1) & 0x3ff;451// Inst{31} = Sbit;452// Inst{30-21} = Lo10;453// Inst{20} = Mid1;454// Inst{19-12} = Hi8;455Value = (Sbit << 19) | (Lo10 << 9) | (Mid1 << 8) | Hi8;456return Value;457}458case RISCV::fixup_riscv_branch: {459if (!isInt<13>(Value))460Ctx.reportError(Fixup.getLoc(), "fixup value out of range");461if (Value & 0x1)462Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned");463// Need to extract imm[12], imm[10:5], imm[4:1], imm[11] from the 13-bit464// Value.465unsigned Sbit = (Value >> 12) & 0x1;466unsigned Hi1 = (Value >> 11) & 0x1;467unsigned Mid6 = (Value >> 5) & 0x3f;468unsigned Lo4 = (Value >> 1) & 0xf;469// Inst{31} = Sbit;470// Inst{30-25} = Mid6;471// Inst{11-8} = Lo4;472// Inst{7} = Hi1;473Value = (Sbit << 31) | (Mid6 << 25) | (Lo4 << 8) | (Hi1 << 7);474return Value;475}476case RISCV::fixup_riscv_call:477case RISCV::fixup_riscv_call_plt: {478// Jalr will add UpperImm with the sign-extended 12-bit LowerImm,479// we need to add 0x800ULL before extract upper bits to reflect the480// effect of the sign extension.481uint64_t UpperImm = (Value + 0x800ULL) & 0xfffff000ULL;482uint64_t LowerImm = Value & 0xfffULL;483return UpperImm | ((LowerImm << 20) << 32);484}485case RISCV::fixup_riscv_rvc_jump: {486if (!isInt<12>(Value))487Ctx.reportError(Fixup.getLoc(), "fixup value out of range");488// Need to produce offset[11|4|9:8|10|6|7|3:1|5] from the 11-bit Value.489unsigned Bit11 = (Value >> 11) & 0x1;490unsigned Bit4 = (Value >> 4) & 0x1;491unsigned Bit9_8 = (Value >> 8) & 0x3;492unsigned Bit10 = (Value >> 10) & 0x1;493unsigned Bit6 = (Value >> 6) & 0x1;494unsigned Bit7 = (Value >> 7) & 0x1;495unsigned Bit3_1 = (Value >> 1) & 0x7;496unsigned Bit5 = (Value >> 5) & 0x1;497Value = (Bit11 << 10) | (Bit4 << 9) | (Bit9_8 << 7) | (Bit10 << 6) |498(Bit6 << 5) | (Bit7 << 4) | (Bit3_1 << 1) | Bit5;499return Value;500}501case RISCV::fixup_riscv_rvc_branch: {502if (!isInt<9>(Value))503Ctx.reportError(Fixup.getLoc(), "fixup value out of range");504// Need to produce offset[8|4:3], [reg 3 bit], offset[7:6|2:1|5]505unsigned Bit8 = (Value >> 8) & 0x1;506unsigned Bit7_6 = (Value >> 6) & 0x3;507unsigned Bit5 = (Value >> 5) & 0x1;508unsigned Bit4_3 = (Value >> 3) & 0x3;509unsigned Bit2_1 = (Value >> 1) & 0x3;510Value = (Bit8 << 12) | (Bit4_3 << 10) | (Bit7_6 << 5) | (Bit2_1 << 3) |511(Bit5 << 2);512return Value;513}514515}516}517518bool RISCVAsmBackend::evaluateTargetFixup(const MCAssembler &Asm,519const MCFixup &Fixup,520const MCFragment *DF,521const MCValue &Target,522const MCSubtargetInfo *STI,523uint64_t &Value, bool &WasForced) {524const MCFixup *AUIPCFixup;525const MCFragment *AUIPCDF;526MCValue AUIPCTarget;527switch (Fixup.getTargetKind()) {528default:529llvm_unreachable("Unexpected fixup kind!");530case RISCV::fixup_riscv_tlsdesc_hi20:531case RISCV::fixup_riscv_pcrel_hi20:532AUIPCFixup = &Fixup;533AUIPCDF = DF;534AUIPCTarget = Target;535break;536case RISCV::fixup_riscv_pcrel_lo12_i:537case RISCV::fixup_riscv_pcrel_lo12_s: {538AUIPCFixup = cast<RISCVMCExpr>(Fixup.getValue())->getPCRelHiFixup(&AUIPCDF);539if (!AUIPCFixup) {540Asm.getContext().reportError(Fixup.getLoc(),541"could not find corresponding %pcrel_hi");542return true;543}544545// MCAssembler::evaluateFixup will emit an error for this case when it sees546// the %pcrel_hi, so don't duplicate it when also seeing the %pcrel_lo.547const MCExpr *AUIPCExpr = AUIPCFixup->getValue();548if (!AUIPCExpr->evaluateAsRelocatable(AUIPCTarget, &Asm, AUIPCFixup))549return true;550break;551}552}553554if (!AUIPCTarget.getSymA() || AUIPCTarget.getSymB())555return false;556557const MCSymbolRefExpr *A = AUIPCTarget.getSymA();558const MCSymbol &SA = A->getSymbol();559if (A->getKind() != MCSymbolRefExpr::VK_None || SA.isUndefined())560return false;561562bool IsResolved = Asm.getWriter().isSymbolRefDifferenceFullyResolvedImpl(563Asm, SA, *AUIPCDF, false, true);564if (!IsResolved)565return false;566567Value = Asm.getSymbolOffset(SA) + AUIPCTarget.getConstant();568Value -= Asm.getFragmentOffset(*AUIPCDF) + AUIPCFixup->getOffset();569570if (shouldForceRelocation(Asm, *AUIPCFixup, AUIPCTarget, STI)) {571WasForced = true;572return false;573}574575return true;576}577578bool RISCVAsmBackend::handleAddSubRelocations(const MCAssembler &Asm,579const MCFragment &F,580const MCFixup &Fixup,581const MCValue &Target,582uint64_t &FixedValue) const {583uint64_t FixedValueA, FixedValueB;584unsigned TA = 0, TB = 0;585switch (Fixup.getKind()) {586case llvm::FK_Data_1:587TA = ELF::R_RISCV_ADD8;588TB = ELF::R_RISCV_SUB8;589break;590case llvm::FK_Data_2:591TA = ELF::R_RISCV_ADD16;592TB = ELF::R_RISCV_SUB16;593break;594case llvm::FK_Data_4:595TA = ELF::R_RISCV_ADD32;596TB = ELF::R_RISCV_SUB32;597break;598case llvm::FK_Data_8:599TA = ELF::R_RISCV_ADD64;600TB = ELF::R_RISCV_SUB64;601break;602case llvm::FK_Data_leb128:603TA = ELF::R_RISCV_SET_ULEB128;604TB = ELF::R_RISCV_SUB_ULEB128;605break;606default:607llvm_unreachable("unsupported fixup size");608}609MCValue A = MCValue::get(Target.getSymA(), nullptr, Target.getConstant());610MCValue B = MCValue::get(Target.getSymB());611auto FA = MCFixup::create(612Fixup.getOffset(), nullptr,613static_cast<MCFixupKind>(FirstLiteralRelocationKind + TA));614auto FB = MCFixup::create(615Fixup.getOffset(), nullptr,616static_cast<MCFixupKind>(FirstLiteralRelocationKind + TB));617auto &Assembler = const_cast<MCAssembler &>(Asm);618Asm.getWriter().recordRelocation(Assembler, &F, FA, A, FixedValueA);619Asm.getWriter().recordRelocation(Assembler, &F, FB, B, FixedValueB);620FixedValue = FixedValueA - FixedValueB;621return true;622}623624void RISCVAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,625const MCValue &Target,626MutableArrayRef<char> Data, uint64_t Value,627bool IsResolved,628const MCSubtargetInfo *STI) const {629MCFixupKind Kind = Fixup.getKind();630if (Kind >= FirstLiteralRelocationKind)631return;632MCContext &Ctx = Asm.getContext();633MCFixupKindInfo Info = getFixupKindInfo(Kind);634if (!Value)635return; // Doesn't change encoding.636// Apply any target-specific value adjustments.637Value = adjustFixupValue(Fixup, Value, Ctx);638639// Shift the value into position.640Value <<= Info.TargetOffset;641642unsigned Offset = Fixup.getOffset();643unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;644645assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");646647// For each byte of the fragment that the fixup touches, mask in the648// bits from the fixup value.649for (unsigned i = 0; i != NumBytes; ++i) {650Data[Offset + i] |= uint8_t((Value >> (i * 8)) & 0xff);651}652}653654// Linker relaxation may change code size. We have to insert Nops655// for .align directive when linker relaxation enabled. So then Linker656// could satisfy alignment by removing Nops.657// The function return the total Nops Size we need to insert.658bool RISCVAsmBackend::shouldInsertExtraNopBytesForCodeAlign(659const MCAlignFragment &AF, unsigned &Size) {660// Calculate Nops Size only when linker relaxation enabled.661const MCSubtargetInfo *STI = AF.getSubtargetInfo();662if (!STI->hasFeature(RISCV::FeatureRelax))663return false;664665bool UseCompressedNop = STI->hasFeature(RISCV::FeatureStdExtC) ||666STI->hasFeature(RISCV::FeatureStdExtZca);667unsigned MinNopLen = UseCompressedNop ? 2 : 4;668669if (AF.getAlignment() <= MinNopLen) {670return false;671} else {672Size = AF.getAlignment().value() - MinNopLen;673return true;674}675}676677// We need to insert R_RISCV_ALIGN relocation type to indicate the678// position of Nops and the total bytes of the Nops have been inserted679// when linker relaxation enabled.680// The function insert fixup_riscv_align fixup which eventually will681// transfer to R_RISCV_ALIGN relocation type.682bool RISCVAsmBackend::shouldInsertFixupForCodeAlign(MCAssembler &Asm,683MCAlignFragment &AF) {684// Insert the fixup only when linker relaxation enabled.685const MCSubtargetInfo *STI = AF.getSubtargetInfo();686if (!STI->hasFeature(RISCV::FeatureRelax))687return false;688689// Calculate total Nops we need to insert. If there are none to insert690// then simply return.691unsigned Count;692if (!shouldInsertExtraNopBytesForCodeAlign(AF, Count) || (Count == 0))693return false;694695MCContext &Ctx = Asm.getContext();696const MCExpr *Dummy = MCConstantExpr::create(0, Ctx);697// Create fixup_riscv_align fixup.698MCFixup Fixup =699MCFixup::create(0, Dummy, MCFixupKind(RISCV::fixup_riscv_align), SMLoc());700701uint64_t FixedValue = 0;702MCValue NopBytes = MCValue::get(Count);703704Asm.getWriter().recordRelocation(Asm, &AF, Fixup, NopBytes, FixedValue);705706return true;707}708709std::unique_ptr<MCObjectTargetWriter>710RISCVAsmBackend::createObjectTargetWriter() const {711return createRISCVELFObjectWriter(OSABI, Is64Bit);712}713714MCAsmBackend *llvm::createRISCVAsmBackend(const Target &T,715const MCSubtargetInfo &STI,716const MCRegisterInfo &MRI,717const MCTargetOptions &Options) {718const Triple &TT = STI.getTargetTriple();719uint8_t OSABI = MCELFObjectTargetWriter::getOSABI(TT.getOS());720return new RISCVAsmBackend(STI, OSABI, TT.isArch64Bit(), Options);721}722723724