AMModelSectionImpl.mesa
Copyright © 1985 by Xerox Corporation. All rights reserved.
Rovner, August 10, 1983 12:45 pm
Russ Atkinson (RRA) February 12, 1985 1:36:00 am PST
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: ROPENIL] = {
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: BOOLEANFALSE] = {
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: BOOLEANFALSE] = {
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
};
SectionSource: PUBLIC PROC [section: Section] RETURNS [ans: Source] = {
param to creator of section.
WITH s: section SELECT FROM
model => {
name: ROPENIL;
version: BcdDefs.VersionStamp;
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[];
name ← BcdNameToRope[bcd, bcd.source];
version ← bcd.sourceVersion;
}
ELSE {
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];
name ← BcdNameToRope[bcd, bcd.source];
version ← bcd.sourceVersion;
}; -- end ENABLE UNWIND => ReleaseRemoteBCD[bcd];
ReleaseRemoteBCD[bcd];
}; -- end ENABLE UNWIND => h.Release[];
h.Release[];
}; -- end ENABLE UNWIND => Unlock[world];
Unlock[world];
}
}
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];
name ← BcdNameToRope[bcd, bcd.source];
version ← bcd.sourceVersion;
RTSymbolsPrivate.ReleaseBCD[bcd];
};
ans ← NEW[SourceObj ← [fileName: name, class: model, versionStamp: version, sourceRange: entire[]]];
};
prog => {
get the compiler output bcd, given the module name and its version stamp. Could poke around in the loadstate, but painful.
name: ROPENIL;
version: BcdDefs.VersionStamp;
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];
name ← BcdNameToRope[bcd, bcd.source];
version ← bcd.sourceVersion;
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];
name ← STB2Source[stb];
version ← STBSourceVersion[stb];
}; -- 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];
name ← STB2Source[stb];
version ← STBSourceVersion[stb];
}; -- end ENABLE UNWIND => ReleaseSTB[stb]
ReleaseSTB[stb];
}; -- end ENABLE UNWIND => ... FREE[@bcd];
ReleaseRemoteBCD[bcd];
}
};
ans ← NEW[SourceObj ← [fileName: name, class: prog, versionStamp: version, sourceRange: entire[]]];
};
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 => {
nSect: REF proc SectionObj ← NARROW[section];
fci: INT;
lci: INT;
name: ROPENIL;
version: BcdDefs.VersionStamp;
[firstCI: fci, lastCI: lci] ← ProcToInfo[nSect];
IF s.prog.someGFHTV = NIL
THEN {
bcd: BcdDefs.BcdBase = RTSymbolsPrivate.AcquireBCDFromVersion [
versionStamp: s.prog.versionStamp,
shortFileNameHint: Rope.Concat[s.prog.moduleName, ".bcd"]];
unloaded proc section
IF bcd = NIL THEN ERROR AMTypes.Error[reason: noSymbols];
name ← BcdNameToRope[bcd, bcd.source];
version ← bcd.sourceVersion;
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];
name ← STB2Source[stb];
version ← STBSourceVersion[stb];
}; -- end ENABLE UNWIND => ReleaseSTB[stb]
ReleaseSTB[stb];
}
ELSE {
bcd: BcdDefs.BcdBase ← GetRemoteBCD[RemoteGFHFromTV[ptv]];
remote world
{ ENABLE UNWIND => ReleaseRemoteBCD[bcd];
stb: SymbolTableBase ← GetModuleSTB[bcd, s.prog.versionStamp];
{ ENABLE UNWIND => ReleaseSTB[stb];
name ← STB2Source[stb];
version ← STBSourceVersion[stb];
}; -- end ENABLE UNWIND => ReleaseSTB[stb]
ReleaseSTB[stb];
}; -- end ENABLE UNWIND => ... FREE[@bcd];
ReleaseRemoteBCD[bcd];
}
};
ans ← NEW[SourceObj ← [fileName: name, class: proc, versionStamp: version, sourceRange: field[firstCharIndex: fci, lastCharIndex: lci]]];
};
statement => {
nSect: REF statement SectionObj ← NARROW[section];
fci: INT;
lci: INT;
name: ROPENIL;
version: BcdDefs.VersionStamp;
[firstCI: fci, lastCI: fci] ← StatementToInfo[nSect];
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];
name ← BcdNameToRope[bcd, bcd.source];
version ← bcd.sourceVersion;
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];
name ← STB2Source[stb];
version ← STBSourceVersion[stb];
}; -- 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];
name ← STB2Source[stb];
version ← STBSourceVersion[stb];
}; -- end ENABLE UNWIND => ReleaseSTB[stb]
ReleaseSTB[stb];
}; -- end ENABLE UNWIND => ... FREE[@bcd];
ReleaseRemoteBCD[bcd];
}
};
ans ← NEW[SourceObj ← [fileName: name, class: statement, versionStamp: version, sourceRange: field[firstCharIndex: fci, lastCharIndex: lci]]];
};
ENDCASE => ERROR
};
SectionParams: PUBLIC PROC [section: Section] RETURNS [list: LIST OF SafeStorage.Type ← NIL] = {
param to creator of section.
(DIRECTORY entries)
Implemented only for model, prog and interface sections
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
};
ParentSection: PUBLIC PROC [section: Section] RETURNS [Section] = {
containers:
prog module for a proc
proc for a statement
WITH s: section SELECT FROM
proc => RETURN[s.prog];
statement => RETURN[NEW[SectionObj ← [proc[prog: s.prog,
entryPointIndex: StatementToInfo[NARROW[section]].epi ]]]];
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: ProcToInfo [NARROW[section]].fgi]]]];
statement => RETURN[NIL];
ENDCASE => ERROR
}; -- end FirstChildSection
NextSiblingSection: PROC [parent, child: Section, indexInParent: INT ← 0] RETURNS [ans: Section ← NIL, newIndexInParent: INT ← 0] = {
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
IF parent = NIL THEN RETURN[NIL];
WITH s: child SELECT FROM
model => ERROR AMTypes.Error[reason: notImplemented];
prog => {
lastWasOldChild: BOOLFALSE;
ftb: Table.Base ← NIL;
FindNextModule: PROC [mth: BcdDefs.MTHandle, mti: BcdDefs.MTIndex] RETURNS [stop: BOOLFALSE] = {
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]]];
}; -- 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: BOOLFALSE] = {
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: BOOLFALSE] = {
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 = StatementToInfo[NARROW[child, REF statement SectionObj]].nextFgi;
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
SectionType: PUBLIC PROC [section: Section] RETURNS [type: SafeStorage.Type] = {
Implemented only for proc sections
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: BOOLEANFALSE] = {
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: BOOLEANFALSE] = {
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 utilities
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]]};
ProcToInfo: PROC [proc: REF proc SectionObj] RETURNS [fgi: FGIndex ← FGNull, firstCI, lastCI: INT ← 0] = {
[prog module bcd, entryPointIndex] => FGIndex
localBCD: BOOLFALSE;
remoteBCD: BOOLFALSE;
versionBCD: BOOLFALSE;
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];
fgi ← EPIToFirstFGI[stb, proc.entryPointIndex, TRUE];
firstCI ← FGIToFirstChar[stb, EPIToFirstFGI[stb, proc.entryPointIndex, TRUE]];
lastCI ← FGIToLastChar[stb, EPIToLastFGI[stb, proc.entryPointIndex]];
IF lastCI = firstCI THEN lastCI ← lastCI - 1;
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};
StatementToInfo: PROC [statement: REF statement SectionObj] RETURNS [epi: EPI ← 0, fgi: FGIndex ← FGNull, nextFgi: FGIndex ← FGNull, firstCI: INT ← 0, lastCI: INT ← 0] = {
[prog module bcd, FGIndex] => entryPointIndex (maybe 0)
localBCD: BOOLFALSE;
remoteBCD: BOOLFALSE;
versionBCD: BOOLFALSE;
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];
fgi ← statement.fgtIndex;
epi ← FGIToEPI[stb, fgi];
nextFgi ← NextFGI[stb, fgi, epi];
firstCI ← FGIToFirstChar[stb, statement.fgtIndex];
lastCI ← FGIToLastChar[stb, statement.fgtIndex];
IF lastCI = firstCI THEN lastCI ← lastCI - 1;
}; -- end ENABLE UNWIND => ReleaseSTB[stb];
ReleaseSTB[stb];
};
STB2Source: PROC [stb: SymbolTableBase] RETURNS [nr: ROPE] = {
RETURN [ConvertUnsafe.ToRope[
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
]];
};
}.