-- FlowExpression.mesa, modified by Sweet, January 17, 1980 5:29 PM DIRECTORY AltoDefs: FROM "altodefs" USING [BYTE, wordlength], Code: FROM "code" USING [CodeNotImplemented, dStar, ZEROlexeme], CodeDefs: FROM "codedefs" USING [ JumpType, LabelCCIndex, Lexeme, NullLex, VarComponent, VarIndex], ComData: FROM "comdata" USING [switches], FOpCodes: FROM "fopcodes" USING [ qDCOMP, qDSUB, qDUCOMP, qDUP, qEXCH, qFCOMP, qFLOAT, qFSUB, qLI, qLINT, qLP, qNEG, qPOP, qPUSH, qRF, qXOR], P5: FROM "p5" USING [ Exp, FlowIn, FlowTree, GenTempLex, LogHeapFree, PushLex, PushRhs, ReleaseTempLex, SAssign], P5L: FROM "p5l" USING [ AllLoaded, EasilyLoadable, FieldOfVar, LoadComponent, LoadVar, MakeComponent, NormalizeExp, NormalLex, ReusableCopies, TOSLex, VarAlignment, VarForLex], P5U: FROM "p5u" USING [ InsertLabel, LabelAlloc, LongTreeAddress, Out0, Out1, Out2, OutJump, PushLitVal, TreeLiteral], SDDefs: FROM "sddefs", Stack: FROM "stack" USING [ Decr, DeleteToMark, Dump, Mark, Off, On, ResetToMark, TempStore, UnMark], Symbols: FROM "symbols" USING [ CTXIndex, HTIndex, ISEIndex, ISENull, SEIndex, seType], Table: FROM "table" USING [Base, Notifier], Tree: FROM "tree" USING [Index, Link, NodeName, treeType], TreeOps: FROM "treeops" USING [ListLength, ScanList]; FlowExpression: PROGRAM IMPORTS CPtr: Code, MPtr: ComData, P5U, P5L, P5, Stack, TreeOps EXPORTS CodeDefs, P5 = BEGIN OPEN FOpCodes, CodeDefs; -- imported definitions BYTE: TYPE = AltoDefs.BYTE; wordlength: CARDINAL = AltoDefs.wordlength; CTXIndex: TYPE = Symbols.CTXIndex; HTIndex: TYPE = Symbols.HTIndex; ISEIndex: TYPE = Symbols.ISEIndex; SEIndex: TYPE = Symbols.SEIndex; ISENull: ISEIndex = Symbols.ISENull; tb: Table.Base; -- tree base (local copy) seb: Table.Base; -- semantic entry base (local copy) cb: Table.Base; -- code base (local copy) FlowExpressionNotify: PUBLIC Table.Notifier = BEGIN -- called by allocator whenever table area is repacked seb _ base[Symbols.seType]; cb _ tb _ base[Tree.treeType]; RETURN END; JumpNN: ARRAY Tree.NodeName[relE..relLE] OF JumpType = [ JumpE, JumpN, JumpL, JumpGE, JumpG, JumpLE]; UJumpNN: ARRAY Tree.NodeName[relE..relLE] OF JumpType _ [ JumpE, JumpN, UJumpL, UJumpGE, UJumpG, UJumpLE]; CNN: ARRAY Tree.NodeName[relE..relLE] OF Tree.NodeName = [ relN, relE, relGE, relL, relLE, relG]; RNN: ARRAY Tree.NodeName[relE..relLE] OF Tree.NodeName = [ relE, relN, relG, relLE, relL, relGE]; PushOnly: PROCEDURE [t: Tree.Link] = BEGIN IF ~CPtr.dStar THEN Stack.Dump[]; -- should never see Case CV P5.PushRhs[t]; RETURN END; FlowExp: PUBLIC PROCEDURE [node: Tree.Index] RETURNS [l: Lexeme] = BEGIN -- generates code for a flow expression SELECT tb[node].name FROM ifx => l _ IfExp[node]; or => l _ Or[node]; and => l _ And[node]; not => l _ Not[node]; relE,relN,relL,relGE,relG,relLE => l _ Rel[node, TRUE]; in => l _ In[node, TRUE]; notin => l _ In[node, FALSE]; abs => l _ Abs[node]; lengthen => l _ Lengthen[node]; min => l _ Min[node]; max => l _ Max[node]; ENDCASE => BEGIN SIGNAL CPtr.CodeNotImplemented; l _ CPtr.ZEROlexeme; END; RETURN END; Abs: PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN -- generate code for ABS poslabel, donelabel: LabelCCIndex; IF tb[node].attr1 THEN RETURN[RealAbs[node]]; IF tb[node].attr2 THEN RETURN [LongAbs[node]]; IF CPtr.dStar THEN RETURN [DAbs[node]]; poslabel _ P5U.LabelAlloc[]; donelabel _ P5U.LabelAlloc[]; Stack.Dump[]; Stack.Mark[]; P5.PushRhs[tb[node].son[1]]; P5U.PushLitVal[0]; P5U.OutJump[JumpGE, poslabel]; P5U.Out0[qPUSH]; P5U.Out0[qNEG]; Stack.ResetToMark[]; P5U.OutJump[Jump, donelabel]; P5U.InsertLabel[poslabel]; P5U.Out0[qPUSH]; Stack.UnMark[]; P5U.InsertLabel[donelabel]; RETURN[P5L.TOSLex[1]] END; DAbs: PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN poslabel: LabelCCIndex _ P5U.LabelAlloc[]; P5.PushRhs[tb[node].son[1]]; P5U.Out0[qDUP]; -- don't use Stack.Dup since Neg will clear info P5U.PushLitVal[0]; P5U.OutJump[JumpGE, poslabel]; P5U.Out0[qNEG]; P5U.InsertLabel[poslabel]; RETURN [P5L.TOSLex[1]]; END; LongAbs: PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN pos, done: LabelCCIndex; var: VarComponent; IF ~CPtr.dStar THEN Stack.Dump[]; Stack.Mark[]; var _ P5L.MakeComponent[P5L.VarForLex[P5.Exp[tb[node].son[1]]]]; var _ P5L.EasilyLoadable[var, load]; P5L.LoadComponent[var]; P5U.Out1[qLI, 0]; P5U.Out1[qLI, 0]; P5U.Out0[qDCOMP]; P5U.PushLitVal[0]; P5U.OutJump[JumpGE, pos _ P5U.LabelAlloc[]]; P5U.Out1[qLI, 0]; P5U.Out1[qLI, 0]; P5L.LoadComponent[var]; P5U.Out0[qDSUB]; Stack.ResetToMark[]; P5U.OutJump[Jump, done _ P5U.LabelAlloc[]]; P5U.InsertLabel[pos]; P5L.LoadComponent[var]; Stack.UnMark[]; P5U.InsertLabel[done]; RETURN [P5L.TOSLex[2]] END; RealAbs: PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN pos, done: LabelCCIndex; var, zero: VarComponent; Stack.Dump[]; IF ~MPtr.switches['f] THEN BEGIN P5U.PushLitVal[0]; P5U.PushLitVal[0]; P5U.Out0[qFLOAT]; zero _ Stack.TempStore[2]; END ELSE zero _ [wSize: 2, space: const[d1: 0, d2: 0]]; var _ P5L.MakeComponent[P5L.VarForLex[P5.Exp[tb[node].son[1]]]]; var _ P5L.EasilyLoadable[var, load]; Stack.Mark[]; P5L.LoadComponent[var]; P5L.LoadComponent[zero]; P5U.Out0[qFCOMP]; P5U.PushLitVal[0]; P5U.OutJump[JumpGE, pos _ P5U.LabelAlloc[]]; P5L.LoadComponent[zero]; P5L.LoadComponent[var]; P5U.Out0[qFSUB]; Stack.ResetToMark[]; P5U.OutJump[Jump, done _ P5U.LabelAlloc[]]; P5U.InsertLabel[pos]; P5L.LoadComponent[var]; Stack.UnMark[]; P5U.InsertLabel[done]; RETURN [P5L.TOSLex[2]] END; Lengthen: PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN r: VarIndex; ime: BOOLEAN _ MPtr.switches['x]; size: CARDINAL; GenLP: PROCEDURE = BEGIN -- short pointer only thing on stack nilLabel, doneLabel: LabelCCIndex; nilLabel _ P5U.LabelAlloc[]; doneLabel _ P5U.LabelAlloc[]; Stack.Mark[]; P5U.PushLitVal[0]; P5U.OutJump[JumpE, nilLabel]; P5U.Out0[qPUSH]; P5U.PushLitVal[177740B]; P5U.Out2[qRF, 0, 301B]; -- [12,1], a 2 bit field Stack.ResetToMark[]; P5U.OutJump[Jump, doneLabel]; P5U.InsertLabel[nilLabel]; P5U.Out0[qPUSH]; P5U.Out0[qDUP]; Stack.UnMark[]; P5U.InsertLabel[doneLabel]; END; IF ime THEN Stack.Dump[]; r _ P5L.VarForLex[P5.Exp[tb[node].son[1]]]; size _ P5L.VarAlignment[r, load].wSize; IF size = 2 THEN -- array descriptor BEGIN IF P5L.AllLoaded[r] THEN BEGIN len: VarComponent _ Stack.TempStore[1]; IF ime THEN GenLP[] ELSE P5U.Out0[qLP]; P5L.LoadComponent[len]; END ELSE BEGIN tr1, tr2: VarIndex; [tr1, tr2] _ P5L.ReusableCopies[r, load]; P5L.FieldOfVar[r: tr1, wSize: 1]; P5L.FieldOfVar[r: tr2, wd: 1, wSize: 1]; P5L.LoadVar[tr1]; IF ime THEN GenLP[] ELSE P5U.Out0[qLP]; P5L.LoadVar[tr2]; END; RETURN[P5L.TOSLex[3]] END; P5L.LoadVar[r]; IF tb[node].attr1 THEN IF ime THEN GenLP[] ELSE P5U.Out0[qLP] ELSE IF tb[node].attr3 THEN P5U.Out0[qLINT] ELSE P5U.Out1[qLI, 0]; RETURN [P5L.TOSLex[2]] END; And: PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN -- generate code for "AND" t1: Tree.Link _ tb[node].son[1]; t2: Tree.Link _ tb[node].son[2]; RETURN[sCand[TRUE, t1, t2]] END; sCand: PROCEDURE [tf: BOOLEAN, t1, t2: Tree.Link] RETURNS [Lexeme] = BEGIN -- main subroutine for Cand label, elabel: LabelCCIndex; label _ P5U.LabelAlloc[]; elabel _ P5U.LabelAlloc[]; Stack.Mark[]; BEGIN ENABLE P5.LogHeapFree => RESUME[FALSE, NullLex]; P5.FlowTree[t1, FALSE, label]; P5.FlowTree[t2, FALSE, label]; END; P5U.PushLitVal[IF tf THEN 1 ELSE 0]; Stack.DeleteToMark[]; P5U.OutJump[Jump,elabel]; P5U.InsertLabel[label]; P5U.PushLitVal[IF tf THEN 0 ELSE 1]; P5U.InsertLabel[elabel]; RETURN[P5L.TOSLex[1]] END; Or: PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN -- generate code for "OR" t1: Tree.Link _ tb[node].son[1]; t2: Tree.Link _ tb[node].son[2]; RETURN[sCor[TRUE, t1, t2]] END; sCor: PROCEDURE [tf: BOOLEAN, t1,t2: Tree.Link] RETURNS [Lexeme] = BEGIN -- main subroutine for Cor labelt, labelf, elabel: LabelCCIndex; labelt _ P5U.LabelAlloc[]; labelf _ P5U.LabelAlloc[]; elabel _ P5U.LabelAlloc[]; Stack.Mark[]; BEGIN ENABLE P5.LogHeapFree => RESUME[FALSE, NullLex]; P5.FlowTree[t1, TRUE, labelt]; P5.FlowTree[t2, FALSE, labelf]; END; P5U.InsertLabel[labelt]; P5U.PushLitVal[IF tf THEN 1 ELSE 0]; Stack.DeleteToMark[]; P5U.OutJump[Jump,elabel]; P5U.InsertLabel[labelf]; P5U.PushLitVal[IF tf THEN 0 ELSE 1]; P5U.InsertLabel[elabel]; RETURN[P5L.TOSLex[1]] END; Not: PROCEDURE [node: Tree.Index] RETURNS [l: Lexeme] = BEGIN -- generate code for "NOT" node1: Tree.Index; BEGIN WITH tb[node].son[1] SELECT FROM subtree => BEGIN node1 _ index; SELECT tb[node1].name FROM or => l _ sCor[FALSE, tb[node1].son[1], tb[node1].son[2]]; and => l _ sCand[FALSE, tb[node1].son[1], tb[node1].son[2]]; relE,relN,relL,relGE,relG,relLE => l _ Rel[node1, FALSE]; in => l _ In[node1, FALSE]; notin => l _ In[node1, TRUE]; not => P5.PushRhs[tb[node1].son[1]]; ENDCASE => GOTO VanillaNot; RETURN [P5L.TOSLex[1]] END; ENDCASE; EXITS VanillaNot => NULL; END; P5.PushRhs[tb[node].son[1]]; P5U.PushLitVal[1]; P5U.Out0[qXOR]; RETURN[P5L.TOSLex[1]] END; Rel: PROCEDURE [node: Tree.Index, tf: BOOLEAN] RETURNS [Lexeme] = BEGIN -- produces code for relationals outside flow tlabel: LabelCCIndex _ P5U.LabelAlloc[]; elabel: LabelCCIndex _ P5U.LabelAlloc[]; P5.FlowTree[[subtree[node]], tf, tlabel]; P5U.PushLitVal[0]; P5U.OutJump[Jump, elabel]; P5U.InsertLabel[tlabel]; Stack.Off[]; P5U.PushLitVal[1]; Stack.On[]; P5U.InsertLabel[elabel]; RETURN[P5L.TOSLex[1]] END; In: PROCEDURE [node: Tree.Index, tf: BOOLEAN] RETURNS [Lexeme] = BEGIN -- generates code for IN expression (outside flow) label: LabelCCIndex _ P5U.LabelAlloc[]; elabel: LabelCCIndex _ P5U.LabelAlloc[]; Stack.Mark[]; P5.FlowIn[Tree.Link[subtree[node]], FALSE, label]; P5U.PushLitVal[IF tf THEN 1 ELSE 0]; P5U.OutJump[Jump, elabel]; Stack.DeleteToMark[]; P5U.InsertLabel[label]; P5U.PushLitVal[IF tf THEN 0 ELSE 1]; P5U.InsertLabel[elabel]; RETURN[P5L.TOSLex[1]] END; IfExp: PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN -- generates code for an IF expression ilabel, elabel: LabelCCIndex; t3: Tree.Link = tb[node].son[3]; t2: Tree.Link = tb[node].son[2]; nwords: CARDINAL; tsei: ISEIndex _ ISENull; bothConst: BOOLEAN _ P5U.TreeLiteral[t2] AND P5U.TreeLiteral[t3]; thenLong: BOOLEAN; elseLong: BOOLEAN _ P5U.LongTreeAddress[t3]; elabel _ P5U.LabelAlloc[]; Stack.Mark[]; P5.FlowTree[tb[node].son[1], FALSE, elabel]; BEGIN ENABLE P5.LogHeapFree => RESUME[FALSE, NullLex]; [nwords: nwords, long: thenLong, tsei: tsei] _ P5L.NormalizeExp[ P5L.VarForLex[P5.Exp[t2]], tsei, bothConst]; IF elseLong AND ~thenLong THEN P5U.Out0[FOpCodes.qLP]; Stack.ResetToMark[]; P5U.OutJump[Jump, ilabel _ P5U.LabelAlloc[]]; P5U.InsertLabel[elabel]; [] _ P5L.NormalizeExp[ P5L.VarForLex[P5.Exp[t3]], tsei, bothConst]; Stack.UnMark[]; IF thenLong AND ~elseLong THEN BEGIN P5U.Out0[qLP]; elseLong _ TRUE END; P5U.InsertLabel[ilabel]; END; IF tsei # ISENull THEN P5.ReleaseTempLex[[se[tsei]]]; RETURN [P5L.NormalLex[nwords, elseLong, bothConst]]; END; Min: PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN -- generate code for "MIN[...]" real: BOOLEAN = tb[node].attr1; double: BOOLEAN = real OR tb[node].attr2; signed: BOOLEAN = tb[node].attr3; sCminmax[relL,tb[node].son[1],double, real, signed]; RETURN[P5L.TOSLex[IF double THEN 2 ELSE 1]] END; Max: PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN -- generates code for "MAX[...]" real: BOOLEAN = tb[node].attr1; double: BOOLEAN = real OR tb[node].attr2; signed: BOOLEAN = tb[node].attr3; sCminmax[relG,tb[node].son[1],double, real, signed]; RETURN[P5L.TOSLex[IF double THEN 2 ELSE 1]] END; sCminmax: PROCEDURE [n: Tree.NodeName, t: Tree.Link, double, real, signed: BOOLEAN] = BEGIN -- common subroutine for Cmin and Cmax node: Tree.Index; label1, label2: LabelCCIndex; tlex: se Lexeme; firstson: BOOLEAN _ TRUE; sscm: PROCEDURE [t: Tree.Link] = BEGIN label3: LabelCCIndex; var: VarComponent; IF firstson THEN BEGIN firstson _ FALSE; RETURN END; label3 _ P5U.LabelAlloc[]; var _ P5L.MakeComponent[P5L.VarForLex[P5.Exp[t]]]; IF double THEN var _ P5L.EasilyLoadable[var, load]; P5L.LoadComponent[var]; P5.PushLex[tlex]; IF double THEN BEGIN P5U.Out0[IF real THEN qFCOMP ELSE IF signed THEN qDCOMP ELSE qDUCOMP]; P5U.PushLitVal[0]; END; P5U.OutJump[IF double OR signed THEN JumpNN[RNN[n]] ELSE UJumpNN[RNN[n]], label3]; IF double THEN P5L.LoadComponent[var] ELSE P5U.Out0[qPUSH]; P5.SAssign[tlex.lexsei]; P5U.InsertLabel[label3]; RETURN END; WITH t SELECT FROM subtree => BEGIN node _ index; IF ~CPtr.dStar THEN Stack.Dump[]; P5.PushRhs[tb[node].son[1]]; IF ~double AND TreeOps.ListLength[t] = 2 THEN BEGIN P5.PushRhs[tb[node].son[2]]; label1 _ P5U.LabelAlloc[]; label2 _ P5U.LabelAlloc[]; P5U.OutJump[IF signed THEN JumpNN[n] ELSE UJumpNN[n], label1]; P5U.Out0[qPUSH]; P5U.Out0[qPUSH]; P5U.Out0[qEXCH]; P5U.Out0[qPOP]; P5U.OutJump[Jump,label2]; Stack.Decr[1]; P5U.InsertLabel[label1]; P5U.Out0[qPUSH]; P5U.InsertLabel[label2]; RETURN; END; tlex _ P5.GenTempLex[IF double THEN 2 ELSE 1]; P5.SAssign[tlex.lexsei]; TreeOps.ScanList[t, sscm]; P5.PushLex[tlex]; END; ENDCASE; RETURN END; END... (1792)