-- AMModelBridgeImpl.Mesa
-- last modified on March 29, 1983 3:57 pm by Paul Rovner

DIRECTORY
AMBridge USING[
IsRemote, TVToRemoteProc, TVToProc, GetWorld, GetWorldIncarnation,
RemoteGFHFromTV, RemoteGlobalFrameHandle,
TVForRemoteProc, TVForProc, GFHFromTV],
AMModel USING[Context, Section, ContextSection],
AMModelBridge USING[LoadedSection, ContextForFrame, FrameFromContext],
AMModelPrivate USING[SectionRec, ProgPCToFGI, z],
AMTypes USING[GlobalParent],
PrincOps USING[BytePC, ControlLink, EPRange, GlobalFrameHandle, ProcDesc],
RTBasic USING[TV],
RTTypesPrivate USING[GetPc, UnwindIndirectProcDesc],
RTTypesRemotePrivate USING[
GetRemotePc, UnwindRemoteIndirectProcDesc, GetRemoteGFHeader];

AMModelBridgeImpl: PROGRAM
IMPORTS AMBridge, AMModel, AMModelBridge, AMModelPrivate, AMTypes,
RTTypesPrivate, RTTypesRemotePrivate
EXPORTS AMModel, AMModelBridge

= BEGIN OPEN AMModel, AMModelBridge, AMModelPrivate, PrincOps,
RTBasic, RTTypesPrivate, RTTypesRemotePrivate;

-- 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;

LoadedSection: TYPE = AMModelBridge.LoadedSection;
-- A LoadedSection is a convenience for clients of AMModelBridge. Each represents one of:
-- loaded compiler output bundle for a prog module [prog, prog]
-- loaded compiler output bundle for a proc [proc, prog]
-- loaded compiler output bundle for a statement [statement, prog]

LoadedSectionForProc: PUBLIC PROC[tv: TV--proc--]
RETURNS[ans: LoadedSection ← [NIL, NIL, [0]]] =
{ c: Context;
s: Section;
ep: CARDINAL;
gf: TV ← AMTypes.GlobalParent[tv];
ans.context ← AMModelBridge.ContextForFrame[gf];
c ← ans.context;
s ← ContextSection[c];
IF AMBridge.IsRemote[tv]
THEN {
gfh: AMBridge.RemoteGlobalFrameHandle ← AMBridge.RemoteGFHFromTV[gf];
ep ← LOOPHOLE[
RTTypesRemotePrivate.UnwindRemoteIndirectProcDesc
[AMBridge.TVToRemoteProc[tv]].pd,
ControlLink].ep;
ans.pc ← RTTypesRemotePrivate.GetRemotePc[gfh, ep];
}
ELSE {
gfh: PrincOps.GlobalFrameHandle ← AMBridge.GFHFromTV[gf];
ep ← RTTypesPrivate.UnwindIndirectProcDesc
[LOOPHOLE[AMBridge.TVToProc[tv], ControlLink]].ep;
ans.pc ← RTTypesPrivate.GetPc[gfh, ep];
};
ans.section ← z.NEW[SectionObj
← [proc[prog: NARROW[s],
entryPointIndex: ep,
procTV: NARROW[tv]]]];
};

ProcFromLoadedSection: PUBLIC PROC[proc: LoadedSection] RETURNS[TV--proc--] =
{s: Section = proc.section;
sr: REF proc SectionObj ← NARROW[s];
IF sr.procTV # NIL
THEN RETURN[sr.procTV]
ELSE {IF AMBridge.IsRemote[FrameFromContext[proc.context]]
THEN
{pd: PrincOps.ProcDesc ← PrincOps.ControlLink[procedure[gfi: 0, ep: 0, tag: TRUE]];
pd.gfi ← GetRemoteGFHeader
[AMBridge.RemoteGFHFromTV[FrameFromContext[proc.context]]].gfi
+ sr.entryPointIndex/PrincOps.EPRange;
pd.ep ← sr.entryPointIndex MOD PrincOps.EPRange;
RETURN[AMBridge.TVForRemoteProc
[[world: AMBridge.GetWorld[FrameFromContext[proc.context]],
worldIncarnation:
AMBridge.GetWorldIncarnation
[FrameFromContext[proc.context]],
pd: pd]]]}
ELSE
{pd: PrincOps.ProcDesc ← PrincOps.ControlLink[procedure[gfi: 0, ep: 0, tag: TRUE]];
pd.gfi ← AMBridge.GFHFromTV[FrameFromContext[proc.context]].gfi
+ sr.entryPointIndex/PrincOps.EPRange;
pd.ep ← sr.entryPointIndex MOD PrincOps.EPRange;
RETURN[AMBridge.TVForProc[LOOPHOLE[pd]]]}
};
};

LoadedSectionForProgPC: PUBLIC PROC[prog: Context, pc: BytePC]
RETURNS[ans: LoadedSection ← [NIL, NIL, [0]]] =
{ s: Section = ContextSection[prog];
ans.context ← prog;
ans.section ← z.NEW[SectionObj
← [statement
[prog: NARROW[s],
fgtIndex: ProgPCToFGI[FrameFromContext[prog], pc]]]];
ans.pc ← pc;
};

END.