selfhost: mirror defer; e2e tests for LIFO ordering
C cgen has carried defer for a while (defers[] global + reverse walk on every return). Selfhost cgen now mirrors: - cgen struct: deferbuf (**node, LIFO stack) + defertop counter. - cgstmt N_DEFER: push n.lhs. - cgreturn: rundefers() at entry — same as the C cgen pattern. - cgfn fall-through return: rundefers() before zero-AX+RET. DEFER_MAX = 16 matches C cgen. Two new e2e rows: defer with an explicit `return acc;` (321 mod 256 = 65), and defer firing on an implicit void-fn fall-through (87). Both rows verified via the wwstage cgen too. Defer's semantics: queued exprs fire LIFO before the return expr is evaluated, so a return that reads memory mutated by a deferred call sees the post-defer state. Matches C cgen and Hare.
This commit is contained in:
@@ -258,6 +258,9 @@ fn cgfn(c: *cgen, fn_: *node) void = {
|
||||
if (fn_.body != nil) { cgstmt(c, fn_.body); };
|
||||
|
||||
if (c.lastwasreturn == 0) {
|
||||
// Run any registered defers in LIFO order before the
|
||||
// implicit return.
|
||||
rundefers(c);
|
||||
// Zero AX before the fall-through return — matches C cgen,
|
||||
// which always emits this so void-returning fns don't leak
|
||||
// a stale callee value to their caller.
|
||||
|
||||
Reference in New Issue
Block a user