Index: llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp =================================================================== --- llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -205,22 +205,14 @@ } } - static bool requiresFixups(MCContext &C, const MCExpr *Value, + static bool requiresFixups(MCContext &C, MCDataFragment *F, const MCExpr *Val, const MCExpr *&LHS, const MCExpr *&RHS) { - auto IsMetadataOrEHFrameSection = [](const MCSection &S) -> bool { - // Additionally check .apple_names/.apple_types. They are fixed-size and - // do not need fixups. llvm-dwarfdump --apple-names does not process - // R_RISCV_{ADD,SUB}32 in them. - return S.getKind().isMetadata() || S.getName() == ".eh_frame" || - S.getName() == ".apple_names" || S.getName() == ".apple_types"; - }; - - const auto *MBE = dyn_cast<MCBinaryExpr>(Value); + const auto *MBE = dyn_cast<MCBinaryExpr>(Val); if (MBE == nullptr) return false; MCValue E; - if (!Value->evaluateAsRelocatable(E, nullptr, nullptr)) + if (!Val->evaluateAsRelocatable(E, nullptr, nullptr)) return false; if (E.getSymA() == nullptr || E.getSymB() == nullptr) return false; @@ -233,15 +225,25 @@ MCConstantExpr::create(E.getConstant(), C), C); RHS = E.getSymB(); - // TODO: when available, R_RISCV_n_PCREL should be preferred. + // If either symbol is in a text section, we need to delay the relocation + // evaluation as relaxation may alter the size of the symbol. + // + // Unfortunately, we cannot identify if the symbol was built with relaxation + // as we do not track the state per symbol or section. However, BFD will + // always emit the relocation and so we follow suit which avoids the need to + // track that information. - // Avoid pairwise relocations for symbolic difference in debug and .eh_frame if (A.isInSection()) - return !IsMetadataOrEHFrameSection(A.getSection()); + if (A.getSection().getKind().isText()) + return true; + if (B.isInSection()) - return !IsMetadataOrEHFrameSection(B.getSection()); - // as well as for absolute symbols. - return !A.getName().empty() || !B.getName().empty(); + if (B.getSection().getKind().isText()) + return true; + + // Support cross-section difference ... + return A.isInSection() && B.isInSection() && + A.getSection().getName() != B.getSection().getName(); } void reset() override { @@ -257,12 +259,13 @@ void emitValueImpl(const MCExpr *Value, unsigned Size, SMLoc Loc) override { const MCExpr *A, *B; - if (!requiresFixups(getContext(), Value, A, B)) + MCDataFragment *DF = getOrCreateDataFragment(); + + if (!requiresFixups(getContext(), DF, Value, A, B)) return MCELFStreamer::emitValueImpl(Value, Size, Loc); MCStreamer::emitValueImpl(Value, Size, Loc); - MCDataFragment *DF = getOrCreateDataFragment(); flushPendingLabels(DF, DF->getContents().size()); MCDwarfLineEntry::make(this, getCurrentSectionOnly());