| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748 |
- 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, both paths.
- Small record arrays (data <= 131072 bytes) are expanded per element
- by `QbeGen.ArrBodyItems`/`ArrData` (predicate `HasArrayField`, not
- just nested ARRAY OF ARRAY), so each inline array field's length word
- is in the static data. Larger ones (e.g. AST.arena, 262144 records)
- are kept compact and their element length words are set at run time
- by a generated init loop (`QbeGen.DeclRecTemplate` +
- `QbeGen.InitRecArray`, driven from `Lower`), which is what keeps the
- image inside the 4 MiB `QbeGen.sessBuf`.
- Regression: compiler/tests/t_arrrecfld.mod (small, exit 42) and
- compiler/tests/t_arrrecbig.mod (large, exit 42). *)
- 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.
|