eric
pushed to master at eric/TP3
edd057f5ce TP3-ARGORDER: push each argument as it is parsed, and read the frame from BP+4 backwards
A call read its whole argument list before pushing any of it, so a value that
existed only in AX (kind 2) did not survive the parse of the argument after it.
PSRC8 cproc/cprlp1/cprlp2 does the opposite: CALL exprsave then CALL epushax
for each argument AS IT IS READ, and only then the CALL.
Three parsers deferred the pushes - ParseCallArgs (a call as a statement),
ParseCall (a function inside an expression) and IoCall (write/writeln/read) -
and the callee was inverted in the other half: parameter offsets were handed
out in declaration order from BP+4, while an argument pushed first ends up
farthest from BP. A one-argument call cannot tell the two apart, which is all
Runtime.mod has, so nothing outside a fixture had ever seen it.
Fix, three sites plus one:
* ParseCallArgs / ParseCall: LoadAtom + EmPushAx right after each ParseExpr;
the deferred args[] loop is gone.
* IoCall: the parse loop and the emit loop are one loop, so an argument is
pushed (or its runtime call made) before the next argument is read. This
also closes IoCall's second loss - it used to push an argument after the
call made for an inline string literal in between.
* ProcFunc: once the parameter list has been read, remap [nestMark, symTop)
with `off := parmOff + 2 - off`, which sends 4 + 2*(k-1) to 4 + 2*(n-k):
the last declared parameter lands at BP+4, where the first-pushed argument
is. That range is exactly the parameters - the parameter's own NewSym is
the only symbol created inside the loop.
New fixture t36_argclobber (eight hand-derived lines) covers all four. It was
compiled and run BEFORE this change, and both oracles came back red for the
same lines:
want 5 3 7 / 0 8 / 8 0 / 8 0 14 / 12 0 / TRUE FALSE / 19 / FALSE 1
got 5 3 7 / 0 8 / 0 0 / 0 0 14 / 0 0 / FALSE FALSE / 10 / TRUE 544
The two plain-name lines were already green and stay green; they are the rows
that would catch a fix flipping only one of the two halves, and they were seen
green before the fix rather than only after it.
No expectation row was re-baselined. t36's row was written while the compiler
was still broken and its numbers held, because the reorder emits the same
bytes in a different order. t28's row held because the remap hands the same
displacements to different names: its two disp16 reads are still +128/+142
(now p8/p1 where they were p63/p70), and its printed sum still comes from the
slots the sixteen pushed arguments land in (p55 + p70 = 1 + 16). The t28
source, its comment and check_framedisp's rule were updated to the TP3 frame
rule instead.
Gates: tests/run_all.sh rc=0, OVERALL: ALL PASS (all fifteen checks);
tests/nonvacuity.sh rc=0, "non-vacuity: 62 ok, 0 failed" with Compiler.mod
restored byte for byte. t36's in-suite mutation cases do not exist yet - its
proof is the pre-fix run above - and SUMMARY.md says so in both the Non-vacuity
section and Next steps rather than letting the 62 imply coverage it has not.
2 days ago