diff --git a/src/backend.rs b/src/backend.rs index 8c15536ff7..1c1dc144ec 100644 --- a/src/backend.rs +++ b/src/backend.rs @@ -397,10 +397,33 @@ fn pop_i32(ctx: &mut Context) -> Value { } fn pop_i32_into(ctx: &mut Context, dst: ValueLocation) { - let val = pop_i32(ctx); - let val_loc = val.location(&ctx.locals); - copy_value(ctx, val_loc, dst); - free_val(ctx, val); + let to_move = match ctx.block_state.stack.pop().expect("Stack is empty") { + StackValue::Local(loc) => Value::Local(loc), + StackValue::Immediate(i) => Value::Immediate(i), + StackValue::Temp(reg) => Value::Temp(reg), + StackValue::Pop => { + ctx.block_state.depth.free(1); + match dst { + ValueLocation::Reg(r) => dynasm!(ctx.asm + ; pop Rq(r) + ), + ValueLocation::Stack(offset) => { + let offset = adjusted_offset(ctx, offset); + dynasm!(ctx.asm + ; pop QWORD [rsp + offset] + ) + } + ValueLocation::Immediate(_) => panic!("Tried to write to literal!"), + } + + // DO NOT DO A `copy_val` + return; + } + }; + + let src = to_move.location(&ctx.locals); + copy_value(ctx, src, dst); + free_val(ctx, to_move); } fn free_val(ctx: &mut Context, val: Value) { diff --git a/src/tests.rs b/src/tests.rs index 822ebb507a..d9368f10b7 100644 --- a/src/tests.rs +++ b/src/tests.rs @@ -317,17 +317,23 @@ const FIBONACCI: &str = r#" #[test] fn fib() { - // fac(x) = y <=> (x, y) - const FIB_SEQ: &[u32] = &[1, 1, 2, 3, 5, 8, 13, 21, 34, 55]; + fn fib(n: u32) -> u32 { + let (mut a, mut b) = (1, 1); + + for _ in 0..n { + let old_a = a; + a = b; + b += old_a; + } + + a + } let translated = translate_wat(FIBONACCI); - for x in 0..10 { + for x in 0..30 { unsafe { - assert_eq!( - translated.execute_func::<_, u32>(0, (x,)), - FIB_SEQ[x as usize] - ); + assert_eq!(translated.execute_func::<_, u32>(0, (x,)), fib(x)); } } }