|
|
@@ -28,11 +28,22 @@ VAR
|
|
|
useStack : BOOLEAN;(* TRUE: NewHeap allocates stack slots *)
|
|
|
funcRes : CHAR; (* current function result class *)
|
|
|
nLoc : CARDINAL; (* function-local name table entries *)
|
|
|
- locNames : ARRAY [0 .. 63] OF SymTab.Name;
|
|
|
- locTag : ARRAY [0 .. 63] OF INTEGER; (* 0 slot, 1 data, 2 addr *)
|
|
|
- locRep : ARRAY [0 .. 63] OF QVal; (* slot temp / mangled / addr *)
|
|
|
- locCls : ARRAY [0 .. 63] OF CHAR;
|
|
|
- locTyp : ARRAY [0 .. 63] OF INTEGER;
|
|
|
+ locNames : ARRAY [0 .. 255] OF SymTab.Name;
|
|
|
+ locTag : ARRAY [0 .. 255] OF INTEGER; (* 0 slot, 1 data, 2 addr *)
|
|
|
+ locRep : ARRAY [0 .. 255] OF QVal; (* slot temp / mangled / addr *)
|
|
|
+ locCls : ARRAY [0 .. 255] OF CHAR;
|
|
|
+ locTyp : ARRAY [0 .. 255] OF INTEGER;
|
|
|
+ funcDepth : CARDINAL; (* open BeginFuncs; main body = 0 *)
|
|
|
+ scopeTop : CARDINAL; (* open procedure scopes *)
|
|
|
+ scopeBase : ARRAY [0 .. 16] OF CARDINAL;
|
|
|
+ scopeLink : ARRAY [0 .. 15] OF QVal; (* per-scope link records *)
|
|
|
+ slTmp : QVal; (* current static-link param temp *)
|
|
|
+ hdrComma : BOOLEAN;
|
|
|
+ stkLink : ARRAY [0 .. 15] OF QVal; (* per-call static links *)
|
|
|
+ outSel : CARDINAL; (* 0 = file, else nestBufs[outSel-1] *)
|
|
|
+ nestBufs : ARRAY [0 .. 15] OF ARRAY [0 .. 65535] OF CHAR;
|
|
|
+ (* one buffer per nesting depth: each nested function stays
|
|
|
+ contiguous no matter how deep the parse interleaves *)
|
|
|
nPar : CARDINAL; (* recorded formal params for the header *)
|
|
|
parCls : ARRAY [0 .. 63] OF CHAR;
|
|
|
parTmp : ARRAY [0 .. 63] OF QVal;
|
|
|
@@ -84,15 +95,40 @@ PROCEDURE App (VAR d: ARRAY OF CHAR; s: ARRAY OF CHAR);
|
|
|
IF i <= HIGH(d) THEN d[i] := 0C END
|
|
|
END App;
|
|
|
|
|
|
+PROCEDURE WEmit (s: ARRAY OF CHAR; eol: BOOLEAN);
|
|
|
+(* Single output sink: file, or the nest buffer for nested
|
|
|
+ functions (QBE rejects definitions inside functions, so nested
|
|
|
+ bodies buffer until EndModule). *)
|
|
|
+ VAR i, j, b : CARDINAL;
|
|
|
+ BEGIN
|
|
|
+ IF ~opened OR noEmit THEN RETURN END;
|
|
|
+ IF outSel = 0 THEN
|
|
|
+ FileIO.WriteString(out, s);
|
|
|
+ IF eol THEN FileIO.WriteLn(out) END;
|
|
|
+ RETURN
|
|
|
+ END;
|
|
|
+ b := outSel - 1;
|
|
|
+ IF b > HIGH(nestBufs) THEN b := HIGH(nestBufs) END;
|
|
|
+ i := 0;
|
|
|
+ WHILE (i <= HIGH(nestBufs[b])) & (nestBufs[b][i] # 0C) DO INC(i) END;
|
|
|
+ j := 0;
|
|
|
+ WHILE (i < HIGH(nestBufs[b])) & (j <= HIGH(s)) & (s[j] # 0C) DO
|
|
|
+ nestBufs[b][i] := s[j]; INC(i); INC(j)
|
|
|
+ END;
|
|
|
+ IF eol & (i < HIGH(nestBufs[b])) THEN
|
|
|
+ nestBufs[b][i] := CHR(10); INC(i)
|
|
|
+ END;
|
|
|
+ IF i <= HIGH(nestBufs[b]) THEN nestBufs[b][i] := 0C END
|
|
|
+ END WEmit;
|
|
|
+
|
|
|
PROCEDURE W (s: ARRAY OF CHAR);
|
|
|
BEGIN
|
|
|
- IF opened & ~noEmit THEN FileIO.WriteString(out, s) END
|
|
|
+ WEmit(s, FALSE)
|
|
|
END W;
|
|
|
|
|
|
PROCEDURE WL (s: ARRAY OF CHAR);
|
|
|
BEGIN
|
|
|
- W(s);
|
|
|
- IF opened & ~noEmit THEN FileIO.WriteLn(out) END
|
|
|
+ WEmit(s, TRUE)
|
|
|
END WL;
|
|
|
|
|
|
PROCEDURE SetNoEmit (b: BOOLEAN);
|
|
|
@@ -102,8 +138,10 @@ PROCEDURE SetNoEmit (b: BOOLEAN);
|
|
|
|
|
|
PROCEDURE Wc (c: CHAR);
|
|
|
(* Writes a single class character (w/d/l). *)
|
|
|
+ VAR s : ARRAY [0 .. 1] OF CHAR;
|
|
|
BEGIN
|
|
|
- IF opened & ~noEmit THEN FileIO.Write(out, c) END
|
|
|
+ s[0] := c; s[1] := 0C;
|
|
|
+ W(s)
|
|
|
END Wc;
|
|
|
|
|
|
PROCEDURE AppNum (VAR d: ARRAY OF CHAR; v: CARDINAL);
|
|
|
@@ -158,19 +196,23 @@ PROCEDURE AddrOfVal (val: ARRAY OF CHAR; VAR addr: QVal): BOOLEAN;
|
|
|
|
|
|
PROCEDURE AddrOf (name: ARRAY OF CHAR; VAR q: QVal);
|
|
|
VAR idx : INTEGER;
|
|
|
+ levels : CARDINAL;
|
|
|
BEGIN
|
|
|
- idx := LocFind(name);
|
|
|
- IF idx = -1 THEN
|
|
|
- Cpy(q, "$");
|
|
|
- App(q, name);
|
|
|
+ IF LocFindUp(name, levels, idx) THEN
|
|
|
+ IF levels = 0 THEN
|
|
|
+ IF locTag[idx] = 1 THEN
|
|
|
+ Cpy(q, "$");
|
|
|
+ App(q, locRep[idx])
|
|
|
+ ELSE
|
|
|
+ Cpy(q, locRep[idx])
|
|
|
+ END
|
|
|
+ ELSE
|
|
|
+ UpAddrOf(idx, levels, q)
|
|
|
+ END;
|
|
|
RETURN
|
|
|
END;
|
|
|
- IF locTag[idx] = 1 THEN
|
|
|
- Cpy(q, "$");
|
|
|
- App(q, locRep[idx])
|
|
|
- ELSE
|
|
|
- Cpy(q, locRep[idx])
|
|
|
- END
|
|
|
+ Cpy(q, "$");
|
|
|
+ App(q, name)
|
|
|
END AddrOf;
|
|
|
|
|
|
PROCEDURE IntStr (v: INTEGER; VAR s: QVal);
|
|
|
@@ -311,6 +353,7 @@ PROCEDURE IsImm (s: ARRAY OF CHAR): BOOLEAN;
|
|
|
|
|
|
PROCEDURE OpenModule (name: ARRAY OF CHAR);
|
|
|
VAR fname : ARRAY [0 .. 127] OF CHAR;
|
|
|
+ i : CARDINAL;
|
|
|
BEGIN
|
|
|
fname[0] := 0C;
|
|
|
App(fname, "gen_ssa/");
|
|
|
@@ -324,6 +367,10 @@ PROCEDURE OpenModule (name: ARRAY OF CHAR);
|
|
|
withTop := 0;
|
|
|
noEmit := FALSE; inFunc := FALSE; useStack := FALSE;
|
|
|
nLoc := 0; nPar := 0; nArg := 0; nn := 0; callDepth := 0;
|
|
|
+ funcDepth := 0; scopeTop := 0; scopeBase[0] := 0;
|
|
|
+ outSel := 0;
|
|
|
+ i := 0;
|
|
|
+ WHILE i <= HIGH(nestBufs) DO nestBufs[i][0] := 0C; INC(i) END;
|
|
|
WL("# QBE IR generated by the V3 step-1 backend");
|
|
|
WL("")
|
|
|
END OpenModule;
|
|
|
@@ -447,6 +494,7 @@ PROCEDURE CloseModule;
|
|
|
END CloseModule;
|
|
|
|
|
|
PROCEDURE EndModule;
|
|
|
+ VAR i : CARDINAL;
|
|
|
BEGIN
|
|
|
IF ~opened THEN RETURN END;
|
|
|
IF ~inBody THEN BeginBody END;
|
|
|
@@ -459,6 +507,13 @@ PROCEDURE EndModule;
|
|
|
WL(" ret 0")
|
|
|
END;
|
|
|
WL("}");
|
|
|
+ i := 0;
|
|
|
+ WHILE i <= HIGH(nestBufs) DO
|
|
|
+ IF nestBufs[i][0] # 0C THEN
|
|
|
+ FileIO.WriteString(out, nestBufs[i])
|
|
|
+ END;
|
|
|
+ INC(i)
|
|
|
+ END;
|
|
|
FlushStrings;
|
|
|
FileIO.Close(out);
|
|
|
opened := FALSE
|
|
|
@@ -481,19 +536,105 @@ PROCEDURE LocFind (name: ARRAY OF CHAR): INTEGER;
|
|
|
RETURN -1
|
|
|
END LocFind;
|
|
|
|
|
|
+PROCEDURE ScopeBegin;
|
|
|
+(* Pushes a procedure scope (always balanced, even under NoEmit). *)
|
|
|
+ BEGIN
|
|
|
+ IF scopeTop > HIGH(scopeLink) THEN RETURN END;
|
|
|
+ scopeBase[scopeTop] := nLoc;
|
|
|
+ INC(scopeTop);
|
|
|
+ scopeBase[scopeTop] := nLoc
|
|
|
+ END ScopeBegin;
|
|
|
+
|
|
|
+PROCEDURE ScopeEnd;
|
|
|
+ BEGIN
|
|
|
+ IF scopeTop > 0 THEN
|
|
|
+ DEC(scopeTop);
|
|
|
+ nLoc := scopeBase[scopeTop]
|
|
|
+ END
|
|
|
+ END ScopeEnd;
|
|
|
+
|
|
|
+PROCEDURE LocFindUp (name: ARRAY OF CHAR; VAR levels: CARDINAL;
|
|
|
+ VAR flat: INTEGER): BOOLEAN;
|
|
|
+(* Innermost procedure scope holding name; levels = scopes crossed,
|
|
|
+ flat = table index. FALSE when purely global. *)
|
|
|
+ VAR s, top, lo, hi, j : CARDINAL;
|
|
|
+ BEGIN
|
|
|
+ levels := 0; flat := -1;
|
|
|
+ IF scopeTop = 0 THEN RETURN FALSE END;
|
|
|
+ top := scopeTop - 1;
|
|
|
+ s := top;
|
|
|
+ LOOP
|
|
|
+ lo := scopeBase[s];
|
|
|
+ IF s = top THEN hi := nLoc ELSE hi := scopeBase[s + 1] END;
|
|
|
+ j := lo;
|
|
|
+ WHILE j < hi DO
|
|
|
+ IF SymTab.Equal(locNames[j], name) THEN
|
|
|
+ levels := top - s;
|
|
|
+ flat := VAL(INTEGER, j);
|
|
|
+ RETURN TRUE
|
|
|
+ END;
|
|
|
+ INC(j)
|
|
|
+ END;
|
|
|
+ IF s = 0 THEN RETURN FALSE END;
|
|
|
+ DEC(s)
|
|
|
+ END
|
|
|
+ END LocFindUp;
|
|
|
+
|
|
|
PROCEDURE LocAdd (name: ARRAY OF CHAR; tag: INTEGER; rep: ARRAY OF CHAR;
|
|
|
cls: CHAR; typ: INTEGER);
|
|
|
+ VAR idx : CARDINAL;
|
|
|
+ off : QVal;
|
|
|
+ lk : QVal;
|
|
|
BEGIN
|
|
|
IF noEmit THEN RETURN END;
|
|
|
- IF nLoc > HIGH(locNames) THEN RETURN END;
|
|
|
+ IF (scopeTop = 0) OR (nLoc > HIGH(locNames)) THEN RETURN END;
|
|
|
+ idx := nLoc - scopeBase[scopeTop - 1];
|
|
|
+ IF idx > 63 THEN RETURN END;
|
|
|
Cpy(locNames[nLoc], name);
|
|
|
locTag[nLoc] := tag;
|
|
|
Cpy(locRep[nLoc], rep);
|
|
|
locCls[nLoc] := cls;
|
|
|
locTyp[nLoc] := typ;
|
|
|
- INC(nLoc)
|
|
|
+ INC(nLoc);
|
|
|
+ IF tag = 1 THEN RETURN END;
|
|
|
+ Cpy(lk, scopeLink[scopeTop - 1]);
|
|
|
+ IntStr(VAL(INTEGER, 8 * (idx + 1)), off);
|
|
|
+ NewTemp(lk);
|
|
|
+ Op3L("add", lk, scopeLink[scopeTop - 1], off);
|
|
|
+ Revive;
|
|
|
+ W(" storel "); W(rep); W(", "); WL(lk)
|
|
|
END LocAdd;
|
|
|
|
|
|
+PROCEDURE LocFull (): BOOLEAN;
|
|
|
+(* TRUE past 64 locals in the current scope (→ 233). *)
|
|
|
+ BEGIN
|
|
|
+ IF scopeTop = 0 THEN RETURN FALSE END;
|
|
|
+ RETURN nLoc - scopeBase[scopeTop - 1] > 63
|
|
|
+ END LocFull;
|
|
|
+
|
|
|
+PROCEDURE UpAddr (levels: CARDINAL; rel: CARDINAL; VAR q: QVal);
|
|
|
+(* Address of an up-level local: walks the static chain, then
|
|
|
+ loads the link cell (slot address or actual address). *)
|
|
|
+ VAR cur, t, off : QVal;
|
|
|
+ L : CARDINAL;
|
|
|
+ BEGIN
|
|
|
+ Cpy(cur, scopeLink[scopeTop - 1]);
|
|
|
+ L := levels;
|
|
|
+ WHILE L > 0 DO
|
|
|
+ NewTemp(t);
|
|
|
+ Revive;
|
|
|
+ W(" "); W(t); W(" =l loadl "); WL(cur);
|
|
|
+ Cpy(cur, t);
|
|
|
+ DEC(L)
|
|
|
+ END;
|
|
|
+ IntStr(VAL(INTEGER, 8 * (rel + 1)), off);
|
|
|
+ NewTemp(t);
|
|
|
+ Op3L("add", t, cur, off);
|
|
|
+ NewTemp(q);
|
|
|
+ Revive;
|
|
|
+ W(" "); W(q); W(" =l loadl "); WL(t)
|
|
|
+ END UpAddr;
|
|
|
+
|
|
|
PROCEDURE ResClass (t: INTEGER): CHAR;
|
|
|
VAR cls : INTEGER;
|
|
|
BEGIN
|
|
|
@@ -553,15 +694,29 @@ PROCEDURE AllocLocal (t: INTEGER; VAR slot: QVal);
|
|
|
END AllocLocal;
|
|
|
|
|
|
PROCEDURE BeginFunc (mangled: ARRAY OF CHAR);
|
|
|
-(* Opens function context; the header is buffered until
|
|
|
- EndFuncHeader (FORWARD/DefUnit paths discard via AbortFunc). *)
|
|
|
+(* Opens function context and scope; the header (with a leading
|
|
|
+ static-link param) buffers until EndFuncHeader. FORWARD/DefUnit
|
|
|
+ paths discard via AbortFunc. *)
|
|
|
BEGIN
|
|
|
+ ScopeBegin;
|
|
|
+ INC(funcDepth);
|
|
|
inFunc := TRUE;
|
|
|
- nLoc := 0;
|
|
|
nPar := 0;
|
|
|
funcRes := "w";
|
|
|
Cpy(funcName, mangled);
|
|
|
- hbuf[0] := 0C
|
|
|
+ hbuf[0] := 0C;
|
|
|
+ NewTemp(slTmp);
|
|
|
+ HApp("l ");
|
|
|
+ HApp(slTmp);
|
|
|
+ hdrComma := TRUE;
|
|
|
+ IF funcDepth > 1 THEN
|
|
|
+ outSel := funcDepth - 1;
|
|
|
+ IF outSel > HIGH(nestBufs) + 1 THEN
|
|
|
+ outSel := HIGH(nestBufs) + 1
|
|
|
+ END
|
|
|
+ ELSE
|
|
|
+ outSel := 0
|
|
|
+ END
|
|
|
END BeginFunc;
|
|
|
|
|
|
PROCEDURE SetFuncRes (t: INTEGER);
|
|
|
@@ -597,7 +752,8 @@ PROCEDURE FuncParam (name: ARRAY OF CHAR; isVar: BOOLEAN;
|
|
|
Cpy(parNam[nPar], name);
|
|
|
parVar[nPar] := isVar;
|
|
|
parTyp[nPar] := t;
|
|
|
- IF nPar > 0 THEN HApp(", ") END;
|
|
|
+ IF hdrComma THEN HApp(", ") END;
|
|
|
+ hdrComma := TRUE;
|
|
|
buf[0] := c; buf[1] := " "; buf[2] := 0C;
|
|
|
App(buf, tmp);
|
|
|
HApp(buf);
|
|
|
@@ -606,9 +762,10 @@ PROCEDURE FuncParam (name: ARRAY OF CHAR; isVar: BOOLEAN;
|
|
|
END FuncParam;
|
|
|
|
|
|
PROCEDURE EndFuncHeader;
|
|
|
-(* Flushes the buffered header + body label + entry copies. *)
|
|
|
+(* Flushes the buffered header + body label, allocates the link
|
|
|
+ record ([0] = parent link), then emits entry copies. *)
|
|
|
VAR i : CARDINAL;
|
|
|
- slot, nb : QVal;
|
|
|
+ slot, nb, lk : QVal;
|
|
|
cls : INTEGER;
|
|
|
BEGIN
|
|
|
W("export function "); Wc(funcRes); W(" $"); W(funcName); W("(");
|
|
|
@@ -616,6 +773,11 @@ PROCEDURE EndFuncHeader;
|
|
|
WL(") {");
|
|
|
WL("@start");
|
|
|
inBody := TRUE;
|
|
|
+ NewTemp(lk);
|
|
|
+ Cpy(scopeLink[scopeTop - 1], lk);
|
|
|
+ Revive;
|
|
|
+ W(" "); W(lk); W(" =l alloc8 520"); WL("");
|
|
|
+ W(" storel "); W(slTmp); W(", "); WL(lk);
|
|
|
i := 0;
|
|
|
WHILE i < nPar DO
|
|
|
cls := SymTab.ClassOf(parTyp[i]);
|
|
|
@@ -648,12 +810,16 @@ PROCEDURE EndFuncHeader;
|
|
|
|
|
|
PROCEDURE AbortFunc;
|
|
|
(* Discards function context without emitting (DefUnit headings,
|
|
|
- FORWARD, methods, nested-in-4.1): resets inFunc and params. *)
|
|
|
+ FORWARD, methods): pops the scope, restores the depth. *)
|
|
|
BEGIN
|
|
|
- inFunc := FALSE;
|
|
|
+ ScopeEnd;
|
|
|
+ IF funcDepth > 0 THEN DEC(funcDepth) END;
|
|
|
+ inFunc := funcDepth > 0;
|
|
|
inBody := FALSE;
|
|
|
nPar := 0;
|
|
|
- nLoc := 0
|
|
|
+ IF funcDepth > 1 THEN outSel := funcDepth - 1
|
|
|
+ ELSE outSel := 0
|
|
|
+ END
|
|
|
END AbortFunc;
|
|
|
|
|
|
PROCEDURE EndFunc (resT: INTEGER);
|
|
|
@@ -666,8 +832,13 @@ PROCEDURE EndFunc (resT: INTEGER);
|
|
|
ELSE WL(" ret 0")
|
|
|
END;
|
|
|
WL("}");
|
|
|
- inFunc := FALSE;
|
|
|
- inBody := FALSE
|
|
|
+ ScopeEnd;
|
|
|
+ IF funcDepth > 0 THEN DEC(funcDepth) END;
|
|
|
+ inFunc := funcDepth > 0;
|
|
|
+ inBody := FALSE;
|
|
|
+ IF funcDepth > 1 THEN outSel := funcDepth - 1
|
|
|
+ ELSE outSel := 0
|
|
|
+ END
|
|
|
END EndFunc;
|
|
|
|
|
|
PROCEDURE EmitRet (q: ARRAY OF CHAR; hasVal: BOOLEAN);
|
|
|
@@ -679,15 +850,34 @@ PROCEDURE EmitRet (q: ARRAY OF CHAR; hasVal: BOOLEAN);
|
|
|
dead := TRUE
|
|
|
END EmitRet;
|
|
|
|
|
|
-PROCEDURE CallBegin (mangled: ARRAY OF CHAR; resT: INTEGER);
|
|
|
- BEGIN
|
|
|
- IF callDepth <= HIGH(stkName) THEN
|
|
|
- Cpy(stkName[callDepth], mangled);
|
|
|
- stkRes[callDepth] := ResClass(resT);
|
|
|
- stkArg[callDepth][0] := 0C;
|
|
|
- stkN[callDepth] := 0;
|
|
|
- INC(callDepth)
|
|
|
- END
|
|
|
+PROCEDURE CallBegin (mangled: ARRAY OF CHAR; resT: INTEGER;
|
|
|
+ fdep: CARDINAL);
|
|
|
+(* Pushes a call level; the static link is resolved now (caller
|
|
|
+ context cannot change mid-call): module callers pass 0, others
|
|
|
+ walk the chain (inFuncDepth - fdep) from their link record. *)
|
|
|
+ VAR walks : INTEGER;
|
|
|
+ cur, t : QVal;
|
|
|
+ BEGIN
|
|
|
+ IF callDepth > HIGH(stkName) THEN RETURN END;
|
|
|
+ Cpy(stkName[callDepth], mangled);
|
|
|
+ stkRes[callDepth] := ResClass(resT);
|
|
|
+ stkArg[callDepth][0] := 0C;
|
|
|
+ stkN[callDepth] := 0;
|
|
|
+ IF funcDepth = 0 THEN
|
|
|
+ Cpy(stkLink[callDepth], "0")
|
|
|
+ ELSE
|
|
|
+ walks := VAL(INTEGER, funcDepth) - VAL(INTEGER, fdep);
|
|
|
+ Cpy(cur, scopeLink[scopeTop - 1]);
|
|
|
+ WHILE walks > 0 DO
|
|
|
+ NewTemp(t);
|
|
|
+ Revive;
|
|
|
+ W(" "); W(t); W(" =l loadl "); WL(cur);
|
|
|
+ Cpy(cur, t);
|
|
|
+ DEC(walks)
|
|
|
+ END;
|
|
|
+ Cpy(stkLink[callDepth], cur)
|
|
|
+ END;
|
|
|
+ INC(callDepth)
|
|
|
END CallBegin;
|
|
|
|
|
|
PROCEDURE CallArg (q: ARRAY OF CHAR; cls: CHAR): BOOLEAN;
|
|
|
@@ -742,7 +932,9 @@ PROCEDURE CallEnd (wantRes: BOOLEAN; VAR q: QVal);
|
|
|
ELSE
|
|
|
W(" ")
|
|
|
END;
|
|
|
- W(" call $"); W(funcName); W("("); W(body); WL(")")
|
|
|
+ W(" call $"); W(funcName); W("(l "); W(stkLink[d]);
|
|
|
+ IF body[0] # 0C THEN W(", "); W(body) END;
|
|
|
+ WL(")")
|
|
|
END CallEnd;
|
|
|
|
|
|
PROCEDURE InitStack (addr: ARRAY OF CHAR; t: INTEGER);
|
|
|
@@ -767,9 +959,9 @@ PROCEDURE NewTemp (VAR t: QVal);
|
|
|
INC(nTemp)
|
|
|
END NewTemp;
|
|
|
|
|
|
-PROCEDURE LocLoad (idx: INTEGER; long: BOOLEAN; VAR q: QVal);
|
|
|
-(* Loads a local entry: slots/data by class (or long for pointers),
|
|
|
- addr entries via ElemLoad. *)
|
|
|
+PROCEDURE LocLoadFlat (idx: INTEGER; long: BOOLEAN; VAR q: QVal);
|
|
|
+(* Loads a same-scope entry: slots/data by class (or long for
|
|
|
+ pointers), addr entries via ElemLoad. *)
|
|
|
BEGIN
|
|
|
IF locTag[idx] = 2 THEN
|
|
|
ElemLoad(locRep[idx], locTyp[idx], q);
|
|
|
@@ -784,11 +976,11 @@ PROCEDURE LocLoad (idx: INTEGER; long: BOOLEAN; VAR q: QVal);
|
|
|
END;
|
|
|
IF locTag[idx] = 1 THEN W("$") END;
|
|
|
WL(locRep[idx])
|
|
|
- END LocLoad;
|
|
|
+ END LocLoadFlat;
|
|
|
|
|
|
-PROCEDURE LocStore (idx: INTEGER; q: ARRAY OF CHAR; long: BOOLEAN);
|
|
|
-(* Stores a local entry: slots/data by class (or long), addr via
|
|
|
- ElemStore. Data stores are grammar-unreachable (consts). *)
|
|
|
+PROCEDURE LocStoreFlat (idx: INTEGER; q: ARRAY OF CHAR; long: BOOLEAN);
|
|
|
+(* Stores a same-scope entry: slots/data by class (or long), addr
|
|
|
+ via ElemStore. Data stores are grammar-unreachable (consts). *)
|
|
|
BEGIN
|
|
|
IF locTag[idx] = 2 THEN
|
|
|
ElemStore(locRep[idx], q, locTyp[idx]);
|
|
|
@@ -802,60 +994,126 @@ PROCEDURE LocStore (idx: INTEGER; q: ARRAY OF CHAR; long: BOOLEAN);
|
|
|
W(q); W(", ");
|
|
|
IF locTag[idx] = 1 THEN W("$") END;
|
|
|
WL(locRep[idx])
|
|
|
- END LocStore;
|
|
|
+ END LocStoreFlat;
|
|
|
|
|
|
-PROCEDURE LoadVar (name: ARRAY OF CHAR; isReal: BOOLEAN; VAR q: QVal);
|
|
|
- VAR idx : INTEGER;
|
|
|
+PROCEDURE UpLoad (flat: INTEGER; levels: CARDINAL; long: BOOLEAN;
|
|
|
+ VAR q: QVal);
|
|
|
+(* Up-level load: data entries live globally; otherwise the link
|
|
|
+ cell yields the address and ElemLoad reads through it. *)
|
|
|
+ VAR a : QVal;
|
|
|
+ rel : CARDINAL;
|
|
|
BEGIN
|
|
|
- idx := LocFind(name);
|
|
|
- IF idx = -1 THEN
|
|
|
+ IF locTag[flat] = 1 THEN
|
|
|
NewTemp(q);
|
|
|
Revive;
|
|
|
W(" "); W(q);
|
|
|
- IF isReal THEN W(" =d loadd $") ELSE W(" =w loadw $") END;
|
|
|
- WL(name);
|
|
|
+ IF long THEN W(" =l loadl $")
|
|
|
+ ELSIF locCls[flat] = "d" THEN W(" =d loadd $")
|
|
|
+ ELSE W(" =w loadw $")
|
|
|
+ END;
|
|
|
+ WL(locRep[flat]);
|
|
|
+ RETURN
|
|
|
+ END;
|
|
|
+ rel := VAL(CARDINAL, flat) - scopeBase[scopeTop - 1 - levels];
|
|
|
+ UpAddr(levels, rel, a);
|
|
|
+ ElemLoad(a, locTyp[flat], q)
|
|
|
+ END UpLoad;
|
|
|
+
|
|
|
+PROCEDURE UpStore (flat: INTEGER; levels: CARDINAL; q: ARRAY OF CHAR;
|
|
|
+ long: BOOLEAN);
|
|
|
+ VAR a : QVal;
|
|
|
+ rel : CARDINAL;
|
|
|
+ BEGIN
|
|
|
+ IF locTag[flat] = 1 THEN
|
|
|
+ Revive;
|
|
|
+ IF long THEN W(" storel ")
|
|
|
+ ELSIF locCls[flat] = "d" THEN W(" stored ")
|
|
|
+ ELSE W(" storew ")
|
|
|
+ END;
|
|
|
+ W(q); W(", $"); WL(locRep[flat]);
|
|
|
+ RETURN
|
|
|
+ END;
|
|
|
+ rel := VAL(CARDINAL, flat) - scopeBase[scopeTop - 1 - levels];
|
|
|
+ UpAddr(levels, rel, a);
|
|
|
+ ElemStore(a, q, locTyp[flat])
|
|
|
+ END UpStore;
|
|
|
+
|
|
|
+PROCEDURE UpAddrOf (flat: INTEGER; levels: CARDINAL; VAR q: QVal);
|
|
|
+(* Up-level address: data entries name globals; otherwise the
|
|
|
+ link cell holds it (composites) or points at it. For scalars
|
|
|
+ the cell IS the usable address (slot or actual address). *)
|
|
|
+ VAR a : QVal;
|
|
|
+ rel : CARDINAL;
|
|
|
+ BEGIN
|
|
|
+ IF locTag[flat] = 1 THEN
|
|
|
+ Cpy(q, "$");
|
|
|
+ App(q, locRep[flat]);
|
|
|
RETURN
|
|
|
END;
|
|
|
- LocLoad(idx, FALSE, q)
|
|
|
+ rel := VAL(CARDINAL, flat) - scopeBase[scopeTop - 1 - levels];
|
|
|
+ UpAddr(levels, rel, q)
|
|
|
+ END UpAddrOf;
|
|
|
+
|
|
|
+PROCEDURE LoadVar (name: ARRAY OF CHAR; isReal: BOOLEAN; VAR q: QVal);
|
|
|
+ VAR idx : INTEGER;
|
|
|
+ levels : CARDINAL;
|
|
|
+ BEGIN
|
|
|
+ IF LocFindUp(name, levels, idx) THEN
|
|
|
+ IF levels = 0 THEN LocLoadFlat(idx, FALSE, q)
|
|
|
+ ELSE UpLoad(idx, levels, FALSE, q)
|
|
|
+ END;
|
|
|
+ RETURN
|
|
|
+ END;
|
|
|
+ NewTemp(q);
|
|
|
+ Revive;
|
|
|
+ W(" "); W(q);
|
|
|
+ IF isReal THEN W(" =d loadd $") ELSE W(" =w loadw $") END;
|
|
|
+ WL(name)
|
|
|
END LoadVar;
|
|
|
|
|
|
PROCEDURE LoadPtr (name: ARRAY OF CHAR; VAR q: QVal);
|
|
|
VAR idx : INTEGER;
|
|
|
+ levels : CARDINAL;
|
|
|
BEGIN
|
|
|
- idx := LocFind(name);
|
|
|
- IF idx = -1 THEN
|
|
|
- NewTemp(q);
|
|
|
- Revive;
|
|
|
- W(" "); W(q); W(" =l loadl $");
|
|
|
- WL(name);
|
|
|
+ IF LocFindUp(name, levels, idx) THEN
|
|
|
+ IF levels = 0 THEN LocLoadFlat(idx, TRUE, q)
|
|
|
+ ELSE UpLoad(idx, levels, TRUE, q)
|
|
|
+ END;
|
|
|
RETURN
|
|
|
END;
|
|
|
- LocLoad(idx, TRUE, q)
|
|
|
+ NewTemp(q);
|
|
|
+ Revive;
|
|
|
+ W(" "); W(q); W(" =l loadl $");
|
|
|
+ WL(name)
|
|
|
END LoadPtr;
|
|
|
|
|
|
PROCEDURE StoreVar (name: ARRAY OF CHAR; q: ARRAY OF CHAR; isReal: BOOLEAN);
|
|
|
VAR idx : INTEGER;
|
|
|
+ levels : CARDINAL;
|
|
|
BEGIN
|
|
|
- idx := LocFind(name);
|
|
|
- IF idx = -1 THEN
|
|
|
- Revive;
|
|
|
- IF isReal THEN W(" stored ") ELSE W(" storew ") END;
|
|
|
- W(q); W(", $"); WL(name);
|
|
|
+ IF LocFindUp(name, levels, idx) THEN
|
|
|
+ IF levels = 0 THEN LocStoreFlat(idx, q, FALSE)
|
|
|
+ ELSE UpStore(idx, levels, q, FALSE)
|
|
|
+ END;
|
|
|
RETURN
|
|
|
END;
|
|
|
- LocStore(idx, q, FALSE)
|
|
|
+ Revive;
|
|
|
+ IF isReal THEN W(" stored ") ELSE W(" storew ") END;
|
|
|
+ W(q); W(", $"); WL(name)
|
|
|
END StoreVar;
|
|
|
|
|
|
PROCEDURE StorePtr (name: ARRAY OF CHAR; q: ARRAY OF CHAR);
|
|
|
VAR idx : INTEGER;
|
|
|
+ levels : CARDINAL;
|
|
|
BEGIN
|
|
|
- idx := LocFind(name);
|
|
|
- IF idx = -1 THEN
|
|
|
- Revive;
|
|
|
- W(" storel "); W(q); W(", $"); WL(name);
|
|
|
+ IF LocFindUp(name, levels, idx) THEN
|
|
|
+ IF levels = 0 THEN LocStoreFlat(idx, q, TRUE)
|
|
|
+ ELSE UpStore(idx, levels, q, TRUE)
|
|
|
+ END;
|
|
|
RETURN
|
|
|
END;
|
|
|
- LocStore(idx, q, TRUE)
|
|
|
+ Revive;
|
|
|
+ W(" storel "); W(q); W(", $"); WL(name)
|
|
|
END StorePtr;
|
|
|
|
|
|
PROCEDURE Op3 (mn: ARRAY OF CHAR; res, l, r: ARRAY OF CHAR;
|
|
|
@@ -1847,5 +2105,7 @@ BEGIN
|
|
|
nTemp := 0; nLab := 0; loopTop := 0; nR := 0; nStr := 0;
|
|
|
withTop := 0;
|
|
|
noEmit := FALSE; inFunc := FALSE; useStack := FALSE;
|
|
|
- nLoc := 0; nPar := 0; nArg := 0; nn := 0; callDepth := 0
|
|
|
+ nLoc := 0; nPar := 0; nArg := 0; nn := 0; callDepth := 0;
|
|
|
+ funcDepth := 0; scopeTop := 0; scopeBase[0] := 0;
|
|
|
+ outSel := 0
|
|
|
END QbeGen.
|