Skip to content

Commit e77eee9

Browse files
committed
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
1 parent 9f961a4 commit e77eee9

File tree

2 files changed

+10
-1
lines changed

2 files changed

+10
-1
lines changed

test/ruby/test_zjit.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -806,6 +806,11 @@ def test
806806
def a(n1,n2,n3,n4,n5,n6,n7,n8,n9) = n1+n9
807807
a(2,0,0,0,0,0,0,0,-1)
808808
}
809+
810+
assert_compiles '0', %q{
811+
def a(n1,n2,n3,n4,n5,n6,n7,n8) = n8
812+
a(1,1,1,1,1,1,1,0)
813+
}
809814
end
810815

811816
def test_opt_aref_with

zjit/src/codegen.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -898,6 +898,10 @@ fn gen_return(jit: &JITState, asm: &mut Assembler, val: lir::Opnd) -> Option<()>
898898
asm.mov(CFP, incr_cfp);
899899
asm.mov(Opnd::mem(64, EC, RUBY_OFFSET_EC_CFP), CFP);
900900

901+
// Order here is important. Because we're about to tear down the frame,
902+
// we need to load the return value, which might be part of the frame.
903+
asm.load_into(C_RET_OPND, val);
904+
901905
// Restore the C stack pointer bumped for basic block arguments
902906
if jit.c_stack_bytes > 0 {
903907
asm_comment!(asm, "restore C stack pointer");
@@ -908,7 +912,7 @@ fn gen_return(jit: &JITState, asm: &mut Assembler, val: lir::Opnd) -> Option<()>
908912
asm.frame_teardown();
909913

910914
// Return from the function
911-
asm.cret(val);
915+
asm.cret(C_RET_OPND);
912916
Some(())
913917
}
914918

0 commit comments

Comments
 (0)