-- file Pass4Xc.Mesa -- last written by Satterthwaite, 12-Jan-82 17:48:02 DIRECTORY Alloc: TYPE USING [Notifier], ComData: TYPE USING [ definitionsOnly, typeCARDINAL, typeINT, typeStringBody, zone], Environment: TYPE USING [maxCARDINAL, maxINTEGER], Heap: TYPE USING [FreeNode, MakeNode], LiteralOps: TYPE USING [ValueDescriptor, FindDescriptor], Log: TYPE USING [Error, ErrorTree, WarningTree], P4: TYPE USING [ Repr, none, unsigned, both, other, RegCount, MaxRegs, BiasForType, BitsForType, CatchNest, CommonRep, Exp, FillMultiWord, MakeArgRecord, MakeStructuredLiteral, MakeTreeLiteral, OperandType, RegsForType, RelTest, RepForType, Rhs, RValue, StructuredLiteral, TreeLiteral, TreeLiteralValue, TypeExp, TypeForTree, VPop, VPush, VRegs, VRep, WordsForType], Symbols: TYPE USING [ Base, BitAddress, ByteLength, WordLength, SEIndex, ISEIndex, CSEIndex, ISENull, codeCHAR, codeINT, lZ, ctxType, seType], SymbolOps: TYPE USING [ ArgRecord, BitsPerElement, Cardinality, FirstCtxSe, NormalType, NextSe, PackedSize, VariantField, UnderType], SymLiteralOps: TYPE USING [TypeRef], Tree: TYPE USING [Base, Index, Link, NodeName, Null, treeType], TreeOps: TYPE USING [ FreeNode, FreeTree, GetNode, IdentityMap, MakeNode, OpName, PopTree, PushSe, PushTree, PushLit, PushNode, SetAttr, SetInfo]; Pass4Xc: PROGRAM IMPORTS Heap, Log, LiteralOps, P4, SymbolOps, SymLiteralOps, TreeOps, dataPtr: ComData EXPORTS P4 = { OPEN SymbolOps, TreeOps, P4; CSEIndex: TYPE = Symbols.CSEIndex; WordLength: CARDINAL = Symbols.WordLength; 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]}; -- interval utilities NormalizeRange: PUBLIC PROC [t: Tree.Link] RETURNS [val: Tree.Link] = { next: Tree.Link; FOR val _ t, next DO WITH val SELECT FROM symbol => { lBound: INTEGER = BiasForType[UnderType[index]]; THROUGH [1..2] DO PushTree[MakeTreeLiteral[ABS[lBound]]]; IF lBound < 0 THEN PushNode[uminus, 1]; ENDLOOP; PushTree[MakeTreeLiteral[Cardinality[index] - 1]]; PushNode[plus, 2]; SetInfo[dataPtr.typeINT]; next _ MakeNode[intCC, 2]}; subtree => { node: Tree.Index = index; SELECT tb[node].name FROM subrangeTC, cdot => { next _ tb[node].son[2]; tb[node].son[2] _ Tree.Null; FreeNode[node]}; IN [intOO .. intCC] => EXIT; ENDCASE => ERROR}; ENDCASE => ERROR; ENDLOOP; RETURN}; Interval: PUBLIC PROC [node: Tree.Index, bias: INTEGER, target: Repr] RETURNS [const: BOOLEAN] = { OPEN tb[node]; rep: Repr; nRegs: RegCount; son[1] _ RValue[son[1], bias, target]; rep _ VRep[]; nRegs _ VRegs[]; son[2] _ RValue[son[2], bias, target]; nRegs _ MAX[VRegs[], nRegs]; rep _ CommonRep[rep, VRep[]]; VPop[]; VPop[]; VPush[bias, rep, nRegs]; const _ StructuredLiteral[son[1]] AND StructuredLiteral[son[2]] AND ~attr1; RETURN}; EmptyInterval: PUBLIC SIGNAL = CODE; ConstantInterval: PUBLIC PROC [node: Tree.Index] RETURNS [origin, range: INTEGER] = { OPEN tb[node]; uBound: INTEGER; rep: Repr; empty: BOOLEAN; rep _ VRep[]; empty _ FALSE; origin _ TreeLiteralValue[son[1]]; uBound _ TreeLiteralValue[son[2]]; SELECT name FROM intOO, intOC => { IF RelTest[son[1], son[2], relGE, rep] THEN empty _ TRUE; origin _ origin + 1; son[1] _ FreeTree[son[1]]; name _ IF name = intOO THEN intCO ELSE intCC; son[1] _ MakeTreeLiteral[origin]}; ENDCASE; SELECT name FROM intCC => IF RelTest[son[1], son[2], relG, rep] THEN empty _ TRUE; intCO => { IF RelTest[son[1], son[2], relGE, rep] THEN empty _ TRUE; uBound _ uBound - 1; son[2] _ FreeTree[son[2]]; name _ intCC; son[2] _ MakeTreeLiteral[uBound]}; ENDCASE => ERROR; IF ~empty THEN range _ uBound - origin ELSE {SIGNAL EmptyInterval; range _ 0}; RETURN}; -- type utilities (move?) -- operators on types TypeOp: PUBLIC PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { SELECT tb[node].name FROM size => val _ Size[node]; first, last => val _ EndPoint[node]; typecode => val _ TypeCode[node]; ENDCASE => { Log.Error[unimplemented]; VPush[0, none, 0]; val _ [subtree[node]]}; RETURN}; Size: PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { type: CSEIndex; ApplyLit: PROC [op: Tree.NodeName, val: WORD] = { PushTree[MakeTreeLiteral[val]]; PushNode[op, 2]; SetInfo[dataPtr.typeINT]; SetAttr[1, FALSE]; SetAttr[2, FALSE]}; IF OpName[tb[node].son[1]] = apply THEN { subNode: Tree.Index = GetNode[tb[node].son[1]]; sei: Symbols.ISEIndex; bitsPerItem: CARDINAL; TypeExp[tb[subNode].son[1]]; type _ UnderType[TypeForTree[tb[subNode].son[1]]]; SELECT TRUE FROM (type = dataPtr.typeStringBody) => bitsPerItem _ Symbols.ByteLength; ((sei _ VariantField[type]) # Symbols.ISENull) => { subType: CSEIndex = UnderType[seb[sei].idType]; bitsPerItem _ WITH t: seb[subType] SELECT FROM sequence => BitsPerElement[t.componentType, t.packed], ENDCASE => ERROR}; ENDCASE => ERROR; PushTree[tb[subNode].son[2]]; tb[subNode].son[2] _ Tree.Null; IF bitsPerItem < WordLength THEN { itemsPerWord: CARDINAL = WordLength/bitsPerItem; ApplyLit[plus, itemsPerWord-1]; ApplyLit[div, itemsPerWord]} ELSE ApplyLit[times, bitsPerItem/WordLength]; ApplyLit[plus, P4.WordsForType[type]]; IF tb[node].son[2] # Tree.Null THEN { PushTree[tb[node].son[2]]; tb[node].son[2] _ Tree.Null; PushNode[times, 2]; SetInfo[dataPtr.typeINT]; SetAttr[1, FALSE]; SetAttr[2, FALSE]}} ELSE { TypeExp[tb[node].son[1]]; type _ UnderType[TypeForTree[tb[node].son[1]]]; IF tb[node].son[2] = Tree.Null THEN PushTree[MakeTreeLiteral[P4.WordsForType[type]]] ELSE { nBits: CARDINAL = P4.BitsForType[type]; PushTree[tb[node].son[2]]; tb[node].son[2] _ Tree.Null; IF nBits <= Symbols.ByteLength THEN { n: CARDINAL = WordLength/PackedSize[nBits]; ApplyLit[plus, n-1]; ApplyLit[div, n]} ELSE ApplyLit[times, P4.WordsForType[type]]}}; val _ Rhs[PopTree[], dataPtr.typeCARDINAL]; FreeNode[node]}; EndPoint: PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { OPEN tb[node]; type, next: CSEIndex; first: BOOLEAN = (name=first); MaxInteger: WORD = Environment.maxINTEGER; MaxWord: WORD = Environment.maxCARDINAL; v: WORD; vv: ARRAY [0..2) OF WORD; TypeExp[son[1]]; FOR type _ UnderType[TypeForTree[son[1]]], next DO WITH seb[type] SELECT FROM basic => { v _ SELECT code FROM Symbols.codeINT => IF first THEN MaxInteger+1 ELSE MaxInteger, Symbols.codeCHAR => IF first THEN 0 ELSE Cardinality[type]-1, ENDCASE => IF first THEN 0 ELSE MaxWord; GO TO short}; enumerated => { v _ IF first THEN 0 ELSE Cardinality[type]-1; GO TO short}; relative => next _ UnderType[offsetType]; subrange => {v _ IF first THEN origin ELSE origin+range; GO TO short}; long => { vv _ IF UnderType[rangeType] = dataPtr.typeINT THEN IF first THEN [0, MaxInteger+1] ELSE [MaxWord, MaxInteger] ELSE IF first THEN [0, 0] ELSE [MaxWord, MaxWord]; GO TO long}; ENDCASE => ERROR; REPEAT short => val _ MakeTreeLiteral[v]; long => { PushLit[LiteralOps.FindDescriptor[DESCRIPTOR[vv]]]; PushNode[mwconst, 1]; SetInfo[type]; val _ PopTree[]}; ENDLOOP; FreeNode[node]; VPush[0, RepForType[type], RegsForType[type]]; RETURN}; TypeCode: PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { TypeExp[tb[node].son[1]]; IF dataPtr.definitionsOnly THEN val _ [subtree[index: node]] ELSE { val _ SymLiteralOps.TypeRef[TypeForTree[tb[node].son[1]], FALSE]; FreeNode[node]}; VPush[0, both, 1]; RETURN}; -- misc transfer operators MiscXfer: PUBLIC PROC [node: Tree.Index] RETURNS [Tree.Link] = { type: CSEIndex; SELECT tb[node].name FROM create => { tb[node].son[1] _ RValue[tb[node].son[1], 0, none]; VPop[]; VPush[0, unsigned, MaxRegs]}; fork => { OPEN tb[node]; son[1] _ Exp[son[1], none]; VPop[]; type _ OperandType[son[1]]; WITH t: seb[type] SELECT FROM transfer => { son[2] _ MakeArgRecord[ArgRecord[t.typeIn], son[2]]; VPush[0, other, MaxRegs]}; ENDCASE => ERROR}; ENDCASE => {Log.Error[unimplemented]; VPush[0, none, 0]}; IF tb[node].nSons > 2 THEN CatchNest[tb[node].son[3]]; RETURN [[subtree[index: node]]]}; -- misc addressing operators AddrOp: PUBLIC PROC [node: Tree.Index] RETURNS [val: Tree.Link] = { nRegs: RegCount; SELECT tb[node].name FROM addr => val _ Addr[node]; base => { tb[node].son[1] _ Exp[tb[node].son[1], none]; nRegs _ VRegs[]; VPop[]; VPush[0, unsigned, nRegs]; val _ [subtree[index: node]]}; length => { type: CSEIndex; tb[node].son[1] _ Exp[tb[node].son[1], none]; type _ OperandType[tb[node].son[1]]; WITH seb[type] SELECT FROM array => { val _ MakeTreeLiteral[Cardinality[indexType]]; FreeNode[node]; nRegs _ 1}; ENDCASE => {val _ [subtree[index: node]]; nRegs _ VRegs[]}; VPop[]; VPush[0, both, nRegs]}; arraydesc => val _ IF OpName[tb[node].son[1]] # list THEN Desc[node] ELSE DescList[node]; ENDCASE => { Log.Error[unimplemented]; VPush[0, none, 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; nRegs: RegCount; son[1] _ Exp[son[1], none]; nRegs _ MAX[VRegs[], RegsForType[info]]; FOR t: Tree.Link _ son[1], v DO WITH t SELECT FROM symbol => { sei: Symbols.ISEIndex = index; IF ctxb[seb[sei].idCtx].level = Symbols.lZ AND (LOOPHOLE[seb[sei].idValue, Symbols.BitAddress].bd # 0 OR LOOPHOLE[seb[sei].idInfo, CARDINAL] MOD WordLength # 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]; 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 WITH tb[subNode].son[2] SELECT FROM symbol => { val _ MakeStructuredLiteral[ TreeLiteralValue[tb[subNode].son[1]] + LOOPHOLE[seb[index].idValue, Symbols.BitAddress].wd, info]; FreeNode[node]}; ENDCASE => ERROR}; VPop[]; VPush[0, unsigned, nRegs]; RETURN}; Desc: PROC [node: Tree.Index] RETURNS [Tree.Link] = { subNode: Tree.Index = GetNode[tb[node].son[1]]; long: BOOLEAN = tb[subNode].attr2; nRegs: RegCount; subType: CSEIndex; tb[subNode].son[1] _ Exp[tb[subNode].son[1], none]; nRegs _ VRegs[]; VPop[]; subType _ OperandType[tb[subNode].son[1]]; WITH t: seb[subType] SELECT FROM array => { n: CARDINAL = Cardinality[t.indexType]; IF n = 0 THEN Log.WarningTree[sizeClash, tb[subNode].son[1]]; IF t.packed AND (BitsForType[subType] MOD WordLength # 0) THEN Log.ErrorTree[nonAddressable, tb[subNode].son[1]]; PushTree[[subtree[subNode]]]; PushTree[MakeTreeLiteral[n]]}; sequence => { copy: Tree.Link = IdentityMap[tb[subNode].son[1]]; PushTree[tb[subNode].son[1]]; PushTree[MakeTreeLiteral[0]]; PushNode[seqindex, 2]; SetInfo[UnderType[t.componentType]]; SetAttr[2, long]; SetAttr[3, FALSE]; tb[subNode].son[1] _ PopTree[]; PushTree[[subtree[subNode]]]; WITH copy SELECT FROM subtree => { cNode: Tree.Index = index; tb[cNode].son[2] _ FreeTree[tb[cNode].son[2]]; tb[cNode].son[2] _ [symbol[index: t.tagSei]]; tb[cNode].info _ dataPtr.typeCARDINAL}; ENDCASE => ERROR; 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]; SetInfo[UnderType[seb[sei].idType]]; SetAttr[2, long]; tb[subNode].son[1] _ PopTree[]; PushTree[[subtree[subNode]]]; PushTree[copy]; PushSe[NextSe[FirstCtxSe[t.fieldCtx]]]; PushNode[dollar, 2]; SetInfo[dataPtr.typeCARDINAL]; SetAttr[2, long]}; ENDCASE => { Log.ErrorTree[typeClash, tb[subNode].son[1]]; PushTree[[subtree[subNode]]]; PushTree[Tree.Null]}; PushTree[Tree.Null]; PushNode[list, 3]; tb[node].son[1] _ PopTree[]; VPush[0, other, MAX[RegsForType[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: CSEIndex = tb[node].info; subType: CSEIndex; nRegs: RegCount; tb[subNode].son[1] _ RValue[tb[subNode].son[1], 0, unsigned]; nRegs _ VRegs[]; subType _ OperandType[tb[subNode].son[1]]; WITH seb[subType] SELECT FROM ref => IF BitsForType[refType] MOD WordLength # 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]; 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 = WordsForType[type]; words: LiteralOps.ValueDescriptor _ DESCRIPTOR[Heap.MakeNode[dataPtr.zone, n], n]; FillMultiWord[words, 0, tb[subNode].son[1]]; words[n-1] _ TreeLiteralValue[tb[subNode].son[2]]; PushLit[LiteralOps.FindDescriptor[words]]; PushNode[mwconst, 1]; SetInfo[type]; Heap.FreeNode[dataPtr.zone, BASE[words]]; val _ PopTree[]; FreeNode[node]} ELSE val _ [subtree[index: node]]; VPush[0, other, MAX[RegsForType[type], nRegs]]; RETURN}; }.