From e77eee96a3bd4ba737f6aee01acaffe795d7be60 Mon Sep 17 00:00:00 2001 From: Alan Wu Date: Fri, 18 Jul 2025 14:30:58 -0400 Subject: ZJIT: Load return value before frame teardown Or else the following returns garbage since it loads after moving SP. Prior bad disassembly: def a(n1,n2,n3,n4,n5,n6,n7,n8) = n8 a(1,1,1,1,1,1,1,0) # Block: bb0(v0, v1, v2, v3, v4, v5, v6, v7, v8) stp x29, x30, [sp, #-0x10]! mov x29, sp # bump C stack pointer sub sp, sp, #0x10 # Insn: v10 Return v8 # pop stack frame adds x19, x19, #0x38 stur x19, [x20, #0x10] # restore C stack pointer add sp, sp, #0x10 mov sp, x29 ldp x29, x30, [sp], #0x10 ldur x0, [sp] ret --- zjit/src/codegen.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'zjit/src') diff --git a/zjit/src/codegen.rs b/zjit/src/codegen.rs index 6ce3915978..54346e0778 100644 --- a/zjit/src/codegen.rs +++ b/zjit/src/codegen.rs @@ -898,6 +898,10 @@ fn gen_return(jit: &JITState, asm: &mut Assembler, val: lir::Opnd) -> Option<()> asm.mov(CFP, incr_cfp); asm.mov(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP); + // Order here is important. Because we're about to tear down the frame, + // we need to load the return value, which might be part of the frame. + asm.load_into(C_RET_OPND, val); + // Restore the C stack pointer bumped for basic block arguments if jit.c_stack_bytes > 0 { asm_comment!(asm, "restore C stack pointer"); @@ -908,7 +912,7 @@ fn gen_return(jit: &JITState, asm: &mut Assembler, val: lir::Opnd) -> Option<()> asm.frame_teardown(); // Return from the function - asm.cret(val); + asm.cret(C_RET_OPND); Some(()) } -- cgit v1.2.3