<<>> <> <> <> <> <> <> <> <> <> <> DIRECTORY BasicTime USING[GMT, Now, Period], CardTab, CCTypes USING[CCError, CCErrorCase, CreateIndirectNode, GetIndirectCreateNode, GetIndirectType, GetRopeType, SetRopeType], CedarOtherPureTypes USING[CreateIndirectToAnUnknownType, CreateRopeNode, CreateUnknownType], CirioMemory, CirioNubAccess USING[Handle, LookupSymEntryByName, RemoteAddress, SymEntry], CirioTypes, Frames USING[CreateIndirectFrameNode, CreateIndirectFrameType, CreateIndirectGlobalFrameNode, CreateIndirectGlobalFrameType, IndirectFrameData, IndirectFrameTypeData, IndirectGlobalFrameData, IndirectGlobalFrameTypeData], --IntHashTable,-- IO, LoadStateAccess, MobAccess, MobObjectFiles USING[FindNearBTHAncestorsForBlock, FindNearBTHAncestorsForPC, GetCatchPhraseStrandedStaticLinkLoc, GetGlobalFrameVarLoc, GetGlobalLinkVar, GetLocalFrameExtensionVar, GetRootBTH, GetSPOffset, GetStaticLinkVar, GetStrandedStaticLinkLoc, GetVarLoc, JointMobParsedInfo, VarLoc, VarLocBody], NewRMTW USING[BaToCnra, CedarModuleSet, FrameNodeInfo, GetLoadedModuleInfo, LoadedModuleInfo, RawFrameInfo], RefTab USING[Create, Fetch, Store], RMTWPrivate, Rope, SymTab, SystemInterface USING [ShowReport]; <<>> RMTWFrames: CEDAR PROGRAM IMPORTS BasicTime, CardTab, CCTypes, CedarOtherPureTypes, CirioMemory, CirioNubAccess, CirioTypes, Frames, --IntHashTable,-- IO, LoadStateAccess, MobAccess, MobObjectFiles, NewRMTW, RefTab, RMTWPrivate, Rope, --SymTab,-- SystemInterface EXPORTS NewRMTW, RMTWPrivate = BEGIN OPEN LSA:LoadStateAccess, MA:MobAccess, MOF:MobObjectFiles, RMTWPrivate; CCE: ERROR[case: CCTypes.CCErrorCase, msg: ROPE _ NIL] _ CCTypes.CCError; BTH: TYPE = MA.BTH; BTR: TYPE = MA.BTR; RemoteAddress: TYPE = CirioNubAccess.RemoteAddress; InvalidRemoteAddress: RemoteAddress _ [NIL, 0, 0, FALSE, FALSE]; invalidPtr: CARD = CARD.LAST; <> <<>> RemoteMimosaTargetWorldBody: PUBLIC TYPE = RMTWPrivate.RemoteMimosaTargetWorldBody; CreateRemoteMimosaTargetWorld: PUBLIC PROC[serverName: ROPE, handle: CirioNubAccess.Handle, cc: CC, cedarModules: NewRMTW.CedarModuleSet, lsh: LSA.LoadStateHandle, reports: IO.STREAM, setCTC: BOOL] RETURNS[RemoteMimosaTargetWorld] = BEGIN now: BasicTime.GMT ~ BasicTime.Now[]; rmtw: RemoteMimosaTargetWorld _ NEW[RemoteMimosaTargetWorldBody_[ sehHash: CreateSehHashTable[], bthHash: CreateBthHashTable[], ctxHash: CreateCtxHashTable[], tcHash: CardTab.Create[], unknownSymbolFlushTime: now, ropeStudyTime: now, atomRecRT: NIL, serverName: serverName, nub: handle, cc: cc, moduleScope: NEW [CirioTypes.ModuleScopeBody _ [GetModule, DontGetInterface, NIL]], cedarModules: cedarModules, lsh: lsh, setCTC: setCTC]]; rmtw.moduleScope.data _ rmtw; IF setCTC THEN StudyRopes[rmtw]; RETURN[rmtw]; END; GetRMTWInfo: PUBLIC PROC [rmtw: RemoteMimosaTargetWorld] RETURNS [serverName: ROPE, handle: CirioNubAccess.Handle, cc: CC, cedarModules: NewRMTW.CedarModuleSet, lsh: LSA.LoadStateHandle] ~ {RETURN[rmtw.serverName, rmtw.nub, rmtw.cc, rmtw.cedarModules, rmtw.lsh]}; GetModuleScope: PUBLIC PROC [rmtw: RemoteMimosaTargetWorld] RETURNS [CirioTypes.ModuleScope] ~ {RETURN [rmtw.moduleScope]}; FlushUnknownSymbolCache: PUBLIC PROC[rmtw: RemoteMimosaTargetWorld, flushTime: BasicTime.GMT, reports: IO.STREAM] = { rmtw.unknownSymbolFlushTime _ flushTime; RETURN}; <> <<>> GetNodeForCedarFrame: PUBLIC PROC[rmtw: RemoteMimosaTargetWorld, loadedModuleInfo: REF NewRMTW.LoadedModuleInfo, rawFrameInfo: REF NewRMTW.RawFrameInfo] RETURNS[REF NewRMTW.FrameNodeInfo] = BEGIN cc: CC _ rmtw.cc; ledo: REF LSA.LoadedModuleInfo _ loadedModuleInfo.loadedModule; dotORelPC: CARD _ rawFrameInfo.absPC - ledo.lsi[text].base; jmpi: MOF.JointMobParsedInfo _ loadedModuleInfo.jmpi; IF jmpi = NIL THEN CCE[operation, "can't find mob or dotO"] ELSE BEGIN blockList: LIST OF BTH _ MOF.FindNearBTHAncestorsForPC[dotORelPC, jmpi]; rootBTH: BTH _ MOF.GetRootBTH[jmpi]; SELECT TRUE FROM (blockList = NIL) => RETURN[NEW[NewRMTW.FrameNodeInfo _ [NIL, GetBadCedarFrameDiagnosticInfo, NEW[BadCedarFrameInfo_["blockList was NIL"]]]]]; (blockList.first = NIL) => RETURN[NEW[NewRMTW.FrameNodeInfo _ [NIL, GetBadCedarFrameDiagnosticInfo, NEW[BadCedarFrameInfo_["blockList.first was NIL"]]]]]; blockList.first = rootBTH => BEGIN -- the frame is the global frame (probably one of the special C procedures) frameTypeInfo: FrameComponentInfo _ CreateIndirectGlobalFrameInfoFromRootBTH[blockList.first, jmpi, ledo, rmtw, FALSE]; targetType: Type _ frameTypeInfo.type; gfTypeInfo: GlobalFrameTypeInfo _ NARROW[frameTypeInfo.typeInfo]; moduleMem: Mem; frameNode: Node; moduleMem _ MakeDualMem[ nub: rmtw.nub, fp: invalidPtr, sp: invalidPtr, fep: [unspecdBA, unspecdBA], text: ledo.lsi[text], data: ledo.lsi[data], bss: ledo.lsi[bss], simple: [unspecdBA, unspecdBA] ]; frameNode _ FinalCreateIndirectGlobalFrameNode[gfTypeInfo, moduleMem].gf; RETURN[NEW[NewRMTW.FrameNodeInfo _ [frameNode, GetBadCedarFrameDiagnosticInfo, NEW[BadCedarFrameInfo_["the frame is the global frame"]]]]]; END; ENDCASE => BEGIN -- this is the normal case (a Mesa procedure) frameTypeInfo: FrameComponentInfo _ CreateProcedureFrameInfoFromBlockList[blockList, loadedModuleInfo, rmtw]; targetType: Type _ frameTypeInfo.type; procFrameTypeInfo: ProcFrameTypeInfo _ NARROW[frameTypeInfo.typeInfo]; codeBase: RemoteAddress _ RemoteAddrFromCard[rmtw, ledo.lsi[text].base]; fes: BitStretch; fm: Mem; frameNode: Node; frameNodeInfo: ProcFrameNodeInfo; WITH procFrameTypeInfo.basicInfo.frameExtensionVarLoc SELECT FROM f: REF frame MOF.VarLocBody => { fes _ [ CirioTypes.BaCons[rawFrameInfo.framePointer, f.bitOffset], CirioTypes.BitsToBa[f.bitSize] ]; <> <> <> }; f: REF indirect MOF.VarLocBody => { WITH f.base SELECT FROM f2: REF frame MOF.VarLocBody => { fes _ [ CirioTypes.BaCons[rawFrameInfo.framePointer, f2.bitOffset], CirioTypes.BitsToBa[f2.bitSize] ]; <> <> <> { tm: Mem ~ CreateSimpleMem[NewRMTW.BaToCnra[rmtw.nub, fes.start], ptrSize]; realStart: CARD _ tm.MemRead[bitsPerPtr, zeroBA]; fes _ [start: CirioTypes.PtrToBa[realStart], size: unspecdBA] }; }; ENDCASE => fes _ [unspecdBA, unspecdBA]; }; ENDCASE => fes _ [unspecdBA, unspecdBA]; fm _ MakeDualMem[ nub: rmtw.nub, fp: rawFrameInfo.framePointer, sp: rawFrameInfo.stackPointer, fep: fes, text: ledo.lsi[text], data: ledo.lsi[data], bss: ledo.lsi[bss], simple: [unspecdBA, unspecdBA] ]; [] _ fm.MemReadSegReg["text", 0]; --make sure it got created OK frameNode _ FinalBuildProcFrameNode[procFrameTypeInfo, NIL, fm, rmtw]; frameNodeInfo _ NEW[ProcFrameNodeInfoBody_[procFrameTypeInfo, fm, frameNode]]; RETURN[NEW[NewRMTW.FrameNodeInfo _ [frameNode, GetCedarFrameDiagnosticInfo, frameNodeInfo]]]; END; END; END; <> <> FrameComponentInfo: TYPE = REF FrameComponentInfoBody; FrameComponentInfoBody: TYPE = RECORD[ analyzedCTX: AnalyzedCTX, -- NIL if not appropriate type: Type, <> typeInfo: REF ANY _ <> <> <> ]; GetFrameComponentInfoForUnknown: PROC[explanation: ROPE, rmtw: RemoteMimosaTargetWorld] RETURNS[REF FrameComponentInfoBody] = BEGIN type: Type _ CedarOtherPureTypes.CreateUnknownType[rmtw.cc, explanation]; RETURN[NEW[FrameComponentInfoBody_[NIL, type, NIL]]]; END; <> <<>> RegByteSize: CARD = 4; CreateSimpleMem: PUBLIC PROC[addr: CirioNubAccess.RemoteAddress, size: BitAddr _ unspecdBA] RETURNS[Mem] ~ { <> RETURN[CirioMemory.CreateSimpleMem[addr, size]]; }; MakeDualMem: PUBLIC PROC [nub: CirioNubAccess.Handle, fp, sp: CARD, text, data, bss: LSA.LoadedSegmentInfo, fep, simple: BitStretch] RETURNS [mem: Mem] ~ { <> RETURN[CirioMemory.MakeDualMem[nub, fp, sp, LsiGetBitStr[text], LsiGetBitStr[data], LsiGetBitStr[bss], fep, simple]]; }; <<>> SelectVarLoc: PUBLIC PROC [nub: CirioNubAccess.Handle, fm: Mem, vl: MobObjectFiles.VarLoc] RETURNS [ans: Mem] ~ { thisSize: BitAddr; IF vl.bitSize = 0 OR vl.bitSize >= CARD[LAST[INT]] THEN CCE[cirioError, "implausible varLoc.bitSize"]; thisSize _ CirioTypes.BitsToBa[vl.bitSize]; WITH vl SELECT FROM regVL: REF register MOF.VarLocBody => { <> rego: INT ~ (regVL.regNum-16)*RegByteSize; --MJS February 6, 1990: this is where the SPARC stores the register, relative to the stack pointer IF NOT regVL.regNum IN [16..32) THEN CCE[cirioError, IO.PutFR1["trying to select var loc in register %g", [cardinal[regVL.regNum]] ]]; --MJS February 5, 1990: I suspect that on SPARCs, as reported through .o files, only registers 16-31 are used ans _ fm.MemPtrRegIndirect[sp, thisSize, CirioTypes.AusToBa[rego], TRUE]; }; frameVL: REF frame MOF.VarLocBody => ans _ fm.MemPtrRegIndirect[fp, thisSize, CirioTypes.BitsToBa[frameVL.bitOffset], TRUE]; frameExtVL: REF frameExtension MOF.VarLocBody => ans _ fm.MemPtrRegIndirect[fe, thisSize, CirioTypes.BitsToBa[frameExtVL.bitOffset], TRUE]; sVL: REF fSegment MOF.VarLocBody => { segName: ROPE ~ sVL.fSeg.fSegName; segMem: Mem ~ fm.MemSelectSegment[segName, 0, TRUE]; ans _ segMem.MemSubfield[[CirioTypes.BitsToBa[sVL.bitOffset], thisSize]]; }; ncVL: REF namedCommon MOF.VarLocBody => { EnsureAbsValid[nub, ncVL]; IF NOT ncVL.absFound THEN CCE[cirioError, IO.PutFR["can't find named common \"%q\"", [rope[ncVL.name]] ]]; ans _ fm.class.CreateSimple[fm.data, [CirioTypes.PtrToBa[ncVL.absBase].BaAdd[CirioTypes.BitsToBa[ncVL.bitOffset]], thisSize], TRUE]}; uVL: REF unknown MOF.VarLocBody => { CCE[cirioError, IO.PutFR["trying to resolve unknown (because %g) VarLoc", [rope[uVL.why]] ]]}; iVL: REF indirect MOF.VarLocBody => { sub: Mem ~ SelectVarLoc[nub, fm, iVL.base]; ans _ sub.MemIndirect[thisSize, iVL.offset]}; ENDCASE => ERROR; IF pickySelect AND vl.bitSize < bitsPerPtr THEN CCE[cirioError, "SelectVarLoc[bitSize<32, ...]"]; RETURN}; pickySelect: BOOL _ FALSE; --MJS, August 15, 1991: don't want to make this check for C; maybe there's a reason we want to make it for Cedar? EnsureAbsValid: PUBLIC PROC [nub: CirioNubAccess.Handle, nc: REF namedCommon MOF.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}; <> <> CreateBthHashTable: PUBLIC PROC RETURNS[BthHashTable] = {RETURN[NEW[BthHashTableBody _ [RefTab.Create[]]]]}; GetBthInfo: PROC[bth: BTH, tw: RemoteMimosaTargetWorld] RETURNS[BthInfo] = BEGIN info: BthInfo _ NARROW[RefTab.Fetch[tw.bthHash.table, bth].val]; IF info = NIL THEN BEGIN info _ NEW[BthInfoBody_[NIL, tw.unknownSymbolFlushTime, NIL, NIL, NIL]]; IF NOT RefTab.Store[tw.bthHash.table, bth, info] THEN CCE[cirioError]; -- shouldn't happen END; IF BasicTime.Period[info.effectiveFlushTime, tw.unknownSymbolFlushTime] > 0 THEN <> BEGIN info.effectiveFlushTime _ tw.unknownSymbolFlushTime; info.nestedBlock _ NIL; info.basicProcedureFrameInfo _ NIL; info.fullProcedureFrameInfo _ NIL; END; RETURN[info]; END; <> <<>> <> BasicProcFrameTypeInfo: TYPE = REF BasicProcFrameTypeInfoBody; BasicProcFrameTypeInfoBody: TYPE = RECORD[ lmi: REF NewRMTW.LoadedModuleInfo, callableBTH, rootBTH: BTH, enclosingBlockList: LIST OF BTH, args: FrameComponentInfo, results: FrameComponentInfo, frameExtensionVar: SEH, -- the frameExtension variable IS the frame extension frameExtensionVarLoc: MOF.VarLoc, staticLinkVar: SEH, -- holds a pointer to the frameExtension of the static enclosing procedure frame staticLinkVarLoc: MOF.VarLoc, globalLinkVar: SEH, -- holds a pointer to the global frame variable of the module. globalLinkVarLoc: MOF.VarLoc, spOffset: INT, -- the SP equals the FP + spOffset, hence spOffset is negative <> enclosingContext: FrameComponentInfo ]; GenDiagnosticRopesFromBasicProcFrameTypeInfo: PROC[info: BasicProcFrameTypeInfo, for: PROC[ROPE]] = BEGIN for[IO.PutFR["codedBti for callable bth = %g", IO.card[MA.GetCodedBTIFromBTH[info.callableBTH]]]]; END; <> CreateBasicProcedureFrameInfo: PROC[bth: BTH, lmi: REF NewRMTW.LoadedModuleInfo, rmtw: RemoteMimosaTargetWorld] RETURNS[BasicProcFrameTypeInfo] = { bthInfo: BthInfo _ GetBthInfo[bth, rmtw]; jmpi: MOF.JointMobParsedInfo _ lmi.jmpi; IF bthInfo.basicProcedureFrameInfo = NIL THEN { btr: BTR _ MA.FetchBTR[bth]; basicInfo: BasicProcFrameTypeInfo _ NEW[BasicProcFrameTypeInfoBody]; basicInfo.enclosingBlockList _ MOF.FindNearBTHAncestorsForBlock[bth, jmpi]; basicInfo.rootBTH _ MOF.GetRootBTH[jmpi]; basicInfo.lmi _ lmi; <> WITH btr.extension SELECT FROM ext: REF Callable MA.BTRExtension => { ioTypeSer: SER _ MA.FetchSER[ext.ioType]; WITH ioTypeSer.body SELECT FROM cons: REF cons MA.BodySE => WITH cons.typeInfo SELECT FROM transfer: REF transfer MA.TypeInfoConsSE => { basicInfo.args _ CreateArgResultRcdInfo[transfer.typeIn, bth, jmpi, rmtw]; basicInfo.results _ CreateArgResultRcdInfo[transfer.typeOut, bth, jmpi, rmtw]}; basic: REF basic MA.TypeInfoConsSE => { <> basicInfo.args _ CreateArgResultRcdInfo[NIL, bth, jmpi, rmtw]; basicInfo.results _ CreateArgResultRcdInfo[NIL, bth, jmpi, rmtw]} ENDCASE => CCE[cirioError]; ENDCASE => CCE[cirioError]}; ENDCASE => CCE[cirioError]; basicInfo.callableBTH _ bth; basicInfo.frameExtensionVar _ MOF.GetLocalFrameExtensionVar[bth, jmpi]; basicInfo.frameExtensionVarLoc _ MOF.GetVarLoc[basicInfo.frameExtensionVar, bth, jmpi]; basicInfo.staticLinkVar _ MOF.GetStaticLinkVar[bth, jmpi]; IF basicInfo.staticLinkVar#NIL THEN basicInfo.staticLinkVarLoc _ MOF.GetVarLoc[basicInfo.staticLinkVar, bth, jmpi] ELSE { IF btr.class=Scope THEN basicInfo.staticLinkVarLoc _ MOF.GetStrandedStaticLinkLoc[bth, jmpi] ELSE IF btr.class=Catch THEN basicInfo.staticLinkVarLoc _ MOF.GetCatchPhraseStrandedStaticLinkLoc[bth, jmpi]; }; <> <> IF basicInfo.frameExtensionVar=NIL AND basicInfo.staticLinkVarLoc#NIL THEN { IF btr.class=Scope OR btr.class=Catch THEN basicInfo.frameExtensionVarLoc _ MakeIndirect[basicInfo.staticLinkVarLoc]; }; basicInfo.globalLinkVar _ MOF.GetGlobalLinkVar[bth, jmpi]; basicInfo.globalLinkVarLoc _ MOF.GetVarLoc[basicInfo.globalLinkVar, bth, jmpi]; basicInfo.spOffset _ MOF.GetSPOffset[bth, jmpi]; <<>> <> { rootBTH: BTH _ basicInfo.rootBTH; enclosingBlockList: LIST OF BTH _ basicInfo.enclosingBlockList; IF enclosingBlockList = NIL THEN basicInfo.enclosingContext _ GetFrameComponentInfoForUnknown["enclosingBlockList = NIL", rmtw] ELSE IF enclosingBlockList.first = NIL THEN basicInfo.enclosingContext _ GetFrameComponentInfoForUnknown["enclosingBlockList.first = NIL", rmtw] ELSE IF enclosingBlockList.first = rootBTH THEN { basicInfo.enclosingContext _ CreateIndirectGlobalFrameInfoFromRootBTH[enclosingBlockList.first, jmpi, lmi.loadedModule, rmtw, FALSE]; } ELSE { basicInfo.enclosingContext _ CreateProcedureFrameInfoFromBlockList[enclosingBlockList, lmi, rmtw]; }; }; bthInfo.basicProcedureFrameInfo _ basicInfo; }; RETURN[bthInfo.basicProcedureFrameInfo]; }; MakeIndirect: PROC [vl: MOF.VarLoc] RETURNS [MOF.VarLoc] ~ { tmpLoc: MOF.VarLoc _ NIL; IF vl=NIL THEN RETURN[NIL]; RETURN [NEW[MOF.VarLocBody _ [ bitSize: vl.bitSize --MJS doesn't know why this is right, on Dec 13, 1991--, where: indirect[base: vl, offset: zeroBA] ]] ]}; CreateArgResultRcdInfo: PROC[seh: SEH, bth: BTH, jmpi: MOF.JointMobParsedInfo, rmtw: RemoteMimosaTargetWorld] RETURNS[FrameComponentInfo] = BEGIN IF seh = NIL THEN RETURN[AnalyzeCTXAsBlockRecord[NIL, bth, jmpi, rmtw]] ELSE BEGIN underSeh: SEH _ UnderTypeSEH[seh, rmtw]; -- should we build definition types? underSer: SER _ MA.FetchSER[underSeh]; WITH underSer.body SELECT FROM cons: REF cons MA.BodySE => WITH cons.typeInfo SELECT FROM ti: REF record MA.TypeInfoConsSE => RETURN[AnalyzeCTXAsBlockRecord[ti.fieldCtx, bth, jmpi, rmtw]]; ENDCASE => CCE[cirioError]; ENDCASE => CCE[cirioError]; END; END; <<>> <<>> <> ProcFrameTypeInfo: TYPE = REF ProcFrameTypeInfoBody; ProcFrameTypeInfoBody: TYPE = RECORD[ basicInfo: BasicProcFrameTypeInfo, frameType: Type, frameTypeData: REF Frames.IndirectFrameTypeData, nestedBlocks: SEQUENCE nBlocks: CARDINAL OF RECORD[bth: BTH, info: FrameComponentInfo]]; BthInfo: TYPE = REF BthInfoBody; BthInfoBody: TYPE = RECORD[ rmtw: RemoteMimosaTargetWorld, effectiveFlushTime: BasicTime.GMT, nestedBlock: FrameComponentInfo, basicProcedureFrameInfo: BasicProcFrameTypeInfo, fullProcedureFrameInfo: FrameComponentInfo ]; GenDiagnosticRopesFromProcFrameTypeInfo: PROC[info: ProcFrameTypeInfo, for: PROC[ROPE]] = BEGIN GenDiagnosticRopesFromBasicProcFrameTypeInfo[info.basicInfo, for]; END; <> <<>> <> CreateProcedureFrameInfoFromBlockList: PROC[blockList: LIST OF BTH, lmi: REF NewRMTW.LoadedModuleInfo, rmtw: RemoteMimosaTargetWorld] RETURNS[FrameComponentInfo] = { blockInfo: AnalyzedBlockList _ AnalyzeBlockList[blockList]; bthInfo: BthInfo _ GetBthInfo[blockInfo.lastBlock, rmtw]; <<>> <> IF bthInfo.fullProcedureFrameInfo = NIL THEN { correctBL: LIST OF BTH _ CorrectBL[blockList]; correctABL: AnalyzedBlockList _ AnalyzeBlockList[correctBL]; basicFrameInfo: BasicProcFrameTypeInfo _ CreateBasicProcedureFrameInfo[blockList.first, lmi, rmtw]; firstBTR: BTR _ MA.FetchBTR[blockList.first]; nBlocks: CARDINAL _ correctABL.nBlocks; frameInfo: ProcFrameTypeInfo _ NEW[ProcFrameTypeInfoBody[nBlocks]]; frameTypeData: REF Frames.IndirectFrameTypeData _ NEW[Frames.IndirectFrameTypeData[nBlocks]]; index: CARDINAL _ 0; FOR bl: LIST OF BTH _ correctBL, bl.rest WHILE bl # NIL DO frameInfo.nestedBlocks[index] _ [bl.first, CreateNestedBlockRecordFromBTH[bl.first, lmi.jmpi, rmtw]]; index _ index + 1; ENDLOOP; frameTypeData.enclosingContext _ basicFrameInfo.enclosingContext.type; frameTypeData.args _ CCTypes.GetIndirectType[basicFrameInfo.args.type]; frameTypeData.results _ CCTypes.GetIndirectType[basicFrameInfo.results.type]; FOR I: CARDINAL IN [0..nBlocks) DO frameTypeData.blocks[I] _ CCTypes.GetIndirectType[frameInfo.nestedBlocks[I].info.type]; ENDLOOP; frameInfo.basicInfo _ basicFrameInfo; frameInfo.frameType _ Frames.CreateIndirectFrameType[frameTypeData, rmtw.cc]; frameInfo.frameTypeData _ frameTypeData; bthInfo.fullProcedureFrameInfo _ NEW[FrameComponentInfoBody _ [NIL, frameInfo.frameType, frameInfo]]; }; RETURN[bthInfo.fullProcedureFrameInfo]}; CorrectBL: PROC [blockList: LIST OF BTH] RETURNS [LIST OF BTH] ~ { <> firstBTR: BTR _ MA.FetchBTR[blockList.first]; childH: BTH _ firstBTR.firstSon; childR: BTR; bestSrc: CARD _ CARD.LAST; bestChild: BTH _ NIL; IF firstBTR.localCtx#NIL THEN RETURN[blockList]; IF firstBTR.class#Scope THEN RETURN[blockList.rest]; WHILE childH#NIL DO childR _ MA.FetchBTR[childH]; IF childR.sourceIndex <= bestSrc THEN { bestSrc _ childR.sourceIndex; bestChild _ childH}; IF childR.link.which=sibling THEN childH _ childR.link.index ELSE childH _ NIL; ENDLOOP; IF bestChild#NIL THEN RETURN[CONS[bestChild, blockList.rest]]; RETURN[blockList.rest]}; AnalyzedBlockList: TYPE = RECORD[nBlocks: CARDINAL, lastBlock: BTH]; AnalyzeBlockList: PROC[blockList: LIST OF BTH] RETURNS[AnalyzedBlockList] = { nominalNBlocks: CARDINAL _ 0; lastBlock: BTH; FOR bl: LIST OF BTH _ blockList, bl.rest WHILE bl # NIL DO nominalNBlocks _ nominalNBlocks + 1; lastBlock _ bl.first; ENDLOOP; RETURN[[nominalNBlocks, lastBlock]]}; <> <<>> <> <<>> <> <> <> <> <> <> <> <> <<>> <<>> <