-- AMModelSectionImpl.mesa -- Last Modified On August 10, 1983 12:45 pm By Paul Rovner -- moduleName, configName should not be source name DIRECTORY AMBridge USING [TVForGFHReferent, TVForRemoteGFHReferent, GFHFromTV, RemoteGFHFromTV, GetWorld, RemoteGlobalFrameHandle, nilRemoteGlobalFrameHandle], AMMiniModel USING [AcquireIRType], AMModel USING [Class, Source, SourceObj, CharIndex], AMModelPrivate USING [FGIndex, FGNull, EPI, EPIToFirstFGI, GetModuleSTB, EPIToLastFGI, FGIToFirstChar, FGIToLastChar, FGIToEPI, NextFGI, SectionRec, RefTVRec, GetLocalBCD, GetRemoteBCD], AMTypes USING [TVType, Error, TVToName, TV], BcdDefs USING [MTIndex, NameRecord, BcdBase, MTHandle, NameString, VersionStamp, ModuleIndex], BcdOps USING [ProcessModules], BrandXSymbolDefs USING[BodyIndex, rootBodyIndex, nullBodyIndex, SymbolTableBase, FineGrainTableHeader], BrandYSymbolDefs USING[BodyIndex, rootBodyIndex, nullBodyIndex, SymbolTableBase, FineGrainTableHeader], ConvertUnsafe USING [ToRope, SubStringToRope, SubString], IO USING [PutR, card], LoadState USING [local, Acquire, Release, Handle, ConfigInfo, ModuleToGlobalFrame, ConfigID, GlobalFrameToModule], PrincOps USING [wordsPerPage, GlobalFrameHandle], Rope USING [ROPE, Concat], RTSymbolDefs USING [SymbolTableBase, SymbolTableHandle], RTSymbolOps USING [AcquireRope, AcquireType, STBSourceVersion], RTSymbols USING [AcquireSTB, ReleaseSTB, GetSTHForModule], RTSymbolsPrivate USING [AcquireBCDFromVersion, ReleaseBCD], RTTypesRemotePrivate USING [AcquireRemoteBCD, ReleaseRemoteBCD], SafeStorage USING [Type], Table USING [Base], WorldVM USING [World, Lock, Unlock, LocalWorld, Loadstate, CurrentIncarnation, Incarnation]; AMModelSectionImpl: PROGRAM IMPORTS AMBridge, AMMiniModel, AMModelPrivate, AMTypes, BcdOps, ConvertUnsafe, IO, LoadState, Rope, RTSymbolOps, RTSymbols, RTSymbolsPrivate, RTTypesRemotePrivate, WorldVM EXPORTS AMModel = { OPEN AMBridge, AMMiniModel, AMTypes, bx: BrandXSymbolDefs, by: BrandYSymbolDefs, PrincOps, Rope, AMModel, AMModelPrivate, RTSymbolDefs, RTSymbolOps, RTSymbols, RTTypesRemotePrivate, WorldVM; -- TYPEs -- either binder output bundle for a config, or compiler output bundle -- for a prog module, DEFs module, proc, or statement Section: TYPE = REF SectionObj; SectionObj: PUBLIC TYPE = SectionRec; -- PROCs dealing with Sections SectionClass: PUBLIC PROC[section: Section] RETURNS[Class] = {RETURN[section.class]}; SectionName: PUBLIC PROC[section: Section] RETURNS[ans: ROPE _ NIL] = {WITH s: section SELECT FROM model => RETURN[s.configName]; prog => RETURN[s.moduleName]; interface => RETURN[s.moduleName]; proc => IF s.procTV # NIL THEN RETURN[TVToName[s.procTV]] ELSE {sth: SymbolTableHandle = GetSTHForModule [stamp: s.prog.versionStamp, fileName: Rope.Concat[s.prog.moduleName, ".bcd"], moduleName: s.prog.moduleName]; stb: SymbolTableBase _ AcquireSTB[sth]; FindProcX: PROC[bti: bx.BodyIndex] RETURNS[stop: BOOLEAN _ FALSE] = {xstb: bx.SymbolTableBase = NARROW[stb, SymbolTableBase.x].e; WITH b: xstb.bb[bti] SELECT FROM Callable => IF ~b.inline AND b.entryIndex = s.entryPointIndex THEN {ans _ AcquireRope[stb, [x[xstb.seb[b.id].hash]]]; RETURN[TRUE]}; ENDCASE}; FindProcY: PROC[bti: by.BodyIndex] RETURNS[stop: BOOLEAN _ FALSE] = {ystb: by.SymbolTableBase = NARROW[stb, SymbolTableBase.y].e; WITH b: ystb.bb[bti] SELECT FROM Callable => IF ~b.inline AND b.entryIndex = s.entryPointIndex THEN {ans _ AcquireRope[stb, [y[ystb.seb[b.id].hash]]]; RETURN[TRUE]}; ENDCASE}; WITH stb SELECT FROM t: SymbolTableBase.x => IF t.e.EnumerateBodies[bx.rootBodyIndex, FindProcX ! UNWIND => ReleaseSTB[stb]] = bx.nullBodyIndex THEN {ReleaseSTB[stb]; ERROR}; t: SymbolTableBase.y => IF t.e.EnumerateBodies[by.rootBodyIndex, FindProcY ! UNWIND => ReleaseSTB[stb]] = by.nullBodyIndex THEN {ReleaseSTB[stb]; ERROR}; ENDCASE => ERROR; ReleaseSTB[stb]; RETURN[ans]}; -- figure it out from the ep# and the prog section statement => RETURN[Rope.Concat[Rope.Concat[s.prog.moduleName, "."], IO.PutR[IO.card[s.fgtIndex.fgCard]]]] ENDCASE => ERROR }; -- param to creator of section. SectionSource: PUBLIC PROC[section: Section] RETURNS[ans: Source] = --param to creator of section {WITH s: section SELECT FROM model => { IF s.configContext # NIL THEN -- loaded model section {IF s.configContext.world = LocalWorld[] THEN { bcd: BcdDefs.BcdBase; LoadState.local.Acquire[]; { ENABLE UNWIND => LoadState.local.Release[]; bcd _ LoadState.local.ConfigInfo[s.configContext.configIndex].bcd; }; -- end ENABLE UNWIND => LoadState.local.Release[]; LoadState.local.Release[]; ans _ NEW[SourceObj _ [fileName: BcdNameToRope[bcd, bcd.source], class: model, versionStamp: bcd.sourceVersion, sourceRange: entire[]]]; RETURN; } ELSE {fileName: ROPE; v: BcdDefs.VersionStamp; world: World = s.configContext.world; Lock[world]; { ENABLE UNWIND => Unlock[world]; h: LoadState.Handle = WorldVM.Loadstate[world]; h.Acquire[]; { ENABLE UNWIND => h.Release[]; bcd: BcdDefs.BcdBase = AcquireRemoteBCD[ world: world, incarnation: CurrentIncarnation[world], bcd: h.ConfigInfo [s.configContext.configIndex].bcd]; IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols]; { ENABLE UNWIND => ReleaseRemoteBCD[bcd]; fileName _ BcdNameToRope[bcd, bcd.source]; v _ bcd.sourceVersion; }; -- end ENABLE UNWIND => ReleaseRemoteBCD[bcd]; ReleaseRemoteBCD[bcd]; }; -- end ENABLE UNWIND => h.Release[]; h.Release[]; ans _ NEW[SourceObj _ [fileName: fileName, class: model, versionStamp: v, sourceRange: entire[]]]; }; -- end ENABLE UNWIND => Unlock[world]; Unlock[world]; RETURN; } } ELSE { -- model section, not loaded. Get the binder output bcd, given the -- config name and its version stamp bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: s.versionStamp, shortFileNameHint: Rope.Concat[s.configName, ".bcd"]]; IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols]; ans _ NEW[SourceObj _ [fileName: BcdNameToRope[bcd, bcd.source], class: model, versionStamp: bcd.sourceVersion, sourceRange: entire[]]]; RTSymbolsPrivate.ReleaseBCD[bcd]; }}; prog => { -- get the compiler output bcd, given the module name and -- its version stamp. Could poke around in the loadstate, but painful. IF s.someGFHTV = NIL THEN -- unloaded prog section {bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: s.versionStamp, shortFileNameHint: Rope.Concat[s.moduleName, ".bcd"]]; IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols]; ans _ NEW[SourceObj _ [fileName: BcdNameToRope[bcd, bcd.source], class: prog, versionStamp: bcd.sourceVersion, sourceRange: entire[]]]; RTSymbolsPrivate.ReleaseBCD[bcd]} ELSE -- loaded prog section; get the bcd from the loadstate {ptv: TV = s.someGFHTV; world: World _ GetWorld[ptv]; IF world = LocalWorld[] THEN {bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[ptv]]; stb: SymbolTableBase _ GetModuleSTB[bcd, s.versionStamp]; { ENABLE UNWIND => ReleaseSTB[stb]; WITH stb SELECT FROM t: SymbolTableBase.x => {ns: LONG STRING = @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO bx.FineGrainTableHeader].sourceFile; ans _ NEW[SourceObj _ [fileName: ConvertUnsafe.ToRope[ns], class: prog, versionStamp: t.e.stHandle.sourceVersion, sourceRange: entire[]]]}; t: SymbolTableBase.y => {ns: LONG STRING = @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO by.FineGrainTableHeader].sourceFile; ans _ NEW[SourceObj _ [fileName: ConvertUnsafe.ToRope[ns], class: prog, versionStamp: t.e.stHandle.sourceVersion, sourceRange: entire[]]]}; ENDCASE => ERROR; }; -- end ENABLE UNWIND => ReleaseSTB[stb] ReleaseSTB[stb]; } ELSE -- remote world {bcd: BcdDefs.BcdBase _ GetRemoteBCD[RemoteGFHFromTV[ptv]]; { ENABLE UNWIND => ReleaseRemoteBCD[bcd]; stb: SymbolTableBase _ GetModuleSTB[bcd, s.versionStamp]; { ENABLE UNWIND => ReleaseSTB[stb]; WITH stb SELECT FROM t: SymbolTableBase.x => {ns: LONG STRING = @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO bx.FineGrainTableHeader].sourceFile; ans _ NEW[SourceObj _ [fileName: ConvertUnsafe.ToRope[ns], class: prog, versionStamp: t.e.stHandle.sourceVersion, sourceRange: entire[]]]}; t: SymbolTableBase.y => {ns: LONG STRING = @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO by.FineGrainTableHeader].sourceFile; ans _ NEW[SourceObj _ [fileName: ConvertUnsafe.ToRope[ns], class: prog, versionStamp: t.e.stHandle.sourceVersion, sourceRange: entire[]]]}; ENDCASE => ERROR; }; -- end ENABLE UNWIND => ReleaseSTB[stb] ReleaseSTB[stb]; }; -- end ENABLE UNWIND => ... FREE[@bcd]; ReleaseRemoteBCD[bcd]; } }; }; interface => { -- get the compiler output bcd, given the module name and its version stamp. bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: s.versionStamp, shortFileNameHint: Rope.Concat[s.moduleName, ".bcd"]]; IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols]; ans _ NEW[SourceObj _ [fileName: BcdNameToRope[bcd, bcd.source], class: interface, versionStamp: bcd.sourceVersion, sourceRange: entire[]]]; RTSymbolsPrivate.ReleaseBCD[bcd]; }; proc => { IF s.prog.someGFHTV = NIL THEN -- unloaded proc section {bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: s.prog.versionStamp, shortFileNameHint: Rope.Concat[s.prog.moduleName, ".bcd"]]; IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols]; ans _ NEW[SourceObj _ [fileName: BcdNameToRope[bcd, bcd.source], class: proc, versionStamp: bcd.sourceVersion, sourceRange: field[firstCharIndex: ProcToFirstCI[NARROW[section]], lastCharIndex: ProcToLastCI[NARROW[section]]]]]; RTSymbolsPrivate.ReleaseBCD[bcd]} ELSE -- loaded proc section; get the bcd from the loadstate {ptv: TV = s.prog.someGFHTV; world: World _ GetWorld[ptv]; IF world = LocalWorld[] THEN {bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[ptv]]; stb: SymbolTableBase _ GetModuleSTB[bcd, s.prog.versionStamp]; { ENABLE UNWIND => ReleaseSTB[stb]; WITH stb SELECT FROM t: SymbolTableBase.x => {ns: LONG STRING = @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO bx.FineGrainTableHeader].sourceFile; ans _ NEW[SourceObj _ [fileName: ConvertUnsafe.ToRope[ns], class: proc, versionStamp: t.e.stHandle.sourceVersion, sourceRange: field[firstCharIndex: ProcToFirstCI[NARROW[section]], lastCharIndex: ProcToLastCI[NARROW[section]]]]]}; t: SymbolTableBase.y => {ns: LONG STRING = @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO by.FineGrainTableHeader].sourceFile; ans _ NEW[SourceObj _ [fileName: ConvertUnsafe.ToRope[ns], class: proc, versionStamp: t.e.stHandle.sourceVersion, sourceRange: field[firstCharIndex: ProcToFirstCI[NARROW[section]], lastCharIndex: ProcToLastCI[NARROW[section]]]]]}; ENDCASE => ERROR; }; -- end ENABLE UNWIND => ReleaseSTB[stb] ReleaseSTB[stb]; } ELSE -- remote world {bcd: BcdDefs.BcdBase _ GetRemoteBCD[RemoteGFHFromTV[ptv]]; { ENABLE UNWIND => ReleaseRemoteBCD[bcd]; stb: SymbolTableBase _ GetModuleSTB[bcd, s.prog.versionStamp]; { ENABLE UNWIND => ReleaseSTB[stb]; WITH stb SELECT FROM t: SymbolTableBase.x => {ns: LONG STRING = @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO bx.FineGrainTableHeader].sourceFile; ans _ NEW[SourceObj _ [fileName: ConvertUnsafe.ToRope[ns], class: proc, versionStamp: t.e.stHandle.sourceVersion, sourceRange: field[firstCharIndex: ProcToFirstCI[NARROW[section]], lastCharIndex: ProcToLastCI[NARROW[section]]]]]}; t: SymbolTableBase.y => {ns: LONG STRING = @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO by.FineGrainTableHeader].sourceFile; ans _ NEW[SourceObj _ [fileName: ConvertUnsafe.ToRope[ns], class: proc, versionStamp: t.e.stHandle.sourceVersion, sourceRange: field[firstCharIndex: ProcToFirstCI[NARROW[section]], lastCharIndex: ProcToLastCI[NARROW[section]]]]]}; ENDCASE => ERROR; }; -- end ENABLE UNWIND => ReleaseSTB[stb] ReleaseSTB[stb]; }; -- end ENABLE UNWIND => ... FREE[@bcd]; ReleaseRemoteBCD[bcd]; } }; }; statement => { IF s.prog.someGFHTV = NIL THEN -- unloaded proc section {bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: s.prog.versionStamp, shortFileNameHint: Rope.Concat[s.prog.moduleName, ".bcd"]]; fci, lci: INT; IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols]; fci _ StatementToFirstCI[NARROW[section]]; lci _ StatementToLastCI[NARROW[section]]; IF fci = lci THEN lci _ fci-1; ans _ NEW[SourceObj _ [fileName: BcdNameToRope[bcd, bcd.source], class: statement, versionStamp: bcd.sourceVersion, sourceRange: field[firstCharIndex: fci, lastCharIndex: lci]]]; RTSymbolsPrivate.ReleaseBCD[bcd]} ELSE -- loaded proc section; get the bcd from the loadstate {ptv: TV = s.prog.someGFHTV; world: World _ GetWorld[ptv]; IF world = LocalWorld[] THEN {bcd: BcdDefs.BcdBase = GetLocalBCD[GFHFromTV[ptv]]; stb: SymbolTableBase _ GetModuleSTB[bcd, s.prog.versionStamp]; { ENABLE UNWIND => ReleaseSTB[stb]; ns: LONG STRING = WITH stb SELECT FROM t: SymbolTableBase.x => @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO bx.FineGrainTableHeader].sourceFile, t: SymbolTableBase.y => @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO by.FineGrainTableHeader].sourceFile, ENDCASE => ERROR; fci, lci: INT; fci _ StatementToFirstCI[NARROW[section]]; lci _ StatementToLastCI[NARROW[section]]; IF fci = lci THEN lci _ fci-1; ans _ NEW[SourceObj _ [fileName: ConvertUnsafe.ToRope[ns], class: statement, versionStamp: STBSourceVersion[stb], sourceRange: field[firstCharIndex: fci, lastCharIndex: lci]]]; }; -- end ENABLE UNWIND => ReleaseSTB[stb] ReleaseSTB[stb]; } ELSE -- remote world {bcd: BcdDefs.BcdBase _ GetRemoteBCD[RemoteGFHFromTV[ptv]]; { ENABLE UNWIND => ReleaseRemoteBCD[bcd]; stb: SymbolTableBase _ GetModuleSTB[bcd, s.prog.versionStamp]; { ENABLE UNWIND => ReleaseSTB[stb]; ns: LONG STRING = WITH stb SELECT FROM t: SymbolTableBase.x => @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO bx.FineGrainTableHeader].sourceFile, t: SymbolTableBase.y => @LOOPHOLE [t.e.stHandle + t.e.stHandle.fgRelPgBase*wordsPerPage, LONG POINTER TO by.FineGrainTableHeader].sourceFile, ENDCASE => ERROR; fci, lci: INT; fci _ StatementToFirstCI[NARROW[section]]; lci _ StatementToLastCI[NARROW[section]]; IF fci = lci THEN lci _ fci-1; ans _ NEW[SourceObj _ [fileName: ConvertUnsafe.ToRope[ns], class: statement, versionStamp: STBSourceVersion[stb], sourceRange: field[firstCharIndex: fci, lastCharIndex: lci]]]; }; -- end ENABLE UNWIND => ReleaseSTB[stb] ReleaseSTB[stb]; }; -- end ENABLE UNWIND => ... FREE[@bcd]; ReleaseRemoteBCD[bcd]; } }; }; ENDCASE => ERROR }; -- end SectionSource -- param to creator of section. -- (DIRECTORY entries) -- Implemented only for model, prog and interface sections SectionParams: PUBLIC PROC[section: Section] RETURNS[list: LIST OF SafeStorage.Type _ NIL] = --ditto (DIRECTORY entries) {WITH s: section SELECT FROM model => ERROR; --NOTE enumerate the directory entries; prog => ERROR; --NOTE enumerate the directory entries; interface => ERROR; --NOTE enumerate the directory entries; proc => ERROR AMTypes.Error[reason: notImplemented]; statement => ERROR AMTypes.Error[reason: notImplemented]; ENDCASE => ERROR }; -- containers: -- prog module for a proc -- proc for a statement ParentSection: PUBLIC PROC[section: Section] RETURNS[Section] = {WITH s: section SELECT FROM proc => RETURN[s.prog]; statement => RETURN[NEW[SectionObj _ [proc[prog: s.prog, entryPointIndex: StatementToParentEPI [NARROW[section]] ] ]]]; ENDCASE => ERROR AMTypes.Error[reason: notImplemented]; }; -- end ParentSections -- parts: modules of a model, procs of a module, statements of a proc SectionChildren: PUBLIC PROC[section: Section, proc: PROC[Section] RETURNS[stop: BOOL]] RETURNS[ans: Section _ NIL--NIL if not stopped--] = {x: INT _ 0; NextSection: PROC[parent, child: Section] RETURNS[s: Section _ NIL] = {[s, x] _ NextSiblingSection[parent: parent, child: child, indexInParent: x]}; FOR s: Section _ FirstChildSection[section], NextSection[section, s] UNTIL s = NIL DO IF proc[s] THEN RETURN[s]; ENDLOOP; }; -- parts: modules of a model, procs of a module, statements of a proc FirstChildSection: PROC[section: Section] RETURNS[ans: Section] = {WITH s: section SELECT FROM model => IF s.configContext # NIL THEN {IF s.configContext.world = LocalWorld[] THEN -- section has a local configContext {bcd: BcdDefs.BcdBase; ftb: Table.Base; mth: BcdDefs.MTHandle; p: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOL] = {RETURN[TRUE]}; LoadState.local.Acquire[]; bcd _ LoadState.local.ConfigInfo[s.configContext.configIndex].bcd; IF bcd = NIL THEN {LoadState.local.Release[]; ERROR AMTypes.Error[reason: noSymbols]}; ftb _ LOOPHOLE[bcd + bcd.ftOffset]; mth _ BcdOps.ProcessModules[bcd, p].mth; ans _ NEW [SectionObj _ [prog[moduleName: BcdNameToRope[bcd, mth.name], versionStamp: ftb[mth.file].version, someGFHTV: NARROW [TVForGFHReferent [LoadState.local.ModuleToGlobalFrame [s.configContext.configIndex, mth.gfi] ] ] ] ] ]; LoadState.local.Release[]; RETURN; } ELSE -- section has a remote configContext {world: World = s.configContext.world; cx: LoadState.ConfigID = s.configContext.configIndex; moduleName: ROPE; v: BcdDefs.VersionStamp; mx: BcdDefs.ModuleIndex; Lock[world]; { ENABLE UNWIND => Unlock[world]; incarnation: Incarnation _ CurrentIncarnation[world]; rgfh: GlobalFrameHandle; newState: LoadState.Handle = WorldVM.Loadstate[world]; newState.Acquire[]; { ENABLE UNWIND => newState.Release[]; bcd: BcdDefs.BcdBase = AcquireRemoteBCD[ world: world, incarnation: CurrentIncarnation[world], bcd: newState.ConfigInfo[cx].bcd]; IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols]; { ENABLE UNWIND => ReleaseRemoteBCD[bcd]; ftb: Table.Base = LOOPHOLE[bcd + bcd.ftOffset]; p: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOL] = {RETURN[TRUE]}; mth: BcdDefs.MTHandle = BcdOps.ProcessModules[bcd, p].mth; v _ ftb[mth.file].version; moduleName _ BcdNameToRope[bcd, mth.name]; mx _ mth.gfi; }; -- end ENABLE UNWIND => ReleaseRemoteBCD[bcd] ReleaseRemoteBCD[bcd]; rgfh _ newState.ModuleToGlobalFrame[cx, mx]; }; -- end ENABLE UNWIND => newState.Release[] newState.Release[]; ans _ NEW[SectionObj _ [prog[moduleName: moduleName, versionStamp: v, someGFHTV: NARROW [TVForRemoteGFHReferent [ [world: world, worldIncarnation: incarnation, gfh: LOOPHOLE[rgfh] ] ]] ] ] ]; }; -- end ENABLE UNWIND => Unlock[world]; Unlock[world]; RETURN; } } ELSE -- here if model section is not loaded { -- get the binder output bcd, given the config name and -- its version stamp bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: s.versionStamp, shortFileNameHint: Rope.Concat[s.configName, ".bcd"]]; ftb: Table.Base; mth: BcdDefs.MTHandle; p: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [BOOLEAN] = {RETURN[TRUE]}; IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols]; ftb _ LOOPHOLE[bcd + bcd.ftOffset]; mth _ BcdOps.ProcessModules[bcd, p].mth; ans _ NEW[SectionObj _ [prog[moduleName: BcdNameToRope [bcd, mth.name], versionStamp: ftb[mth.file].version, someGFHTV: NIL ] ] ]; RTSymbolsPrivate.ReleaseBCD[bcd]; }; prog => RETURN[NEW[SectionObj _ [proc[prog: NARROW[section, REF prog SectionObj], entryPointIndex: 0]]]]; --ep# wizardry: StartProc. interface => RETURN[NIL]; proc => RETURN[NEW[SectionObj _ [statement[prog: s.prog, fgtIndex: ProcToFirstFGI [NARROW[section]]]]]]; statement => RETURN[NIL]; ENDCASE => ERROR }; -- end FirstChildSection -- parts: modules of a model, procs of a module, statements of a proc -- NextSiblingSection will never get a child that represents a loadstate entry -- for children that are progs, indexInParent # 0 means use it to pass over previous modules -- returns NIL if nomore NextSiblingSection: PROC[parent, child: Section, indexInParent: INT _ 0] RETURNS[ans: Section _ NIL, newIndexInParent: INT _ 0] = {IF parent = NIL THEN RETURN[NIL]; WITH s: child SELECT FROM model => ERROR AMTypes.Error[reason: notImplemented]; prog => { lastWasOldChild: BOOL _ FALSE; ftb: Table.Base _ NIL; FindNextModule: PROC[mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [stop: BOOL _ FALSE] = { newIndexInParent _ newIndexInParent + 1; IF lastWasOldChild THEN RETURN[TRUE]; IF (indexInParent = 0 OR newIndexInParent >= indexInParent) AND s.versionStamp = ftb[mth.file].version THEN lastWasOldChild _ TRUE; }; IF s.someGFHTV # NIL THEN -- the sections are loaded { world: World = GetWorld[s.someGFHTV]; IF world = LocalWorld[] THEN {gfh: GlobalFrameHandle _ NIL; bcd: BcdDefs.BcdBase; mth: BcdDefs.MTHandle; LoadState.local.Acquire[]; { ENABLE UNWIND => LoadState.local.Release[]; config: LoadState.ConfigID = LoadState.local.GlobalFrameToModule [GFHFromTV[s.someGFHTV]].config; bcd _ LoadState.local.ConfigInfo[config].bcd; ftb _ LOOPHOLE[bcd + bcd.ftOffset]; mth _ BcdOps.ProcessModules[bcd, FindNextModule].mth; IF mth # NIL THEN gfh _ LoadState.local.ModuleToGlobalFrame[config, mth.gfi]; }; -- ENABLE UNWIND => LoadState.local.Release[]; LoadState.local.Release[]; IF gfh # NIL THEN ans _ NEW [SectionObj _ [prog[moduleName: BcdNameToRope[bcd, mth.name], versionStamp: ftb[mth.file].version, someGFHTV: NARROW[TVForGFHReferent[gfh]] ] ] ]; } ELSE -- NextSiblingSection, prog child, the sections are loaded, remote world { Lock[world]; { ENABLE UNWIND => Unlock[world]; v: BcdDefs.VersionStamp; moduleName: ROPE; rgfh: RemoteGlobalFrameHandle _ nilRemoteGlobalFrameHandle; h: LoadState.Handle = WorldVM.Loadstate[world]; h.Acquire[]; { ENABLE UNWIND => h.Release[]; config: LoadState.ConfigID = h.GlobalFrameToModule [LOOPHOLE[RemoteGFHFromTV[s.someGFHTV].gfh]].config; bcd: BcdDefs.BcdBase = GetRemoteBCD[RemoteGFHFromTV[s.someGFHTV]]; IF bcd = NIL THEN ERROR; ftb _ LOOPHOLE[bcd + bcd.ftOffset]; { ENABLE UNWIND => ReleaseRemoteBCD[bcd]; mth: BcdDefs.MTHandle = BcdOps.ProcessModules[bcd, FindNextModule].mth; IF mth # NIL THEN {gfh: GlobalFrameHandle = h.ModuleToGlobalFrame[config, mth.gfi]; v _ ftb[mth.file].version; moduleName _ BcdNameToRope[bcd, mth.name]; rgfh _ [world, CurrentIncarnation[world], LOOPHOLE[gfh]]}; }; -- ENABLE UNWIND => ReleaseRemoteBCD[bcd]; ReleaseRemoteBCD[bcd]; }; -- ENABLE UNWIND => h.Release[]; h.Release[]; IF rgfh # nilRemoteGlobalFrameHandle THEN ans _ NEW [SectionObj _ [prog[moduleName: moduleName, versionStamp: v, someGFHTV: NARROW[TVForRemoteGFHReferent[rgfh]] ] ] ]; }; -- ENABLE UNWIND => Unlock[world]; }; -- end ELSE } -- end case where the sections are loaded ELSE -- NextSiblingSection, prog child, not loaded { -- get the binder output bcd, given the config name and version stamp p: REF model SectionObj = NARROW[parent]; mth: BcdDefs.MTHandle; bcd: BcdDefs.BcdBase _ RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: p.versionStamp, shortFileNameHint: Rope.Concat[p.configName, ".bcd"]]; IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols]; { ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]; ftb _ LOOPHOLE[bcd + bcd.ftOffset]; mth _ BcdOps.ProcessModules[bcd, FindNextModule].mth; IF mth # NIL THEN ans _ NEW[SectionObj _ [prog[moduleName: BcdNameToRope[bcd, mth.name], versionStamp: ftb[mth.file].version, someGFHTV: NIL -- not loaded ] ] ]; }; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]; RTSymbolsPrivate.ReleaseBCD[bcd]; }}; -- end prog child case of NextSiblingSection interface => ERROR AMTypes.Error[reason: notImplemented]; proc => {sth: SymbolTableHandle = GetSTHForModule [stamp: s.prog.versionStamp, fileName: Rope.Concat[s.prog.moduleName, ".bcd"], moduleName: s.prog.moduleName]; stb: SymbolTableBase _ AcquireSTB[sth]; maxEI: EPI _ 0; GetMaxX: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOL _ FALSE] = { WITH NARROW[stb, SymbolTableBase.x].e.bb[bti] SELECT FROM Callable => IF ~inline THEN maxEI _ MAX[maxEI, entryIndex]; ENDCASE}; GetMaxY: PROC [bti: by.BodyIndex] RETURNS [stop: BOOL _ FALSE] = { WITH NARROW[stb, SymbolTableBase.y].e.bb[bti] SELECT FROM Callable => IF ~inline THEN maxEI _ MAX[maxEI, entryIndex]; ENDCASE}; WITH stb SELECT FROM t: SymbolTableBase.x => [] _ t.e.EnumerateBodies[bx.rootBodyIndex, GetMaxX]; t: SymbolTableBase.y => [] _ t.e.EnumerateBodies[by.rootBodyIndex, GetMaxY]; ENDCASE => ERROR; IF s.entryPointIndex = maxEI THEN ans _ NIL ELSE ans _ NEW[SectionObj _ [proc[prog: NARROW[parent, REF prog SectionObj], entryPointIndex: s.entryPointIndex + 1]]]; ReleaseSTB[stb]}; -- end proc child case of NextSiblingSection statement => {nextFGI: FGIndex = NextStatementFGI[NARROW [child, REF statement SectionObj]]; IF nextFGI = FGNull THEN RETURN[NIL] ELSE RETURN[NEW[SectionObj _ [statement[prog: NARROW[parent, REF proc SectionObj].prog, fgtIndex: nextFGI ]]]]; }; -- end statement child case of NextSiblingSection ENDCASE => ERROR }; -- end NextSiblingSection -- Implemented only for proc sections SectionType: PUBLIC PROC[section: Section] RETURNS[--procedure--type: SafeStorage.Type] = {WITH s: section SELECT FROM model => ERROR AMTypes.Error[reason: notImplemented]; prog => ERROR AMTypes.Error[reason: notImplemented]; interface => RETURN[AcquireIRType[defsName: s.moduleName, version: s.versionStamp]]; proc => IF s.procTV = NIL THEN {sth: SymbolTableHandle = GetSTHForModule [stamp: s.prog.versionStamp, fileName: Rope.Concat[s.prog.moduleName, ".bcd"], moduleName: s.prog.moduleName]; stb: SymbolTableBase _ AcquireSTB[sth]; FindProcX: PROC[bti: bx.BodyIndex] RETURNS[stop: BOOLEAN _ FALSE] = {WITH b: NARROW[stb, SymbolTableBase.x].e.bb[bti] SELECT FROM Callable => IF ~b.inline AND b.entryIndex = s.entryPointIndex THEN {type _ AcquireType[stb, [x[b.ioType]]]; RETURN[TRUE]}; ENDCASE}; FindProcY: PROC[bti: by.BodyIndex] RETURNS[stop: BOOLEAN _ FALSE] = {WITH b: NARROW[stb, SymbolTableBase.y].e.bb[bti] SELECT FROM Callable => IF ~b.inline AND b.entryIndex = s.entryPointIndex THEN {type _ AcquireType[stb, [y[b.ioType]]]; RETURN[TRUE]}; ENDCASE}; WITH stb SELECT FROM t: SymbolTableBase.x => IF t.e.EnumerateBodies[bx.rootBodyIndex, FindProcX ! UNWIND => ReleaseSTB[stb]] = bx.nullBodyIndex THEN {ReleaseSTB[stb]; ERROR}; t: SymbolTableBase.y => IF t.e.EnumerateBodies[by.rootBodyIndex, FindProcY ! UNWIND => ReleaseSTB[stb]] = by.nullBodyIndex THEN {ReleaseSTB[stb]; ERROR}; ENDCASE => ERROR; ReleaseSTB[stb]; RETURN[type]} -- figure it out from the ep# and the prog section ELSE RETURN[TVType[s.procTV]]; statement => ERROR AMTypes.Error[reason: notImplemented]; ENDCASE => ERROR }; SectionVersion: PUBLIC PROC[section: Section] RETURNS[BcdDefs.VersionStamp] = {WITH s: section SELECT FROM model => RETURN[s.versionStamp]; prog => RETURN[s.versionStamp]; interface => RETURN[s.versionStamp]; proc => RETURN[s.prog.versionStamp]; statement => RETURN[s.prog.versionStamp]; ENDCASE => ERROR; }; -- Private Procedures BcdNameToRope: PROC[bcd: BcdDefs.BcdBase, n: BcdDefs.NameRecord] RETURNS[ROPE] = {ssb: BcdDefs.NameString = LOOPHOLE[bcd + bcd.ssOffset]; ssd: ConvertUnsafe.SubString _ [base: @ssb.string, offset: n, length: ssb.size[n]]; RETURN[ConvertUnsafe.SubStringToRope[ssd]]}; -- [prog module bcd, entryPointIndex] => CharIndex ProcToFirstCI: PROC[proc: REF proc SectionObj] RETURNS[ans: CharIndex _ 0] = {localBCD: BOOL _ FALSE; remoteBCD: BOOL _ FALSE; versionBCD: BOOL _ FALSE; bcd: BcdDefs.BcdBase; ptv: TV = proc.prog.someGFHTV; stb: SymbolTableBase; IF ptv = NIL -- proc not loaded THEN {bcd _ RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: proc.prog.versionStamp, shortFileNameHint: Rope.Concat[proc.prog.moduleName, ".bcd"]]; versionBCD _ TRUE} ELSE IF GetWorld[ptv] = LocalWorld[] THEN {bcd _ GetLocalBCD[GFHFromTV[ptv]]; localBCD _ TRUE} ELSE { bcd _ GetRemoteBCD[RemoteGFHFromTV[ptv]]; remoteBCD _ TRUE}; { ENABLE UNWIND => IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; stb _ GetModuleSTB[bcd, proc.prog.versionStamp]; }; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]; { ENABLE UNWIND => ReleaseSTB[stb]; IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; ans _ FGIToFirstChar[stb, EPIToFirstFGI[stb, proc.entryPointIndex, TRUE]]; }; -- end ENABLE UNWIND => ReleaseSTB[stb]; ReleaseSTB[stb]; }; -- [prog module bcd, entryPointIndex] => CharIndex ProcToLastCI: PROC[proc: REF proc SectionObj] RETURNS[ans: CharIndex _ 0] = {localBCD: BOOL _ FALSE; remoteBCD: BOOL _ FALSE; versionBCD: BOOL _ FALSE; bcd: BcdDefs.BcdBase; ptv: TV = proc.prog.someGFHTV; stb: SymbolTableBase; IF ptv = NIL -- proc not loaded THEN {bcd _ RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: proc.prog.versionStamp, shortFileNameHint: Rope.Concat[proc.prog.moduleName, ".bcd"]]; versionBCD _ TRUE} ELSE IF GetWorld[ptv] = LocalWorld[] THEN {bcd _ GetLocalBCD[GFHFromTV[ptv]]; localBCD _ TRUE} ELSE { bcd _ GetRemoteBCD[RemoteGFHFromTV[ptv]]; remoteBCD _ TRUE}; { ENABLE UNWIND => IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; stb _ GetModuleSTB[bcd, proc.prog.versionStamp]; }; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]; { ENABLE UNWIND => ReleaseSTB[stb]; IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; ans _ FGIToLastChar[stb, EPIToLastFGI[stb, proc.entryPointIndex]]; }; -- end ENABLE UNWIND => ReleaseSTB[stb]; ReleaseSTB[stb]; }; -- [prog module bcd, FGIndex] => CharIndex StatementToFirstCI: PROC[statement: REF statement SectionObj] RETURNS[ans: CharIndex _ 0] = {localBCD: BOOL _ FALSE; remoteBCD: BOOL _ FALSE; versionBCD: BOOL _ FALSE; bcd: BcdDefs.BcdBase; ptv: TV = statement.prog.someGFHTV; stb: SymbolTableBase; IF ptv = NIL -- statement not loaded THEN {bcd _ RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: statement.prog.versionStamp, shortFileNameHint: Rope.Concat[statement.prog.moduleName, ".bcd"]]; versionBCD _ TRUE} ELSE IF GetWorld[ptv] = LocalWorld[] THEN {bcd _ GetLocalBCD[GFHFromTV[ptv]]; localBCD _ TRUE} ELSE { bcd _ GetRemoteBCD[RemoteGFHFromTV[ptv]]; remoteBCD _ TRUE}; { ENABLE UNWIND => IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; stb _ GetModuleSTB[bcd, statement.prog.versionStamp]; }; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]; { ENABLE UNWIND => ReleaseSTB[stb]; IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; ans _ FGIToFirstChar[stb, statement.fgtIndex]; }; -- end ENABLE UNWIND => ReleaseSTB[stb]; ReleaseSTB[stb]; }; -- [prog module bcd, FGIndex] => CharIndex StatementToLastCI: PROC[statement: REF statement SectionObj] RETURNS[ans: CharIndex _ 0] = {localBCD: BOOL _ FALSE; remoteBCD: BOOL _ FALSE; versionBCD: BOOL _ FALSE; bcd: BcdDefs.BcdBase; ptv: TV = statement.prog.someGFHTV; stb: SymbolTableBase; IF ptv = NIL -- statement not loaded THEN {bcd _ RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: statement.prog.versionStamp, shortFileNameHint: Rope.Concat[statement.prog.moduleName, ".bcd"]]; versionBCD _ TRUE} ELSE IF GetWorld[ptv] = LocalWorld[] THEN {bcd _ GetLocalBCD[GFHFromTV[ptv]]; localBCD _ TRUE} ELSE { bcd _ GetRemoteBCD[RemoteGFHFromTV[ptv]]; remoteBCD _ TRUE}; { ENABLE UNWIND => IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; stb _ GetModuleSTB[bcd, statement.prog.versionStamp]; }; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]; { ENABLE UNWIND => ReleaseSTB[stb]; IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; ans _ FGIToLastChar[stb, statement.fgtIndex]; }; -- end ENABLE UNWIND => ReleaseSTB[stb]; ReleaseSTB[stb]; }; -- [prog module bcd, FGIndex] => entryPointIndex (maybe 0) StatementToParentEPI: PROC[statement: REF statement SectionObj] RETURNS[ans: EPI _ 0] = {localBCD: BOOL _ FALSE; remoteBCD: BOOL _ FALSE; versionBCD: BOOL _ FALSE; bcd: BcdDefs.BcdBase; ptv: TV = statement.prog.someGFHTV; stb: SymbolTableBase; IF ptv = NIL -- statement not loaded THEN {bcd _ RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: statement.prog.versionStamp, shortFileNameHint: Rope.Concat[statement.prog.moduleName, ".bcd"]]; versionBCD _ TRUE} ELSE IF GetWorld[ptv] = LocalWorld[] THEN {bcd _ GetLocalBCD[GFHFromTV[ptv]]; localBCD _ TRUE} ELSE { bcd _ GetRemoteBCD[RemoteGFHFromTV[ptv]]; remoteBCD _ TRUE}; { ENABLE UNWIND => IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; stb _ GetModuleSTB[bcd, statement.prog.versionStamp]; }; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]; { ENABLE UNWIND => ReleaseSTB[stb]; IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; ans _ FGIToEPI[stb, statement.fgtIndex]; }; -- end ENABLE UNWIND => ReleaseSTB[stb]; ReleaseSTB[stb]; }; -- [prog module bcd, entryPointIndex] => FGIndex ProcToFirstFGI: PROC[proc: REF proc SectionObj] RETURNS[ans: FGIndex _ FGNull] = {localBCD: BOOL _ FALSE; remoteBCD: BOOL _ FALSE; versionBCD: BOOL _ FALSE; bcd: BcdDefs.BcdBase; ptv: TV = proc.prog.someGFHTV; stb: SymbolTableBase; IF ptv = NIL -- proc not loaded THEN {bcd _ RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: proc.prog.versionStamp, shortFileNameHint: Rope.Concat[proc.prog.moduleName, ".bcd"]]; versionBCD _ TRUE} ELSE IF GetWorld[ptv] = LocalWorld[] THEN {bcd _ GetLocalBCD[GFHFromTV[ptv]]; localBCD _ TRUE} ELSE { bcd _ GetRemoteBCD[RemoteGFHFromTV[ptv]]; remoteBCD _ TRUE}; { ENABLE UNWIND => IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; stb _ GetModuleSTB[bcd, proc.prog.versionStamp]; }; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]; { ENABLE UNWIND => ReleaseSTB[stb]; IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; ans _ EPIToFirstFGI[stb, proc.entryPointIndex, TRUE]; }; -- end ENABLE UNWIND => ReleaseSTB[stb]; ReleaseSTB[stb]; }; -- [prog module bcd, FGIndex, entryPointIndex] => FGIndex -- (or FGNull if in a different proc than entryPointIndex) NextStatementFGI: PROC[statement: REF statement SectionObj] RETURNS[ans: FGIndex _ FGNull] = {localBCD: BOOL _ FALSE; remoteBCD: BOOL _ FALSE; versionBCD: BOOL _ FALSE; bcd: BcdDefs.BcdBase; ptv: TV = statement.prog.someGFHTV; stb: SymbolTableBase; IF ptv = NIL -- statement not loaded THEN {bcd _ RTSymbolsPrivate.AcquireBCDFromVersion [versionStamp: statement.prog.versionStamp, shortFileNameHint: Rope.Concat[statement.prog.moduleName, ".bcd"]]; versionBCD _ TRUE} ELSE IF GetWorld[ptv] = LocalWorld[] THEN {bcd _ GetLocalBCD[GFHFromTV[ptv]]; localBCD _ TRUE} ELSE { bcd _ GetRemoteBCD[RemoteGFHFromTV[ptv]]; remoteBCD _ TRUE}; { ENABLE UNWIND => IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; stb _ GetModuleSTB[bcd, statement.prog.versionStamp]; }; -- end ENABLE UNWIND => RTSymbolsPrivate.ReleaseBCD[bcd]; { ENABLE UNWIND => ReleaseSTB[stb]; IF versionBCD THEN RTSymbolsPrivate.ReleaseBCD[bcd] ELSE IF remoteBCD THEN ReleaseRemoteBCD[bcd]; ans _ NextFGI[stb, statement.fgtIndex, StatementToParentEPI[statement]]; }; -- end ENABLE UNWIND => ReleaseSTB[stb]; ReleaseSTB[stb]; }; }.