Skip to content

Commit

Permalink
RISCV: adjust relocation emission
Browse files Browse the repository at this point in the history
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
  • Loading branch information
compnerd committed Sep 30, 2022
1 parent fb30324 commit 519a731
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 21 deletions.
32 changes: 15 additions & 17 deletions llvm/lib/Target/RISCV/MCTargetDesc/RISCVELFStreamer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<MCBinaryExpr>(Value);
if (MBE == nullptr)
return false;
Expand All @@ -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 {
Expand Down
14 changes: 10 additions & 4 deletions llvm/test/MC/RISCV/riscv64-64b-pcrel.s
Original file line number Diff line number Diff line change
@@ -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 {
Expand All @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 519a731

Please sign in to comment.