-- Address.mesa, modified by Sweet, January 18, 1980 3:49 PM DIRECTORY AltoDefs: FROM "altodefs" USING [BYTE, charlength, wordlength], Code: FROM "code", CodeDefs: FROM "codedefs" USING [ BoVarIndex, IndVarIndex, Lexeme, VarComponent, VarIndex, VarNull], ComData: FROM "comdata" USING [typeINTEGER], ControlDefs: FROM "controldefs" USING [framelink, globalbase, localbase], FOpCodes: FROM "fopcodes" USING [qBNDCK, qNILCK, qNILCKL], InlineDefs: FROM "inlinedefs" USING [LongNumber], Literals: FROM "literals" USING [LTIndex], OpCodeParams: FROM "opcodeparams", P5: FROM "p5" USING [Exp, P5Error], P5L: FROM "p5l" USING [ ComponentForLex, CopyVarItem, EasilyLoadable, FieldOfVar, FieldOfVarOnly, GenVarItem, LoadBoth, LoadComponent, LoadVar, MakeBo, MakeComponent, ModComponent, ReleaseVarItem, TOSComponent, VarForLex, Words], P5S: FROM "p5s", P5U: FROM "p5u" USING [OperandType, Out0, TreeLiteral, TreeLiteralValue], Stack: FROM "stack" USING [Mark], SymbolOps: FROM "symbolops" USING [ BitsForType, Cardinality, NormalType, UnderType, WordsForType], Symbols: FROM "symbols" USING [ BitAddress, ContextLevel, CSEIndex, CTXIndex, ctxType, HTIndex, ISEIndex, lG, lZ, SEIndex, seType], Table: FROM "table" USING [Base, Notifier], Tree: FROM "tree" USING [Index, Link, Null, treeType], TreeOps: FROM "treeops" USING [ FreeNode, PopTree, PushNode, PushTree, SetAttr, SetInfo]; Address: PROGRAM IMPORTS MPtr: ComData, CPtr: Code, P5U, CodeDefs, P5L, P5, Stack, SymbolOps, TreeOps EXPORTS CodeDefs, P5S = BEGIN OPEN CodeDefs; -- imported definitions BYTE: TYPE = AltoDefs.BYTE; wordlength: CARDINAL = AltoDefs.wordlength; charlength: CARDINAL = AltoDefs.charlength; framelink: CARDINAL = ControlDefs.framelink; globalbase: CARDINAL = ControlDefs.globalbase; localbase: CARDINAL = ControlDefs.localbase; BitAddress: TYPE = Symbols.BitAddress; ContextLevel: TYPE = Symbols.ContextLevel; CTXIndex: TYPE = Symbols.CTXIndex; HTIndex: TYPE = Symbols.HTIndex; ISEIndex: TYPE = Symbols.ISEIndex; CSEIndex: TYPE = Symbols.CSEIndex; lG: ContextLevel = Symbols.lG; lZ: ContextLevel = Symbols.lZ; SEIndex: TYPE = Symbols.SEIndex; LTIndex: TYPE = Literals.LTIndex; tb: Table.Base; -- tree base (local copy) seb: Table.Base; -- semantic entry base (local copy) ctxb: Table.Base; -- context entry base (local copy) cb: Table.Base; -- code base (local copy) AddressNotify: PUBLIC Table.Notifier = BEGIN -- called by Code whenever table area is repacked seb ← base[Symbols.seType]; ctxb ← base[Symbols.ctxType]; cb ← tb ← base[Tree.treeType]; RETURN END; Index: PUBLIC PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN -- generates code for array indexing elementWords: CARDINAL ← SymbolOps.WordsForType[tb[node].info]; grain, ePerWord: CARDINAL; ar: VarIndex; bar: BoVarIndex; er: IndVarIndex; arraytype: CSEIndex; delta: INTEGER; treeInserted, packed: BOOLEAN ← FALSE; t1, t2: Tree.Link; base, index, offset: VarComponent; indexMax, owd: CARDINAL; t1 ← tb[node].son[1]; t2 ← tb[node].son[2]; arraytype ← P5U.OperandType[t1]; WITH a:seb[arraytype] SELECT FROM array => BEGIN indexMax ← SymbolOps.Cardinality[a.indexType]; IF a.oldPacked THEN BEGIN SELECT SymbolOps.BitsForType[a.componentType] FROM 1 => grain ← 1; 2 => grain ← 2; 3,4 => grain ← 4; 5,6,7,8 => grain ← 8; ENDCASE => GO TO not; grain ← 8; -- *************** until after 6.0c bootstrap ePerWord ← 16/grain; packed ← TRUE; EXITS not => packed ← FALSE; END ELSE packed ← FALSE; END; ENDCASE => ERROR; ar ← P5L.VarForLex[P5.Exp[t1]]; bar ← P5L.MakeBo[ar]; IF bar = VarNull THEN SIGNAL CPtr.CodeNotImplemented; -- no packed arrays of arrays base ← cb[bar].base; offset ← cb[bar].offset; WITH oo: offset SELECT FROM frame => BEGIN IF oo.level # lZ THEN ERROR; IF packed THEN BEGIN IF oo.bd MOD grain # 0 THEN ERROR; oo.wd ← (oo.wd*ePerWord) + oo.bd / grain; -- above converts wd to element count vs word count oo.bd ← 0; offset.wSize ← 0; offset.bSize ← grain; END ELSE BEGIN IF oo.bd # 0 OR offset.bSize # 0 THEN ERROR; -- arrays start on word boundaries and are words long offset.wSize ← elementWords; END; owd ← oo.wd; END; code => BEGIN -- this gets cross jumped IF packed THEN BEGIN IF oo.bd MOD grain # 0 THEN ERROR; oo.wd ← (oo.wd*ePerWord) + oo.bd / grain; -- above converts wd to element count vs word count oo.bd ← 0; offset.wSize ← 0; offset.bSize ← grain; END ELSE BEGIN IF oo.bd # 0 OR offset.bSize # 0 THEN ERROR; -- arrays start on word boundaries and are words long offset.wSize ← elementWords; END; owd ← oo.wd; END; ENDCASE => ERROR; [t2, delta, treeInserted] ← CheckAdditivity[t2, elementWords, owd]; P5L.ModComponent[var: @offset, wd: INTEGER[elementWords] * delta]; index ← P5L.ComponentForLex[P5.Exp[t2]]; WITH ii: index SELECT FROM const => BEGIN co: InlineDefs.LongNumber; co.lc ← LONG[elementWords] * ii.d1; IF co.highbits # 0 THEN GO TO tooBig; IF packed THEN BEGIN newwd: CARDINAL; newbd: [0..wordlength); IF LONG[owd] + co.lc > LONG[LAST[CARDINAL]] THEN GO TO tooBig; owd ← owd + co.lowbits; newwd ← owd / ePerWord; newbd ← (owd MOD ePerWord) * grain; WITH oo: offset SELECT FROM frame => BEGIN oo.wd ← newwd; oo.bd ← newbd; END; code => BEGIN oo.wd ← newwd; oo.bd ← newbd; END; ENDCASE; END ELSE BEGIN IF LONG[owd] + co.lc > LONG[LAST[CARDINAL]] THEN GO TO tooBig; P5L.ModComponent[var: @offset, wd: co.lowbits]; END; cb[bar].offset ← offset; RETURN [[bdo[bar]]]; EXITS tooBig => NULL; END; ENDCASE; P5L.ReleaseVarItem[bar]; er ← LOOPHOLE[P5L.GenVarItem[ind]]; cb[er] ← [body: ind[base: base, index: index, offset: offset, simple: NULL, packinfo: NULL]]; IF packed THEN BEGIN cb[er].simple ← SymbolOps.WordsForType[arraytype] <= 256; cb[er].packinfo ← packed [grain: grain]; END ELSE BEGIN longBase: BOOLEAN ← P5L.Words[base.wSize, base.bSize] > 1; cb[er].simple ← ~longBase OR (indexMax # 0 AND LONG[elementWords]*LONG[indexMax] < 200000B); cb[er].packinfo ← notPacked[elementWords]; END; IF treeInserted THEN WITH t2 SELECT FROM subtree => BEGIN tb[index].son[1] ← Tree.Null; TreeOps.FreeNode[index]; END; ENDCASE => P5.P5Error[323]; RETURN [[bdo[er]]]; END; CheckAdditivity: PROCEDURE [t: Tree.Link, elementWords, current: CARDINAL] RETURNS [rt: Tree.Link, delta: INTEGER, insertedtree: BOOLEAN] = BEGIN OPEN Tree, TreeOps; node: Tree.Index; p: BOOLEAN; cDelta: CARDINAL; rt ← t; delta ← 0; insertedtree ← FALSE; WITH t SELECT FROM subtree => BEGIN node ← index; IF (p ← (tb[node].name = plus)) OR tb[node].name = minus THEN IF P5U.TreeLiteral[tb[node].son[1]] THEN BEGIN cDelta ← P5U.TreeLiteralValue[tb[node].son[1]]; IF LONG[cDelta]*LONG[elementWords] > LONG[LAST[CARDINAL] - current] THEN GO TO tooBig; delta ← cDelta; -- ok if > LAST[INTEGER] as used later IF p THEN rt ← tb[node].son[2] ELSE BEGIN PushTree[tb[node].son[2]]; PushNode[uminus, 1]; SetInfo[MPtr.typeINTEGER]; SetAttr[1, FALSE]; rt ← PopTree[]; insertedtree ← TRUE; END; END ELSE IF P5U.TreeLiteral[tb[node].son[2]] THEN BEGIN cDelta ← P5U.TreeLiteralValue[tb[node].son[2]]; IF p THEN IF LONG[cDelta]*LONG[elementWords] > LONG[LAST[CARDINAL] - current] THEN GO TO tooBig ELSE delta ← cDelta -- ok if > LAST[INTEGER] as used later ELSE IF LONG[cDelta]*LONG[elementWords] > LONG[current] THEN GO TO tooBig ELSE delta ← -INTEGER[cDelta]; rt ← tb[node].son[1]; END; EXITS tooBig => delta ← 0; END; ENDCASE; RETURN END; DIndex: PUBLIC PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN -- generates code for indexing from an array descriptor er: IndVarIndex; rBase: VarIndex; nilck: BOOLEAN ← tb[node].attr1; long: BOOLEAN = tb[node].attr2; bndck: BOOLEAN ← tb[node].attr3; elementWords: CARDINAL ← SymbolOps.WordsForType[tb[node].info]; treeInserted: BOOLEAN ← FALSE; packed: BOOLEAN; pLength: CARDINAL = IF long THEN 2 ELSE 1; arraytype, arraydtype: CSEIndex; t1, t2: Tree.Link; delta, grain, owd: CARDINAL; base, bound, index: VarComponent; offset: frame VarComponent; t1 ← tb[node].son[1]; t2 ← tb[node].son[2]; arraydtype ← SymbolOps.NormalType[P5U.OperandType[t1]]; WITH seb[arraydtype] SELECT FROM arraydesc => arraytype ← SymbolOps.UnderType[describedType]; ENDCASE; WITH a:seb[arraytype] SELECT FROM array => IF a.oldPacked THEN BEGIN SELECT SymbolOps.BitsForType[a.componentType] FROM 1 => grain ← 1; 2 => grain ← 2; 3,4 => grain ← 4; 5,6,7,8 => grain ← 8; ENDCASE => GO TO not; grain ← 8; -- *************** until after 6.0c bootstrap packed ← TRUE; EXITS not => packed ← FALSE; END ELSE packed ← FALSE; ENDCASE => ERROR; IF packed THEN offset ← [bSize: grain, space: frame[wd: 0]] ELSE offset ← [wSize: elementWords, space: frame[wd: 0]]; rBase ← P5L.VarForLex[P5.Exp[t1]]; IF bndck THEN BEGIN rBound: VarIndex ← P5L.CopyVarItem[rBase]; P5L.FieldOfVar[r: rBound, wd: pLength, wSize: 1]; P5L.FieldOfVar[r: rBase, wSize: pLength]; bound ← P5L.MakeComponent[rBound]; END ELSE P5L.FieldOfVarOnly[r: rBase, wSize: pLength]; base ← P5L.MakeComponent[rBase]; IF nilck THEN BEGIN P5L.LoadComponent[base]; P5U.Out0[IF long THEN FOpCodes.qNILCKL ELSE FOpCodes.qNILCK]; base ← P5L.TOSComponent[pLength]; END; [t2, delta, treeInserted] ← CheckAdditivity[t2, 1, 0]; offset.wd ← owd ← elementWords * delta; -- elementWords = 1 if packed index ← P5L.ComponentForLex[P5.Exp[t2]]; IF bndck THEN BEGIN P5L.LoadBoth[@index, @bound, FALSE]; P5U.Out0[FOpCodes.qBNDCK]; index ← P5L.TOSComponent[1]; END ELSE WITH index SELECT FROM const => BEGIN bar: VarIndex; co: InlineDefs.LongNumber; co.lc ← elementWords * d1; IF co.highbits # 0 THEN GO TO tooBig; bar ← P5L.GenVarItem[bo]; IF packed THEN BEGIN ePerWord: CARDINAL = wordlength / grain; IF LONG[owd] + co.lc > LONG[LAST[CARDINAL]] THEN GO TO tooBig; owd ← owd + co.lowbits; offset.wd ← owd / ePerWord; offset.bd ← (owd MOD ePerWord) * grain; END ELSE BEGIN IF LONG[owd] + co.lc > LONG[LAST[CARDINAL]] THEN GO TO tooBig; P5L.ModComponent[var: @offset, wd: co.lowbits]; END; cb[bar] ← [body: bo[base: base, offset: offset]]; RETURN [[bdo[bar]]]; EXITS tooBig => NULL; END; ENDCASE; er ← LOOPHOLE[P5L.GenVarItem[ind]]; cb[er] ← [body: ind[base: base, index: index, offset: offset, simple: NULL, packinfo: NULL]]; IF packed THEN BEGIN cb[er].simple ← FALSE; cb[er].packinfo ← packed [grain: grain]; END ELSE BEGIN cb[er].simple ← ~long; cb[er].packinfo ← notPacked[elementWords]; END; IF treeInserted THEN WITH t2 SELECT FROM subtree => BEGIN tb[index].son[1] ← Tree.Null; TreeOps.FreeNode[index]; END; ENDCASE => P5.P5Error[323]; RETURN[[bdo[er]]]; END; SeqIndex: PUBLIC PROCEDURE [node: Tree.Index] RETURNS [Lexeme] = BEGIN easy: BOOLEAN ← FALSE; nilck: BOOLEAN ← tb[node].attr1; long: BOOLEAN ← tb[node].attr2; bndck: BOOLEAN ← tb[node].attr3; t1: Tree.Link ← tb[node].son[1]; t2: Tree.Link ← tb[node].son[2]; base, index: VarComponent; rBound: VarIndex; er: VarIndex; delta: INTEGER; treeInserted: BOOLEAN ← FALSE; StringHeaderSize: CARDINAL = 2; CharsPerWord: CARDINAL = 2; byteOffset: CARDINAL = StringHeaderSize*CharsPerWord; IF long AND bndck THEN Stack.Mark[]; base ← P5L.ComponentForLex[P5.Exp[t1]]; IF bndck THEN BEGIN base ← P5L.EasilyLoadable[base, load]; rBound ← P5L.GenVarItem[bo]; cb[rBound] ← [body: bo[base: base, offset: [wSize: 1, space: frame[wd: 1]]]]; END; IF nilck THEN BEGIN P5L.LoadComponent[base]; P5U.Out0[IF long THEN FOpCodes.qNILCKL ELSE FOpCodes.qNILCK]; base ← P5L.TOSComponent[IF long THEN 2 ELSE 1]; END; [t2, delta, treeInserted] ← CheckAdditivity[t2, 1, byteOffset]; index ← P5L.ComponentForLex[P5.Exp[t2]]; IF bndck THEN BEGIN P5L.LoadComponent[index]; P5L.LoadVar[rBound]; P5U.Out0[FOpCodes.qBNDCK]; index ← P5L.TOSComponent[1]; END ELSE WITH index SELECT FROM const => BEGIN co: CARDINAL = d1 + CARDINAL[byteOffset + delta]; bar: VarIndex = P5L.GenVarItem[bo]; cb[bar] ← [body: bo[base: base, offset: [bSize: charlength, space: frame[wd: co/CharsPerWord, bd: (co MOD CharsPerWord)*charlength]]]]; RETURN [[bdo[bar]]]; END; ENDCASE; er ← P5L.GenVarItem[ind]; cb[er] ← [body: ind[ base: base, index: index, offset: [bSize: 8, space: frame[wd: 4+delta]], simple: FALSE, packinfo: packed[grain: 8]]]; IF treeInserted THEN WITH t2 SELECT FROM subtree => BEGIN tb[index].son[1] ← Tree.Null; TreeOps.FreeNode[index]; END; ENDCASE => P5.P5Error[323]; RETURN[[bdo[er]]]; END; END...