|
|
@@ -1846,78 +1846,49 @@ PRODUCTIONS
|
|
|
END
|
|
|
END; .) .
|
|
|
IfStat (. VAR t: SymTab.TypeIndex;
|
|
|
- q, lThen, lElse, lEnd:
|
|
|
- QbeGen.QVal;
|
|
|
+ q: QbeGen.QVal;
|
|
|
hasElse: BOOLEAN;
|
|
|
astCond, astIf, astLast,
|
|
|
astNode: AST.Node; .)
|
|
|
= "IF" (. hasElse := FALSE; .)
|
|
|
Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- SemError(214) END;
|
|
|
- QbeGen.NewLabel(lThen);
|
|
|
- QbeGen.NewLabel(lElse);
|
|
|
- QbeGen.NewLabel(lEnd);
|
|
|
- QbeGen.Jnz(q, lThen, lElse);
|
|
|
- QbeGen.EmitLabel(lThen); .)
|
|
|
+ SemError(214) END; .)
|
|
|
"THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
AST.SetChild(astNode, 0, astCond);
|
|
|
AST.SetChild(astNode, 1, astStmt);
|
|
|
astIf := astNode;
|
|
|
- astLast := astNode;
|
|
|
- QbeGen.Jmp(lEnd); .)
|
|
|
- { "ELSIF" (. QbeGen.EmitLabel(lElse);
|
|
|
- QbeGen.NewLabel(lElse); .)
|
|
|
+ astLast := astNode; .)
|
|
|
+ { "ELSIF"
|
|
|
Expr<t, q> (. astCond := astCur; astStmt := AST.NoNode;
|
|
|
IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- SemError(214) END;
|
|
|
- QbeGen.NewLabel(lThen);
|
|
|
- QbeGen.Jnz(q, lThen, lElse);
|
|
|
- QbeGen.EmitLabel(lThen); .)
|
|
|
+ SemError(214) END; .)
|
|
|
"THEN" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkIf);
|
|
|
AST.SetChild(astNode, 0, astCond);
|
|
|
AST.SetChild(astNode, 1, astStmt);
|
|
|
AST.SetChild(astLast, 2, astNode);
|
|
|
- astLast := astNode;
|
|
|
- QbeGen.Jmp(lEnd); .) }
|
|
|
- [ "ELSE" (. QbeGen.EmitLabel(lElse);
|
|
|
- hasElse := TRUE;
|
|
|
+ astLast := astNode; .) }
|
|
|
+ [ "ELSE" (. hasElse := TRUE;
|
|
|
astStmt := AST.NoNode; .)
|
|
|
[ StatSeq ] (. AST.SetChild(astLast, 2, astStmt); .) ]
|
|
|
- "END" (. astStmt := astIf;
|
|
|
- IF hasElse THEN
|
|
|
- QbeGen.EmitLabel(lEnd)
|
|
|
- ELSE QbeGen.EmitLabel(lElse);
|
|
|
- QbeGen.EmitLabel(lEnd)
|
|
|
- END; .) .
|
|
|
+ "END" (. astStmt := astIf; .) .
|
|
|
WhileStat (. VAR t: SymTab.TypeIndex;
|
|
|
- q, lTop, lBody, lEnd:
|
|
|
- QbeGen.QVal;
|
|
|
+ q: QbeGen.QVal;
|
|
|
astCond, astNode: AST.Node; .)
|
|
|
- = "WHILE" (. astStmt := AST.NoNode;
|
|
|
- QbeGen.NewLabel(lTop);
|
|
|
- QbeGen.NewLabel(lBody);
|
|
|
- QbeGen.NewLabel(lEnd);
|
|
|
- QbeGen.EmitLabel(lTop); .)
|
|
|
+ = "WHILE" (. astStmt := AST.NoNode; .)
|
|
|
Expr<t, q> (. astCond := astCur;
|
|
|
IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- SemError(214) END;
|
|
|
- QbeGen.Jnz(q, lBody, lEnd);
|
|
|
- QbeGen.EmitLabel(lBody); .)
|
|
|
- "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
+ SemError(214) END; .)
|
|
|
+ "DO" [ StatSeq ] (. astNode := AST.MakeNode(AST.NkWhile);
|
|
|
AST.SetChild(astNode, 0, astCond);
|
|
|
AST.SetChild(astNode, 1, astStmt);
|
|
|
- astStmt := astNode;
|
|
|
- QbeGen.Jmp(lTop); .)
|
|
|
- "END" (. QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ astStmt := astNode; .)
|
|
|
+ "END" .
|
|
|
RepeatStat (. VAR t: SymTab.TypeIndex;
|
|
|
- q, lTop, lEnd: QbeGen.QVal;
|
|
|
+ q: QbeGen.QVal;
|
|
|
astCond, astBody, astNode:
|
|
|
AST.Node; .)
|
|
|
- = "REPEAT" (. astStmt := AST.NoNode;
|
|
|
- QbeGen.NewLabel(lTop);
|
|
|
- QbeGen.NewLabel(lEnd);
|
|
|
- QbeGen.EmitLabel(lTop); .)
|
|
|
+ = "REPEAT" (. astStmt := AST.NoNode; .)
|
|
|
[ StatSeq ] (. astBody := astStmt; .)
|
|
|
"UNTIL" Expr<t, q> (. astCond := astCur;
|
|
|
astNode := AST.MakeNode(AST.NkRepeat);
|
|
|
@@ -1925,22 +1896,16 @@ PRODUCTIONS
|
|
|
AST.SetChild(astNode, 1, astCond);
|
|
|
astStmt := astNode;
|
|
|
IF NOT SymTab.BoolCheck(t) THEN
|
|
|
- SemError(214) END;
|
|
|
- QbeGen.Jnz(q, lEnd, lTop);
|
|
|
- QbeGen.EmitLabel(lEnd); .) .
|
|
|
- LoopStat (. VAR lTop, lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
- = "LOOP" (. QbeGen.NewLabel(lTop);
|
|
|
- astStmt := AST.NoNode;
|
|
|
+ SemError(214) END; .) .
|
|
|
+ LoopStat (. VAR lEnd: QbeGen.QVal; astNode: AST.Node; .)
|
|
|
+ = "LOOP" (. astStmt := AST.NoNode;
|
|
|
QbeGen.NewLabel(lEnd);
|
|
|
- QbeGen.PushLoop(lEnd);
|
|
|
- QbeGen.EmitLabel(lTop); .)
|
|
|
+ QbeGen.PushLoop(lEnd); .)
|
|
|
[ StatSeq ]
|
|
|
"END" (. astNode := AST.MakeNode(AST.NkLoop);
|
|
|
AST.SetChild(astNode, 0, astStmt);
|
|
|
astStmt := astNode;
|
|
|
- QbeGen.Jmp(lTop);
|
|
|
- QbeGen.PopLoop;
|
|
|
- QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ QbeGen.PopLoop; .) .
|
|
|
(* FOR with static-sign BY (literal, non-zero; 220 otherwise).
|
|
|
Runtime direction would need a compare-select; the literal
|
|
|
sign picks cslew/csegew at "DO" time. *)
|
|
|
@@ -1990,23 +1955,7 @@ PRODUCTIONS
|
|
|
ELSIF by = 0 THEN
|
|
|
SemError(220); by := 1
|
|
|
END; .) ]
|
|
|
- "DO" (. IF ok THEN
|
|
|
- QbeGen.StoreVar(lv, qlo,
|
|
|
- FALSE) END;
|
|
|
- QbeGen.NewLabel(lTop);
|
|
|
- QbeGen.NewLabel(lBody);
|
|
|
- QbeGen.NewLabel(lEnd);
|
|
|
- QbeGen.EmitLabel(lTop);
|
|
|
- QbeGen.LoadVar(lv, FALSE, qt);
|
|
|
- QbeGen.NewTemp(qk);
|
|
|
- IF by > 0 THEN
|
|
|
- QbeGen.Op3("cslew", qk,
|
|
|
- qt, qhi, FALSE)
|
|
|
- ELSE QbeGen.Op3("csgew", qk,
|
|
|
- qt, qhi, FALSE)
|
|
|
- END;
|
|
|
- QbeGen.Jnz(qk, lBody, lEnd);
|
|
|
- QbeGen.EmitLabel(lBody); .)
|
|
|
+ "DO"
|
|
|
[ StatSeq ]
|
|
|
"END" (. astNode := AST.MakeNode(AST.NkFor);
|
|
|
AST.SetChild(astNode, 0, astVar);
|
|
|
@@ -2015,17 +1964,7 @@ PRODUCTIONS
|
|
|
AST.SetChild(astNode, 3, astBy);
|
|
|
AST.SetChild(astNode, 4, astStmt);
|
|
|
astStmt := astNode;
|
|
|
- IF ok THEN
|
|
|
- QbeGen.LoadVar(lv, FALSE,
|
|
|
- qt);
|
|
|
- QbeGen.IntStr(by, qb);
|
|
|
- QbeGen.NewTemp(qk);
|
|
|
- QbeGen.Op3("add", qk,
|
|
|
- qt, qb, FALSE);
|
|
|
- QbeGen.StoreVar(lv, qk,
|
|
|
- FALSE) END;
|
|
|
- QbeGen.Jmp(lTop);
|
|
|
- QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ .) .
|
|
|
CaseStat (. VAR tsel: SymTab.TypeIndex;
|
|
|
qsel, lEnd: QbeGen.QVal;
|
|
|
arm, astNode, astArms,
|
|
|
@@ -2034,7 +1973,7 @@ PRODUCTIONS
|
|
|
AST.SetChild(astNode, 0, astCur);
|
|
|
astArms := AST.NoNode;
|
|
|
astArmsTail := AST.NoNode;
|
|
|
- QbeGen.NewLabel(lEnd); .)
|
|
|
+ .)
|
|
|
"OF" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail>
|
|
|
{ "|" CaseAlt<tsel, qsel, lEnd, astArms, astArmsTail> }
|
|
|
[ "ELSE" (. astStmt := AST.NoNode; .)
|
|
|
@@ -2045,31 +1984,25 @@ PRODUCTIONS
|
|
|
astArms, astArmsTail, arm); .) ]
|
|
|
"END" (. AST.SetChild(astNode, 1, astArms);
|
|
|
astStmt := astNode;
|
|
|
- QbeGen.EmitLabel(lEnd); .) .
|
|
|
+ .) .
|
|
|
(* Compare-chain lowering: each alternative ends its match-tests
|
|
|
with "jmp lAfter", so the no-match fallthrough skips the body:
|
|
|
"cmp; jnz(lBody,lF); lF: ... ; jmp lAfter; lBody: S; jmp lEnd;
|
|
|
lAfter:". Falls into the next alternative, ELSE, or END. *)
|
|
|
CaseAlt<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
lEnd: QbeGen.QVal; VAR arms, armsTail: AST.Node>
|
|
|
- (. VAR lBody, lAfter: QbeGen.QVal;
|
|
|
- arm: AST.Node; .)
|
|
|
- = (. arm := AST.MakeNode(AST.NkCaseArm);
|
|
|
- QbeGen.NewLabel(lBody);
|
|
|
- QbeGen.NewLabel(lAfter); .)
|
|
|
- CaseLabel<tsel, qsel, lBody, arm>
|
|
|
- { "," CaseLabel<tsel, qsel, lBody, arm> }
|
|
|
- ":" (. astStmt := AST.NoNode;
|
|
|
- QbeGen.Jmp(lAfter);
|
|
|
- QbeGen.EmitLabel(lBody); .)
|
|
|
+ (. VAR arm: AST.Node; .)
|
|
|
+ = (. arm := AST.MakeNode(AST.NkCaseArm); .)
|
|
|
+ CaseLabel<tsel, qsel, arm>
|
|
|
+ { "," CaseLabel<tsel, qsel, arm> }
|
|
|
+ ":" (. astStmt := AST.NoNode; .)
|
|
|
[ StatSeq ] (. AST.SetChild(arm, AST.NChild(arm),
|
|
|
astStmt);
|
|
|
AstAppend(AST.NkBlock,
|
|
|
arms, armsTail, arm);
|
|
|
- QbeGen.Jmp(lEnd);
|
|
|
- QbeGen.EmitLabel(lAfter); .) .
|
|
|
+ .) .
|
|
|
CaseLabel<tsel: SymTab.TypeIndex; qsel: QbeGen.QVal;
|
|
|
- lBody: QbeGen.QVal; arm: AST.Node>
|
|
|
+ arm: AST.Node>
|
|
|
(. VAR t2, t3: SymTab.TypeIndex;
|
|
|
q2, q3, qc, qd, qe:
|
|
|
QbeGen.QVal;
|
|
|
@@ -2092,15 +2025,9 @@ PRODUCTIONS
|
|
|
AND NOT SymTab.EqCheck(t2,
|
|
|
tsel) THEN
|
|
|
SemError(213) END;
|
|
|
- IF NOT QbeGen.IsImm(q2) THEN
|
|
|
- SemError(230);
|
|
|
- QbeGen.CopyOp("0", q2)
|
|
|
- END;
|
|
|
- QbeGen.NewLabel(lNext);
|
|
|
- QbeGen.Cmp(SymTab.OpEq,
|
|
|
- qsel, q2, qc, FALSE);
|
|
|
- QbeGen.Jnz(qc, lBody, lNext);
|
|
|
- QbeGen.EmitLabel(lNext); .)
|
|
|
+ IF NOT QbeGen.IsImm(q2) THEN
|
|
|
+ SemError(230)
|
|
|
+ END; .)
|
|
|
[ ".." Expr<t3, q3> (. astLab := AST.MakeBin(
|
|
|
AST.NkSubrange, 0, astLab, astCur);
|
|
|
IF (t3 #
|
|
|
@@ -2110,20 +2037,9 @@ PRODUCTIONS
|
|
|
AND NOT SymTab.EqCheck(t3,
|
|
|
tsel) THEN
|
|
|
SemError(213) END;
|
|
|
- IF NOT QbeGen.IsImm(q3) THEN
|
|
|
- SemError(230);
|
|
|
- QbeGen.CopyOp("0", q3)
|
|
|
- END;
|
|
|
- QbeGen.Cmp(SymTab.OpGe,
|
|
|
- qsel, q2, qc, FALSE);
|
|
|
- QbeGen.Cmp(SymTab.OpLe,
|
|
|
- qsel, q3, qd, FALSE);
|
|
|
- QbeGen.NewTemp(qe);
|
|
|
- QbeGen.Op3("and", qe, qc, qd,
|
|
|
- FALSE);
|
|
|
- QbeGen.NewLabel(lNext);
|
|
|
- QbeGen.Jnz(qe, lBody, lNext);
|
|
|
- QbeGen.EmitLabel(lNext); .) ]
|
|
|
+ IF NOT QbeGen.IsImm(q3) THEN
|
|
|
+ SemError(230)
|
|
|
+ END; .) ]
|
|
|
(. AST.SetChild(arm,
|
|
|
AST.NChild(arm), astLab); .) .
|
|
|
ReturnStat (. VAR t: SymTab.TypeIndex;
|
|
|
@@ -2146,8 +2062,6 @@ PRODUCTIONS
|
|
|
IF res #
|
|
|
SymTab.InvalidType THEN
|
|
|
SemError(232)
|
|
|
- ELSE QbeGen.EmitRet(q,
|
|
|
- FALSE)
|
|
|
END
|
|
|
ELSIF (res =
|
|
|
SymTab.InvalidType)
|
|
|
@@ -2156,16 +2070,7 @@ PRODUCTIONS
|
|
|
AND NOT SymTab.Assignable(t,
|
|
|
res) THEN
|
|
|
SemError(232)
|
|
|
- ELSE
|
|
|
- conv := (SymTab.ClassOf(
|
|
|
- res) = SymTab.ClReal)
|
|
|
- AND SymTab.IsIntFamily(t);
|
|
|
- IF conv THEN
|
|
|
- QbeGen.ConvIR(q, qt);
|
|
|
- QbeGen.EmitRet(qt, TRUE)
|
|
|
- ELSE QbeGen.EmitRet(q, TRUE)
|
|
|
- END
|
|
|
- END
|
|
|
+ END
|
|
|
END; .) .
|
|
|
HaltStat (. VAR t: SymTab.TypeIndex;
|
|
|
q: QbeGen.QVal;
|
|
|
@@ -2177,7 +2082,7 @@ PRODUCTIONS
|
|
|
AST.SetChild(astNode, 0, astVal)
|
|
|
END;
|
|
|
astStmt := astNode;
|
|
|
- QbeGen.HaltQ; .) .
|
|
|
+ .) .
|
|
|
(* Designator: scalar loads, array addresses, and index suffixes.
|
|
|
Each index descends one level (bounds-checked, trap on breach);
|
|
|
nested levels reload the inner descriptor address. q ends as the
|