Address.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Sweet, August 29, 1980 2:04 PM
Satterthwaite, April 16, 1986 3:48:50 pm PST
Maxwell, August 11, 1983 9:01 am
Russ Atkinson (RRA) March 6, 1985 11:55:59 pm PST
DIRECTORY
Alloc USING [Notifier],
Basics USING [LongMult],
Code USING [CodeNotImplemented],
CodeDefs USING [Base, BoVarIndex, codeType, IndVarIndex, Lexeme, OpWordCount, VarComponent, VarIndex, VarNull],
ComData USING [typeINT],
FOpCodes USING [qBNDCK, qNILCK, qNILCKL],
P5 USING [AdjustNilCheck, Exp, PushRhs],
P5L USING [ComponentForLex, ComponentForSE, FieldOfVar, FieldOfVarOnly, GenVarItem, LoadBoth, LoadComponent, LoadVar, MakeBo, MakeComponent, ModComponent, ReleaseVarItem, ReusableCopies, TOSComponent, VarForLex, Words],
P5S USING [],
P5U USING [OperandType, Out0, TreeLiteral, TreeLiteralValue],
SymbolOps USING [BitsPerElement, Cardinality, NormalType, UnderType],
Symbols USING [Base, BitCount, ByteLength, CSEIndex, ISEIndex, lZ, seType, PackedBitCount, WordCount, WordLength],
Tree USING [Base, Index, Link, treeType],
TreeOps USING [PopTree, PushNode, PushTree, SetAttr, SetInfo];
Address: PROGRAM
IMPORTS MPtr: ComData, CPtr: Code, Basics, P5U, P5L, P5, SymbolOps, TreeOps
EXPORTS CodeDefs, P5S =
BEGIN OPEN CodeDefs;
imported definitions
BitCount: TYPE = Symbols.BitCount;
PackedBitCount: TYPE = Symbols.PackedBitCount;
WordCount: TYPE = Symbols.WordCount;
wordLength: CARDINAL = Symbols.WordLength;
CSEIndex: TYPE = Symbols.CSEIndex;
ISEIndex: TYPE = Symbols.ISEIndex;
tb: Tree.Base;  -- tree base (local copy)
seb: Symbols.Base;  -- semantic entry base (local copy)
cb: CodeDefs.Base;  -- code base (local copy)
AddressNotify: PUBLIC Alloc.Notifier =
BEGIN -- called by Code whenever table area is repacked
seb ← base[Symbols.seType];
tb ← base[Tree.treeType];
cb ← base[codeType];
END;
utilities
LongMult: PROC [CARDINAL, CARDINAL] RETURNS [LONG CARDINAL] =
Basics.LongMult;
WordOffset: PROC [sei: ISEIndex] RETURNS [CARDINAL] =
BEGIN
var: VarComponent = P5L.ComponentForSE[sei];
RETURN [WITH vv: var SELECT FROM
frame => P5L.Words[w: vv.wd, b: vv.bd],
ENDCASE => ERROR]
END;
in a packed ind VarItem, the wd of the offset is scaled
and measured in units of element size
ScaleComponent: PROC [var: POINTER TO VarComponent, grain: PackedBitCount] =
BEGIN
ePerWord: [0..wordLength] = wordLength/grain;
WITH vv: var^ SELECT FROM
frame =>
BEGIN
vv.wd ← (vv.wd*ePerWord) + vv.bd/grain;
vv.bd ← vv.bd MOD grain;
END;
code =>
BEGIN -- this gets cross jumped
vv.wd ← (vv.wd*ePerWord) + vv.bd/grain;
vv.bd ← vv.bd MOD grain;
END;
ENDCASE => ERROR;
END;
UnscaleComponent: PROC [var: POINTER TO VarComponent, grain: PackedBitCount] =
BEGIN
ePerWord: [0..wordLength] = wordLength/grain;
WITH vv: var^ SELECT FROM
frame =>
BEGIN
newBd: CARDINAL = vv.bd + (vv.wd MOD ePerWord)*grain;
vv.wd ← vv.wd/ePerWord + newBd/wordLength;
vv.bd ← newBd MOD wordLength;
END;
code =>
BEGIN -- this gets cross jumped
newBd: CARDINAL = vv.bd + (vv.wd MOD ePerWord)*grain;
vv.wd ← vv.wd/ePerWord + newBd/wordLength;
vv.bd ← newBd MOD wordLength;
END;
ENDCASE => ERROR;
END;
operations
Index: PUBLIC PROC [node: Tree.Index] RETURNS [Lexeme] =
BEGIN -- generates code for array indexing
arrayType: CSEIndex = P5U.OperandType[tb[node].son[1]];
grain, tBits: BitCount;
packed: BOOL;
elementWords: OpWordCount;
indexRange: LONG CARDINAL;
owd: CARDINAL;
delta: INTEGER;
t2: Tree.Link;
base, index, offset: VarComponent;
er: IndVarIndex;
bar: BoVarIndex ← P5L.MakeBo[P5L.VarForLex[P5.Exp[tb[node].son[1]]]];
IF bar = VarNull THEN
SIGNAL CPtr.CodeNotImplemented; -- no packed arrays of arrays
base ← cb[bar].base; offset ← cb[bar].offset;
WITH a: seb[arrayType] SELECT FROM
array =>
BEGIN
grain ← SymbolOps.BitsPerElement[a.componentType, a.packed];
packed ← grain < wordLength;
elementWords ← IF packed THEN 1 ELSE OpWordCount[grain/wordLength];
indexRange ← SymbolOps.Cardinality[a.indexType];
END;
ENDCASE => ERROR;
IF packed AND (tBits ← indexRange*grain) IN (0..wordLength) THEN
BEGIN
fieldSize: CARDINAL = offset.wSize*wordLength + offset.bSize;
IF tBits < fieldSize THEN
P5L.ModComponent[var: @offset, wd: 0, bd: fieldSize-tBits];
END;
WITH oo: offset SELECT FROM
frame =>
BEGIN
IF oo.level # Symbols.lZ THEN ERROR;
IF packed THEN
BEGIN
ScaleComponent[@offset, PackedBitCount[grain]];
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
ScaleComponent[@offset, PackedBitCount[grain]];
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] ← CheckAdditivity[tb[node].son[2], elementWords, owd];
P5L.ModComponent[var: @offset, wd: INTEGER[elementWords] * delta];
index ← P5L.ComponentForLex[P5.Exp[t2]];
WITH ii: index SELECT FROM
const =>
BEGIN
co: LONG CARDINAL = LongMult[elementWords, ii.d1];
IF co + owd.LONG > OpWordCount.LAST THEN GO TO tooBig;
P5L.ModComponent[var: @offset, wd: co];
IF packed THEN UnscaleComponent[@offset, PackedBitCount[grain]];
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: TRASH, packinfo: TRASH]];
IF packed THEN
BEGIN
cb[er].simple ← indexRange # 0 AND grain*(owd+indexRange) <= 4096;
cb[er].packinfo ← packed[grain: PackedBitCount[grain]];
END
ELSE
BEGIN
cb[er].simple ←
(P5L.Words[base.wSize, base.bSize] = 1) OR
(indexRange # 0 AND elementWords*indexRange <= OpWordCount.LAST.LONG+1);
cb[er].packinfo ← notPacked[elementWords];
END;
RETURN [[bdo[er]]]
END;
CheckAdditivity: PROC [t: Tree.Link, elementWords: OpWordCount, current: LONG CARDINAL]
RETURNS [rt: Tree.Link, delta: INTEGER ← 0] =
BEGIN
node: Tree.Index;
p: BOOL;
cDelta: CARDINAL;
rt ← t;
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 LongMult[cDelta, elementWords] > OpWordCount.LAST.LONG - current THEN
GO TO tooBig;
delta ← cDelta; -- ok if > INTEGER.LAST as used later
IF ~p THEN
BEGIN OPEN TreeOps;
PushTree[tb[node].son[2]]; PushNode[uminus, 1];
SetInfo[MPtr.typeINT]; SetAttr[1, FALSE];
tb[node].son[2] ← PopTree[]; tb[node].name ← plus;
END;
rt ← tb[node].son[2]
END
ELSE IF P5U.TreeLiteral[tb[node].son[2]] THEN
BEGIN
cDelta ← P5U.TreeLiteralValue[tb[node].son[2]];
IF p THEN
IF LongMult[cDelta, elementWords] > OpWordCount.LAST.LONG - current THEN
GO TO tooBig
ELSE delta ← cDelta -- ok if > INTEGER.LAST as used later
ELSE
IF LongMult[cDelta, elementWords] > current THEN
GO TO tooBig
ELSE delta ← -INTEGER[cDelta];
rt ← tb[node].son[1];
END;
EXITS
tooBig => NULL;
END;
ENDCASE;
RETURN
END;
DIndex: PUBLIC PROC [node: Tree.Index] RETURNS [Lexeme] =
BEGIN -- generates code for indexing from an array descriptor
arrayDType: CSEIndex = SymbolOps.NormalType[P5U.OperandType[tb[node].son[1]]];
arrayType: CSEIndex = WITH seb[arrayDType] SELECT FROM
arraydesc => SymbolOps.UnderType[describedType],
ENDCASE => ERROR;
grain: BitCount;
packed: BOOL;
elementWords: OpWordCount;
nilck: BOOL = tb[node].attr1;
long: BOOL = tb[node].attr2;
pLength: CARDINAL = IF long THEN 2 ELSE 1;
bndck: BOOL = tb[node].attr3;
owd: CARDINAL;
delta: CARDINAL ← 0;
t2: Tree.Link;
rBase, rBound: VarIndex;
base, bound, index: VarComponent;
offset: VarComponent.frame;
er: IndVarIndex;
WITH a:seb[arrayType] SELECT FROM
array =>
BEGIN
grain ← SymbolOps.BitsPerElement[a.componentType, a.packed];
packed ← grain < wordLength;
elementWords ← IF packed THEN 1 ELSE OpWordCount[grain/wordLength];
END
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[tb[node].son[1]]];
IF bndck THEN
BEGIN
IF nilck THEN [first: rBase, next: rBound] ← P5L.ReusableCopies[rBase, load, TRUE]
ELSE [first: rBound, next: rBase] ← P5L.ReusableCopies[rBase, load, TRUE];
P5L.FieldOfVar[r: rBound, wd: pLength, wSize: 1];
P5L.FieldOfVar[r: rBase, wSize: pLength];
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;
IF bndck THEN t2 ← tb[node].son[2]
ELSE [t2, delta] ← CheckAdditivity[tb[node].son[2], elementWords, 0];
offset.wd ← owd ← elementWords*delta; -- elementWords = 1 if packed
index ← P5L.ComponentForLex[P5.Exp[t2]];
IF bndck THEN
BEGIN
bound ← P5L.MakeComponent[rBound];
P5L.LoadBoth[@index, @bound, FALSE];
P5U.Out0[FOpCodes.qBNDCK];
index ← P5L.TOSComponent[1];
END
ELSE WITH ii: index SELECT FROM
const =>
BEGIN
bar: VarIndex;
co: LONG CARDINAL = LongMult[elementWords, ii.d1];
IF co + owd.LONG > OpWordCount.LAST THEN GO TO tooBig;
P5L.ModComponent[var: @offset, wd: co];
IF packed THEN UnscaleComponent[@offset, PackedBitCount[grain]];
bar ← P5L.GenVarItem[bo];
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: TRASH, packinfo: TRASH]];
IF packed
THEN {cb[er].simple ← FALSE; cb[er].packinfo ← packed[grain: PackedBitCount[grain]]}
ELSE {cb[er].simple ← ~long; cb[er].packinfo ← notPacked[elementWords]};
RETURN [[bdo[er]]]
END;
SeqIndex: PUBLIC PROC [node: Tree.Index] RETURNS [Lexeme] =
BEGIN
seqType: CSEIndex = P5U.OperandType[tb[node].son[1]];
isString: BOOLFALSE;
grain: BitCount;
packed: BOOL;
elementWords: OpWordCount;
indexRange: LONG CARDINAL;
long: BOOL = tb[node].attr2;
bndck: BOOL = tb[node].attr3;
owd: CARDINAL;
rBound, bor: BoVarIndex;
base, offset, index: VarComponent;
er: IndVarIndex;
WITH ss: seb[seqType] SELECT FROM
array =>
BEGIN
isString ← packed ← TRUE; grain ← Symbols.ByteLength;
elementWords ← 1;
indexRange ← SymbolOps.Cardinality[ss.indexType];
END;
sequence =>
BEGIN
grain ← SymbolOps.BitsPerElement[ss.componentType, ss.packed];
packed ← grain < wordLength;
elementWords ← IF packed THEN 1 ELSE OpWordCount[grain/wordLength];
indexRange ← SymbolOps.Cardinality[seb[ss.tagSei].idType];
IF bndck THEN P5.AdjustNilCheck[tb[node].son[1], WordOffset[ss.tagSei]];
END;
ENDCASE => ERROR;
bor ← P5L.MakeBo[P5L.VarForLex[P5.Exp[tb[node].son[1]]]];
IF bor = VarNull THEN
SIGNAL CPtr.CodeNotImplemented; -- no packed arrays of sequences
IF bndck THEN
BEGIN
[first: LOOPHOLE[bor, VarIndex], next: LOOPHOLE[rBound, VarIndex]] ←
P5L.ReusableCopies[bor, load, FALSE];
P5L.LoadComponent[cb[bor].base];
cb[bor].base ← P5L.TOSComponent[IF long THEN 2 ELSE 1];
END;
IF isString THEN
BEGIN
IF bndck THEN WITH vv: cb[rBound].offset SELECT FROM
frame => {vv.wd ← vv.wd - 1; vv.wSize ← 1}; -- maxlength precedes text
ENDCASE => ERROR;
END
ELSE P5L.FieldOfVar[
r: bor, wd: cb[bor].offset.wSize, bd: cb[bor].offset.bSize]; -- skip tag
base ← cb[bor].base; offset ← cb[bor].offset;
IF packed THEN {offset.bSize ← grain; offset.wSize ← 0}
ELSE {offset.wSize ← elementWords; offset.bSize ← 0};
WITH vv: offset SELECT FROM
frame =>
BEGIN
IF packed THEN ScaleComponent[@offset, PackedBitCount[grain]];
owd ← vv.wd;
END;
ENDCASE => ERROR;
IF bndck THEN
BEGIN
P5.PushRhs[tb[node].son[2]];
P5L.LoadVar[rBound];
P5U.Out0[FOpCodes.qBNDCK];
index ← P5L.TOSComponent[1];
END
ELSE
BEGIN
t2: Tree.Link;
delta: INTEGER;
[t2, delta] ← CheckAdditivity[tb[node].son[2], elementWords, owd];
P5L.ModComponent[var: @offset, wd: INTEGER[elementWords] * delta];
index ← P5L.ComponentForLex[P5.Exp[t2]];
END;
WITH ii: index SELECT FROM
const =>
BEGIN
co: LONG CARDINAL = LongMult[elementWords, ii.d1];
IF co + owd.LONG > OpWordCount.LAST THEN GO TO tooBig;
P5L.ModComponent[var: @offset, wd: co];
IF packed THEN UnscaleComponent[@offset, PackedBitCount[grain]];
cb[bor].offset ← offset;
RETURN [[bdo[bor]]]
EXITS
tooBig => NULL;
END;
ENDCASE;
P5L.ReleaseVarItem[bor];
er ← LOOPHOLE[P5L.GenVarItem[ind]];
cb[er] ← [body: ind[base: base, index: index, offset: offset,
simple: TRASH, packinfo: TRASH]];
IF packed THEN
BEGIN
cb[er].simple ← indexRange # 0 AND grain*(owd+indexRange) <= 4096;
cb[er].packinfo ← packed[grain: PackedBitCount[grain]];
END
ELSE
BEGIN
cb[er].simple ←
(P5L.Words[base.wSize, base.bSize] = 1) OR
(indexRange # 0 AND elementWords*indexRange <= OpWordCount.LAST.LONG+1);
cb[er].packinfo ← notPacked[elementWords];
END;
RETURN [[bdo[er]]]
END;
END.