//! returns: 0 //! Regression test: address-taken variable inside a loop. //! //! When `&mut var` appears inside a loop body, the variable must be //! memory-backed from the start. Otherwise the SSA phi at the loop header //! merges an integer value (from before the first iteration) with a pointer //! value (the stack slot created by `&mut`), producing invalid IL. //! //! The critical case is when the loop executes zero iterations: the merge //! block tries to `load` through the initial integer value (not a valid //! pointer), crashing the program. unsafe fn store(ptr: *mut u32, val: u32) { set *ptr = val; } /// Zero-iteration loop with &mut inside the body. /// Without the fix, `val` starts as integer 42 in SSA, but the post-loop /// merge tries to `load` through it as if it were a pointer. unsafe fn testZeroIter(n: u32) -> u32 { let mut val: u32 = 42; let mut i: u32 = 0; while i < n { store(&mut val, val + 1); set i += 1; } return val; } /// Multiple iterations: accumulate via &mut pointer in a loop. unsafe fn testMultiIter() -> u32 { let mut acc: u32 = 0; let mut i: u32 = 0; while i < 5 { store(&mut acc, acc + i); set i += 1; } return acc; } /// Multiple address-taken variables in the same loop. unsafe fn testMultipleVars() -> u32 { let mut a: u32 = 0; let mut b: u32 = 100; let mut i: u32 = 0; while i < 3 { store(&mut a, a + 1); store(&mut b, b - 1); set i += 1; } return a + b; } @default unsafe fn main() -> i32 { // Zero iterations: the critical regression case. assert testZeroIter(0) == 42; // Non-zero iterations still work. assert testZeroIter(3) == 45; // Accumulation: 0+0+1+2+3+4 = 10 assert testMultiIter() == 10; // Multiple vars: 3 + 97 = 100 assert testMultipleVars() == 100; return 0; }