|
|
@@ -1,25 +1,47 @@
|
|
|
IMPLEMENTATION MODULE Lower;
|
|
|
-(* Scalar L0 walk: see Lower.def and docs/plan-lower.md. *)
|
|
|
+(* Scalar + boolean walk (L0/L1): see Lower.def and docs/plan-lower.md. *)
|
|
|
|
|
|
IMPORT AST, SymTab, QbeGen;
|
|
|
|
|
|
PROCEDURE Name (n: AST.Node; VAR s: ARRAY OF CHAR);
|
|
|
-(* The interned text of a leaf node (NkIdent / NkIntLit / ...). *)
|
|
|
BEGIN
|
|
|
IF n = AST.NoNode THEN s[0] := CHR(0)
|
|
|
ELSE AST.Txt(AST.Child(n, 0), s)
|
|
|
END
|
|
|
END Name;
|
|
|
|
|
|
-PROCEDURE IsIntOp (op: INTEGER): BOOLEAN;
|
|
|
+PROCEDURE IsArith (op: INTEGER): BOOLEAN;
|
|
|
BEGIN
|
|
|
RETURN (op = AST.OpAdd) OR (op = AST.OpSub) OR (op = AST.OpMul)
|
|
|
OR (op = AST.OpDiv) OR (op = AST.OpMod)
|
|
|
- END IsIntOp;
|
|
|
+ END IsArith;
|
|
|
+
|
|
|
+PROCEDURE IsRel (op: INTEGER): BOOLEAN;
|
|
|
+ BEGIN
|
|
|
+ RETURN (op >= AST.OpEq) AND (op <= AST.OpGe)
|
|
|
+ END IsRel;
|
|
|
+
|
|
|
+PROCEDURE RelSym (a: INTEGER; VAR s: INTEGER): BOOLEAN;
|
|
|
+ BEGIN
|
|
|
+ IF a = AST.OpEq THEN s := SymTab.OpEq
|
|
|
+ ELSIF a = AST.OpNe THEN s := SymTab.OpNeq1
|
|
|
+ ELSIF a = AST.OpLt THEN s := SymTab.OpLt
|
|
|
+ ELSIF a = AST.OpLe THEN s := SymTab.OpLe
|
|
|
+ ELSIF a = AST.OpGt THEN s := SymTab.OpGt
|
|
|
+ ELSIF a = AST.OpGe THEN s := SymTab.OpGe
|
|
|
+ ELSE RETURN FALSE
|
|
|
+ END;
|
|
|
+ RETURN TRUE
|
|
|
+ END RelSym;
|
|
|
+
|
|
|
+PROCEDURE IsScalarClass (cls: INTEGER): BOOLEAN;
|
|
|
+ BEGIN
|
|
|
+ RETURN (cls = SymTab.ClInt) OR (cls = SymTab.ClBool)
|
|
|
+ OR (cls = SymTab.ClChar) OR (cls = SymTab.ClUChar)
|
|
|
+ OR (cls = SymTab.ClEnum)
|
|
|
+ END IsScalarClass;
|
|
|
|
|
|
PROCEDURE IsSimpleScalar (n: AST.Node): BOOLEAN;
|
|
|
-(* A parenthesised-free identifier designator whose symbol is a scalar
|
|
|
- INTEGER VAR/PARAM/CONST. *)
|
|
|
VAR nm: SymTab.Name; k: INTEGER;
|
|
|
BEGIN
|
|
|
IF (AST.Kind(n) # AST.NkDesignator) OR (AST.NChild(n) # 1) THEN
|
|
|
@@ -31,20 +53,28 @@ PROCEDURE IsSimpleScalar (n: AST.Node): BOOLEAN;
|
|
|
IF (k # SymTab.KindVar) AND (k # SymTab.KindParam)
|
|
|
AND (k # SymTab.KindConst) THEN
|
|
|
RETURN FALSE END;
|
|
|
- RETURN SymTab.ClassOf(SymTab.SymType(nm)) = SymTab.ClInt
|
|
|
+ IF SymTab.Equal(nm, "TRUE") OR SymTab.Equal(nm, "FALSE") THEN
|
|
|
+ RETURN TRUE END;
|
|
|
+ RETURN IsScalarClass(SymTab.ClassOf(SymTab.SymType(nm)))
|
|
|
END IsSimpleScalar;
|
|
|
|
|
|
PROCEDURE CanExpr (n: AST.Node): BOOLEAN;
|
|
|
+ VAR op: INTEGER;
|
|
|
BEGIN
|
|
|
IF n = AST.NoNode THEN RETURN FALSE END;
|
|
|
IF AST.Kind(n) = AST.NkIntLit THEN RETURN TRUE END;
|
|
|
IF AST.Kind(n) = AST.NkDesignator THEN RETURN IsSimpleScalar(n) END;
|
|
|
IF AST.Kind(n) = AST.NkUnary THEN
|
|
|
- RETURN (AST.Op(n) = AST.OpSub) AND CanExpr(AST.Child(n, 0))
|
|
|
+ op := AST.Op(n);
|
|
|
+ IF (op # AST.OpSub) AND (op # AST.OpNot) THEN RETURN FALSE END;
|
|
|
+ RETURN CanExpr(AST.Child(n, 0))
|
|
|
END;
|
|
|
IF AST.Kind(n) = AST.NkBinExpr THEN
|
|
|
- RETURN IsIntOp(AST.Op(n)) AND CanExpr(AST.Child(n, 0))
|
|
|
- AND CanExpr(AST.Child(n, 1))
|
|
|
+ op := AST.Op(n);
|
|
|
+ IF NOT (IsArith(op) OR IsRel(op)
|
|
|
+ OR (op = AST.OpAnd) OR (op = AST.OpOr)) THEN
|
|
|
+ RETURN FALSE END;
|
|
|
+ RETURN CanExpr(AST.Child(n, 0)) AND CanExpr(AST.Child(n, 1))
|
|
|
END;
|
|
|
RETURN FALSE
|
|
|
END CanExpr;
|
|
|
@@ -53,7 +83,7 @@ PROCEDURE CanDecl (c: AST.Node): BOOLEAN;
|
|
|
VAR i: CARDINAL;
|
|
|
BEGIN
|
|
|
IF AST.Kind(c) = AST.NkVarDecl THEN
|
|
|
- IF SymTab.ClassOf(AST.Ty(c)) # SymTab.ClInt THEN RETURN FALSE END;
|
|
|
+ IF NOT IsScalarClass(SymTab.ClassOf(AST.Ty(c))) THEN RETURN FALSE END;
|
|
|
IF AST.NChild(c) < 1 THEN RETURN FALSE END;
|
|
|
i := 0;
|
|
|
WHILE i < AST.NChild(c) DO
|
|
|
@@ -63,7 +93,7 @@ PROCEDURE CanDecl (c: AST.Node): BOOLEAN;
|
|
|
RETURN TRUE
|
|
|
END;
|
|
|
IF AST.Kind(c) = AST.NkConstDecl THEN
|
|
|
- RETURN (SymTab.ClassOf(AST.Ty(c)) = SymTab.ClInt)
|
|
|
+ RETURN IsScalarClass(SymTab.ClassOf(AST.Ty(c)))
|
|
|
AND (AST.Kind(AST.Child(c, 1)) = AST.NkIntLit)
|
|
|
END;
|
|
|
RETURN FALSE
|
|
|
@@ -130,7 +160,11 @@ PROCEDURE LowerDesign (n: AST.Node; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
END;
|
|
|
t := SymTab.SymType(nm); k := SymTab.SymKind(nm);
|
|
|
IF k = SymTab.KindConst THEN
|
|
|
- IF SymTab.GetSymVal(nm, cv) AND QbeGen.IsImm(cv) THEN
|
|
|
+ IF SymTab.Equal(nm, "TRUE") THEN
|
|
|
+ t := SymTab.BoolType(); QbeGen.CopyOp("1", q)
|
|
|
+ ELSIF SymTab.Equal(nm, "FALSE") THEN
|
|
|
+ t := SymTab.BoolType(); QbeGen.CopyOp("0", q)
|
|
|
+ ELSIF SymTab.GetSymVal(nm, cv) AND QbeGen.IsImm(cv) THEN
|
|
|
QbeGen.CopyOp(cv, q)
|
|
|
ELSE QbeGen.CopyOp("0", q)
|
|
|
END
|
|
|
@@ -143,8 +177,10 @@ PROCEDURE LowerDesign (n: AST.Node; VAR t: SymTab.TypeIndex; VAR k: INTEGER;
|
|
|
|
|
|
PROCEDURE LowerExpr (n: AST.Node; VAR t: SymTab.TypeIndex;
|
|
|
VAR q: QbeGen.QVal);
|
|
|
- VAR t2: SymTab.TypeIndex; q2, qt, qf: QbeGen.QVal;
|
|
|
- kind, op, k: INTEGER; qn: SymTab.Name; sfx: BOOLEAN; folded: BOOLEAN;
|
|
|
+ VAR t2: SymTab.TypeIndex; q2, qt, qf, qs, qr: QbeGen.QVal;
|
|
|
+ lNext, lFalse, lTrue, lDone: QbeGen.QVal;
|
|
|
+ kind, op, k, rop: INTEGER; qn: SymTab.Name; sfx: BOOLEAN;
|
|
|
+ folded, isR: BOOLEAN;
|
|
|
BEGIN
|
|
|
IF AST.Kind(n) = AST.NkIntLit THEN
|
|
|
Name(n, qn); QbeGen.NormInt(qn, q); t := SymTab.IntType()
|
|
|
@@ -152,34 +188,87 @@ PROCEDURE LowerExpr (n: AST.Node; VAR t: SymTab.TypeIndex;
|
|
|
LowerDesign(n, t, k, q, qn, sfx)
|
|
|
ELSIF AST.Kind(n) = AST.NkUnary THEN
|
|
|
LowerExpr(AST.Child(n, 0), t, q);
|
|
|
- IF QbeGen.IsImm(q) THEN QbeGen.NegFold(q, q)
|
|
|
- ELSE QbeGen.NewTemp(qt); QbeGen.NegQ(q, qt, FALSE); QbeGen.CopyOp(qt, q)
|
|
|
+ IF AST.Op(n) = AST.OpSub THEN
|
|
|
+ IF QbeGen.IsImm(q) THEN QbeGen.NegFold(q, q)
|
|
|
+ ELSE QbeGen.NewTemp(qt); QbeGen.NegQ(q, qt, FALSE); QbeGen.CopyOp(qt, q)
|
|
|
+ END
|
|
|
+ ELSE
|
|
|
+ QbeGen.NotQ(q, qt); QbeGen.CopyOp(qt, q); t := SymTab.BoolType()
|
|
|
END
|
|
|
ELSIF AST.Kind(n) = AST.NkBinExpr THEN
|
|
|
- LowerExpr(AST.Child(n, 0), t, q);
|
|
|
- LowerExpr(AST.Child(n, 1), t2, q2);
|
|
|
- op := AST.Op(n); kind := 0;
|
|
|
- IF op = AST.OpSub THEN kind := 1
|
|
|
- ELSIF op = AST.OpMul THEN kind := 2
|
|
|
- ELSIF op = AST.OpDiv THEN kind := 3
|
|
|
- ELSIF op = AST.OpMod THEN kind := 4
|
|
|
- END;
|
|
|
- folded := FALSE;
|
|
|
- IF QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
- folded := QbeGen.Fold2(kind, q, q2, qf)
|
|
|
- END;
|
|
|
- IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ op := AST.Op(n);
|
|
|
+ IF IsRel(op) THEN
|
|
|
+ LowerExpr(AST.Child(n, 0), t, q);
|
|
|
+ LowerExpr(AST.Child(n, 1), t2, q2);
|
|
|
+ rop := SymTab.OpEq; folded := RelSym(op, rop);
|
|
|
+ isR := (t # SymTab.InvalidType) AND (SymTab.ClassOf(t) = SymTab.ClReal);
|
|
|
+ t := SymTab.BoolType();
|
|
|
+ QbeGen.Cmp(rop, q, q2, qt, isR);
|
|
|
+ QbeGen.CopyOp(qt, q)
|
|
|
+ ELSIF op = AST.OpAnd THEN
|
|
|
+ LowerExpr(AST.Child(n, 0), t, q);
|
|
|
+ QbeGen.DelayBegin;
|
|
|
+ LowerExpr(AST.Child(n, 1), t2, q2);
|
|
|
+ QbeGen.DelayEnd;
|
|
|
+ QbeGen.Slot4(qs);
|
|
|
+ QbeGen.NewLabel(lNext); QbeGen.NewLabel(lFalse); QbeGen.NewLabel(lDone);
|
|
|
+ QbeGen.Jnz(q, lNext, lFalse);
|
|
|
+ QbeGen.EmitLabel(lNext);
|
|
|
+ QbeGen.DelayFlush;
|
|
|
+ QbeGen.StoreW(qs, q2);
|
|
|
+ QbeGen.Jmp(lDone);
|
|
|
+ QbeGen.EmitLabel(lFalse);
|
|
|
+ QbeGen.StoreW(qs, "0");
|
|
|
+ QbeGen.Jmp(lDone);
|
|
|
+ QbeGen.EmitLabel(lDone);
|
|
|
+ QbeGen.LoadW(qs, qr);
|
|
|
+ QbeGen.CopyOp(qr, q);
|
|
|
+ t := SymTab.BoolType()
|
|
|
+ ELSIF op = AST.OpOr THEN
|
|
|
+ LowerExpr(AST.Child(n, 0), t, q);
|
|
|
+ QbeGen.DelayBegin;
|
|
|
+ LowerExpr(AST.Child(n, 1), t2, q2);
|
|
|
+ QbeGen.DelayEnd;
|
|
|
+ QbeGen.Slot4(qs);
|
|
|
+ QbeGen.NewLabel(lTrue); QbeGen.NewLabel(lNext); QbeGen.NewLabel(lDone);
|
|
|
+ QbeGen.Jnz(q, lTrue, lNext);
|
|
|
+ QbeGen.EmitLabel(lTrue);
|
|
|
+ QbeGen.StoreW(qs, "1");
|
|
|
+ QbeGen.Jmp(lDone);
|
|
|
+ QbeGen.EmitLabel(lNext);
|
|
|
+ QbeGen.DelayFlush;
|
|
|
+ QbeGen.StoreW(qs, q2);
|
|
|
+ QbeGen.Jmp(lDone);
|
|
|
+ QbeGen.EmitLabel(lDone);
|
|
|
+ QbeGen.LoadW(qs, qr);
|
|
|
+ QbeGen.CopyOp(qr, q);
|
|
|
+ t := SymTab.BoolType()
|
|
|
ELSE
|
|
|
- QbeGen.NewTemp(qt);
|
|
|
- IF op = AST.OpAdd THEN QbeGen.Op3("add", qt, q, q2, FALSE)
|
|
|
- ELSIF op = AST.OpSub THEN QbeGen.Op3("sub", qt, q, q2, FALSE)
|
|
|
- ELSIF op = AST.OpMul THEN QbeGen.Op3("mul", qt, q, q2, FALSE)
|
|
|
- ELSIF op = AST.OpDiv THEN QbeGen.Op3("div", qt, q, q2, FALSE)
|
|
|
- ELSE QbeGen.Op3("rem", qt, q, q2, FALSE)
|
|
|
+ LowerExpr(AST.Child(n, 0), t, q);
|
|
|
+ LowerExpr(AST.Child(n, 1), t2, q2);
|
|
|
+ kind := 0;
|
|
|
+ IF op = AST.OpSub THEN kind := 1
|
|
|
+ ELSIF op = AST.OpMul THEN kind := 2
|
|
|
+ ELSIF op = AST.OpDiv THEN kind := 3
|
|
|
+ ELSIF op = AST.OpMod THEN kind := 4
|
|
|
END;
|
|
|
- QbeGen.CopyOp(qt, q)
|
|
|
- END;
|
|
|
- t := SymTab.IntType()
|
|
|
+ folded := FALSE;
|
|
|
+ IF QbeGen.IsImm(q) AND QbeGen.IsImm(q2) THEN
|
|
|
+ folded := QbeGen.Fold2(kind, q, q2, qf)
|
|
|
+ END;
|
|
|
+ IF folded THEN QbeGen.CopyOp(qf, q)
|
|
|
+ ELSE
|
|
|
+ QbeGen.NewTemp(qt);
|
|
|
+ IF op = AST.OpAdd THEN QbeGen.Op3("add", qt, q, q2, FALSE)
|
|
|
+ ELSIF op = AST.OpSub THEN QbeGen.Op3("sub", qt, q, q2, FALSE)
|
|
|
+ ELSIF op = AST.OpMul THEN QbeGen.Op3("mul", qt, q, q2, FALSE)
|
|
|
+ ELSIF op = AST.OpDiv THEN QbeGen.Op3("div", qt, q, q2, FALSE)
|
|
|
+ ELSE QbeGen.Op3("rem", qt, q, q2, FALSE)
|
|
|
+ END;
|
|
|
+ QbeGen.CopyOp(qt, q)
|
|
|
+ END;
|
|
|
+ t := SymTab.IntType()
|
|
|
+ END
|
|
|
END
|
|
|
END LowerExpr;
|
|
|
|