This is an archive of the discontinued LLVM Phabricator instance.

[RuntimeDyldChecker] Support offset in decode_operand expr
ClosedPublic

Authored by StephenFan on Jul 6 2021, 10:34 PM.

Details

Summary

In RISCV's relocations, some relocations are comprised of two relocation types. For example, R_RISCV_PCREL_HI20 and R_RISCV_PCREL_LO12_I compose a PC relative relocation. In general the compiler will set a label in the position of R_RISCV_PCREL_HI20. So, to test the R_RISCV_PCREL_LO12_I relocation, we need decode instruction at position of the label points to R_RISCV_PCREL_HI20 plus 4 (the size of a riscv non-compress instruction).

Diff Detail

Event Timeline

StephenFan created this revision.Jul 6 2021, 10:34 PM
StephenFan requested review of this revision.Jul 6 2021, 10:34 PM
Herald added a project: Restricted Project. · View Herald TranscriptJul 6 2021, 10:34 PM

Why can't you just add a label for the instruction you want to test?

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
588

Don't change formatting for code you didn't touch

llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s
22 ↗(On Diff #356867)

This is just (named_data - test_pcrel32) & 0xfff sign-extended from 12 to 64 bits. The + 0x800 for the HI is to compensate for the sign extension for the LO, feeding it back into the LO calculation is backwards and results in circular reasoning.

lhames added a comment.Jul 8 2021, 3:33 AM

Why can't you just add a label for the instruction you want to test?

Actually I really like the idea of allowing offsets here. Avoiding artificial labels has two benefits: improved readability, and clearer layout control on MachO where labels implicitly start new subsections.

This is just (named_data - test_pcrel32) & 0xfff sign-extended from 12 to 64 bits. The + 0x800 for the HI is to compensate for the sign extension for the LO, feeding it back into the LO calculation is backwards and results in circular reasoning.

I don't know RISCV, so I defer to Jessica here.

Side note: Some comparisons may be easier to express with the bit-slicing operator. E.g. this example from MachO_arm64_relocations.s:

# jitlink-check: decode_operand(test_local_call, 0)[25:0] = (named_func - test_local_call)[27:2]
        .globl  test_local_call
        .p2align  2
test_local_call:
        bl   named_func

Please address Jessica's feedback, but otherwise LGTM. Thanks Stephen!

llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldChecker.cpp
240–247

You should error out for the other binop tokens with an unexpected token error.

StephenFan added inline comments.Jul 13 2021, 11:56 PM
llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s
22 ↗(On Diff #356867)

This is just (named_data - test_pcrel32) & 0xfff sign-extended from 12 to 64 bits. The + 0x800 for the HI is to compensate for the sign extension for the LO, feeding it back into the LO calculation is backwards and results in circular reasoning.

@jrtc27 Thank you for reminding me! You're right! By thinking again, here is my understanding:

If the pc relative value is 0x00001fff, if don't add 0x800, then the value will be split to high 20bits(0x00001) and low 12bits(0xfff). However, the low 12bits will be considered as a signed number. so the MSB of 0xfff which originally represent 2^11 now changed to -2^11. The difference is 2^12. So we need to add 0x800 to compensate the difference. Are there any errors in my understanding?

jrtc27 added inline comments.Jul 14 2021, 4:13 AM
llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s
22 ↗(On Diff #356867)

2^12 is 0x1000. You're conditionally adding 0x1000 to the hi20 value based on whether the 12th bit is set which, given hi20 throws away the low 12 bits, is the same as unconditionally adding 0x800 and relying on the carry bit of 0x800 + 0x800 to give you 0x1000.

Side note: Some comparisons may be easier to express with the bit-slicing operator. E.g. this example from MachO_arm64_relocations.s:

Thanks, lhames! Bit-slicing looks like a great idea! I will change it.

# jitlink-check: decode_operand(test_local_call, 0)[25:0] = (named_func - test_local_call)[27:2]
        .globl  test_local_call
        .p2align  2
test_local_call:
        bl   named_func

Please address Jessica's feedback, but otherwise LGTM. Thanks Stephen!

Ok! I will!

Address @jrtc27 and @lhames 's comment

Address @jrtc27 and @lhames 's comment

StephenFan marked 4 inline comments as done.Jul 18 2021, 4:18 AM
jrtc27 added inline comments.Jul 18 2021, 7:03 AM
llvm/test/ExecutionEngine/JITLink/RISCV/ELF_pc_indirect.s
22 ↗(On Diff #359611)

(... & 0xfff)[11:0] is a strange thing to write, you don't need both

Address @jrtc27's comments

StephenFan marked an inline comment as done.Jul 19 2021, 1:08 AM

Fail fast when SymbolMem's size < Offset + instruction size

Fail faster when SymbolMem's size < Offset + instruction size

@jrtc27 Any other feedback on this?

Otherwise LGTM.

LGTM.

Note: I don't know what is the current standard for the ExecutionEngine test exhaustiveness, but the error condition, the subtracted offset, and the invalid offset cases aren't exercised in the tests.

lhames accepted this revision.Jul 26 2021, 5:51 PM

LGTM.

Note: I don't know what is the current standard for the ExecutionEngine test exhaustiveness, but the error condition, the subtracted offset, and the invalid offset cases aren't exercised in the tests.

Testing of the ExecutionEngine libraries is basic (though reasonably effective) -- definitely not exhaustive, but improving.

Testing of the test infrastructure itself (e.g. the jitlink checker) is currently non-existent.

Improving library testing is the higher priority, but more testing of the test tools would be nice too.

This revision is now accepted and ready to land.Jul 26 2021, 5:51 PM

Disable support of negative offset. A negative offset may get a invalid address.

This revision was landed with ongoing or failed builds.Aug 2 2021, 8:30 PM
This revision was automatically updated to reflect the committed changes.