From 519a73111b40f0df1926879ab71e662b718bf109 Mon Sep 17 00:00:00 2001 From: Saleem Abdulrasool Date: Fri, 19 Aug 2022 21:30:36 +0000 Subject: [PATCH] RISCV: adjust relocation emission Simplify and make the pair-wise relocation more precise. If either of the symbol references are textual, the relocation must be delayed. If the difference is across sections, delay it as well which partially matches the behaviour of gas. We unfortunately do not handle the case where the difference references a symbol that is not yet defined. In such a case, we simply fail to resolve the difference, which should hopefully not be too onerous (particularly since no other target supports cross-section references and it is not clear if this was intentional on the part of RISCV). Differential Revision: https://reviews.llvm.org/D132262 Reviewed By: @MaskRay --- .../RISCV/MCTargetDesc/RISCVELFStreamer.cpp | 32 +++++++++---------- llvm/test/MC/RISCV/riscv64-64b-pcrel.s | 14 +++++--- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp index fef8cb2798a39..c63488bb4d347 100644 --- a/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp +++ b/llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp @@ -209,14 +209,6 @@ class RISCVELFStreamer : public MCELFStreamer { static bool requiresFixups(MCContext &C, const MCExpr *Value, 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(Value); if (MBE == nullptr) return false; @@ -235,15 +227,21 @@ class RISCVELFStreamer : public MCELFStreamer { MCConstantExpr::create(E.getConstant(), C), C); RHS = E.getSymB(); - // TODO: when available, R_RISCV_n_PCREL should be preferred. - - // Avoid pairwise relocations for symbolic difference in debug and .eh_frame - if (A.isInSection()) - return !IsMetadataOrEHFrameSection(A.getSection()); - if (B.isInSection()) - return !IsMetadataOrEHFrameSection(B.getSection()); - // as well as for absolute symbols. - return !A.getName().empty() || !B.getName().empty(); + // 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. + if (A.isInSection() && A.getSection().getKind().isText()) + return true; + if (B.isInSection() && B.getSection().getKind().isText()) + return true; + + // Support cross-section symbolic differences ... + return A.isInSection() && B.isInSection() && + A.getSection().getName() != B.getSection().getName(); } void reset() override { diff --git a/llvm/test/MC/RISCV/riscv64-64b-pcrel.s b/llvm/test/MC/RISCV/riscv64-64b-pcrel.s index 593820b8778c3..5f5870ee73319 100644 --- a/llvm/test/MC/RISCV/riscv64-64b-pcrel.s +++ b/llvm/test/MC/RISCV/riscv64-64b-pcrel.s @@ -1,5 +1,7 @@ # RUN: llvm-mc -triple riscv64-unknown-linux-gnu -filetype obj -o - %s \ # RUN: | llvm-readobj -r - | FileCheck %s +# RUN: not llvm-mc -triple riscv64-unknown-linux-gnu -filetype obj --defsym ERR=1 -o /dev/null %s 2>&1 \ +# RUN: | FileCheck %s --check-prefix CHECK-ERROR # CHECK: Relocations [ # CHECK: .relasx { @@ -10,10 +12,6 @@ # CHECK-NEXT: 0x0 R_RISCV_ADD64 x 0x0 # CHECK-NEXT: 0x0 R_RISCV_SUB64 y 0x0 # CHECK: } -# CHECK: .relasz { -# CHECK-NEXT: 0x0 R_RISCV_ADD64 z 0x0 -# CHECK-NEXT: 0x0 R_RISCV_SUB64 a 0x0 -# CHECK: } # CHECK: .relasa { # CHECK-NEXT: 0x0 R_RISCV_ADD64 a 0x0 # CHECK-NEXT: 0x0 R_RISCV_SUB64 z 0x0 @@ -30,8 +28,16 @@ y: .section sz z: +.ifdef ERR .quad z-a +# CHECK-ERROR: Cannot represent a difference across sections +# CHECK-ERROR: .quad z-a +# CHECK-ERROR: ^ +.else + .quad 0 +.endif + .section sa a: .quad a-z