Procházet zdrojové kódy

fix: record/class/set element stride in array data (ArrBodyItems)

QbeGen.ArrBodyItems computed the element stride itself and fell through
to 4 for record/class/set elements, so an ARRAY OF record was emitted
with 4-byte records: overlapping elements, bad field/index access
(arr[i].field read neighbours).  It now uses SymTab.TypeSize, mirroring
the Stage-A ElemSize fix.

Repro/regression: t_recarr.mod (ARRAY OF record with a CHAR-array field)
now exits 42.  The nested-array-field case (arr[i].field[j][k] with a
nested ARRAY OF ARRAY field) still needs per-element sub-descriptors
(docs/wip/nested-array-field-bug.mod) -- a separate fix.

Gates: suite 183/183; fixpoint OK (stage2 == stage3, 3148993 bytes).
Eric Streit před 6 dny
rodič
revize
dd760634de
3 změnil soubory, kde provedl 20 přidání a 1 odebrání
  1. 1 0
      compiler/run_tests.sh
  2. 5 1
      compiler/src/QbeGen.mod
  3. 14 0
      compiler/tests/t_recarr.mod

+ 1 - 0
compiler/run_tests.sh

@@ -91,6 +91,7 @@ expect_run t_long.mod 42
 expect_run t_unicode.mod 31
 expect_run t_charbounds.mod 3
 expect_run t_record.mod 160
+expect_run t_recarr.mod 42
 expect_run t_with.mod 114
 expect_run t_set.mod 131
 expect_run t_setchar.mod 77

+ 5 - 1
compiler/src/QbeGen.mod

@@ -2059,7 +2059,11 @@ PROCEDURE ArrBodyItems (prefix: ARRAY OF CHAR; t: INTEGER);
         W(bv)
       ELSE
         IF (ecls = SymTab.ClReal) OR (ecls = SymTab.ClPtr)
-           OR (ecls = SymTab.ClProc) THEN esz := 8
+           OR (ecls = SymTab.ClProc) OR (ecls = SymTab.ClLong) THEN esz := 8
+        ELSIF (ecls = SymTab.ClRecord) OR (ecls = SymTab.ClClass)
+           OR (ecls = SymTab.ClSet) THEN
+          (* inline footprint, not a fixed 4 (same fix as ElemSize) *)
+          esz := SymTab.TypeSize(elem)
         ELSE esz := 4
         END;
         IF n > 0 THEN

+ 14 - 0
compiler/tests/t_recarr.mod

@@ -0,0 +1,14 @@
+MODULE TRecArr;
+(* Regression: a RECORD element in an ARRAY must stride by the record's
+   size, not 4 (QbeGen.ArrBodyItems fell through to 4 for record/class/
+   set elements).  Exit 42. *)
+VAR ExitCode : INTEGER;
+TYPE R = RECORD a : ARRAY [0..63] OF CHAR; n : INTEGER END;
+VAR x : ARRAY [0..3] OF R;
+BEGIN
+  x[2].a[0] := "Z"; x[2].n := 7;
+  x[0].n := 1; x[1].n := 2; x[3].n := 4;
+  IF (x[2].a[0] = "Z") AND (x[2].n = 7)
+     AND (x[0].n = 1) AND (x[1].n = 2) AND (x[3].n = 4)
+  THEN ExitCode := 42 ELSE ExitCode := 1 END
+END TRecArr.