-- Store.mesa, modified by Sweet, January 9, 1980 9:34 PM DIRECTORY AltoDefs: FROM "altodefs" USING [BYTE, charlength, wordlength], Code: FROM "code" USING [fileindex, xtracting, xtractlex, xtractsei], CodeDefs: FROM "codedefs" USING [ BoVarIndex, Lexeme, NullLex, VarComponent, VarIndex, VarNull], FOpCodes: FROM "fopcodes" USING [qFREE, qLI, qPSD, qSL], Literals: FROM "literals" USING [ltType, MSTIndex, stType], P5: FROM "p5" USING [ All, AllExp, Construct, ConstructExp, Exp, FreeTempSei, GenStringBodyLex, LogHeapFree, PushLProcDesc, PushNonnestedProcDesc, RowCons, RowConsExp, VariantConstruct], P5L: FROM "p5l" USING [ AdjustComponent, ComponentForSE, CopyToTemp, EasilyLoadable, EasyToLoad, FieldOfComponent, FieldOfVar, GenVarItem, LoadAddress, LoadComponent, MakeBo, ModComponent, OVarItem, ReleaseVarItem, StoreComponent, TOSComponent, TOSLex, VarForLex, VarVarAssign], P5S: FROM "p5s", P5U: FROM "p5u" USING [ BitsForOperand, FieldAddress, LongTreeAddress, NextVar, OperandType, Out0, Out1, PrevVar, PushLitVal, TreeLiteralValue, WordAligned], Stack: FROM "stack" USING [Dup, Pop], SymbolOps: FROM "symbolops" USING [FnField, NextSe], Symbols: FROM "symbols" USING [ BitAddress, bodyType, BTIndex, CBTIndex, ContextLevel, CSEIndex, CTXIndex, ctxType, HTIndex, ISEIndex, ISENull, lG, lZ, RecordSEIndex, SEIndex, seType, TypeClass], Table: FROM "table" USING [Base, Notifier], Tree: FROM "tree" USING [Index, Link, Null, treeType], TreeOps: FROM "treeops" USING [ReverseUpdateList, ScanList, TestTree]; Store: PROGRAM IMPORTS CPtr: Code, P5U, P5L, P5, Stack, SymbolOps, TreeOps EXPORTS CodeDefs, P5, P5S SHARES Literals = BEGIN OPEN CodeDefs, SymbolOps; -- imported definitions BYTE: TYPE = AltoDefs.BYTE; wordlength: CARDINAL = AltoDefs.wordlength; charlength: CARDINAL = AltoDefs.charlength; BitAddress: TYPE = Symbols.BitAddress; BTIndex: TYPE = Symbols.BTIndex; CBTIndex: TYPE = Symbols.CBTIndex; ContextLevel: TYPE = Symbols.ContextLevel; CSEIndex: TYPE = Symbols.CSEIndex; CTXIndex: TYPE = Symbols.CTXIndex; HTIndex: TYPE = Symbols.HTIndex; ISEIndex: TYPE = Symbols.ISEIndex; ISENull: ISEIndex = Symbols.ISENull; lZ: ContextLevel = Symbols.lZ; lG: ContextLevel = Symbols.lG; RecordSEIndex: TYPE = Symbols.RecordSEIndex; SEIndex: TYPE = Symbols.SEIndex; TypeClass: TYPE = Symbols.TypeClass; MSTIndex: TYPE = Literals.MSTIndex; tb: Table.Base; -- tree base (local copy) seb: Table.Base; -- semantic entry base (local copy) ctxb: Table.Base; -- context entry base (local copy) bb: Table.Base; -- body entry base (local copy) cb: Table.Base; -- code base (local copy) stb: Table.Base; -- string base (local copy) ltb: Table.Base; -- literal base (local copy) StoreNotify: PUBLIC Table.Notifier = BEGIN -- called by allocator whenever table area is repacked seb ← base[Symbols.seType]; ctxb ← base[Symbols.ctxType]; bb ← base[Symbols.bodyType]; stb ← base[Literals.stType]; tb ← base[Tree.treeType]; cb ← LOOPHOLE[tb]; ltb ← base[Literals.ltType]; RETURN END; Extract: PUBLIC PROCEDURE [node: Tree.Index] = BEGIN t1: Tree.Link = tb[node].son[1]; tsei: RecordSEIndex ← LOOPHOLE[P5U.OperandType[t1]]; r: VarIndex; transferrec: BOOLEAN ← FALSE; r ← P5L.VarForLex[P5.Exp[tb[node].son[2] !P5.LogHeapFree => IF calltree = tb[node].son[2] THEN BEGIN transferrec ← TRUE; RESUME[TRUE, NullLex] END]]; ExtractFrom[t1, tsei, r, transferrec]; RETURN END; ExtractFrom: PUBLIC PROCEDURE [ t1: Tree.Link, tsei: RecordSEIndex, r: VarIndex, transferrec: BOOLEAN] = BEGIN saveExtractState: RECORD [ xtracting: BOOLEAN, xtractlex: Lexeme, xtractsei: Symbols.ISEIndex] ← [CPtr.xtracting, CPtr.xtractlex, CPtr.xtractsei]; fa: PROCEDURE[ISEIndex] RETURNS [BitAddress, CARDINAL] ← IF seb[tsei].argument THEN FnField ELSE P5U.FieldAddress; startsei: ISEIndex ← ctxb[seb[tsei].fieldCtx].seList; sei: ISEIndex ← startsei; isei: ISEIndex ← startsei; soncount: CARDINAL ← 0; tbase, toffset: VarComponent; onStack, useDup: BOOLEAN ← FALSE; xlist: Tree.Link; node: Tree.Index; totalBits: CARDINAL; trashOnStack: CARDINAL ← 0; xcount: PROCEDURE [t: Tree.Link] = BEGIN IF t # Tree.Null THEN soncount ← soncount+1; RETURN END; sextract: PROCEDURE [t: Tree.Link] RETURNS [v: Tree.Link] = BEGIN posn: BitAddress; size: CARDINAL; rr: VarIndex; offset, base: VarComponent; v ← t; [posn, size] ← fa[sei]; IF t # Tree.Null THEN BEGIN soncount ← soncount-1; IF onStack THEN BEGIN offset ← toffset; -- original record on stack END ELSE BEGIN IF useDup THEN BEGIN IF (transferrec OR soncount > 0) THEN Stack.Dup[load: FALSE]; base ← P5L.TOSComponent[1]; END ELSE base ← tbase; offset ← toffset; END; P5L.FieldOfComponent[ var: @offset, wd: posn.wd, bd: posn.bd, wSize: size/wordlength, bSize: size MOD wordlength]; IF fa # FnField AND totalBits <= wordlength THEN P5L.AdjustComponent[var: @offset, rSei: tsei, fSei: sei, tBits: totalBits]; IF onStack THEN rr ← P5L.OVarItem[offset] ELSE BEGIN rr ← P5L.GenVarItem[bo]; cb[rr] ← [body: bo[base: base, offset: offset]]; END; CPtr.xtractlex ← [bdo[rr]]; CPtr.xtractsei ← sei; WITH t SELECT FROM subtree => BEGIN node: Tree.Index = index; SELECT tb[node].name FROM assign => Assign[node]; extract => Extract[node]; ENDCASE => ERROR; END; ENDCASE => ERROR; END ELSE IF onStack THEN Stack.Pop[size/wordlength]; sei ← P5U.PrevVar[startsei, sei]; RETURN END; -- of sextract WITH t1 SELECT FROM subtree => BEGIN node ← index; xlist ← tb[node].son[1]; END; ENDCASE => ERROR; UNTIL (isei ← NextSe[sei]) = ISENull DO isei ← P5U.NextVar[isei]; IF isei = ISENull THEN EXIT; sei ← isei; ENDLOOP; WITH cc: cb[r] SELECT FROM o => WITH vv: cc.var SELECT FROM stack => IF P5U.WordAligned[tsei] THEN BEGIN trashOnStack ← vv.wd; vv.wd ← 0; toffset ← cc.var; IF trashOnStack # 0 THEN P5L.ModComponent[var: @toffset, wd: trashOnStack]; P5L.ReleaseVarItem[r]; onStack ← TRUE; END ELSE BEGIN -- copy whole thing to temp var: VarComponent ← P5L.CopyToTemp[r].var; r ← P5L.OVarItem[var]; END; ENDCASE; ENDCASE; IF ~onStack THEN BEGIN bor: BoVarIndex ← P5L.MakeBo[r]; IF bor = VarNull THEN -- not addressable BEGIN -- r was not freed in this case var: VarComponent ← P5L.CopyToTemp[r].var; r ← P5L.OVarItem[var]; bor ← P5L.MakeBo[r]; -- it will work this time END; tbase ← cb[bor].base; toffset ← cb[bor].offset; P5L.ReleaseVarItem[bor]; IF tbase.wSize > 1 THEN tbase ← P5L.EasilyLoadable[tbase, store] ELSE IF ~P5L.EasyToLoad[tbase, store] THEN BEGIN P5L.LoadComponent[tbase]; useDup ← TRUE; END; END; totalBits ← toffset.wSize * wordlength + toffset.bSize; TreeOps.ScanList[xlist, xcount]; IF soncount = 0 THEN BEGIN IF onStack THEN trashOnStack ← trashOnStack + (totalBits+wordlength-1) / wordlength; END ELSE BEGIN CPtr.xtracting ← TRUE; tb[node].son[1] ← TreeOps.ReverseUpdateList[xlist, sextract]; END; IF transferrec THEN BEGIN IF ~useDup THEN P5L.LoadComponent[tbase]; P5U.Out0[FOpCodes.qFREE]; END; THROUGH [0..trashOnStack) DO Stack.Pop[] ENDLOOP; [CPtr.xtracting, CPtr.xtractlex, CPtr.xtractsei] ← saveExtractState; RETURN END; SAssign: PUBLIC PROCEDURE [sei: ISEIndex] = BEGIN -- assigns to a simple variable from the stack var: VarComponent = P5L.ComponentForSE[sei]; P5L.StoreComponent[var]; RETURN END; Assign: PUBLIC PROCEDURE [node: Tree.Index] = BEGIN -- generates code for assignment statement IF tb[node].attr1 AND TreeOps.TestTree[tb[node].son[2], union] THEN BEGIN P5.VariantConstruct[node]; RETURN END; [] ← ComAssign[tb[node].son[1], tb[node].son[2], FALSE]; RETURN END; AssignExp: PUBLIC PROCEDURE [node: Tree.Index] RETURNS [l: Lexeme] = BEGIN -- generates code for assignment expression l ← ComAssign[tb[node].son[1], tb[node].son[2], TRUE]; END; TTAssign: PUBLIC PROCEDURE [t1, t2: Tree.Link] = BEGIN [] ← ComAssign[t1, t2, FALSE]; END; ComAssign: PROCEDURE [t1,t2: Tree.Link, isexp: BOOLEAN] RETURNS [l: Lexeme] = BEGIN nbits: CARDINAL; node: Tree.Index; longAddressLhs: BOOLEAN ← P5U.LongTreeAddress[t1]; aligned: BOOLEAN ← FALSE; lv, rv: VarIndex; l ← NullLex; nbits ← P5U.BitsForOperand[t1]; IF t2 # Tree.Null THEN WITH t2 SELECT FROM subtree => BEGIN node ← index; SELECT tb[node].name FROM pad => BEGIN t2 ← tb[node].son[1]; nbits ← P5U.BitsForOperand[t2]; aligned ← TRUE; END; ENDCASE; END; ENDCASE; IF t2 # Tree.Null THEN WITH t2 SELECT FROM subtree => BEGIN node ← index; SELECT tb[node].name FROM construct => IF ~longAddressLhs THEN BEGIN IF isexp THEN l ← P5.ConstructExp[t1, node] ELSE P5.Construct[t1, node]; RETURN END; rowcons => IF ~longAddressLhs THEN BEGIN IF isexp THEN l ← P5.RowConsExp[t1, node] ELSE P5.RowCons[t1, node]; RETURN END; all => BEGIN IF isexp THEN l ← P5.AllExp[t1, node] ELSE P5.All[t1, node]; RETURN END; ENDCASE; END; ENDCASE; rv ← P5L.VarForLex[P5.Exp[t2]]; lv ← P5L.VarForLex[P5.Exp[t1]]; IF aligned THEN P5L.FieldOfVar[r: lv, wSize: nbits/wordlength, bSize: nbits MOD wordlength]; l ← P5L.VarVarAssign[lv, rv, isexp]; RETURN END; ReleaseLex: PROCEDURE[l: Lexeme] = BEGIN WITH l SELECT FROM bdo => P5L.ReleaseVarItem[lexbdoi]; ENDCASE; RETURN END; TLLAssign: PUBLIC PROCEDURE [leftson: Tree.Link, leftlex, l: Lexeme, exp: BOOLEAN, nbits: CARDINAL] = BEGIN -- main subroutine for doing assignment statements and expressions OPEN FOpCodes; rightr, leftr: VarIndex; rightr ← P5L.VarForLex[l]; IF leftson # Tree.Null THEN leftlex ← P5.Exp[leftson]; leftr ← P5L.VarForLex[leftlex]; [] ← P5L.VarVarAssign[leftr, rightr, exp]; RETURN END; SLAssign: PUBLIC PROCEDURE [sei: ISEIndex, l: Lexeme, exp: BOOLEAN, nwords: CARDINAL] = BEGIN -- sei-lexeme interface to tllCassign TLLAssign[Tree.Null, [se[sei]], l, exp, nwords*wordlength]; RETURN END; PortInit: PUBLIC PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN P5U.Out1[FOpCodes.qLI, 0]; P5U.Out1[FOpCodes.qLI, 0]; RETURN[P5L.TOSLex[2]] END; BodyInit: PUBLIC PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN -- assigns proc. desc for proc. variable bti: CBTIndex ← tb[node].info; WITH bb[bti].info SELECT FROM Internal => CPtr.fileindex ← sourceIndex; ENDCASE; P5.PushLProcDesc[bti]; RETURN [P5L.TOSLex[1]] END; StringInit: PUBLIC PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN -- inits string storage and pushes pointer on stack nchars: CARDINAL; l: se Lexeme; nchars ← P5U.TreeLiteralValue[tb[node].son[2]]; l ← P5.GenStringBodyLex[nchars]; [] ← P5L.LoadAddress[P5L.VarForLex[l]]; P5.FreeTempSei[l.lexsei]; P5U.PushLitVal[0]; P5U.PushLitVal[nchars]; P5U.Out1[FOpCodes.qPSD, 0]; RETURN [P5L.TOSLex[1]] END; ProcInit: PUBLIC PROCEDURE [node: Tree.Index] = BEGIN bti: CBTIndex ← tb[node].info; WITH bb[bti] SELECT FROM Inner => BEGIN P5.PushNonnestedProcDesc[entryIndex]; P5U.Out1[FOpCodes.qSL, frameOffset]; END; ENDCASE; RETURN END; END...