|
|
@@ -2034,6 +2034,16 @@ PROCEDURE HasArrayField (t: SymTab.TypeIndex): BOOLEAN;
|
|
|
RETURN FALSE
|
|
|
END HasArrayField;
|
|
|
|
|
|
+PROCEDURE RecArrayExpanded (n: CARDINAL; t: INTEGER): BOOLEAN;
|
|
|
+(* TRUE when a record-/class-array's per-element expansion fits the image
|
|
|
+ budget. Larger tables keep the compact zero blob and are instead
|
|
|
+ initialised at run time (RecArrayNeedsInit/InitRecArray). The budget
|
|
|
+ keeps the compiler's own huge tables (AST.arena: 262144 records) from
|
|
|
+ inflating the 4 MiB image. *)
|
|
|
+ BEGIN
|
|
|
+ RETURN VAL(INTEGER, n) * VAL(INTEGER, SymTab.TypeSize(t)) <= 131072
|
|
|
+ END RecArrayExpanded;
|
|
|
+
|
|
|
PROCEDURE ArrBodyItems (prefix: ARRAY OF CHAR; t: INTEGER);
|
|
|
(* Inline contents of an array descriptor (no "data $name = {" wrapper
|
|
|
and no closing brace): "l <n>[, <elem>...]". Nested levels are
|
|
|
@@ -2107,8 +2117,7 @@ PROCEDURE ArrBodyItems (prefix: ARRAY OF CHAR; t: INTEGER);
|
|
|
END
|
|
|
ELSIF ((ecls = SymTab.ClRecord) OR (ecls = SymTab.ClClass))
|
|
|
AND HasArrayField(elem)
|
|
|
- AND (VAL(INTEGER, n) * VAL(INTEGER, SymTab.TypeSize(elem))
|
|
|
- <= 131072) THEN
|
|
|
+ AND RecArrayExpanded(n, elem) THEN
|
|
|
i := 0;
|
|
|
WHILE i < n DO
|
|
|
Cpy(sub, prefix); App(sub, "_");
|
|
|
@@ -2210,8 +2219,7 @@ PROCEDURE ArrData (name: ARRAY OF CHAR; t: INTEGER);
|
|
|
ELSIF ((SymTab.ClassOf(elem) = SymTab.ClRecord)
|
|
|
OR (SymTab.ClassOf(elem) = SymTab.ClClass))
|
|
|
AND HasArrayField(elem)
|
|
|
- AND (VAL(INTEGER, SymTab.ArrayLen(t))
|
|
|
- * VAL(INTEGER, SymTab.TypeSize(elem)) <= 131072) THEN
|
|
|
+ AND RecArrayExpanded(SymTab.ArrayLen(t), elem) THEN
|
|
|
(* Sub-descriptors referenced (as $name_i_field_k) from the inline
|
|
|
items emitted by ArrBodyItems; one set per element. *)
|
|
|
n := SymTab.ArrayLen(t);
|
|
|
@@ -3847,6 +3855,76 @@ PROCEDURE InitHeap (addr: ARRAY OF CHAR; t: SymTab.TypeIndex);
|
|
|
END
|
|
|
END InitHeap;
|
|
|
|
|
|
+PROCEDURE InFunction (): BOOLEAN;
|
|
|
+(* TRUE while a function body is open (module-level test). *)
|
|
|
+ BEGIN
|
|
|
+ RETURN inFunc
|
|
|
+ END InFunction;
|
|
|
+
|
|
|
+PROCEDURE RecArrayNeedsInit (n: CARDINAL; t: INTEGER): BOOLEAN;
|
|
|
+(* TRUE for an array of records/classes that (recursively) has array
|
|
|
+ fields and is too large to expand inline: its inline length words
|
|
|
+ must be initialised at run time (InitRecArray). *)
|
|
|
+ VAR elem: INTEGER;
|
|
|
+ BEGIN
|
|
|
+ IF SymTab.ClassOf(t) # SymTab.ClArray THEN RETURN FALSE END;
|
|
|
+ elem := SymTab.ArrayElem(t);
|
|
|
+ IF (SymTab.ClassOf(elem) # SymTab.ClRecord)
|
|
|
+ AND (SymTab.ClassOf(elem) # SymTab.ClClass) THEN RETURN FALSE END;
|
|
|
+ IF NOT HasArrayField(elem) THEN RETURN FALSE END;
|
|
|
+ RETURN NOT RecArrayExpanded(n, elem)
|
|
|
+ END RecArrayNeedsInit;
|
|
|
+
|
|
|
+PROCEDURE DeclRecTemplate (varName: ARRAY OF CHAR; rec: INTEGER);
|
|
|
+(* "data $<mod>_<varName>_tmpl = { <one record with counts set> }" plus
|
|
|
+ any nested sub-descriptors; InitRecArray copies it over each element
|
|
|
+ of the compact array-of-record blob. *)
|
|
|
+ VAR g: QVal; first: BOOLEAN;
|
|
|
+ BEGIN
|
|
|
+ IF NOT opened THEN RETURN END;
|
|
|
+ Cpy(g, curModName); App(g, "_"); App(g, varName); App(g, "_tmpl");
|
|
|
+ RecStatics(g, rec);
|
|
|
+ W("data $"); W(g); W(" = { ");
|
|
|
+ first := TRUE;
|
|
|
+ RecItems(rec, g, first);
|
|
|
+ WL(" }")
|
|
|
+ END DeclRecTemplate;
|
|
|
+
|
|
|
+PROCEDURE InitRecArray (varName: ARRAY OF CHAR; arrT: INTEGER);
|
|
|
+(* value-initialise $<mod>_<varName>'s element length words: copy the
|
|
|
+ template record over each element (element i is at base + 8 +
|
|
|
+ i*stride). *)
|
|
|
+ VAR base, tmpl, slot, i, il, off, tb, p, c, one, two, nStr, stStr: QVal;
|
|
|
+ elem: INTEGER; lTop, lBody, lDone: QVal;
|
|
|
+ BEGIN
|
|
|
+ IF NOT opened THEN RETURN END;
|
|
|
+ elem := SymTab.ArrayElem(arrT);
|
|
|
+ Cpy(base, "$"); App(base, curModName); App(base, "_"); App(base, varName);
|
|
|
+ Cpy(tmpl, base); App(tmpl, "_tmpl");
|
|
|
+ IntStr(VAL(INTEGER, SymTab.ArrayLen(arrT)), nStr);
|
|
|
+ IntStr(VAL(INTEGER, SymTab.TypeSize(elem)), stStr);
|
|
|
+ Slot4(slot);
|
|
|
+ StoreW(slot, "0");
|
|
|
+ NewLabel(lTop); NewLabel(lBody); NewLabel(lDone);
|
|
|
+ EmitLabel(lTop);
|
|
|
+ LoadW(slot, i);
|
|
|
+ NewTemp(c); Op3("csltw", c, i, nStr, FALSE);
|
|
|
+ Jnz(c, lBody, lDone);
|
|
|
+ EmitLabel(lBody);
|
|
|
+ LoadW(slot, i);
|
|
|
+ WidenIndex(i, il);
|
|
|
+ NewTemp(off); Op3L("mul", off, il, stStr);
|
|
|
+ NewTemp(tb); Op3L("add", tb, base, "8");
|
|
|
+ NewTemp(p); Op3L("add", p, tb, off);
|
|
|
+ CopyRecord(p, tmpl, elem);
|
|
|
+ LoadW(slot, i);
|
|
|
+ NewTemp(one); CopyOp("1", one);
|
|
|
+ NewTemp(two); Op3("add", two, i, one, FALSE);
|
|
|
+ StoreW(slot, two);
|
|
|
+ Jmp(lTop);
|
|
|
+ EmitLabel(lDone)
|
|
|
+ END InitRecArray;
|
|
|
+
|
|
|
BEGIN
|
|
|
opened := FALSE;
|
|
|
inBody := FALSE;
|