arrrec-field-openarray.mod 1.8 KB

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