nested-array-field-bug.mod 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061
  1. MODULE NestedArrayFieldBug;
  2. (* Repro: a RECORD field that is a nested ARRAY OF ARRAY OF CHAR, accessed
  3. as `arr[i].field[j][k]`, is miscompiled by V3 -> segfault (rc 139).
  4. Observed 2026-10-05; the flat-array form works (rc 42).
  5. Found while adding Lower's procedure-formal name table (a module-level
  6. ARRAY OF RECORD with a `pname : ARRAY [0..31] OF ARRAY [0..63] OF
  7. CHAR` field): the V3-built compiler crashed (SIGABRT) on every input.
  8. Flattening the field to `ARRAY [0..2047] OF CHAR` fixed the crash.
  9. Compare with docs/wip/local-array-bug.mod (local arrays) and the
  10. Stage-A array-of-record stride fix (QbeGen.ElemSize). Likely the
  11. element stride / descriptor-pointer setup for a nested-array field is
  12. wrong. Expected exit 42; observed 139. *)
  13. VAR ExitCode : INTEGER;
  14. CONST MaxName = 63; MaxProc = 4;
  15. TYPE PE = RECORD
  16. name : ARRAY [0..MaxName] OF CHAR;
  17. npar : CARDINAL;
  18. pname : ARRAY [0..3] OF ARRAY [0..MaxName] OF CHAR; (* nested *)
  19. END;
  20. VAR procs : ARRAY [0..MaxProc-1] OF PE;
  21. nProcs : CARDINAL;
  22. PROCEDURE Reset;
  23. BEGIN nProcs := 0 END Reset;
  24. PROCEDURE NoteProc (name : ARRAY OF CHAR);
  25. VAR i : CARDINAL;
  26. BEGIN
  27. IF nProcs >= MaxProc THEN RETURN END;
  28. i := 0;
  29. WHILE (i < MaxName) AND (name[i] # CHR(0)) DO
  30. procs[nProcs].name[i] := name[i]; INC(i)
  31. END;
  32. procs[nProcs].name[i] := CHR(0);
  33. procs[nProcs].npar := 0; INC(nProcs)
  34. END NoteProc;
  35. PROCEDURE NoteParam (name : ARRAY OF CHAR);
  36. VAR j, i : CARDINAL;
  37. BEGIN
  38. IF nProcs = 0 THEN RETURN END;
  39. j := procs[nProcs-1].npar;
  40. i := 0;
  41. WHILE (i < MaxName) AND (name[i] # CHR(0)) DO
  42. procs[nProcs-1].pname[j][i] := name[i]; INC(i)
  43. END;
  44. procs[nProcs-1].pname[j][i] := CHR(0);
  45. procs[nProcs-1].npar := j + 1
  46. END NoteParam;
  47. BEGIN
  48. Reset; NoteProc("Add"); NoteParam("a");
  49. IF (nProcs = 1) AND (procs[0].pname[0][0] = "a")
  50. THEN ExitCode := 42 ELSE ExitCode := 1 END
  51. END NestedArrayFieldBug.