Open ArsenyBochkarev opened 1 day ago
Turned out "relaxation" is not only an optimization. There are cases when we must do a relaxation to compile the program. For example, from LLVM's llvm/test/MC/RISCV/long-jump-disable-relax.s
test:
.text
# Branches to defined out-of-range symbols should report an error
# ONLY when we compile without relaxation!
test_defined_out_of_range:
bne a0, a1, 1f # error: fixup value out of range
.skip (1 << 12)
1:
c.beqz a0, 1f # error: fixup value out of range
.skip (1 << 8)
1:
c.j 1f # error: fixup value out of range
.skip (1 << 11)
1:
but if a relaxation happens, the RISCV::BNE
instruction in RISCVAsmBackend::getRelaxedOpcode
transforms into RISCV::PseudoLongBNE
, which is then translated into inverted conditional branch and an unconditional jump. So I cannot simply passthrough the -riscv-asm-relax-branches=0
option to backend. However, we still can unfold all branches into such a sequence. I did a hack in RISCVAsmBackend::fixupNeedsRelaxationAdvanced
, always returning true
for RISCV::fixup_riscv_branch
case. Here is the example (based on LLVM's llvm/test/MC/RISCV/long-jump-disable-relax.s
test):
Test case:
test_defined_out_of_range:
bne a0, a1, 1f
.skip (1 << 12)
1:
c.beqz a0, 1f
.skip (1 << 8)
1:
c.j 1f
.skip (1 << 11)
1:
without fuzzing:
./relaxation_test_output.out: file format elf64-littleriscv
Disassembly of section .text:
0000000000000000 <test_defined_out_of_range>:
0: 63 04 b5 00 beq a0, a1, 0x8 <test_defined_out_of_range+0x8>
4: 6f 10 40 00 jal zero, 0x1008 <test_defined_out_of_range+0x1008>
...
1008: 63 02 05 10 beq a0, zero, 0x110c <test_defined_out_of_range+0x110c>
...
110c: 6f 00 50 00 jal zero, 0x1910 <test_defined_out_of_range+0x1910>
...
with fuzzing:
./relaxation_test_output.out: file format elf64-littleriscv
Disassembly of section .text:
0000000000000000 <test_defined_out_of_range>:
0: 63 04 b5 00 beq a0, a1, 0x8 <test_defined_out_of_range+0x8>
4: 6f 10 40 00 jal zero, 0x1008 <test_defined_out_of_range+0x1008>
...
1008: 19 e1 c.bnez a0, 0x100e <test_defined_out_of_range+0x100e>
100a: 6f 00 40 10 jal zero, 0x110e <test_defined_out_of_range+0x110e>
...
110e: 6f 00 50 00 jal zero, 0x1912 <test_defined_out_of_range+0x1912>
...
Break the relaxation of relocations provided in LLVM. High-level steps are:
-riscv-asm-relax-branches
option-mc-relax-all
optionAdditionally take a look at these links: