|
@@ -1,5 +1,7 @@
|
|
|
IMPLEMENTATION MODULE Lower;
|
|
IMPLEMENTATION MODULE Lower;
|
|
|
-(* Scalar + boolean walk (L0/L1): see Lower.def and docs/plan-lower.md. *)
|
|
|
|
|
|
|
+(* Scalar/boolean/control-flow walk (L0-L2): see Lower.def and
|
|
|
|
|
+ docs/plan-lower.md. No FORWARD declarations: sequence iteration and
|
|
|
|
|
+ statement dispatch are merged into CanStmt / LowerStmt. *)
|
|
|
|
|
|
|
|
IMPORT AST, SymTab, QbeGen;
|
|
IMPORT AST, SymTab, QbeGen;
|
|
|
|
|
|
|
@@ -79,6 +81,49 @@ PROCEDURE CanExpr (n: AST.Node): BOOLEAN;
|
|
|
RETURN FALSE
|
|
RETURN FALSE
|
|
|
END CanExpr;
|
|
END CanExpr;
|
|
|
|
|
|
|
|
|
|
+PROCEDURE CanStmt (n: AST.Node): BOOLEAN;
|
|
|
|
|
+ VAR i: CARDINAL; k: INTEGER; by: AST.Node;
|
|
|
|
|
+ BEGIN
|
|
|
|
|
+ IF n = AST.NoNode THEN RETURN TRUE END;
|
|
|
|
|
+ k := AST.Kind(n);
|
|
|
|
|
+ IF k = AST.NkBlock THEN
|
|
|
|
|
+ i := 0;
|
|
|
|
|
+ WHILE i < AST.NChild(n) DO
|
|
|
|
|
+ IF NOT CanStmt(AST.Child(n, i)) THEN RETURN FALSE END;
|
|
|
|
|
+ INC(i)
|
|
|
|
|
+ END;
|
|
|
|
|
+ RETURN TRUE
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF k = AST.NkAssign THEN
|
|
|
|
|
+ RETURN IsSimpleScalar(AST.Child(n, 0)) AND CanExpr(AST.Child(n, 1))
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF k = AST.NkIf THEN
|
|
|
|
|
+ RETURN CanExpr(AST.Child(n, 0)) AND CanStmt(AST.Child(n, 1))
|
|
|
|
|
+ AND CanStmt(AST.Child(n, 2))
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF k = AST.NkWhile THEN
|
|
|
|
|
+ RETURN CanExpr(AST.Child(n, 0)) AND CanStmt(AST.Child(n, 1))
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF k = AST.NkRepeat THEN
|
|
|
|
|
+ RETURN CanStmt(AST.Child(n, 0)) AND CanExpr(AST.Child(n, 1))
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF k = AST.NkLoop THEN RETURN CanStmt(AST.Child(n, 0)) END;
|
|
|
|
|
+ IF k = AST.NkExit THEN RETURN TRUE END;
|
|
|
|
|
+ IF k = AST.NkFor THEN
|
|
|
|
|
+ by := AST.Child(n, 3);
|
|
|
|
|
+ IF (by # AST.NoNode) AND (AST.Kind(by) # AST.NkIntLit) THEN
|
|
|
|
|
+ RETURN FALSE END;
|
|
|
|
|
+ RETURN (AST.Kind(AST.Child(n, 0)) = AST.NkIdent)
|
|
|
|
|
+ AND CanExpr(AST.Child(n, 1)) AND CanExpr(AST.Child(n, 2))
|
|
|
|
|
+ AND CanStmt(AST.Child(n, 4))
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF k = AST.NkHalt THEN
|
|
|
|
|
+ IF AST.Child(n, 0) = AST.NoNode THEN RETURN TRUE END;
|
|
|
|
|
+ RETURN CanExpr(AST.Child(n, 0))
|
|
|
|
|
+ END;
|
|
|
|
|
+ RETURN FALSE
|
|
|
|
|
+ END CanStmt;
|
|
|
|
|
+
|
|
|
PROCEDURE CanDecl (c: AST.Node): BOOLEAN;
|
|
PROCEDURE CanDecl (c: AST.Node): BOOLEAN;
|
|
|
VAR i: CARDINAL;
|
|
VAR i: CARDINAL;
|
|
|
BEGIN
|
|
BEGIN
|
|
@@ -117,34 +162,12 @@ PROCEDURE CanDecls (seq: AST.Node): BOOLEAN;
|
|
|
RETURN TRUE
|
|
RETURN TRUE
|
|
|
END CanDecls;
|
|
END CanDecls;
|
|
|
|
|
|
|
|
-PROCEDURE CanStat (s: AST.Node): BOOLEAN;
|
|
|
|
|
- BEGIN
|
|
|
|
|
- IF AST.Kind(s) # AST.NkAssign THEN RETURN FALSE END;
|
|
|
|
|
- RETURN IsSimpleScalar(AST.Child(s, 0)) AND CanExpr(AST.Child(s, 1))
|
|
|
|
|
- END CanStat;
|
|
|
|
|
-
|
|
|
|
|
-PROCEDURE CanBody (seq: AST.Node): BOOLEAN;
|
|
|
|
|
- VAR i: CARDINAL; c: AST.Node;
|
|
|
|
|
- BEGIN
|
|
|
|
|
- IF seq = AST.NoNode THEN RETURN TRUE END;
|
|
|
|
|
- i := 0;
|
|
|
|
|
- WHILE i < AST.NChild(seq) DO
|
|
|
|
|
- c := AST.Child(seq, i);
|
|
|
|
|
- IF i = AST.MaxChild - 1 THEN
|
|
|
|
|
- IF NOT CanBody(c) THEN RETURN FALSE END
|
|
|
|
|
- ELSIF NOT CanStat(c) THEN RETURN FALSE
|
|
|
|
|
- END;
|
|
|
|
|
- INC(i)
|
|
|
|
|
- END;
|
|
|
|
|
- RETURN TRUE
|
|
|
|
|
- END CanBody;
|
|
|
|
|
-
|
|
|
|
|
PROCEDURE CanLower (unit: AST.Node): BOOLEAN;
|
|
PROCEDURE CanLower (unit: AST.Node): BOOLEAN;
|
|
|
BEGIN
|
|
BEGIN
|
|
|
IF AST.Kind(unit) # AST.NkUnit THEN RETURN FALSE END;
|
|
IF AST.Kind(unit) # AST.NkUnit THEN RETURN FALSE END;
|
|
|
IF AST.Kind(AST.Child(unit, 0)) # AST.NkIdent THEN RETURN FALSE END;
|
|
IF AST.Kind(AST.Child(unit, 0)) # AST.NkIdent THEN RETURN FALSE END;
|
|
|
IF AST.Child(unit, 3) # AST.NoNode THEN RETURN FALSE END;
|
|
IF AST.Child(unit, 3) # AST.NoNode THEN RETURN FALSE END;
|
|
|
- RETURN CanDecls(AST.Child(unit, 1)) AND CanBody(AST.Child(unit, 2))
|
|
|
|
|
|
|
+ RETURN CanDecls(AST.Child(unit, 1)) AND CanStmt(AST.Child(unit, 2))
|
|
|
END CanLower;
|
|
END CanLower;
|
|
|
|
|
|
|
|
PROCEDURE LowerDesign (n: AST.Node; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
PROCEDURE LowerDesign (n: AST.Node; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
@@ -272,24 +295,101 @@ PROCEDURE LowerExpr (n: AST.Node; VAR t: SymTab.TypeIndex;
|
|
|
END
|
|
END
|
|
|
END LowerExpr;
|
|
END LowerExpr;
|
|
|
|
|
|
|
|
-PROCEDURE LowerAssign (n: AST.Node);
|
|
|
|
|
- VAR dt: SymTab.TypeIndex; k, et, cls: INTEGER;
|
|
|
|
|
- qd, qe: QbeGen.QVal; qn: SymTab.Name; sfx, isR, conv: BOOLEAN;
|
|
|
|
|
|
|
+PROCEDURE LowerStmt (seq: AST.Node);
|
|
|
|
|
+ VAR i: CARDINAL; c, els, by: AST.Node; k: INTEGER;
|
|
|
|
|
+ t, t2, dt, et: SymTab.TypeIndex;
|
|
|
|
|
+ q, q2, qt, qf, qd, qe: QbeGen.QVal;
|
|
|
|
|
+ qlo, qhi, qk, qb: QbeGen.QVal;
|
|
|
|
|
+ lTop, lBody, lEnd, lThen, lElse, lNext, lFalse, lDone, lx: QbeGen.QVal;
|
|
|
|
|
+ qn, lv: SymTab.Name;
|
|
|
|
|
+ kind, op, rop, cls: INTEGER;
|
|
|
|
|
+ sfx, folded, isR, conv, hasElse: BOOLEAN;
|
|
|
BEGIN
|
|
BEGIN
|
|
|
- LowerDesign(AST.Child(n, 0), dt, k, qd, qn, sfx);
|
|
|
|
|
- LowerExpr(AST.Child(n, 1), et, qe);
|
|
|
|
|
- cls := SymTab.ClassOf(dt);
|
|
|
|
|
- isR := (dt # SymTab.InvalidType) AND (cls = SymTab.ClReal);
|
|
|
|
|
- conv := isR AND SymTab.IsIntFamily(et);
|
|
|
|
|
- IF (k = SymTab.KindVar) OR (k = SymTab.KindParam) THEN
|
|
|
|
|
- IF SymTab.IsLongFamily(dt) THEN
|
|
|
|
|
- QbeGen.StoreLong(qn, qe)
|
|
|
|
|
- ELSIF conv THEN
|
|
|
|
|
- QbeGen.ConvIR(qe, qd); QbeGen.StoreVar(qn, qd, TRUE)
|
|
|
|
|
- ELSE QbeGen.StoreVar(qn, qe, isR)
|
|
|
|
|
|
|
+ IF seq = AST.NoNode THEN RETURN END;
|
|
|
|
|
+ k := AST.Kind(seq);
|
|
|
|
|
+
|
|
|
|
|
+ IF k = AST.NkBlock THEN
|
|
|
|
|
+ i := 0;
|
|
|
|
|
+ WHILE i < AST.NChild(seq) DO
|
|
|
|
|
+ LowerStmt(AST.Child(seq, i)); INC(i)
|
|
|
|
|
+ END
|
|
|
|
|
+ ELSIF k = AST.NkAssign THEN
|
|
|
|
|
+ LowerDesign(AST.Child(seq, 0), dt, cls, qd, qn, sfx);
|
|
|
|
|
+ LowerExpr(AST.Child(seq, 1), et, qe);
|
|
|
|
|
+ isR := (dt # SymTab.InvalidType) AND (SymTab.ClassOf(dt) = SymTab.ClReal);
|
|
|
|
|
+ conv := isR AND SymTab.IsIntFamily(et);
|
|
|
|
|
+ IF (cls = SymTab.KindVar) OR (cls = SymTab.KindParam) THEN
|
|
|
|
|
+ IF SymTab.IsLongFamily(dt) THEN QbeGen.StoreLong(qn, qe)
|
|
|
|
|
+ ELSIF conv THEN QbeGen.ConvIR(qe, qd); QbeGen.StoreVar(qn, qd, TRUE)
|
|
|
|
|
+ ELSE QbeGen.StoreVar(qn, qe, isR)
|
|
|
|
|
+ END
|
|
|
|
|
+ END
|
|
|
|
|
+ ELSIF k = AST.NkIf THEN
|
|
|
|
|
+ LowerExpr(AST.Child(seq, 0), t, q);
|
|
|
|
|
+ QbeGen.NewLabel(lThen); QbeGen.NewLabel(lElse); QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ QbeGen.Jnz(q, lThen, lElse); QbeGen.EmitLabel(lThen);
|
|
|
|
|
+ LowerStmt(AST.Child(seq, 1));
|
|
|
|
|
+ QbeGen.Jmp(lEnd);
|
|
|
|
|
+ els := AST.Child(seq, 2); hasElse := FALSE;
|
|
|
|
|
+ WHILE (els # AST.NoNode) AND (AST.Kind(els) = AST.NkIf) DO
|
|
|
|
|
+ QbeGen.EmitLabel(lElse); QbeGen.NewLabel(lElse);
|
|
|
|
|
+ LowerExpr(AST.Child(els, 0), t, q);
|
|
|
|
|
+ QbeGen.NewLabel(lThen); QbeGen.Jnz(q, lThen, lElse);
|
|
|
|
|
+ QbeGen.EmitLabel(lThen);
|
|
|
|
|
+ LowerStmt(AST.Child(els, 1));
|
|
|
|
|
+ QbeGen.Jmp(lEnd);
|
|
|
|
|
+ els := AST.Child(els, 2)
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF els # AST.NoNode THEN
|
|
|
|
|
+ QbeGen.EmitLabel(lElse); hasElse := TRUE; LowerStmt(els)
|
|
|
|
|
+ END;
|
|
|
|
|
+ IF hasElse THEN QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ ELSE QbeGen.EmitLabel(lElse); QbeGen.EmitLabel(lEnd)
|
|
|
END
|
|
END
|
|
|
|
|
+ ELSIF k = AST.NkWhile THEN
|
|
|
|
|
+ QbeGen.NewLabel(lTop); QbeGen.NewLabel(lBody); QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ QbeGen.EmitLabel(lTop);
|
|
|
|
|
+ LowerExpr(AST.Child(seq, 0), t, q);
|
|
|
|
|
+ QbeGen.Jnz(q, lBody, lEnd); QbeGen.EmitLabel(lBody);
|
|
|
|
|
+ LowerStmt(AST.Child(seq, 1));
|
|
|
|
|
+ QbeGen.Jmp(lTop); QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ ELSIF k = AST.NkRepeat THEN
|
|
|
|
|
+ QbeGen.NewLabel(lTop); QbeGen.NewLabel(lEnd); QbeGen.EmitLabel(lTop);
|
|
|
|
|
+ LowerStmt(AST.Child(seq, 0));
|
|
|
|
|
+ LowerExpr(AST.Child(seq, 1), t, q);
|
|
|
|
|
+ QbeGen.Jnz(q, lEnd, lTop); QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ ELSIF k = AST.NkLoop THEN
|
|
|
|
|
+ QbeGen.NewLabel(lTop); QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ QbeGen.PushLoop(lEnd); QbeGen.EmitLabel(lTop);
|
|
|
|
|
+ LowerStmt(AST.Child(seq, 0));
|
|
|
|
|
+ QbeGen.Jmp(lTop); QbeGen.PopLoop; QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ ELSIF k = AST.NkExit THEN
|
|
|
|
|
+ IF QbeGen.TopLoop(lx) THEN QbeGen.Jmp(lx) END
|
|
|
|
|
+ ELSIF k = AST.NkFor THEN
|
|
|
|
|
+ Name(AST.Child(seq, 0), lv);
|
|
|
|
|
+ LowerExpr(AST.Child(seq, 1), t, qlo);
|
|
|
|
|
+ LowerExpr(AST.Child(seq, 2), t2, qhi);
|
|
|
|
|
+ QbeGen.StoreVar(lv, qlo, FALSE);
|
|
|
|
|
+ QbeGen.NewLabel(lTop); QbeGen.NewLabel(lBody); QbeGen.NewLabel(lEnd);
|
|
|
|
|
+ QbeGen.EmitLabel(lTop);
|
|
|
|
|
+ QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
|
|
+ QbeGen.NewTemp(qk);
|
|
|
|
|
+ QbeGen.Op3("cslew", qk, qt, qhi, FALSE);
|
|
|
|
|
+ QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
|
|
+ QbeGen.EmitLabel(lBody);
|
|
|
|
|
+ LowerStmt(AST.Child(seq, 4));
|
|
|
|
|
+ QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
|
|
+ QbeGen.IntStr(1, qb);
|
|
|
|
|
+ QbeGen.NewTemp(qk);
|
|
|
|
|
+ QbeGen.Op3("add", qk, qt, qb, FALSE);
|
|
|
|
|
+ QbeGen.StoreVar(lv, qk, FALSE);
|
|
|
|
|
+ QbeGen.Jmp(lTop); QbeGen.EmitLabel(lEnd)
|
|
|
|
|
+ ELSIF k = AST.NkHalt THEN
|
|
|
|
|
+ IF AST.Child(seq, 0) # AST.NoNode THEN
|
|
|
|
|
+ LowerExpr(AST.Child(seq, 0), t, q) END;
|
|
|
|
|
+ QbeGen.HaltQ
|
|
|
END
|
|
END
|
|
|
- END LowerAssign;
|
|
|
|
|
|
|
+ END LowerStmt;
|
|
|
|
|
|
|
|
PROCEDURE LowerDecls (seq: AST.Node);
|
|
PROCEDURE LowerDecls (seq: AST.Node);
|
|
|
VAR i, j: CARDINAL; c: AST.Node; nm, txt: SymTab.Name; qv: QbeGen.QVal;
|
|
VAR i, j: CARDINAL; c: AST.Node; nm, txt: SymTab.Name; qv: QbeGen.QVal;
|
|
@@ -317,20 +417,6 @@ PROCEDURE LowerDecls (seq: AST.Node);
|
|
|
END
|
|
END
|
|
|
END LowerDecls;
|
|
END LowerDecls;
|
|
|
|
|
|
|
|
-PROCEDURE LowerBody (seq: AST.Node);
|
|
|
|
|
- VAR i: CARDINAL; c: AST.Node;
|
|
|
|
|
- BEGIN
|
|
|
|
|
- IF seq = AST.NoNode THEN RETURN END;
|
|
|
|
|
- i := 0;
|
|
|
|
|
- WHILE i < AST.NChild(seq) DO
|
|
|
|
|
- c := AST.Child(seq, i);
|
|
|
|
|
- IF i = AST.MaxChild - 1 THEN LowerBody(c)
|
|
|
|
|
- ELSE LowerAssign(c)
|
|
|
|
|
- END;
|
|
|
|
|
- INC(i)
|
|
|
|
|
- END
|
|
|
|
|
- END LowerBody;
|
|
|
|
|
-
|
|
|
|
|
PROCEDURE LowerUnit (unit: AST.Node);
|
|
PROCEDURE LowerUnit (unit: AST.Node);
|
|
|
VAR nm: SymTab.Name; out: ARRAY [0 .. 255] OF CHAR; i: CARDINAL;
|
|
VAR nm: SymTab.Name; out: ARRAY [0 .. 255] OF CHAR; i: CARDINAL;
|
|
|
BEGIN
|
|
BEGIN
|
|
@@ -345,7 +431,7 @@ PROCEDURE LowerUnit (unit: AST.Node);
|
|
|
QbeGen.SetModule(nm);
|
|
QbeGen.SetModule(nm);
|
|
|
LowerDecls(AST.Child(unit, 1));
|
|
LowerDecls(AST.Child(unit, 1));
|
|
|
QbeGen.BeginBody;
|
|
QbeGen.BeginBody;
|
|
|
- LowerBody(AST.Child(unit, 2));
|
|
|
|
|
|
|
+ LowerStmt(AST.Child(unit, 2));
|
|
|
QbeGen.EndModule(nm)
|
|
QbeGen.EndModule(nm)
|
|
|
END LowerUnit;
|
|
END LowerUnit;
|
|
|
|
|
|