-- file Debug.Mesa -- last modified by Satterthwaite, December 20, 1979 12:01 PM DIRECTORY CharIO: FROM "chario" USING [CR, TAB, PutChar, PutDecimal, PutOctal, PutString], ComData: FROM "comdata" USING [bodyRoot, definitionsOnly, errorStream], CompilerUtil: FROM "compilerutil" USING [debug, TableSegment], ControlDefs: FROM "controldefs" USING [ControlLink], DebugTable: FROM "debugtable" USING [CSRptr], Literals: FROM "literals" USING [LitDescriptor, ltType], LiteralOps: FROM "literalops" USING [DescriptorValue, MasterString, StringValue], SegmentDefs: FROM "segmentdefs" USING [FileSegmentHandle, SegmentAddress, SwapIn, Unlock], StringDefs: FROM "stringdefs" USING [SubString, SubStringDescriptor], Symbols: FROM "symbols" USING [ seType, ctxType, mdType, bodyType, BitAddress, CTXRecord, TransferMode, TypeClass, HTIndex, SEIndex, ISEIndex, RecordSEIndex, CTXIndex, BTIndex, HTNull, SENull, BTNull, lG, lZ, typeTYPE], SymbolOps: FROM "symbolops" USING [FindExtension, NextSe, SubStringForHash, TypeLink, XferMode], Table: FROM "table" USING [Base, Notifier, AddNotify, DropNotify, Bounds], Tree: FROM "tree" USING [Index, Link, Map, NodeName, NullIndex, treeType], TreeOps: FROM "treeops" USING [GetNode, UpdateTree]; Debug: PROGRAM IMPORTS CharIO, CompilerUtil, LiteralOps, SegmentDefs, SymbolOps, Table, TreeOps, dataPtr: ComData EXPORTS CompilerUtil = BEGIN OPEN Symbols; tb: Table.Base; seb: Table.Base; ctxb: Table.Base; mdb: Table.Base; bb: Table.Base; ltb: Table.Base; DebugNotify: Table.Notifier = BEGIN tb ← base[Tree.treeType]; seb ← base[seType]; ctxb ← base[ctxType]; mdb ← base[mdType]; bb ← base[bodyType]; ltb ← base[Literals.ltType]; END; SubString: TYPE = StringDefs.SubString; -- basic io WriteChar: PROCEDURE [c: CHARACTER] = BEGIN CharIO.PutChar[dataPtr.errorStream, c] END; WriteString: PROCEDURE [s: STRING] = BEGIN CharIO.PutString[dataPtr.errorStream, s] END; WriteDecimal: PROCEDURE [n: INTEGER] = BEGIN CharIO.PutDecimal[dataPtr.errorStream, n] END; NewLine: PROCEDURE = INLINE BEGIN WriteChar[CharIO.CR] END; Indent: PROCEDURE [n: CARDINAL] = BEGIN NewLine[]; THROUGH [1..n/8] DO WriteChar[CharIO.TAB] ENDLOOP; THROUGH [1..n MOD 8] DO WriteChar[' ] ENDLOOP; END; -- csrP and desc.base are set by LockStringTable debugSeg: SegmentDefs.FileSegmentHandle = CompilerUtil.TableSegment[CompilerUtil.debug]; csrP: DebugTable.CSRptr; desc: StringDefs.SubStringDescriptor; ss: SubString = @desc; LockStringTable: PROCEDURE = BEGIN SegmentDefs.SwapIn[debugSeg]; csrP ← LOOPHOLE[SegmentDefs.SegmentAddress[debugSeg]]; ss.base ← @csrP[csrP.stringOffset]; END; UnlockStringTable: PROCEDURE = BEGIN SegmentDefs.Unlock[debugSeg] END; WriteSubString: PROCEDURE [ss: SubString] = BEGIN i: CARDINAL; FOR i IN [ss.offset..ss.offset+ss.length) DO WriteChar[ss.base[i]] ENDLOOP; END; -- tree printing PrintLiteral: PROCEDURE[t: literal Tree.Link] = BEGIN desc: Literals.LitDescriptor; i: CARDINAL; v: WORD; WITH t.info SELECT FROM string => BEGIN WriteChar['"]; WriteString[LiteralOps.StringValue[index]]; WriteChar['"]; IF index # LiteralOps.MasterString[index] THEN WriteChar['L]; END; word => BEGIN desc ← LiteralOps.DescriptorValue[index]; IF desc.length # 1 THEN WriteChar['[]; FOR i IN [0 .. desc.length) DO IF (v ← ltb[desc.offset][i]) < 1000 THEN WriteDecimal[v] ELSE CharIO.PutOctal[dataPtr.errorStream, v]; IF i+1 # desc.length THEN WriteChar[',]; ENDLOOP; IF desc.length # 1 THEN WriteChar[']]; END; ENDCASE; END; WriteNodeName: PROCEDURE [n: Tree.NodeName] = BEGIN ss.offset ← csrP.NodePrintName[n].offset; ss.length ← csrP.NodePrintName[n].length; WriteSubString[ss]; END; PrintSubTree: PROCEDURE [t: Tree.Link, nBlanks: CARDINAL] = BEGIN OPEN Tree; Printer: Tree.Map = BEGIN node: Tree.Index; Indent[nBlanks]; WITH s: t SELECT FROM hash => PrintHti[s.index]; symbol => BEGIN PrintSei[s.index]; WriteChar['[]; PrintIndex[s.index]; WriteChar[']]; END; literal => PrintLiteral[s]; subtree => BEGIN node ← s.index; IF node = Tree.NullIndex THEN WriteString["<empty>"L] ELSE BEGIN OPEN tb[node]; WriteNodeName[name]; WriteChar['[]; PrintIndex[node]; WriteString["] "L]; IF info # 0 THEN BEGIN WriteString[" info="L]; PrintIndex[info] END; IF attr1 OR attr2 OR attr3 THEN BEGIN IF info = 0 THEN WriteChar[' ]; WriteChar['(]; IF attr1 THEN WriteChar['1]; IF attr2 THEN WriteChar['2]; IF attr3 THEN WriteChar['3]; WriteChar[')]; END; nBlanks ← nBlanks + 2; IF name # thread THEN [] ← TreeOps.UpdateTree[s, Printer] ELSE BEGIN WriteString[" link="L]; PrintIndex[TreeOps.GetNode[son[2]]]; [] ← Printer[son[1]]; END; nBlanks ← nBlanks - 2; END; END; ENDCASE; RETURN [t] END; [] ← Printer[t]; END; PrintTree: PUBLIC PROCEDURE [t: Tree.Link] = BEGIN Table.AddNotify[DebugNotify]; LockStringTable[]; PrintSubTree[t, 0]; NewLine[]; NewLine[]; UnlockStringTable[]; Table.DropNotify[DebugNotify]; END; PrintBodies: PUBLIC PROCEDURE = BEGIN bti, prev: BTIndex; Table.AddNotify[DebugNotify]; LockStringTable[]; bti ← dataPtr.bodyRoot; DO PrintBody[bti]; NewLine[]; NewLine[]; IF bb[bti].firstSon # BTNull THEN bti ← bb[bti].firstSon ELSE DO prev ← bti; bti ← bb[bti].link.index; IF bti = BTNull THEN GO TO Done; IF bb[prev].link.which # parent THEN EXIT; ENDLOOP; REPEAT Done => NULL; ENDLOOP; NewLine[]; UnlockStringTable[]; Table.DropNotify[DebugNotify]; END; PrintBody: PROCEDURE [bti: BTIndex] = BEGIN OPEN body: bb[bti]; WriteString["Body: "L]; WITH b: body SELECT FROM Callable => BEGIN PrintSei[b.id]; IF b.inline THEN WriteString[" [inline]"] ELSE BEGIN WriteString[", ep: "L]; WriteDecimal[b.entryIndex]; WITH b SELECT FROM Inner => BEGIN WriteString[", frame address: "L]; WriteDecimal[frameOffset]; END; ENDCASE; END; END; ENDCASE => WriteString["(anon)"L]; Indent[2]; WriteString["context: "L]; PrintIndex[body.localCtx]; WriteString[", level: "L]; WriteDecimal[body.level]; WITH body.info SELECT FROM Internal => BEGIN WriteString[", frame size: "L]; WriteDecimal[frameSize]; IF body.kind = Callable THEN PrintSubTree[[subtree[index: bodyTree]], 0] ELSE BEGIN WriteString[", tree root: "L]; PrintIndex[bodyTree] END; END; ENDCASE; END; PrintSymbols: PUBLIC PROCEDURE = BEGIN ctx: CTXIndex; limit: CTXIndex = LOOPHOLE[Table.Bounds[Symbols.ctxType].size]; ctx ← FIRST[CTXIndex] + SIZE [nil CTXRecord]; UNTIL ctx = limit DO PrintContext[ctx]; NewLine[]; NewLine[]; ctx ← ctx + (WITH ctxb[ctx] SELECT FROM included => SIZE [included CTXRecord], imported => SIZE [imported CTXRecord], ENDCASE => SIZE [simple CTXRecord]); ENDLOOP; NewLine[]; END; PrintContext: PROCEDURE [ctx: CTXIndex] = BEGIN sei, root: ISEIndex; Table.AddNotify[DebugNotify]; LockStringTable[]; WriteString["Context: "L]; PrintIndex[ctx]; IF ctxb[ctx].level # lZ THEN BEGIN WriteString[", level: "L]; WriteDecimal[ctxb[ctx].level] END; WITH ctxb[ctx] SELECT FROM included => BEGIN WriteString[", copied from: "L]; PrintHti[mdb[module].moduleId]; WriteString[" [file: "L]; PrintHti[mdb[module].fileId]; WriteString["], context: "L]; PrintIndex[map]; END; imported => BEGIN WriteString[", imported from : "L]; PrintHti[mdb[ctxb[includeLink].module].moduleId]; END; ENDCASE; root ← sei ← ctxb[ctx].seList; DO IF sei = SENull THEN EXIT; PrintSE[sei, 2]; IF (sei ← SymbolOps.NextSe[sei]) = root THEN EXIT; ENDLOOP; UnlockStringTable[]; Table.DropNotify[DebugNotify]; END; PrintSE: PROCEDURE [sei: ISEIndex, nBlanks: CARDINAL] = BEGIN OPEN seb[sei]; typeSei: SEIndex; addr: BitAddress; link: ControlDefs.ControlLink; Indent[nBlanks]; PrintSei[sei]; WriteString[" ["L]; PrintIndex[sei]; WriteChar[']]; IF public THEN WriteString[" [public]"L]; IF mark3 THEN BEGIN WriteString[", type = "L]; IF idType = typeTYPE THEN BEGIN typeSei ← idInfo; WriteString["TYPE, equated to: "L]; PrintType[typeSei]; IF ctxb[idCtx].level = lZ AND SymbolOps.TypeLink[sei] # SENull THEN BEGIN WriteString[", tag code: "L]; WriteDecimal[idValue] END; END ELSE BEGIN typeSei ← idType; PrintType[typeSei]; SELECT TRUE FROM constant => WriteString[" [const]"L]; immutable => WriteString[" [init only]"L]; ENDCASE; IF ~mark4 THEN BEGIN WriteString[", # refs: "L]; WriteDecimal[idInfo] END ELSE SELECT TRUE FROM constant => IF ~ extended THEN BEGIN WriteString[", value: "L]; SELECT SymbolOps.XferMode[typeSei] FROM procedure, program, signal, error => BEGIN link ← idValue; WriteChar['[]; WriteDecimal[link.gfi]; WriteChar[',]; WriteDecimal[link.ep]; WriteChar[',]; WriteDecimal[LOOPHOLE[link.tag]]; WriteChar[']]; END; ENDCASE => IF LOOPHOLE[idValue, CARDINAL] < 1000 THEN WriteDecimal[idValue] ELSE CharIO.PutOctal[dataPtr.errorStream, idValue]; END; (dataPtr.definitionsOnly AND ctxb[idCtx].level = lG) => BEGIN WriteString[", index: "L]; WriteDecimal[idValue] END; ENDCASE => BEGIN addr ← idValue; WriteString[", address: "L]; WriteDecimal[addr.wd]; WriteChar[' ]; WriteChar['[]; WriteDecimal[addr.bd]; WriteChar[':]; WriteDecimal[idInfo]; WriteChar[']]; IF linkSpace THEN WriteChar['*]; END; END; PrintTypeInfo[typeSei, nBlanks+2]; IF extended THEN PrintSubTree[SymbolOps.FindExtension[sei].tree, nBlanks+4]; END; END; PrintHti: PROCEDURE [hti: HTIndex] = BEGIN desc: StringDefs.SubStringDescriptor; s: SubString = @desc; IF hti = HTNull THEN WriteString["(anon)"L] ELSE BEGIN SymbolOps.SubStringForHash[s, hti]; WriteSubString[s] END; END; PrintSei: PROCEDURE [sei: ISEIndex] = BEGIN PrintHti[IF sei=SENull THEN HTNull ELSE seb[sei].hash] END; WriteTypeName: PROCEDURE [n: TypeClass] = BEGIN ss.offset ← csrP.TypePrintName[n].offset; ss.length ← csrP.TypePrintName[n].length; WriteSubString[ss]; END; WriteModeName: PROCEDURE [n: TransferMode] = BEGIN ss.offset ← csrP.ModePrintName[n].offset; ss.length ← csrP.ModePrintName[n].length; WriteSubString[ss]; END; PrintType: PROCEDURE [sei: SEIndex] = BEGIN tSei: SEIndex; IF sei = SENull THEN WriteChar['?] ELSE WITH t: seb[sei] SELECT FROM cons => WITH t SELECT FROM transfer => WriteModeName[mode]; ENDCASE => WriteTypeName[t.typeTag]; id => FOR tSei ← sei, SymbolOps.TypeLink[tSei] UNTIL tSei = SENull DO WITH seb[tSei] SELECT FROM id => BEGIN IF sei # tSei THEN WriteChar[' ]; PrintSei[LOOPHOLE[tSei, ISEIndex]]; IF ~mark3 OR ctxb[idCtx].level # lZ THEN EXIT; END; ENDCASE; ENDLOOP; ENDCASE; WriteString[" ["L]; PrintIndex[sei]; WriteChar[']]; END; PrintTypeInfo: PROCEDURE [sei: SEIndex, nBlanks: CARDINAL] = BEGIN IF sei # SENull THEN WITH s: seb[sei] SELECT FROM cons => BEGIN Indent[nBlanks]; WriteChar['[]; PrintIndex[sei]; WriteString["] "L]; WITH s SELECT FROM transfer => WriteModeName[mode]; ENDCASE => WriteTypeName[s.typeTag]; WITH t: s SELECT FROM basic => NULL; enumerated => BEGIN WriteString[", value ctx: "L]; PrintIndex[t.valueCtx]; END; record => BEGIN IF t.machineDep THEN WriteString[" (md)"L]; IF t.monitored THEN WriteString[" (monitored)"L]; IF t.hints.variant THEN WriteString[" (variant)"L]; OutRecordCtx[", field ctx: "L, LOOPHOLE[sei, RecordSEIndex]]; WITH ctxb[t.fieldCtx] SELECT FROM included => IF ~complete THEN WriteString[" [partial]"L]; imported => WriteString[" [partial]"L]; ENDCASE; WITH t SELECT FROM linked => BEGIN WriteString[", link: "L]; PrintType[linkType] END; ENDCASE; END; pointer => BEGIN IF t.ordered THEN WriteString[" (ordered)"L]; IF t.basing THEN WriteString[" (base)"L]; WriteString[", pointing to: "L]; PrintType[t.refType]; IF t.readOnly THEN WriteString[" (readonly)"L]; PrintTypeInfo[t.refType, nBlanks+2]; END; array => BEGIN IF t.oldPacked THEN WriteString[" (packed)"L]; WriteString[", index type: "L]; PrintType[t.indexType]; WriteString[", component type: "L]; PrintType[t.componentType]; PrintTypeInfo[t.indexType, nBlanks+2]; PrintTypeInfo[t.componentType, nBlanks+2]; END; arraydesc => BEGIN WriteString[", described type: "L]; PrintType[t.describedType]; IF t.readOnly THEN WriteString[" (readonly)"L]; PrintTypeInfo[t.describedType, nBlanks+2]; END; transfer => BEGIN OutRecordCtx[", input ctx: "L, t.inRecord]; OutRecordCtx[", output ctx: "L, t.outRecord]; END; definition => BEGIN WriteString[", ctx: "L]; PrintIndex[t.defCtx]; WriteString[", ngfi: "L]; WriteDecimal[t.nGfi]; END; union => BEGIN IF t.overlayed THEN WriteString[" (overlaid)"L]; IF t.controlled THEN BEGIN WriteString[", tag: "L]; PrintSei[t.tagSei] END; WriteString[", tag type: "L]; PrintType[seb[t.tagSei].idType]; WriteString[", case ctx: "L]; PrintIndex[t.caseCtx]; IF t.controlled THEN PrintSE[t.tagSei, nBlanks+2]; END; relative => BEGIN WriteString[", base type: "L]; PrintType[t.baseType]; WriteString[", offset type: "L]; PrintType[t.offsetType]; PrintTypeInfo[t.baseType, nBlanks+2]; PrintTypeInfo[t.offsetType, nBlanks+2]; PrintTypeInfo[t.resultType, nBlanks+2]; END; subrange => BEGIN WriteString[" of: "L]; PrintType[t.rangeType]; IF t.filled THEN BEGIN WriteString[" origin: "L]; WriteDecimal[t.origin]; WriteString[", range: "L]; IF t.flexible THEN WriteChar['*] ELSE WriteDecimal[t.range]; END; PrintTypeInfo[t.rangeType, nBlanks+2]; END; long, real => BEGIN WriteString[" of: "L]; PrintType[t.rangeType]; PrintTypeInfo[t.rangeType, nBlanks+2]; END; ENDCASE; END; ENDCASE; END; OutRecordCtx: PROCEDURE [message: STRING, sei: RecordSEIndex] = BEGIN WriteString[message]; IF sei = SENull THEN WriteString["NIL"L] ELSE PrintIndex[seb[sei].fieldCtx]; END; PrintIndex: PROCEDURE [v: UNSPECIFIED] = LOOPHOLE[WriteDecimal]; END.