Skip to content

v2.8.20

Choose a tag to compare

@Pantelis23 Pantelis23 released this 27 Apr 22:46

Fix: return N from main was silently ignored.

The auto-inserted exit syscall at the end of main was clobbering the return register (rax on x86_64, x0 on aarch64) with a hardcoded 0 right before the syscall, so:

```kernrift
fn main() -> int32 { return 42 }
```

exited with status 0 instead of 42 — on every backend (legacy and IR, both arches). The user-visible symptom was that while 1 == 1 { if cond { return 42 } } ignored the return, but it was the same root cause; the loop had nothing to do with it. Existing examples like hello.kr were fine because they call exit(0) explicitly and never reach the auto-glue.

Fix:

  • Auto-exit syscall now forwards the current rax/x0 as the exit code.
  • IR_RET_VOID zeros rax/x0 before branching to the epilogue, so fn main() { ... } (void) still exits with 0.
  • Legacy backends do the same zero at the start of main's body.
  • Function-local return (in non-main functions) is unaffected: callers don't read the return register on void returns.

Verified:

  • fn main() -> int32 { return 42 } → exit 42 ✓
  • while 1 == 1 { ...; return 7 } → exit 7 ✓
  • while 1 == 1 { println(i); if i == 3 { return 42 } } → prints 1 2 3, exit 42 ✓
  • fn main() { ... } (void) → exit 0 ✓

Bootstrap fixed point at 1,244,072 bytes; 439/439 tests pass.

Full Changelog: v2.8.19...v2.8.20

Full Changelog: v2.8.19...v2.8.20