-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Cranelift: Illegal instruction on riscv64 #5569
Description
👋 Hey,
Fuzzgen found this a week or so ago, but I haven't been able to minimize this. Whenever I try to remove seemingly any instruction the test case passes.
I'm going to keep running fuzzgen with a smaller max_len to try to find a smaller example.
.clif Test Case
Steps to Reproduce
clif-util test ./the-above.clif
Expected Results
The test to pass
Actual Results
afonso@DESKTOP-VSTS4BC:~/git/wasmtime/cranelift$ cargo run --target riscv64gc-unknown-linux-gnu -- test ./lmao.clif
Finished dev [unoptimized + debuginfo] target(s) in 0.16s
Running `qemu-riscv64 -L /usr/riscv64-linux-gnu -E LD_LIBRARY_PATH=/usr/riscv64-linux-gnu/lib /home/afonso/git/wasmtime/target/riscv64gc-unknown-linux-gnu/debug/clif-util test ./lmao.clif`
Illegal instruction
Versions and Environment
Cranelift version or commit: main
Operating system: linux
Architecture: riscv64
Extra Info
Disassembly
Running this under GDB it crashes in:
0x3ff7fd5b70: bne zero,a7,0x3ff7fd5b78
0x3ff7fd5b74: unimp
0x3ff7fd5b76: unimp
0x3ff7fd5b78: divw t2,a6,a7
0x3ff7fd5b7c: feq.d a2,fa0,fa0
0x3ff7fd5b80: beqz a2,0x3ff7fd5b90
0x3ff7fd5b84: auipc t6,0x0
0x3ff7fd5b88: ld t6,12(t6)
0x3ff7fd5b8c: j 0x3ff7fd5b98
0x3ff7fd5b90: auipc t6,0x0
0x3ff7fd5b94: jr 48(t6)
=> 0x3ff7fd5b98: unimp
0x3ff7fd5b9a: unimp
0x3ff7fd5b9c: unimp
0x3ff7fd5b9e: lw s0,4(a4)
0x3ff7fd5ba0: fmv.d.x fa3,t6
0x3ff7fd5ba4: fabs.d fa1,fa0
0x3ff7fd5ba8: flt.d a2,fa3,fa1
0x3ff7fd5bac: bnez a2,0x3ff7fd5bc8
0x3ff7fd5bb0: fcvt.l.d a2,fa0,rne
The start of the function is at 0x3ff7fd4000, so this is at offset 0x1B98 in the disassembly. Which appears to be a embedded constant?
1b88: 83 bf cf 00 ld t6, 0xc(t6)
1b8c: 6f 00 c0 00 j 0xc
1b90: 97 0f 00 00 auipc t6, 0
1b94: 67 80 0f 03 jalr zero, t6, 0x30
1b98: 00 00 00 00 .byte 0x00, 0x00, 0x00, 0x00
1b9c: 00 00 40 43 .byte 0x00, 0x00, 0x40, 0x43
1ba0: d3 86 0f f2 fmv.d.x fa3, t6
I suspect the issue here is that the instruction at 1b8c is a jump directly into the embedded constant at 1b98.
Looking at the trace logs for this range, it looks like we are emitting a veneer right at that offset? And maybe we have a constant offset in some branch that is causing this.
1b8c = 7052
1b98 = 7064
TRACE cranelift_codegen::machinst::buffer > emit_island: fixup MachLabelFixup { label: MachLabel(529), offset: 7040, kind: B12 }
TRACE cranelift_codegen::machinst::buffer > MachBuffer: align to 4
TRACE cranelift_codegen::machinst::buffer > making a veneer at 7056
TRACE cranelift_codegen::machinst::buffer > patching original at offset 7040 to veneer offset 7056
TRACE cranelift_codegen::machinst::buffer > MachBuffer: put data @ 7056: len 8
TRACE cranelift_codegen::machinst::buffer > generated veneer; fixup offset 7056, label_use PCRel32
TRACE cranelift_codegen::machinst::buffer > MachBuffer: use_label_at_offset: offset 7056 label MachLabel(529) kind PCRel32
TRACE cranelift_codegen::machinst::buffer > MachBuffer: put data @ 7064: len 8
TRACE cranelift_codegen::machinst::buffer > MachBuffer: put 32-bit word @ 7072: f20f86d3
TRACE cranelift_codegen::machinst::buffer > MachBuffer: put 32-bit word @ 7076: 22a525d3
TRACE cranelift_codegen::machinst::buffer > MachBuffer: put 32-bit word @ 7080: a2b69653
TRACE cranelift_codegen::machinst::buffer > MachBuffer: use_label_at_offset: offset 7084 label MachLabel(530) kind B12
I'm not too sure how to translate these offsets into an actual clif instruction that is causing this issue.
Edit: This seems to be caused by us not using labels in load_constant.