DIRECTORY
Alloc: TYPE USING [Notifier],
ComData: TYPE USING [idCARDINAL, idINTEGER, interface, typeINTEGER, typeStringBody],
LiteralOps: TYPE USING [Find, FindDescriptor],
Log: TYPE USING [Error, ErrorTree, WarningTree],
P4: TYPE USING [Attr, AUsForType, BiasForType, BitsForType, both, ByteSeq, CatchNest, CommonAttr, CommonProp, Exp, FillMultiWord, ForceType, LiteralAttr, MakeArgRecord, MakeStructuredLiteral, MakeTreeLiteral, maxRegs, none, OperandStruct, OperandType, other, Prop, RegCount, RegsForType, RelTest, RepForType, Repr, Rhs, RValue, SetType, StructuredLiteral, TreeLiteral, TreeLiteralValue, TypeExp, TypeForTree, unsigned, ValueDescriptor, VAttr, voidAttr, VPop, VProp, VPush, VRegs, VRep],
Symbols: TYPE USING [Base, BitAddress, BitCount, codeCHAR, codeINT, CSEIndex, ctxType, ISEIndex, ISENull, lZ, seType, Type],
SymbolOps: TYPE USING [ArgRecord, BitsPerElement, Cardinality, CtxLevel, DecodeBitAddr, DecodeCard, FirstCtxSe, FromType, NormalType, NextSe, PackedSize, VariantField, ToType, UnderType],
SymLiteralOps: TYPE USING [TypeRef],
Target: TYPE MachineParms USING [bitsPerAU, bitsPerByte, bitsPerChar, bitsPerWord, maxWord, maxLongWord],
Tree: TYPE USING [Base, Index, Link, NodeName, Null, treeType],
TreeOps:
TYPE
USING [FreeNode, FreeTree, GetNode, GetSe, GetTag, IdentityMap, MakeNode, OpName, PopTree, PushLit, PushNode, PushSe, PushTree, SetAttr];
Pass4Xc:
PROGRAM
IMPORTS Log, LiteralOps, P4, SymbolOps, SymLiteralOps, TreeOps, dataPtr: ComData
EXPORTS P4 = {
OPEN SymbolOps, TreeOps, P4;
Type: TYPE = Symbols.Type;
CSEIndex: TYPE = Symbols.CSEIndex;
bitsPerWord: CARDINAL = Target.bitsPerWord;
tb: Tree.Base; -- tree base address (local copy)
seb: Symbols.Base; -- se table base address (local copy)
ctxb: Symbols.Base; -- context table base address (local copy)
ExpCNotify:
PUBLIC Alloc.Notifier = {
called by allocator whenever table area is repacked
tb ← base[Tree.treeType];
seb ← base[Symbols.seType]; ctxb ← base[Symbols.ctxType]};
AddrOp:
PUBLIC
PROC [node: Tree.Index]
RETURNS [val: Tree.Link] = {
attr: Attr;
nRegs: RegCount;
SELECT tb[node].name FROM
addr => val ← Addr[node];
base => {
tb[node].son[1] ← Exp[tb[node].son[1], none];
nRegs ← VRegs[]; attr ← [prop: VProp[], rep: unsigned]; VPop[];
VPush[0, attr, nRegs]; val ← [subtree[index: node]]};
length => {
type: CSEIndex;
tb[node].son[1] ← Exp[tb[node].son[1], none];
type ← OperandStruct[tb[node].son[1]];
WITH seb[type]
SELECT
FROM
array => {
val ← MakeTreeLiteral[Cardinality[indexType]];
FreeNode[node]; attr ← LiteralAttr[both]; nRegs ← 1};
ENDCASE => {
val ← [subtree[index: node]]; attr ← [prop: VProp[], rep: both]; nRegs ← VRegs[]};
VPop[]; VPush[0, attr, nRegs]};
arraydesc =>
val ← IF OpName[tb[node].son[1]] # list THEN Desc[node] ELSE DescList[node];
ENDCASE => {
Log.Error[unimplemented]; VPush[0, voidAttr, 0]; val ← [subtree[node]]};
RETURN};
Addr:
PROC [node: Tree.Index]
RETURNS [val: Tree.Link] = {
OPEN tb[node];
v: Tree.Link;
subNode: Tree.Index;
type, next: CSEIndex;
prop: Prop;
nRegs: RegCount;
son[1] ← Exp[son[1], none];
nRegs ← MAX[VRegs[], RegsForType[ToType[info]]];
prop ← VProp[]; prop.noFreeVar ← FALSE;
FOR t: Tree.Link ← son[1], v
DO
WITH t
SELECT GetTag[t]
FROM
symbol => {
sei: Symbols.ISEIndex = index;
IF seb[sei].constant THEN GO TO fail;
IF CtxLevel[seb[sei].idCtx] = Symbols.lZ
AND
(DecodeBitAddr[seb[sei].idValue].bd
MOD bitsPerWord # 0
OR
DecodeCard[seb[sei].idInfo] MOD bitsPerWord # 0) THEN GO TO fail;
GO TO pass};
subtree => {
subNode ← index;
SELECT tb[subNode].name
FROM
dot, dollar => v ← tb[subNode].son[2];
index, dindex, seqindex =>
FOR type ← NormalType[OperandType[tb[subNode].son[1]]], next
DO
WITH t: seb[type]
SELECT
FROM
array => IF t.packed THEN GO TO fail ELSE GO TO pass;
sequence => IF t.packed THEN GO TO fail ELSE GO TO pass;
arraydesc => next ← UnderType[t.describedType];
ENDCASE => ERROR;
ENDLOOP;
apply => GO TO fail;
uparrow, reloc => GO TO pass;
cast, chop => v ← tb[subNode].son[1];
base, length => GO TO pass;
ENDCASE => ERROR};
ENDCASE => ERROR;
REPEAT
pass => NULL;
fail => Log.ErrorTree[nonAddressable, son[1]];
ENDLOOP;
val ← [subtree[index: node]];
IF OpName[son[1]] = dot
THEN {
subNode ← GetNode[son[1]];
IF TreeLiteral[tb[subNode].son[1]]
THEN {
val ← MakeStructuredLiteral[
TreeLiteralValue[tb[subNode].son[1]] +
DecodeBitAddr[seb[GetSe[tb[subNode].son[2]]].idValue]/bitsPerWord,
ToType[info]];
FreeNode[node]}};
VPop[];
VPush[0, [prop: prop, rep: unsigned], nRegs]; RETURN};
Desc:
PROC [node: Tree.Index]
RETURNS [Tree.Link] = {
subNode: Tree.Index = GetNode[tb[node].son[1]];
long: BOOL = tb[subNode].attr2;
prop: Prop;
nRegs: RegCount;
subType: CSEIndex;
tb[subNode].son[1] ← Exp[tb[subNode].son[1], none];
nRegs ← VRegs[]; prop ← VProp[]; VPop[];
subType ← OperandStruct[tb[subNode].son[1]];
WITH t: seb[subType]
SELECT
FROM
array => {
n: CARDINAL = Cardinality[t.indexType];
IF n = 0 THEN Log.WarningTree[emptyArray, tb[subNode].son[1]];
IF t.packed
AND (BitsForType[subType]
MOD bitsPerWord # 0)
THEN
Log.ErrorTree[nonAddressable, tb[subNode].son[1]];
PushTree[[subtree[subNode]]]; PushTree[MakeTreeLiteral[n]]};
sequence => {
copy: Tree.Link = IdentityMap[tb[subNode].son[1]];
cNode: Tree.Index = GetNode[copy];
PushTree[tb[subNode].son[1]]; PushTree[MakeTreeLiteral[0]];
PushNode[seqindex, 2]; SetType[t.componentType];
SetAttr[2, long]; SetAttr[3, FALSE];
tb[subNode].son[1] ← PopTree[]; PushTree[[subtree[subNode]]];
tb[cNode].son[2] ← FreeTree[tb[cNode].son[2]];
tb[cNode].son[2] ← [symbol[index: t.tagSei]];
tb[cNode].info ← FromType[dataPtr.idCARDINAL];
PushTree[copy]};
record => {
-- StringBody only (compatibility glitch)
copy: Tree.Link = IdentityMap[tb[subNode].son[1]];
sei: Symbols.ISEIndex = NextSe[NextSe[FirstCtxSe[t.fieldCtx]]];
PushTree[tb[subNode].son[1]]; PushSe[sei]; PushNode[dollar, 2];
SetType[seb[sei].idType]; SetAttr[2, long];
tb[subNode].son[1] ← PopTree[]; PushTree[[subtree[subNode]]];
PushTree[copy]; PushSe[NextSe[FirstCtxSe[t.fieldCtx]]]; PushNode[dollar, 2];
SetType[dataPtr.idCARDINAL]; SetAttr[2, long]};
ENDCASE => {
PushTree[[subtree[subNode]]]; PushTree[Tree.Null]};
PushTree[Tree.Null]; PushNode[list, 3]; tb[node].son[1] ← PopTree[];
VPush[0, [prop: prop, rep: other], MAX[RegsForType[ToType[tb[node].info]], nRegs]];
RETURN[[subtree[index: node]]]};
DescList:
PROC [node: Tree.Index]
RETURNS [val: Tree.Link] = {
subNode: Tree.Index = GetNode[tb[node].son[1]];
type: Type = ToType[tb[node].info];
subType: CSEIndex;
prop: Prop;
nRegs: RegCount;
tb[subNode].son[1] ← RValue[tb[subNode].son[1], 0, unsigned];
nRegs ← VRegs[]; prop ← VProp[]; subType ← OperandStruct[tb[subNode].son[1]];
WITH seb[subType]
SELECT
FROM
ref =>
IF BitsForType[refType]
MOD bitsPerWord # 0
THEN
Log.ErrorTree[nonAddressable, tb[subNode].son[1]];
ENDCASE;
tb[subNode].son[2] ← RValue[tb[subNode].son[2], 0, none];
nRegs ← MAX[VRegs[], nRegs]; prop ← CommonProp[VProp[], prop];
IF tb[subNode].son[3] # Tree.Null THEN TypeExp[tb[subNode].son[3]];
VPop[]; VPop[];
IF StructuredLiteral[tb[subNode].son[1]]
AND TreeLiteral[tb[subNode].son[2]]
THEN {
n: CARDINAL = AUsForType[type]*(Target.bitsPerAU/Target.bitsPerByte);
bytes: ValueDescriptor ← NEW[ByteSeq[n]];
FillMultiWord[bytes, 0, tb[subNode].son[1]];
bytes[n-1] ← TreeLiteralValue[tb[subNode].son[2]];
PushLit[LiteralOps.FindDescriptor[DESCRIPTOR[bytes]]];
PushNode[mwconst, 1]; SetType[type];
bytes ← NIL;
val ← PopTree[]; FreeNode[node]}
ELSE val ← [subtree[index: node]];
VPush[0, [prop: prop, rep: other], MAX[RegsForType[type], nRegs]]; RETURN};
}.