-- file Pass4Xb.mesa -- last written by Satterthwaite, September 17, 1982 4:15 pm DIRECTORY Alloc: TYPE USING [Notifier], ComData: TYPE USING [ definitionsOnly, switches, typeCARDINAL, typeINT, typeSTRING, zone], Heap: TYPE USING [FreeNode, MakeNode], LiteralOps: TYPE USING [ MasterString, ValueDescriptor, FindDescriptor, FindLocalString, StringReference], Log: TYPE USING [ErrorTree, WarningTree], P4: TYPE USING [ Repr, none, signed, unsigned, both, long, other, RegCount, MaxRegs, checked, currentLevel, AddrOp, All, Assignment, BiasForType, BindCase, BindType, BoolValue, Call, CanonicalType, CaseDriver, CatchNest, CheckRange, CommonRep, ComparableType, ConstantInterval, Construct, DeclItem, Dollar, EmptyInterval, Extract, FoldExpr, Index, Interval, IntToReal, LiteralRep, LongToShort, MakeTreeLiteral, MarkString, MiscXfer, Narrow, New, NormalizeRange, PadRecord, Reloc, RepForType, Rhs, RowConstruct, SeqIndex, ShortToLong, Subst, TreeLiteralValue, TypeExp, TypeOp, Union, WordsForType], Pass4: TYPE USING [implicitBias, implicitRep, implicitType, tFALSE, tTRUE], Symbols: TYPE USING [ Base, SEIndex, ISEIndex, CSEIndex, lG, typeANY, seType], SymbolOps: TYPE USING [ Cardinality, ConstantId, FindExtension, NormalType, RCType, TypeForm, UnderType, WordsForType, XferMode], SymLiteralOps: TYPE USING [AtomRef, TextRef], Tree: TYPE USING [Base, Index, Link, Map, NodeName, Null, treeType], TreeOps: TYPE USING [ FreeNode, GetHash, GetNode, IdentityMap, ListLength, OpName, PopTree, PushLit, PushNode, PushTree, SetAttr, SetInfo, SetShared, Shared, UpdateList]; Pass4Xb: PROGRAM IMPORTS Heap, Log, LiteralOps, P4, SymbolOps, SymLiteralOps, TreeOps, dataPtr: ComData, passPtr: Pass4 EXPORTS P4 = { OPEN SymbolOps, P4, TreeOps; -- pervasive definitions from Symbols ISEIndex: TYPE = Symbols.ISEIndex; CSEIndex: TYPE = Symbols.CSEIndex; tb: Tree.Base; -- tree base address (local copy) seb: Symbols.Base; -- se table base address (local copy) zone: UNCOUNTED ZONE ← NIL; ExpBNotify: PUBLIC Alloc.Notifier = { -- called by allocator whenever table area is repacked tb ← base[Tree.treeType]; seb ← base[Symbols.seType]}; -- intermediate result bookkeeping ValueDescriptor: TYPE = RECORD[ bias: INTEGER, -- bias in representation (scalars only) nRegs: RegCount, -- estimate of register requirement rep: Repr]; -- signed/unsigned (scalars only) VStack: TYPE = RECORD [SEQUENCE length: NAT OF ValueDescriptor]; vStack: LONG POINTER TO VStack ← NIL; vI: INTEGER; -- index into vStack VPush: PUBLIC PROC [bias: INTEGER, rep: Repr, nRegs: RegCount] = { vI ← vI + 1; WHILE vI >= vStack.length DO newLength: NAT = vStack.length + 16; newStack: LONG POINTER TO VStack = zone.NEW[VStack[newLength]]; FOR i: INTEGER IN [0 .. vI) DO newStack[i] ← vStack[i] ENDLOOP; zone.FREE[@vStack]; vStack ← newStack; ENDLOOP; vStack[vI] ← [bias:bias, rep:rep, nRegs:nRegs]}; VPop: PUBLIC PROC = {IF vI < 0 THEN ERROR; vI ← vI-1}; VBias: PUBLIC PROC RETURNS [INTEGER] = {RETURN [vStack[vI].bias]}; VRep: PUBLIC PROC RETURNS [Repr] = {RETURN [vStack[vI].rep]}; VRegs: PUBLIC PROC RETURNS [RegCount] = {RETURN [vStack[vI].nRegs]}; ExpInit: PUBLIC PROC [scratchZone: UNCOUNTED ZONE] = { zone ← scratchZone; vStack ← zone.NEW[VStack[32]]; vI ← -1}; ExpReset: PUBLIC PROC = { IF vStack # NIL THEN zone.FREE[@vStack]; zone ← NIL}; OperandType: PUBLIC PROC [t: Tree.Link] RETURNS [CSEIndex] = { RETURN [WITH t SELECT FROM symbol => UnderType[seb[index].idType], literal => IF info.litTag = string THEN dataPtr.typeSTRING ELSE dataPtr.typeINT, subtree => IF t = Tree.Null THEN passPtr.implicitType ELSE tb[index].info, ENDCASE => Symbols.typeANY]}; ForceType: PUBLIC PROC [t: Tree.Link, type: CSEIndex] RETURNS [Tree.Link] = { PushTree[t]; IF (OpName[t] # mwconst AND OpName[t] # cast) OR Shared[t] THEN PushNode[cast, 1]; SetInfo[type]; RETURN [PopTree[]]}; ChopType: PROC [t: Tree.Link, type: CSEIndex] RETURNS [Tree.Link] = { PushTree[t]; PushNode[chop, 1]; SetInfo[type]; RETURN [PopTree[]]}; -- literals TreeLiteral: PUBLIC PROC [t: Tree.Link] RETURNS [BOOLEAN] = { RETURN [WITH t SELECT FROM literal => info.litTag = word, subtree => SELECT tb[index].name FROM cast => TreeLiteral[tb[index].son[1]], ENDCASE => FALSE, ENDCASE => FALSE]}; StructuredLiteral: PUBLIC PROC [t: Tree.Link] RETURNS [BOOLEAN] = { RETURN [WITH t SELECT FROM literal => info.litTag = word, subtree => SELECT tb[index].name FROM mwconst => TRUE, cast => StructuredLiteral[tb[index].son[1]], ENDCASE => FALSE, ENDCASE => FALSE]}; MakeStructuredLiteral: PUBLIC PROC [val: WORD, type: CSEIndex] RETURNS [t: Tree.Link] = { t ← MakeTreeLiteral[val]; SELECT seb[type].typeTag FROM basic, enumerated, subrange, mode => NULL; ENDCASE => t ← ForceType[t, type]; RETURN}; -- register accounting RegsForType: PUBLIC PROC [type: CSEIndex] RETURNS [RegCount] = { n: RegCount = IF seb[type].mark4 THEN SymbolOps.WordsForType[type] ELSE 0; RETURN [IF n = 2 THEN 2 ELSE 1]}; ComputeRegs: PROC [node: Tree.Index] RETURNS [RegCount] = { n1: RegCount = vStack[vI-1].nRegs; n2: RegCount = vStack[vI].nRegs; k: RegCount = RegsForType[tb[node].info]; RETURN [MIN[MAX[n1, n2+k], MaxRegs]]}; ComputeIndexRegs: PUBLIC PROC [node: Tree.Index] RETURNS [RegCount] = { n1: RegCount = vStack[vI-1].nRegs; n2: RegCount = vStack[vI].nRegs; k: RegCount = RegsForType[OperandType[tb[node].son[1]]]; RETURN [MIN[MAX[RegsForType[tb[node].info], n1, n2+k], MaxRegs]]}; AdjustRegs: PROC [node: Tree.Index, commuteOp: Tree.NodeName] RETURNS [RegCount] = { n1: RegCount = vStack[vI-1].nRegs; n2: RegCount = vStack[vI].nRegs; k: RegCount = RegsForType[tb[node].info]; n: CARDINAL; IF n1 >= n2 THEN n ← n2 + k ELSE { v: ValueDescriptor; t: Tree.Link ← tb[node].son[1]; tb[node].son[1] ← tb[node].son[2]; tb[node].son[2] ← t; tb[node].name ← commuteOp; v ← vStack[vI]; vStack[vI] ← vStack[vI-1]; vStack[vI-1] ← v; n ← n1 + k}; RETURN [MIN[MAX[n1, n2, n], MaxRegs]]}; -- operators Fold: PROC [node: Tree.Index, rep: Repr] RETURNS [Tree.Link] = { fullRep: Repr = IF tb[node].attr2 THEN long + rep ELSE rep; RETURN [FoldExpr[node, fullRep]]}; Substx: PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { type: CSEIndex = tb[node].info; subNode: Tree.Index; val ← Subst[node]; node ← GetNode[val]; IF OpName[tb[node].son[2]] = result THEN { subNode ← GetNode[tb[node].son[2]]; SELECT ListLength[tb[subNode].son[1]] FROM 0 => ERROR; 1 => { tb[subNode].son[1] ← Unsafen[tb[subNode].son[1]]; val ← IF tb[subNode].attr3 THEN tb[subNode].son[1] ELSE ForceType[tb[subNode].son[1], type]}; ENDCASE => { PushTree[Tree.Null]; PushTree[tb[subNode].son[1]]; PushNode[construct, 2]; SetInfo[type]; val ← PopTree[]}; tb[subNode].son[1] ← Tree.Null; FreeNode[node]}; VPush[BiasForType[type], RepForType[type], MaxRegs]; RETURN}; Unsafen: Tree.Map = { IF OpName[t] = safen THEN { node: Tree.Index = GetNode[t]; v ← tb[node].son[1]; tb[node].son[1] ← Tree.Null; FreeNode[node]} ELSE v ← t; RETURN}; UMinus: PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { tb[node].son[1] ← Exp[tb[node].son[1], signed]; SELECT vStack[vI].rep FROM both => vStack[vI].rep ← signed; none => {Log.WarningTree[mixedRepresentation, val]; vStack[vI].rep ← signed}; ENDCASE => NULL; IF ~StructuredLiteral[tb[node].son[1]] THEN { tb[node].attr3 ← TRUE; val ← [subtree[index: node]]} ELSE val ← Fold[node, vStack[vI].rep]; IF vStack[vI].rep = unsigned THEN vStack[vI].rep ← signed; vStack[vI].bias ← -VBias[]; RETURN}; Abs: PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { rep: Repr; tb[node].son[1] ← RValue[tb[node].son[1], 0, signed]; val ← [subtree[index: node]]; rep ← vStack[vI].rep; SELECT rep FROM unsigned, both => { Log.WarningTree[unsignedCompare, val]; val ← tb[node].son[1]; tb[node].son[1] ← Tree.Null; FreeNode[node]}; none => {Log.ErrorTree[mixedRepresentation, val]; vStack[vI].rep ← both}; ENDCASE => { tb[node].attr3 ← TRUE; IF StructuredLiteral[tb[node].son[1]] THEN val ← Fold[node, rep]; IF rep # other THEN vStack[vI].rep ← both}; RETURN}; EnumOp: PROC [node: Tree.Index, target: Repr] RETURNS [Tree.Link] = { t: Tree.Link; type: CSEIndex = tb[node].info; nType: CSEIndex = NormalType[type]; long: BOOLEAN = seb[type].typeTag = long; d: INTEGER ← 0; DO d ← IF tb[node].name = pred THEN d-1 ELSE d+1; t ← tb[node].son[1]; tb[node].son[1] ← Tree.Null; FreeNode[node]; SELECT OpName[t] FROM pred, succ => NULL; ENDCASE => EXIT; node ← GetNode[t]; ENDLOOP; PushTree[t]; PushTree[MakeTreeLiteral[ABS[d]]]; IF long THEN {PushNode[lengthen, 1]; SetInfo[type]}; PushNode[IF d < 0 THEN minus ELSE plus, 2]; SetInfo[type]; SetAttr[1, FALSE]; SetAttr[2, long]; RETURN [IF seb[nType].typeTag = enumerated THEN CheckRange[ RValue[PopTree[], BiasForType[nType], target], Cardinality[nType], nType] ELSE AddOp[GetNode[PopTree[]], target]]}; ArithRep: PROC [rep, target: Repr] RETURNS [Repr] = { RETURN [SELECT rep FROM both, none => SELECT target FROM both, none, other => signed, ENDCASE => target, ENDCASE => rep]}; BiasedFold: PROC [node: Tree.Index, rep: Repr] RETURNS [Tree.Link] = { fullRep: Repr = IF tb[node].attr2 THEN long + rep ELSE rep; tb[node].son[1] ← AdjustBias[tb[node].son[1], -vStack[vI-1].bias]; tb[node].son[2] ← AdjustBias[tb[node].son[2], -vStack[vI].bias]; RETURN [FoldExpr[node, fullRep]]}; AddOp: PROC [node: Tree.Index, target: Repr] RETURNS [val: Tree.Link] = { OPEN tb[node]; op: Tree.NodeName = tb[node].name; type: CSEIndex = tb[node].info; bias, shift: INTEGER; rep: Repr; nRegs: RegCount; son[1] ← Exp[son[1], target]; son[2] ← Exp[son[2], target]; val ← [subtree[index: node]]; rep ← CommonRep[vStack[vI-1].rep, vStack[vI].rep]; SELECT rep FROM both => rep ← ArithRep[rep, target]; none => IF target = none THEN {Log.WarningTree[mixedRepresentation, val]; rep ← both} ELSE rep ← IF target = both THEN signed ELSE target; ENDCASE => NULL; IF StructuredLiteral[son[1]] AND StructuredLiteral[son[2]] AND ~attr1 THEN { val ← BiasedFold[node, rep]; rep ← LiteralRep[val, rep]; bias ← 0; nRegs ← RegsForType[type]} ELSE { nRegs ← IF op=plus THEN AdjustRegs[node, plus] ELSE ComputeRegs[node]; bias ← vStack[vI-1].bias; shift ← vStack[vI].bias; attr3 ← rep # unsigned; SELECT TRUE FROM TreeLiteral[son[2]] => { val ← son[1]; shift ← shift + TreeLiteralValue[son[2]]; son[1] ← Tree.Null; FreeNode[node]}; (op = plus AND TreeLiteral[son[1]]) => { val ← son[2]; shift ← shift + TreeLiteralValue[son[1]]; son[2] ← Tree.Null; FreeNode[node]}; ENDCASE; bias ← bias + (IF op=plus THEN shift ELSE -shift)}; VPop[]; VPop[]; VPush[bias, rep, nRegs]; IF type # dataPtr.typeINT AND OperandType[val] # type THEN val ← ForceType[val, type]; RETURN}; Mult: PROC [node: Tree.Index, target: Repr] RETURNS [val: Tree.Link] = { OPEN tb[node]; rep: Repr; const1, const2: BOOLEAN; v1, v2: WORD; bias: INTEGER; nRegs: RegCount; t: Tree.Link; son[1] ← Exp[son[1], target]; son[2] ← Exp[son[2], target]; val ← [subtree[index: node]]; rep ← CommonRep[vStack[vI-1].rep, vStack[vI].rep]; SELECT rep FROM both => rep ← ArithRep[rep, target]; none => IF target = none THEN {Log.WarningTree[mixedRepresentation, val]; rep ← both} ELSE rep ← IF target = both THEN signed ELSE target; ENDCASE => NULL; IF StructuredLiteral[son[1]] AND StructuredLiteral[son[2]] AND ~attr1 THEN { nRegs ← RegsForType[info]; val ← BiasedFold[node, rep]; rep ← LiteralRep[val, rep]; bias ← 0} ELSE { nRegs ← AdjustRegs[node, times]; const1 ← TreeLiteral[son[1]]; const2 ← TreeLiteral[son[2]]; IF const1 OR ~const2 THEN son[1] ← AdjustBias[son[1], -vStack[vI-1].bias]; IF ~const1 OR const2 THEN son[2] ← AdjustBias[son[2], -vStack[vI].bias]; IF const1 THEN v1 ← TreeLiteralValue[son[1]]; IF const2 THEN v2 ← TreeLiteralValue[son[2]]; attr3 ← rep # unsigned; bias ← SELECT TRUE FROM const1 => v1*vStack[vI].bias, const2 => vStack[vI-1].bias*v2, ENDCASE => 0; IF StructuredLiteral[son[1]] -- AND ~const2 -- THEN { t ← son[2]; son[2] ← son[1]; son[1] ← t}; IF const1 OR const2 THEN SELECT (IF const1 THEN v1 ELSE v2) FROM 0 => {val ← son[2]; son[2] ← Tree.Null; FreeNode[node]; rep ← both}; 1 => { val ← son[1]; son[1] ← Tree.Null; FreeNode[node]; rep ← vStack[IF const1 THEN vI ELSE vI-1].rep}; -1 => { PushTree[son[1]]; son[1] ← Tree.Null; FreeNode[node]; PushNode[uminus, 1]; SetInfo[dataPtr.typeINT]; SetAttr[1, FALSE]; SetAttr[2, FALSE]; SetAttr[3, TRUE]; val ← PopTree[]}; ENDCASE}; VPop[]; VPop[]; VPush[bias, rep, nRegs]; RETURN}; DivMod: PROC [node: Tree.Index, target: Repr] RETURNS [val: Tree.Link] = { OPEN tb[node]; rep: Repr; nRegs: RegCount; son[1] ← RValue[son[1], 0, target]; son[2] ← RValue[son[2], 0, target]; val ← [subtree[index: node]]; rep ← CommonRep[vStack[vI-1].rep, vStack[vI].rep]; SELECT rep FROM both => NULL; -- preserved by div and mod none => IF target = none THEN {Log.ErrorTree[mixedRepresentation, val]; rep ← both} ELSE rep ← target; ENDCASE => NULL; IF StructuredLiteral[son[1]] AND StructuredLiteral[son[2]] AND ~attr1 THEN { nRegs ← RegsForType[info]; val ← Fold[node, rep]; rep ← LiteralRep[val, rep]} ELSE { nRegs ← ComputeRegs[node]; attr3 ← CommonRep[rep, unsigned] = none; IF name = div AND TreeLiteral[son[2]] THEN SELECT TreeLiteralValue[son[2]] FROM = 1 => {val ← son[1]; son[1] ← Tree.Null; FreeNode[node]}; >=2 => IF rep = unsigned THEN rep ← both; ENDCASE}; VPop[]; VPop[]; VPush[0, rep, nRegs]; RETURN}; RelOp: PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { OPEN tb[node]; rep, rep1, rep2: Repr; nRegs: RegCount; d1, d2: INTEGER; uc: BOOLEAN; ZeroWarning: ARRAY Tree.NodeName [relE..relLE] OF [0..2] = [0, 0, 2, 2, 1, 1]; CommutedOp: ARRAY Tree.NodeName [relE..relLE] OF Tree.NodeName = [relE, relN, relG, relLE, relL, relGE]; son[1] ← Exp[son[1], none]; son[2] ← Exp[son[2], none]; val ← [subtree[index: node]]; IF ~ComparableSons[node] THEN Log.ErrorTree[sizeClash, son[2]]; rep1 ← vStack[vI-1].rep; d1 ← vStack[vI-1].bias; rep2 ← vStack[vI].rep; d2 ← vStack[vI].bias; rep ← CommonRep[rep1, rep2]; IF rep = none THEN SELECT name FROM relE, relN => Log.WarningTree[mixedRepresentation, val]; ENDCASE => Log.ErrorTree[mixedRepresentation, val]; SELECT name FROM relE, relN => uc ← FALSE; ENDCASE => { IF rep1 = unsigned OR rep2 = unsigned THEN { son[1] ← AdjustBias[son[1], -d1]; d1 ← 0; son[2] ← AdjustBias[son[2], -d2]; d2 ← 0}; uc ← CommonRep[rep, unsigned] # none}; IF d1 # d2 THEN IF (~uc AND TreeLiteral[son[2]]) OR (uc AND d2 > d1) THEN son[2] ← AdjustBias[son[2], d1-d2] ELSE son[1] ← AdjustBias[son[1], d2-d1]; IF CommonRep[rep, signed+other] = none THEN { SELECT ZeroWarning[name] FROM 1 => IF TreeLiteral[son[1]] AND TreeLiteralValue[son[1]] = 0 THEN GO TO warn; 2 => IF TreeLiteral[son[2]] AND TreeLiteralValue[son[2]] = 0 THEN GO TO warn; ENDCASE; EXITS warn => Log.WarningTree[unsignedCompare, val]}; IF StructuredLiteral[son[1]] AND StructuredLiteral[son[2]] AND ~attr1 THEN { val ← Fold[node, rep]; nRegs ← 1} ELSE {nRegs ← AdjustRegs[node, CommutedOp[name]]; attr3 ← rep # unsigned}; VPop[]; VPop[]; VPush[0, both, nRegs]; RETURN}; ComparableSons: PROC [node: Tree.Index] RETURNS [BOOLEAN] = { OPEN tb[node]; -- compatibility version type1: CSEIndex = OperandType[son[1]]; n1: CARDINAL = P4.WordsForType[type1]; type2: CSEIndex = OperandType[son[2]]; n2: CARDINAL = P4.WordsForType[type2]; IF n1 = 0 OR n2 = 0 THEN RETURN [FALSE]; SELECT TRUE FROM (n1 = n2) => NULL; (seb[type1].typeTag = record AND seb[type2].typeTag = record) => IF n1 < n2 THEN -- account for lost discrimination son[2] ← ChopType[son[2], type1] ELSE son[1] ← ChopType[son[1], type2]; ENDCASE => RETURN [FALSE]; RETURN [ComparableType[type1] OR ComparableType[type2]]}; In: PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { OPEN tb[node]; bias: INTEGER; rep: Repr; nRegs: RegCount; void, const: BOOLEAN; subNode: Tree.Index; son[1] ← Exp[son[1], none]; bias ← VBias[]; rep ← VRep[]; -- IF rep = unsigned THEN {son[1] ← AdjustBias[son[1], -bias]; bias ← 0}; void ← FALSE; val ← [subtree[index: node]]; son[2] ← NormalizeRange[son[2]]; subNode ← GetNode[son[2]]; IF (const ← Interval[subNode, bias, none].const) AND ~tb[node].attr2 THEN [] ← ConstantInterval[subNode ! EmptyInterval => {void ← TRUE; RESUME}]; rep ← CommonRep[rep, VRep[]]; IF rep = none THEN Log.ErrorTree[mixedRepresentation, val]; tb[subNode].attr3 ← attr3 ← rep # unsigned; SELECT TRUE FROM void AND son[1] # Tree.Null => { FreeNode[node]; val ← passPtr.tFALSE; nRegs ← 1}; const AND StructuredLiteral[son[1]] AND ~attr1 => { val ← Fold[node, rep]; nRegs ← 1}; ENDCASE => nRegs ← ComputeRegs[node]; VPop[]; VPop[]; VPush[0, both, nRegs]; RETURN}; BoolOp: PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { OPEN tb[node]; b: Tree.Link = IF (name = and) THEN passPtr.tTRUE ELSE passPtr.tFALSE; n1, n2, nRegs: RegCount; son[1] ← BoolValue[son[1]]; n1 ← VRegs[]; son[2] ← BoolValue[son[2]]; n2 ← VRegs[]; IF TreeLiteral[son[1]] THEN { IF son[1] = b THEN {val ← son[2]; son[2] ← Tree.Null; nRegs ← n2} ELSE { val ← IF (name = and) THEN passPtr.tFALSE ELSE passPtr.tTRUE; nRegs ← 1}; FreeNode[node]} ELSE IF son[2] # b THEN {val ← [subtree[index: node]]; nRegs ← MAX[n1, n2]} ELSE {val ← son[1]; son[1] ← Tree.Null; nRegs ← n1; FreeNode[node]}; VPop[]; VPop[]; VPush[0, both, nRegs]; RETURN}; CheckAlt: PROC [t: Tree.Link, target: CSEIndex] RETURNS [Tree.Link] = { type: CSEIndex = OperandType[t]; IF P4.WordsForType[type] # P4.WordsForType[target] THEN IF seb[type].typeTag = record AND seb[target].typeTag = record THEN t ← PadRecord[t, target] ELSE Log.ErrorTree[sizeClash, t]; RETURN [t]}; IfExp: PROC [node: Tree.Index, target: Repr] RETURNS [val: Tree.Link] = { OPEN tb[node]; select: Tree.Link; rep: Repr; nRegs: RegCount; bias: INTEGER = BiasForType[info]; son[1] ← BoolValue[son[1]]; nRegs ← VRegs[]; VPop[]; IF TreeLiteral[son[1]] THEN { IF son[1] # passPtr.tFALSE THEN {select ← son[2]; son[2] ← Tree.Null} ELSE {select ← son[3]; son[3] ← Tree.Null}; FreeNode[node]; val ← Exp[select, target]} ELSE { son[2] ← CheckAlt[RValue[son[2], bias, target], info]; rep ← VRep[]; nRegs ← MAX[VRegs[], nRegs]; VPop[]; son[3] ← CheckAlt[RValue[son[3], bias, target], info]; val ← [subtree[index: node]]; rep ← CommonRep[VRep[], rep]; IF rep = none THEN IF target = none THEN {Log.WarningTree[mixedRepresentation, val]; rep ← both} ELSE rep ← target; vStack[vI].rep ← rep; vStack[vI].nRegs ← MAX[VRegs[], nRegs]}; RETURN}; CaseExp: PROC [node: Tree.Index, target: Repr, caseBias: INTEGER] RETURNS [val: Tree.Link] = { op: Tree.NodeName = tb[node].name; type: CSEIndex = tb[node].info; bias: INTEGER = BiasForType[type]; rep: Repr; const: BOOLEAN; Selection: Tree.Map = { v ← CheckAlt[RValue[t, bias, target], type]; rep ← CommonRep[rep, VRep[]]; VPop[]; const ← const AND StructuredLiteral[v]; RETURN}; rep ← both+other; const ← TRUE; val ← CaseDriver[node, Selection, caseBias]; IF OpName[val] = op THEN {PushTree[val]; SetAttr[1, const]; val ← PopTree[]}; IF rep = none THEN IF target = none THEN {Log.WarningTree[mixedRepresentation, val]; rep ← both} ELSE rep ← target; VPush[bias, rep, MaxRegs]; RETURN}; BindCaseExp: PROC [node: Tree.Index, target: Repr] RETURNS [Tree.Link] = { BoundExp: PROC [t: Tree.Link, labelBias: INTEGER] RETURNS [Tree.Link] = { RETURN [CaseExp[GetNode[t], target, labelBias]]}; RETURN [BindCase[node, casex, BoundExp]]}; BindTypeExp: PROC [node: Tree.Index, target: Repr] RETURNS [val: Tree.Link] = { type: CSEIndex = tb[node].info; bias: INTEGER = BiasForType[type]; rep: Repr; const: BOOLEAN; Selection: Tree.Map = { v ← CheckAlt[RValue[t, bias, target], type]; rep ← CommonRep[rep, VRep[]]; VPop[]; const ← const AND StructuredLiteral[v]; RETURN}; rep ← both+other; const ← TRUE; val ← BindType[node, Selection]; IF rep = none THEN IF target = none THEN {Log.WarningTree[mixedRepresentation, val]; rep ← both} ELSE rep ← target; VPush[bias, rep, MaxRegs]; RETURN}; MinMax: PROC [node: Tree.Index, target: Repr] RETURNS [val: Tree.Link] = { OPEN tb[node]; const, zeroTest: BOOLEAN; rep: Repr; nRegs: RegCount; k: RegCount = RegsForType[info]; Item: Tree.Map = { v ← RValue[t, 0, target]; IF ~StructuredLiteral[v] THEN const ← FALSE ELSE IF TreeLiteral[v] AND TreeLiteralValue[v] = 0 THEN zeroTest ← TRUE; rep ← CommonRep[rep, VRep[]]; nRegs ← MIN[MAX[nRegs, VRegs[]+k], MaxRegs]; VPop[]; RETURN}; IF ListLength[son[1]] = 1 THEN { val ← Exp[son[1], target]; son[1] ← Tree.Null; FreeNode[node]} ELSE { const ← TRUE; zeroTest ← FALSE; rep ← both+other; nRegs ← 0; son[1] ← UpdateList[son[1], Item]; val ← [subtree[index: node]]; IF zeroTest AND CommonRep[rep, unsigned] # none THEN Log.WarningTree[unsignedCompare, val]; SELECT rep FROM both => rep ← IF target = none THEN both ELSE target; none => IF target = none THEN {Log.ErrorTree[mixedRepresentation, val]; rep ← both} ELSE rep ← target; ENDCASE => NULL; IF const AND ~attr1 THEN { val ← Fold[node, rep]; rep ← LiteralRep[val, rep]; nRegs ← k} ELSE attr3 ← rep # unsigned; VPush[0, rep, nRegs]}; RETURN}; Nil: PROC [node: Tree.Index] RETURNS [Tree.Link] = { type: CSEIndex = tb[node].info; n: CARDINAL; d: LiteralOps.ValueDescriptor; IF tb[node].son[1] # Tree.Null THEN TypeExp[tb[node].son[1]]; n ← P4.WordsForType[type]; d ← DESCRIPTOR[Heap.MakeNode[dataPtr.zone, n], n]; FOR i: CARDINAL IN [0..n) DO d[i] ← 0 ENDLOOP; PushLit[LiteralOps.FindDescriptor[d]]; IF n > 1 THEN {PushNode[mwconst, 1]; SetInfo[type]}; FreeNode[node]; Heap.FreeNode[dataPtr.zone, BASE[d]]; VPush[BiasForType[type], RepForType[type], RegsForType[type]]; RETURN [ForceType[PopTree[], type]]}; Lengthen: PROC [node: Tree.Index, target: Repr] RETURNS [val: Tree.Link] = { OPEN tb[node]; rep: Repr; nRegs: RegCount; son[1] ← RValue[son[1], 0, IF target=both THEN unsigned ELSE target]; attr1 ← SELECT TypeForm[CanonicalType[OperandType[son[1]]]] FROM ref, arraydesc => TRUE, ENDCASE => FALSE; IF (rep ← VRep[]) = none THEN {Log.ErrorTree[mixedRepresentation, son[1]]; rep ← both}; attr3 ← CommonRep[rep, unsigned] = none; nRegs ← MAX[VRegs[], RegsForType[info]]; IF ~TreeLiteral[son[1]] OR (attr1 AND TreeLiteralValue[son[1]] # 0--NIL--) THEN val ← [subtree[index: node]] ELSE {val ← ShortToLong[node, rep]; rep ← LiteralRep[val, rep]}; VPop[]; VPush[0, IF rep = unsigned AND ~attr1 THEN both ELSE rep, nRegs]; RETURN}; Shorten: PROC [node: Tree.Index, target: Repr] RETURNS [val: Tree.Link] = { OPEN tb[node]; rep: Repr; nRegs: RegCount; son[1] ← RValue[son[1], 0, IF target=both THEN unsigned ELSE target]; nRegs ← VRegs[]; rep ← VRep[]; VPop[]; IF CommonRep[target, unsigned] # none THEN rep ← unsigned; attr1 ← checked OR dataPtr.switches['b]; IF CommonRep[rep, unsigned] = none THEN attr3 ← TRUE ELSE {attr3 ← FALSE; info ← dataPtr.typeCARDINAL}; IF ~StructuredLiteral[son[1]] THEN val ← [subtree[index: node]] ELSE {val ← LongToShort[node, rep]; rep ← LiteralRep[val, rep]}; VPush[0, rep, nRegs]; RETURN}; Loophole: PROC [node: Tree.Index, target: Repr] RETURNS [val: Tree.Link] = { OPEN tb[node]; type: CSEIndex = info; rep: Repr = IF tb[node].son[2] # Tree.Null OR target = none THEN RepForType[type] ELSE target; son[1] ← Exp[son[1], rep]; IF son[2] # Tree.Null THEN TypeExp[son[2]]; IF P4.WordsForType[OperandType[son[1]]] # P4.WordsForType[type] THEN Log.ErrorTree[sizeClash, son[1]]; IF RCType[type] # none THEN val ← [subtree[index: node]] ELSE { val ← ForceType[son[1], type]; son[1] ← Tree.Null; FreeNode[node]}; vStack[vI].rep ← rep; RETURN}; AdjustBias: PUBLIC PROC [t: Tree.Link, delta: INTEGER] RETURNS [Tree.Link] = { op: Tree.NodeName; type: CSEIndex; IF delta = 0 THEN RETURN [t]; IF OpName[t] = safen THEN { subNode: Tree.Index = GetNode[t]; tb[subNode].son[1] ← AdjustBias[tb[subNode].son[1], delta]; RETURN [t]}; IF t = Tree.Null THEN passPtr.implicitBias ← passPtr.implicitBias + delta; type ← OperandType[t]; IF TreeLiteral[t] THEN RETURN [MakeStructuredLiteral[TreeLiteralValue[t]-delta, type]]; IF delta > 0 THEN op ← minus ELSE {op ← plus; delta ← -delta}; PushTree[t]; PushTree[MakeTreeLiteral[delta]]; PushNode[op, 2]; SetInfo[type]; SetAttr[1, FALSE]; SetAttr[2, FALSE]; RETURN [PopTree[]]}; RValue: PUBLIC PROC [exp: Tree.Link, bias: INTEGER, target: Repr] RETURNS [val: Tree.Link] = { d: INTEGER; val ← Exp[exp, target]; d ← bias - vStack[vI].bias; IF d # 0 THEN {val ← AdjustBias[val, d]; vStack[vI].bias ← bias}; RETURN}; Exp: PUBLIC PROC [exp: Tree.Link, target: Repr] RETURNS [val: Tree.Link] = { rep: Repr; WITH expr: exp SELECT FROM symbol => { sei: ISEIndex = expr.index; type: CSEIndex; IF ~seb[sei].mark4 THEN DeclItem[Tree.Link[subtree[index: seb[sei].idValue]]]; type ← UnderType[seb[sei].idType]; rep ← RepForType[type]; IF ~seb[sei].constant THEN val ← expr ELSE SELECT XferMode[type] FROM proc, signal, error, program => val ← IF ConstantId[sei] AND ~seb[sei].extended THEN MakeStructuredLiteral[seb[sei].idValue, type] ELSE expr; ENDCASE => IF seb[sei].extended THEN { val ← IdentityMap[FindExtension[sei].tree]; WITH val SELECT FROM subtree => tb[index].info ← type; ENDCASE; val ← Exp[val, target]; rep ← VRep[]; VPop[]} ELSE { val ← MakeStructuredLiteral[seb[sei].idValue, type]; rep ← LiteralRep[val, rep]}; VPush[BiasForType[type], rep, RegsForType[type]]}; literal => { WITH expr.info SELECT FROM word => rep ← LiteralRep[expr, unsigned]; string => { LiteralOps.StringReference[index]; MarkString[local: index # LiteralOps.MasterString[index]]; rep ← unsigned}; ENDCASE => rep ← none; VPush[0, rep, 1]; val ← expr}; subtree => IF expr = Tree.Null THEN { val ← Tree.Null; VPush[passPtr.implicitBias, passPtr.implicitRep, MaxRegs]} ELSE { node: Tree.Index = expr.index; SELECT tb[node].name FROM dot => { OPEN tb[node]; nRegs: RegCount; son[1] ← RValue[son[1], 0, unsigned]; nRegs ← MAX[RegsForType[info], VRegs[]]; VPop[]; son[2] ← Exp[son[2], target]; vStack[vI].nRegs ← nRegs; attr1 ← ~attr3 AND (checked OR dataPtr.switches['n]); val ← expr}; dollar => val ← Dollar[node]; cdot => { val ← Exp[tb[node].son[2], target]; tb[node].son[2] ← Tree.Null; FreeNode[node]}; uparrow => { OPEN tb[node]; nRegs: RegCount; son[1] ← RValue[son[1], 0, unsigned]; nRegs ← MAX[RegsForType[info], VRegs[]]; VPop[]; VPush[BiasForType[info], RepForType[info], nRegs]; attr1 ← ~attr3 AND (checked OR dataPtr.switches['n]); val ← expr}; callx, portcallx, signalx, errorx, startx, joinx => val ← Call[node]; substx => val ← Substx[node]; index, dindex => val ← Index[node]; seqindex => val ← SeqIndex[node]; reloc => val ← Reloc[node]; construct => val ← Construct[node]; union => val ← Union[node]; rowcons => val ← RowConstruct[node]; all => val ← All[node]; uminus => val ← UMinus[node]; abs => val ← Abs[node]; pred, succ => val ← EnumOp[node, target]; plus, minus => val ← AddOp[node, target]; times => val ← Mult[node, target]; div, mod => val ← DivMod[node, target]; relE, relN, relL, relGE, relG, relLE => val ← RelOp[node]; in, notin => val ← In[node]; not => { tb[node].son[1] ← BoolValue[tb[node].son[1]]; IF ~TreeLiteral[tb[node].son[1]] THEN val ← expr ELSE { val ← IF tb[node].son[1] # passPtr.tFALSE THEN passPtr.tFALSE ELSE passPtr.tTRUE; FreeNode[node]; vStack[vI].nRegs ← 1}}; or, and => val ← BoolOp[node]; ifx => val ← IfExp[node, target]; casex => val ← CaseExp[node, target, 0]; bindx => val ← IF tb[node].attr3 THEN BindTypeExp[node, target] ELSE BindCaseExp[node, target]; assignx => val ← Assignment[node]; extractx => val ← Extract[node]; min, max => val ← MinMax[node, target]; mwconst => { rep: Repr; val ← expr; rep ← LiteralRep[val, RepForType[tb[node].info]]; VPush[0, rep, RegsForType[tb[node].info]]}; clit => {val ← tb[node].son[1]; FreeNode[node]; VPush[0, both, 1]}; llit => { IF currentLevel > Symbols.lG THEN WITH e: tb[node].son[1] SELECT FROM literal => WITH e.info SELECT FROM string => index ← LiteralOps.FindLocalString[index]; ENDCASE; ENDCASE; val ← Exp[tb[node].son[1], none]; tb[node].son[1] ← Tree.Null; FreeNode[node]}; textlit => { nRegs: RegCount = RegsForType[tb[node].info]; IF dataPtr.definitionsOnly THEN val ← expr ELSE { val ← WITH e: tb[node].son[1] SELECT FROM literal => WITH e.info SELECT FROM string => SymLiteralOps.TextRef[index], ENDCASE => ERROR, ENDCASE => ERROR; FreeNode[node]}; VPush[0, unsigned, nRegs]}; atom => { IF dataPtr.definitionsOnly THEN val ← expr ELSE { val ← SymLiteralOps.AtomRef[GetHash[tb[node].son[1]]]; FreeNode[node]}; VPush[0, unsigned, 2]}; new => val ← New[node]; nil => val ← Nil[node]; create, fork => val ← MiscXfer[node]; syserrorx => {val ← expr; VPush[0, RepForType[tb[node].info], MaxRegs]}; lengthen => val ← Lengthen[node, target]; shorten => val ← Shorten[node, target]; float => { tb[node].son[1] ← RValue[tb[node].son[1], 0, signed]; IF StructuredLiteral[tb[node].son[1]] AND vStack[vI].rep # unsigned THEN val ← IntToReal[node] ELSE {val ← expr; vStack[vI].nRegs ← MaxRegs}; vStack[vI].rep ← other}; safen, proccheck => { tb[node].son[1] ← Exp[tb[node].son[1], target]; val ← expr}; loophole => val ← Loophole[node, target]; cast => { OPEN tb[node]; rep: Repr = RepForType[info]; son[1] ← Exp[son[1], rep]; vStack[vI].rep ← rep; val ← expr; IF P4.WordsForType[OperandType[son[1]]] # P4.WordsForType[info] THEN name ← chop; vStack[vI].rep ← rep; val ← expr}; check => { rep: Repr = RepForType[tb[node].info]; val ← Rhs[tb[node].son[1], tb[node].info]; vStack[vI].rep ← rep; tb[node].son[1] ← Tree.Null; FreeNode[node]}; narrow => val ← Narrow[node]; istype => { OPEN tb[node]; son[1] ← RValue[son[1], 0, RepForType[OperandType[son[1]]]]; VPop[]; TypeExp[son[2]]; IF nSons > 2 THEN CatchNest[son[3]]; IF attr2 OR attr3 THEN {val ← expr; VPush[0, both, MaxRegs]} ELSE {FreeNode[node]; val ← passPtr.tTRUE; VPush[0, both, 1]}}; openx => { OPEN tb[node]; type: CSEIndex = OperandType[son[1]]; IF attr1 THEN val ← son[1] ELSE { son[1] ← NeutralExp[son[1]]; IF Shared[son[1]] THEN -- must generate an unshared node son[1] ← ForceType[son[1], type]; SetShared[son[1], TRUE]; attr1 ← TRUE; val ← expr}; VPush[0, other, RegsForType[type]]}; stringinit => { MarkString[]; tb[node].son[2] ← P4.Rhs[tb[node].son[2], dataPtr.typeCARDINAL]; VPop[]; val ← expr; VPush[0, unsigned, MaxRegs]}; size, first, last, typecode => val ← TypeOp[node]; apply => {VPush[0, none, 0]; val ← expr}; ENDCASE => val ← AddrOp[node]}; ENDCASE => ERROR; RETURN}; NeutralExp: PUBLIC PROC [exp: Tree.Link] RETURNS [val: Tree.Link] = { val ← RValue[exp, 0, none]; VPop[]; RETURN}; }.