This is an archive of the discontinued LLVM Phabricator instance.

[RISCV] Fix evaluation of %pcrel_lo
ClosedPublic

Authored by rogfer01 on Apr 13 2019, 1:08 PM.

Details

Summary

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.

$ ./bin/llvm-mc -triple riscv64 -filetype obj t.s | ./bin/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.

This issue seems related to D57240.

Diff Detail

Event Timeline

rogfer01 created this revision.Apr 13 2019, 1:08 PM
Herald added a project: Restricted Project. · View Herald TranscriptApr 13 2019, 1:08 PM
jrtc27 added inline comments.Apr 13 2019, 3:06 PM
llvm/lib/Target/RISCV/MCTargetDesc/RISCVAsmBackend.cpp
59

Is it even possible to not have a valid FixupFragment? Isn't that effectively how we found T in the first place in getPCRelHiFixup?

Thanks for this. I realize D58843 is a very heavy-handed approach so I'd be happy if we could avoid it cleanly with target-specific changes, however I'm not certain we would be able to cover all the combinations we would need to with patches like this?

For example would we be able to cover pairs that occur out of order?

Thanks for this. I realize D58843 is a very heavy-handed approach so I'd be happy if we could avoid it cleanly with target-specific changes, however I'm not certain we would be able to cover all the combinations we would need to with patches like this?

For example would we be able to cover pairs that occur out of order?

Yes, this seems to work just fine with them:

% cat pcrel-lohi.s
foo:
    j 1f
0:  addi a0, a0, %pcrel_lo(1f)
    ret
1: auipc a0, %pcrel_hi(bar)
    j 0b

.align 2
bar:
% llvm-mc -filetype=obj -triple riscv32 pcrel-lohi.s | llvm-objdump -d -r -

<stdin>:        file format ELF32-riscv

Disassembly of section .text:
0000000000000000 foo:
       0:       6f 00 c0 00     j       12
       4:       13 05 85 00     addi    a0, a0, 8
       8:       67 80 00 00     ret
       c:       17 05 00 00     auipc   a0, 0
      10:       6f f0 5f ff     j       -12
jrtc27 added a comment.Sep 3 2019, 2:25 AM

@asb Would be great if you could review this; this is the revision I was referring to back in Boston.

jrtc27 added inline comments.Sep 15 2019, 8:00 AM
llvm/test/MC/RISCV/pcrel-fixups.s
2

fixups.s uses -riscv-no-aliases so you can check the mv is really an addi with 0 immediate.

17

It's probably a good idea to put a # NORELAX-NOT: R_RISCV after each of these instructions (especially since the auipc with 0 immediate is also what you get if there's a relocation for the line).

rogfer01 updated this revision to Diff 220293.Sep 16 2019, 2:04 AM

ChangeLog:

  • Remove unneeded runtime check and turn it into an assertion.
  • Avoid instruction aliases in testcase
  • Strengthen check directives for the NORELAX case.
rogfer01 marked 3 inline comments as done.Sep 16 2019, 2:04 AM

Thanks for the review @jrtc27 and apologies for the delay. I had forgotten I had posted this.

This revision is now accepted and ready to land.Nov 5 2019, 3:25 AM

Thanks for the review @luismarques . I plan to commit this shortly.

This revision was automatically updated to reflect the committed changes.