<<>> <> <> <> <> <> <> <> <> <> <> DIRECTORY CCTypes USING[CCError, CCErrorCase, CreateIndirectNode, GetBitSize, GetIndirectType, GetTargetTypeOfIndirect, GetTypeClass, PrintType], CedarOtherPureTypes USING[CreateIndirectToAnUnknownType, CreateUnknownType], CirioMemory, CirioNubAccess USING[Handle, RemoteAddress, LookupSymEntryByName, SymEntry], CirioTypes, DeferringTypes USING [UndertypeStar], Frames USING[CreateIndirectFrameNode, CreateIndirectFrameType, CreateIndirectGlobalFrameNode, CreateIndirectGlobalFrameType, IndirectFrameData, IndirectFrameTypeData, IndirectGlobalFrameData, IndirectGlobalFrameTypeData], IO USING[EndOf, EndOfStream, GetChar, PeekChar, PutFR, PutFR1, RIS, RopeFromROS, ROS, STREAM], ObjectFiles USING[BracketNest, BracketPair, CGrammar, CGrammarOfStab, DescribeModule, GenSymbolStabs, MakeUnknownVarLoc, Module, Stab, VarLocFromStab], ObjectFilesPrivate, RCTW, Records USING[CreateIndirectRecordNode, CreateRecordType, IndirectRecordNodeProcs, RecordTypeProcs], RefTab USING[Fetch, Key, Ref, Store], RMTWPrivate, Rope USING[Cat, Concat, Find, FromChar, IsEmpty, ROPE, Substr], SymTab USING [Create, Fetch, Insert, Key, Pairs, Ref, Replace, Store, Val], SystemInterface, SGI; RCTWFrames: CEDAR PROGRAM IMPORTS CCTypes, CedarOtherPureTypes, CirioMemory, CirioNubAccess, DeferringTypes, Frames, IO, ObjectFiles, RCTW, Records, RefTab, RMTWPrivate, Rope, SymTab, SystemInterface EXPORTS RCTW = BEGIN OPEN ObjF:ObjectFiles, RCTW; ROPE: TYPE ~ Rope.ROPE; RopeList: TYPE ~ LIST OF ROPE; CCError: ERROR[case: CCTypes.CCErrorCase, msg: ROPE _ NIL] _ CCTypes.CCError; <> <<>> Parsed: TYPE = REF ParsedBody; ParsedBody: PUBLIC TYPE = ObjectFilesPrivate.ParsedBody; Module: TYPE = REF ModuleBody; ModuleBody: PUBLIC TYPE = ObjectFilesPrivate.ModuleBody; <> <<>> CreateZeroLengthRecordType: PROC[cc: CC] RETURNS[Type] = {RETURN[Records.CreateRecordType[ZeroLengthRecordTypeProcs, cc, NIL]]}; ZeroLengthRecordTypeProcs: REF Records.RecordTypeProcs _ NEW[Records.RecordTypeProcs_[ getPaint: ZeroLengthRecordGetPaint, comparePaint: ZeroLengthRecordComparePaint, nFields: ZeroLengthRecordnFields, fieldIndexToName: ZeroLengthRecordFieldIndexToName, nameToFieldIndex: ZeroLengthRecordNameToFieldIndex, fieldIndexToType: ZeroLengthRecordFieldIndexToType]]; ZeroLengthRecordGetPaint: PROC[data: REF ANY] RETURNS[REF ANY] = {RETURN[NIL]}; ZeroLengthRecordComparePaint: PROC[data: REF ANY, otherPaint: REF ANY] RETURNS[BOOLEAN] = {ERROR}; ZeroLengthRecordnFields: PROC[data: REF ANY] RETURNS[INT] = {RETURN[0]}; ZeroLengthRecordFieldIndexToName: PROC[index: INT, data: REF ANY] RETURNS[ROPE] = {ERROR}; ZeroLengthRecordNameToFieldIndex: PROC[name: ROPE, data: REF ANY] RETURNS[INT] = {RETURN[-1]}; ZeroLengthRecordFieldIndexToType: PROC[index: INT, cc: CC, data: REF ANY] RETURNS[Type] = {ERROR}; <> <<>> CreateZeroLengthRecordNode: PROC[indirectRecordType: Type, cc: CC] RETURNS[Node] = BEGIN RETURN[Records.CreateIndirectRecordNode[CCTypes.GetTargetTypeOfIndirect[indirectRecordType], ZeroLengthRecordNodeProcs, NIL, cc]]; END; ZeroLengthRecordNodeProcs: REF Records.IndirectRecordNodeProcs _ NEW[Records.IndirectRecordNodeProcs _ [ selectField: NIL]]; <<>> <<>> <> CreateArgsRecordType: PROC [rctw: RCTWData] RETURNS [type: Type] ~ { bracketPair:ObjF.BracketPair _ rctw.bracketNest.rest.first; type _ CreateBlockRecordType[ArgumentListFromRCTW[rctw], bracketPair, rctw]; type _ CCTypes.GetIndirectType[type]; RETURN}; CreateLocalsRecordType: PROC [bracketPair: ObjF.BracketPair, rctw: RCTWData, procTop: BOOL] RETURNS [type: Type] ~ { locals: RopeList ~ LocalsListFromBracketPair[bracketPair, rctw, procTop]; type _ CreateBlockRecordType[locals, bracketPair, rctw]; type _ CCTypes.GetIndirectType[type]; RETURN}; CreateBlockRecordType: PROC [argumentList: RopeList, bracketPair: ObjF.BracketPair, rctw: RCTWData] RETURNS [type: Type] ~ { numberOfArguments: INT _ RopeListLength[argumentList]; abc: AnalyzedCTX; index: INT; abc _ NEW[AnalyzedCTXBody[numberOfArguments]]; index _ 0; FOR remainingArguments: RopeList _ argumentList, remainingArguments.rest WHILE remainingArguments # NIL DO dotOListings: DotOListings _ DotOListingsFromRope[remainingArguments.first, rctw, bracketPair]; abc[index].name _ remainingArguments.first; abc[index].idStab _ dotOListings; SELECT dotOListings.kind FROM ordinary => abc[index].fiValid _ FALSE; enumerator => {abc[index].fiValid _ TRUE; abc[index].fieldCase _ typeTimeConstant; abc[index].fieldLoc _ abc[index].fieldDirectType _ NIL}; ENDCASE => ERROR; index _ index + 1 ENDLOOP; abc.blockRecord _ TRUE; abc.bitSize _ CirioTypes.unspecdBA; abc.rctw _ rctw; abc.recordType _ Records.CreateRecordType[CTXRecordTypeProcs, rctw.cc, abc]; RETURN[abc.recordType]}; IsDigit: PROC [c:CHAR] RETURNS [BOOL] = INLINE { RETURN [c IN ['0 .. '9]] }; <<>> GetTokenRope: PUBLIC PROC [stream: IO.STREAM] RETURNS [ROPE] ~ { IsNonDigit: PROC [c:CHAR] RETURNS [BOOL] = INLINE { RETURN [c IN ['a .. 'z] OR c IN ['A .. 'Z] OR c='_ OR c = '-] }; IsAlphaNum: PROC [c:CHAR] RETURNS [BOOL] = INLINE { RETURN [c IN ['0 .. '9] OR c IN ['a .. 'z] OR c IN ['A .. 'Z] OR c='_ OR c = '-] }; token: ROPE _ NIL; IF NOT IO.EndOf[stream] AND IsNonDigit[IO.PeekChar[stream]] THEN { token _ Rope.FromChar[IO.GetChar[stream]]; WHILE NOT IO.EndOf[stream] AND IsAlphaNum[IO.PeekChar[stream]] DO token _ Rope.Concat[token, Rope.FromChar[IO.GetChar[stream]]]; ENDLOOP}; RETURN[token]}; DotOListingsFromRope: PROC [symbol: ROPE, rctw: RCTWData, bracketPair: ObjF.BracketPair] RETURNS [DotOListings] ~ { bracketEntry: BracketEntry _ GetBracketEntry[bracketPair, rctw]; dotOListings: DotOListings _ NARROW[SymTab.Fetch[bracketEntry.symbolHashTable, symbol].val]; IF dotOListings = NIL THEN CCError[cirioError, Rope.Concat["no .o listings for ", symbol]]; RETURN [dotOListings]}; <<>> GetBracketEntry: PROC [bracketPair: ObjF.BracketPair, rctw: RCTWData] RETURNS [bracketEntry: BracketEntry] = BEGIN ProcessStab:PROC [stab: ObjF.Stab] RETURNS [BOOLEAN] = { ParseStab[stab, rctw, bracketEntry]; RETURN [FALSE]; }; bracketEntry _ NARROW[RefTab.Fetch[rctw.bracketHashTable, bracketPair].val]; IF bracketEntry = NIL THEN BEGIN bracketEntry _ NEW[BracketEntryBody]; bracketEntry.symbolHashTable _ SymTab.Create[]; bracketEntry.typeNameHashTable _ SymTab.Create[]; IF NOT RefTab.Store[rctw.bracketHashTable, bracketPair, bracketEntry] THEN CCError[cirioError]; ObjF.GenSymbolStabs[bracketPair, ProcessStab]; END; RETURN[bracketEntry] END; -- of GetBracketEntry GetSymbol: PROC [sourceStream: IO.STREAM] RETURNS [symbol: ROPE] ~ { WHILE IO.PeekChar[sourceStream] # ': DO symbol _ Rope.Concat[symbol, Rope.FromChar[IO.GetChar[sourceStream]]]; ENDLOOP; RETURN[symbol] }; <> CCE: ERROR[case: CCTypes.CCErrorCase, msg: Rope.ROPE _ NIL] _ CCTypes.CCError; FmtType: PROC [type: Type, printDepth: INT, printWidth: INT, cc: CC, oc: Type _ NIL] RETURNS [ans: ROPE] = { ENABLE CCE => {ans _ "??"; CONTINUE}; buf1: IO.STREAM ~ IO.ROS[]; CCTypes.PrintType[buf1, type, printDepth, printWidth, cc, oc]; RETURN [buf1.RopeFromROS]}; DebugStabParsing: BOOLEAN _ FALSE; ParseStab: PROC [stab: ObjF.Stab, rctw: RCTWData, bracketEntry: BracketEntry] ~ { Bitch: PROC [why: ROPE] ~ {CCError[cirioError, IO.PutFR["%g in stab (X: %g, string: \"%q\") in %g", [rope[why]], [cardinal[stab.stabX]], [rope[stab.rope]], [rope[ObjF.DescribeModule[rctw.module]]] ]]}; Define: PROC [name: ROPE, l: ordinary DotOGlorp] ~ { ls: DotOListings _ NARROW[bracketEntry.symbolHashTable.Fetch[name].val]; IF ls#NIL THEN WITH ls SELECT FROM x: DotOEnumr => CCError[cirioError, IO.PutFR["enumerator (%g=%g) has same name as a non-enumerator (stabX=%g, string=%g) in %g", [rope[name]], [integer[x.value]], [cardinal[stab.stabX]], [rope[stab.rope]], [rope[ObjF.DescribeModule[rctw.module]]] ]]; x: DotOListing => IF (x.directType # l.directType) THEN { SystemInterface.ShowReport[IO.PutFR["New type (%g) different from other one (%g) in stab (X: %g, string: \"%q\") in %g", [rope[FmtType[l.directType, 2,10, rctw.cc]]], [rope[FmtType[x.directType, 2,10, rctw.cc]]], [cardinal[stab.stabX]], [rope[stab.rope]], [rope[ObjF.DescribeModule[rctw.module]]] ], $normal]; RETURN}; ENDCASE => ERROR; l.rest _ ls; ls _ NEW [DotOGlorp[ordinary] _ l]; [] _ bracketEntry.symbolHashTable.Store[name, ls]; IF DebugStabParsing THEN SystemInterface.ShowReport[Rope.Cat["Defining symbol ", name, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; RETURN}; ParseStabFromRope: PROC [stab: ObjF.Stab] ~ { <> SELECT stab.stabType FROM LSym, GSym, PSym, STSym, LCSym, RSym, Fun => { sourceStream: IO.STREAM _ IO.RIS[stab.rope]; symbol: ROPE _ GetSymbol[sourceStream]; symbolDescriptor: CHAR; noDescriptor: BOOLEAN _ FALSE; IF IO.GetChar[sourceStream] # ': THEN Bitch["no colon after symbol"]; symbolDescriptor _ IO.PeekChar[sourceStream ! IO.EndOfStream => Bitch["nothing after colon"]]; SELECT symbolDescriptor FROM 't, 'T => { <> type: Type; IF IO.GetChar[sourceStream] # symbolDescriptor THEN ERROR; type _ AnalyzeType[sourceStream, bracketEntry, rctw].directType; IF Rope.IsEmpty[symbol] THEN { <> symbol _ Rope.Concat["unnamed", Rope.Substr[stab.rope, 3, Rope.Find[stab.rope, ")"] - 3]]; }; IF NOT bracketEntry.typeNameHashTable.Insert[symbol, type] THEN { oldVal: Type ~ NARROW[bracketEntry.typeNameHashTable.Fetch[symbol].val]; <> IF NOT (DeferringTypes.UndertypeStar[type] = DeferringTypes.UndertypeStar[oldVal]) THEN { [] _ bracketEntry.typeNameHashTable.Replace[symbol, type]; SystemInterface.ShowReport[Rope.Cat["REDEFINING symbol ", symbol, " in ", ObjectFiles.DescribeModule[rctw.module]], $urgent]; }; }; }; 'F, 'f, 'G, 'S, 'V, 'p, 'P, 'r => { <> IF symbolDescriptor#'f AND symbolDescriptor#'F AND IO.GetChar[sourceStream]#symbolDescriptor THEN ERROR; Define[symbol, [NIL, ordinary[ descriptor: Rope.FromChar[symbolDescriptor], directType: AnalyzeType[sourceStream, bracketEntry, rctw].directType, stab: stab]]]; }; '( => {--This must be either a local variable declaration or a register variable declaration Define[symbol, [NIL, ordinary[ descriptor: Rope.FromChar[symbolDescriptor], directType: AnalyzeType[sourceStream, bracketEntry, rctw].directType, stab: stab]]]; }; ENDCASE => { IF IsDigit[symbolDescriptor] OR symbolDescriptor = '- THEN { <> Define[symbol, [NIL, ordinary[ descriptor: Rope.FromChar[symbolDescriptor], directType: AnalyzeType[sourceStream, bracketEntry, rctw].directType, stab: stab]]]; } ELSE Bitch["unrecognized descriptor"]; } } ENDCASE => {} -- We do not parse these types of stabs }; ParseStabFromFile: PROC [stab: ObjF.Stab] = TRUSTED { <> DefineFileStab: PROC [name: ROPE, l: ordinary DotOGlorp] = TRUSTED { ls: DotOListings _ NARROW[bracketEntry.symbolHashTable.Fetch[name].val]; l.rest _ ls; ls _ NEW [DotOGlorp[ordinary] _ l]; [] _ bracketEntry.symbolHashTable.Store[name, ls]; RETURN }; ParseTypeFromFile: PROC [wireTables: SGI.WireTables] = TRUSTED { sourceStream: IO.STREAM _ IO.RIS[stab.rope]; symbol: ROPE _ GetSymbol[sourceStream]; auxIndex: INT32; auxSyms: SGI.AuxSymTable _ wireTables.auxSyms; typeInfo: SGI.WireTypeInfoBody; basicType: CARD _ 0; type: Type _ NIL; thisSymAuxIndex: INT32; maxQualifier: CARD = 256; numQualifiers: INT32 _ 0; qualifier: ARRAY [0..maxQualifier) OF BYTE; -- for now just make big enough to handle an outrageous number of qualifiers, CHANGE ME! thisSym: SGI.WireSTEntry; fdIndex: INT32; <> IF stab.extRef THEN { thisSym _ LOOPHOLE[@wireTables.extSyms[stab.stabX].sym]; fdIndex _ wireTables.extSyms[stab.stabX].fileDescrIndex; } ELSE { thisSym _ LOOPHOLE[@wireTables.localSyms[stab.stabX]]; fdIndex _ stab.fdIndex; }; thisSymAuxIndex _ auxIndex _ wireTables.fileDescr[fdIndex].iauxBase + thisSym.index; SELECT stab.stabType FROM LSym, GSym, PSym, STSym, LCSym, RSym, Fun => { IF stab.stabType = Fun THEN { <> thisSymAuxIndex _ auxIndex + 1; }; typeInfo _ auxSyms[auxIndex].typeInfo; basicType _ typeInfo.basicType; IF (basicType = SGI.BTNil) THEN RETURN; <> DO typeInfo _ auxSyms[auxIndex].typeInfo; auxIndex _ auxIndex + 1; IF (typeInfo.typeQual0 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual0; numQualifiers _ numQualifiers + 1; IF (typeInfo.typeQual1 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual1; numQualifiers _ numQualifiers + 1; IF (typeInfo.typeQual2 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual2; numQualifiers _ numQualifiers + 1; IF (typeInfo.typeQual3 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual3; numQualifiers _ numQualifiers + 1; IF (typeInfo.typeQual4 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual4; numQualifiers _ numQualifiers + 1; IF (typeInfo.typeQual5 = SGI.TQNil) THEN EXIT; qualifier[numQualifiers] _ typeInfo.typeQual5; numQualifiers _ numQualifiers + 1; IF (numQualifiers > maxQualifier) THEN ERROR; IF (LOOPHOLE[typeInfo.continued,CARD] = 0) THEN EXIT; ENDLOOP; IF numQualifiers # 0 THEN { i,low,high,bitWidth: INT32; <> FOR i IN [0..numQualifiers) DO SELECT qualifier[i] FROM SGI.TQNil => NULL; -- do nuthin, we should never get this SGI.TQPtr => NULL; -- we have a pointer SGI.TQProc => NULL; -- we have a function SGI.TQVol => NULL; -- volatile is pretty irrelevant SGI.TQArray => { <<-- go past the rndx (it always is the same) and the blank>> auxIndex _ auxIndex + 2; low _ LOOPHOLE[auxSyms[auxIndex].lowIndex]; auxIndex _ auxIndex + 1; high _ LOOPHOLE[auxSyms[auxIndex].highIndex]; auxIndex _ auxIndex + 1; bitWidth _ LOOPHOLE[auxSyms[auxIndex].bitWidth]; auxIndex _ auxIndex + 1; } ENDCASE => NULL; ENDLOOP; SELECT qualifier[i] FROM SGI.TQPtr => -- we have a pointer { DefineFileStab[symbol, [NIL, ordinary[descriptor:Rope.FromChar['z], directType: AnalyzePointerTypeFileStab[thisSymAuxIndex, wireTables, bracketEntry, rctw, stab, stab.stabX].directType, stab: stab]]]; }; SGI.TQProc => -- we have a function returning { DefineFileStab[symbol, [NIL, ordinary[descriptor:Rope.FromChar['z], directType: AnalyzeProcedureTypeFileStab[thisSymAuxIndex, wireTables, bracketEntry, rctw, stab, stab.stabX].directType, stab: stab]]]; }; SGI.TQVol => -- volatile is pretty irrelevant { DefineFileStab[symbol, [NIL, ordinary[descriptor:Rope.FromChar['z], directType: AnalyzeTypeFromFile[thisSymAuxIndex, wireTables, bracketEntry, rctw, stab, stab.stabX].directType, stab: stab]]]; }; SGI.TQArray => NULL; ENDCASE => NULL; } ELSE { <> DefineFileStab[symbol, [NIL, ordinary[descriptor:Rope.FromChar['z], directType: AnalyzeTypeFromFile[thisSymAuxIndex, wireTables, bracketEntry, rctw, stab, stab.stabX].directType, stab: stab]]]; }; } ENDCASE => {} -- We do not parse these types of stabs }; module: Module; parsed: Parsed; wireTables: SGI.WireTables; module _ LOOPHOLE[stab.module]; parsed _ module.whole; wireTables _ LOOPHOLE[parsed.privateInfo]; ParseTypeFromFile[wireTables]; }; SELECT ObjectFiles.CGrammarOfStab[stab] FROM SunADotOut, XCOFF => ParseStabFromRope[stab]; SGIOBJ => ParseStabFromFile[stab]; UNKNOWN => NULL; ENDCASE => Bitch["unrecognized C grammar type"]; }; StabValueAsInt: PROC [x: CARD32] RETURNS [INT] ~ {RETURN[LOOPHOLE[x, INT]]}; RemoteAddrFromCard: PROC[rctw: RCTWData, card: CARD, bitOffset: CARD _ 0] RETURNS[CirioNubAccess.RemoteAddress] = {RETURN[[rctw.nub, card, bitOffset, FALSE, rctw.nub # NIL]]}; VarLocFromDotOListings: PUBLIC PROC [dotOListings: DotOListings, rctw: RCTWData] RETURNS [VarLoc] ~ { dol: DotOListing _ NIL; indirectType: Type; vl: VarLoc; WHILE dol=NIL DO WITH dotOListings SELECT FROM x: DotOEnumr => CCError[cirioError, "asking for VarLoc of enumerator"]; x: DotOListing => { goRound: BOOL _ x.stab.stabType#RSym AND dotOListings.rest#NIL; IF goRound THEN { WITH dotOListings.rest SELECT FROM y: DotOEnumr => CCError[cirioError, "mixed dotOListings"]; y: DotOListing => goRound _ y.stab.stabType=RSym; ENDCASE => ERROR}; IF goRound THEN dotOListings _ dotOListings.rest ELSE dol _ x}; ENDCASE => ERROR; ENDLOOP; indirectType _ CCTypes.GetIndirectType[dol.directType]; vl _ ObjF.VarLocFromStab[dol.stab]; vl.bitSize _ SELECT CCTypes.GetTypeClass[indirectType] FROM $unknown => 32, ENDCASE => CCTypes.GetBitSize[indirectType, rctw.cc]; WITH vl SELECT FROM nc: REF namedCommon VarLocBody => { EnsureAbsValid[rctw.nub, nc]; IF NOT nc.absFound THEN RETURN ObjF.MakeUnknownVarLoc[IO.PutFR1["named common %g not found", [rope[nc.name]] ]]}; ENDCASE => NULL; RETURN [vl]}; EnsureAbsValid: PUBLIC PROC [nub: CirioNubAccess.Handle, nc: REF namedCommon VarLocBody] ~ { IF NOT nc.absValid THEN { se: CirioNubAccess.SymEntry ~ CirioNubAccess.LookupSymEntryByName[nub, nc.name, TRUE, TRUE, 0]; IF se#NIL THEN {nc.absBase _ se.value; nc.absFound _ TRUE} ELSE nc.absFound _ FALSE; nc.absValid _ TRUE}; RETURN}; <> <> <> ArgumentListFromRCTW: PROC [rctw: RCTWData] RETURNS [RopeList] ~ { argumentList: RopeList _ NIL; reverseArgumentList: RopeList _ NIL; MakeArgsList:PROC [stab: ObjF.Stab] RETURNS [BOOLEAN] ~ { IF stab.stabType = PSym THEN BEGIN sourceStream:IO.STREAM _ IO.RIS[stab.rope]; reverseArgumentList _ CONS[GetSymbol[sourceStream], reverseArgumentList] END; RETURN[FALSE] }; lastBracketPair: ObjF.BracketPair; lastBracketPair _ rctw.bracketNest.rest.first; ObjF.GenSymbolStabs[lastBracketPair, MakeArgsList]; FOR remainingArguments: RopeList _ reverseArgumentList, remainingArguments.rest WHILE remainingArguments # NIL DO argumentList _ CONS[remainingArguments.first, argumentList]; ENDLOOP; RETURN [argumentList] }; LocalsListFromBracketPair: PROC [bracketPair: ObjF.BracketPair, rctw: RCTWData, procTop: BOOL] RETURNS [RopeList] ~ { localsList: RopeList _ NIL; AddSymbol: PROC [key:SymTab.Key, val:SymTab.Val] RETURNS [BOOLEAN] = { FOR dotOListings: DotOListings _ NARROW[val], dotOListings.rest WHILE dotOListings#NIL DO WITH dotOListings SELECT FROM x: DotOListing => IF procTop AND x.stab.stabType=PSym THEN RETURN [FALSE]; x: DotOEnumr => NULL; ENDCASE => ERROR; REPEAT FINISHED => localsList _ CONS[key, localsList]; ENDLOOP; RETURN[FALSE]}; bracketEntry: BracketEntry _ GetBracketEntry[bracketPair, rctw]; [] _ SymTab.Pairs[bracketEntry.symbolHashTable, AddSymbol]; RETURN[localsList]}; RopeListLength: PROC [list: RopeList] RETURNS [length: INT] ~ { length _ 0; FOR remaining: RopeList _ list, remaining.rest WHILE remaining # NIL DO length _ length + 1; ENDLOOP }; MakeSimpleFrame: PUBLIC PROC[frameInfo: ProcedureFrameInfo, rctw: RCTWData] RETURNS[Node] = { cc: CC _ rctw.cc; globalsType: Type; --indirect argsType: Type; --indirect blockType: Type; blockCount:INT _ 0; blockTypeList: LIST OF Type _ NIL; igftd: REF Frames.IndirectGlobalFrameTypeData; igfd: REF Frames.IndirectGlobalFrameData; iftd: REF Frames.IndirectFrameTypeData; ifd: REF Frames.IndirectFrameData; frameType: Type; frameNode: Node; frameMem: Mem; BuildIGFTD: PROC RETURNS [REF Frames.IndirectGlobalFrameTypeData] = { x: REF Frames.IndirectGlobalFrameTypeData _ NEW[Frames.IndirectGlobalFrameTypeData _ [globalVars: globalsType]]; RETURN[x]}; BuildIGFD: PROC RETURNS [REF Frames.IndirectGlobalFrameData] = { x: REF Frames.IndirectGlobalFrameData _ NEW[Frames.IndirectGlobalFrameData]; x.globalVars _ CCTypes.CreateIndirectNode[igftd.globalVars, frameMem, rctw.cc]; x.descriptor _ CedarOtherPureTypes.CreateIndirectToAnUnknownType[CedarOtherPureTypes.CreateUnknownType[cc, "C Frame Descriptor"], "C Global Frame", cc]; RETURN[x]}; BuildIFTD: PROC RETURNS[REF Frames.IndirectFrameTypeData] = { x: REF Frames.IndirectFrameTypeData _ NEW[Frames.IndirectFrameTypeData[blockCount]]; index:INT _ 0; x.enclosingContext _ Frames.CreateIndirectGlobalFrameType[igftd, cc]; x.args _ argsType; x.results _ CCTypes.GetIndirectType[CreateZeroLengthRecordType[cc]]; FOR remainingBlocks: LIST OF Type _ blockTypeList, remainingBlocks.rest WHILE remainingBlocks # NIL DO x.blocks[index] _ remainingBlocks.first; index _ index +1 ENDLOOP; RETURN[x]}; BuildIFD: PROC RETURNS[REF Frames.IndirectFrameData] = { x: REF Frames.IndirectFrameData _ NEW[Frames.IndirectFrameData[blockCount]]; x.procedure _ CedarOtherPureTypes.CreateIndirectToAnUnknownType[CedarOtherPureTypes.CreateUnknownType[cc, "no procedure for simple c frame types"], "no procedure for simple c frame types", cc]; x.descriptor _ CedarOtherPureTypes.CreateIndirectToAnUnknownType[CedarOtherPureTypes.CreateUnknownType[cc, "C Frame Descriptor"], "C Frame Descriptor", cc]; x.enclosingContext _ Frames.CreateIndirectGlobalFrameNode[igfd, iftd.enclosingContext, cc]; x.args _ CCTypes.CreateIndirectNode[iftd.args, frameMem, rctw.cc]; x.results _ CreateZeroLengthRecordNode[iftd.results, cc]; FOR index: INT IN [0..iftd.nBlocks) DO x.blocks[index] _ CCTypes.CreateIndirectNode[iftd.blocks[index], frameMem, rctw.cc]; ENDLOOP; RETURN[x]}; frameMem _ RMTWPrivate.MakeDualMem[rctw.nub, frameInfo.framePointer, frameInfo.stackPointer, [frameInfo.codeBase, INT.LAST], [frameInfo.dataBase, INT.LAST], [frameInfo.bssBase, INT.LAST], [unspecdBA, unspecdBA], [unspecdBA, unspecdBA] ]; [] _ frameMem.MemReadSegReg["text", 0]; --make sure it got created OK globalsType _ CreateLocalsRecordType[rctw.bracketNest.first, rctw, FALSE]; igftd _ BuildIGFTD[]; igfd _ BuildIGFD[]; FOR remainingBrackets:ObjectFiles.BracketNest _ rctw.bracketNest.rest, remainingBrackets.rest WHILE remainingBrackets # NIL DO blockType _ CreateLocalsRecordType[remainingBrackets.first, rctw, blockCount=0]; blockTypeList _ CONS[blockType, blockTypeList]; blockCount _ blockCount + 1 ENDLOOP; argsType _ CreateArgsRecordType[rctw]; iftd _ BuildIFTD[]; frameType _ Frames.CreateIndirectFrameType[iftd, cc]; ifd _ BuildIFD[]; frameNode _ Frames.CreateIndirectFrameNode[ifd, frameType, cc]; RETURN [frameNode]}; END..