Commit Graph

2 Commits

Author SHA1 Message Date
James Clarke 3f5976c97d [RISCV] Fix evaluating %pcrel_lo against global and weak symbols
Summary:
Previously, we would erroneously turn %pcrel_lo(label), where label has
a %pcrel_hi against a weak symbol, into %pcrel_lo(label + offset), as
evaluatePCRelLo would believe the target independent logic was going to
fold it. Moreover, even if that were fixed, shouldForceRelocation lacks
an MCAsmLayout and thus cannot evaluate the %pcrel_hi fixup to a value
and check the symbol, so we would then erroneously constant-fold the
%pcrel_lo whilst leaving the %pcrel_hi intact. After D72197, this same
sequence also occurs for symbols with global binding, which is triggered
in real-world code.

Instead, as discussed in D71978, we introduce a new FKF_IsTarget flag to
avoid these kinds of issues. All the resolution logic happens in one
place, with no coordination required between RISCAsmBackend and
RISCVMCExpr to ensure they implement the same logic twice. Although the
implementation of %pcrel_hi can be left as target independent, we make
it target dependent to ensure that they are handled identically to
%pcrel_lo, otherwise we risk one of them being constant folded but the
other being preserved. This also allows us to properly support fixup
pairs where the instructions are in different fragments.

Reviewers: asb, lenary, efriedma

Reviewed By: efriedma

Subscribers: arichardson, hiraditya, rbar, johnrusso, simoncook, sabuasal, niosHD, kito-cheng, shiva0217, MaskRay, zzheng, edward-jones, rogfer01, MartinMosbeck, brucehoult, the_o, rkruppe, PkmX, jocewei, psnobl, benna, Jim, s.egerton, pzheng, sameer.abuasal, apazos, luismarques, llvm-commits

Tags: #llvm

Differential Revision: https://reviews.llvm.org/D73211
2020-01-23 02:05:48 +00:00
Roger Ferrer Ibanez 41449c58c5 [RISCV] Fix evaluation of %pcrel_lo
The following testcase

  function:
  .Lpcrel_label1:
  	auipc	a0, %pcrel_hi(other_function)
  	addi	a1, a0, %pcrel_lo(.Lpcrel_label1)
  	.p2align	2          # Causes a new fragment to be emitted

  	.type	other_function,@function
  other_function:
  	ret

exposes an odd behaviour in which only the %pcrel_hi relocation is
evaluated but not the %pcrel_lo.

  $ llvm-mc -triple riscv64 -filetype obj t.s | llvm-objdump  -d -r -

  <stdin>:	file format ELF64-riscv

  Disassembly of section .text:
  0000000000000000 function:
         0:	17 05 00 00	auipc	a0, 0
         4:	93 05 05 00	mv	a1, a0
  		0000000000000004:  R_RISCV_PCREL_LO12_I	other_function+4

  0000000000000008 other_function:
         8:	67 80 00 00	ret

The reason seems to be that in RISCVAsmBackend::shouldForceRelocation we
only consider the fragment but in RISCVMCExpr::evaluatePCRelLo we
consider the section. This usually works but there are cases where the
section may still be the same but the fragment may be another one. In
that case we end forcing a %pcrel_lo relocation without any %pcrel_hi.

This patch makes RISCVAsmBackend::shouldForceRelocation use the section,
if any, to determine if the relocation must be forced or not.

Differential Revision: https://reviews.llvm.org/D60657
2019-11-08 08:37:37 +00:00