| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950 |
- MODULE ArrRecFieldOpenArray;
- (* Repro: an array field of an array-of-record element passed as an open
- array actual. The field's descriptor length word is never initialized
- in the static array-of-record data, so the callee reads length 0 and
- traps. V3-built compilers miscompile this; gm2-built ones happen to
- work. Expected: exit 0. Actual (buggy V3): SIGABRT (134).
- Status (2026-10-08): FIXED for record arrays whose data is at most
- 131072 bytes — `QbeGen.ArrBodyItems`/`ArrData` now expand record/
- class elements per element (predicate `HasArrayField`, not just
- nested ARRAY OF ARRAY) so each inline array field's length word is
- initialised. This case used to be a single zero blob, so the field's
- count stayed 0 and the callee trapped. Regression: compiler/tests/
- t_arrrecfld.mod (exit 42).
- Larger tables (e.g. AST.arena, 262144 records) keep the compact zero
- blob on purpose: expanding them (even interleaved `l <len>, z <n>`)
- would push the compiler image past the 4 MiB QbeGen.sessBuf. The
- principled general fix is to initialise such counts at runtime (a
- generated init loop), not in the static data; until then the latent
- 0-count bug remains for very large record arrays. See
- docs/summary_l3_selfhost_fix.md. *)
- TYPE
- ProcEnt = RECORD
- name : ARRAY [0..63] OF CHAR;
- END;
- VAR
- procs : ARRAY [0..3] OF ProcEnt;
- nProcs : CARDINAL;
- ExitCode: INTEGER;
- PROCEDURE CopyN (src: ARRAY OF CHAR; VAR dst: ARRAY OF CHAR);
- VAR i: CARDINAL;
- BEGIN
- i := 0;
- WHILE (i < 63) AND (src[i] # CHR(0)) DO dst[i] := src[i]; INC(i) END;
- dst[i] := CHR(0)
- END CopyN;
- PROCEDURE NoteProc (name: ARRAY OF CHAR);
- BEGIN
- CopyN(name, procs[nProcs].name);
- INC(nProcs)
- END NoteProc;
- BEGIN
- NoteProc("hello");
- IF procs[0].name[0] = "h" THEN ExitCode := 0 ELSE ExitCode := 1 END
- END ArrRecFieldOpenArray.
|