AMModelPrivateImpl.Mesa
Russ Atkinson, April 8, 1983 2:25 pm
Paul Rovner, November 29, 1983 7:25 pm
DIRECTORY
AMModel USING [CharIndex],
AMModelPrivate USING [EPI, FGIndex, FGNull, NullPCOffset, PCOffset],
BrandXSymbolDefs USING [
SymbolTableBase, BodyTableEntry, FineGrainTableEntry, rootBodyIndex, BodyIndex, nullBodyIndex],
BrandYSymbolDefs USING [
SymbolTableBase, BodyTableEntry, FineGrainTableEntry, rootBodyIndex, BodyIndex, nullBodyIndex],
RTSymbolDefs USING [SymbolTableBase];
AMModelPrivateImpl: PROGRAM
EXPORTS AMModelPrivate
= BEGIN OPEN
AMModel, AMModelPrivate, bx: BrandXSymbolDefs, by: BrandYSymbolDefs, RTSymbolDefs;
local type definitions
XBodyPtr: TYPE = LONG POINTER TO bx.BodyTableEntry;
YBodyPtr: TYPE = LONG POINTER TO by.BodyTableEntry;
EPIndex: TYPE = AMModelPrivate.EPI;
FGCard: TYPE = CARDINAL;
XFGPtr: TYPE = LONG POINTER TO bx.FineGrainTableEntry;
YFGPtr: TYPE = LONG POINTER TO by.FineGrainTableEntry;
kludge for the missing FGI
fudge: INT ← 8; -- number of characters to assume beyond the last fgi in a procedure
procedures exported to AMModelPrivate
FGIToEPI: PUBLIC PROC
[stb: SymbolTableBase, fgi: FGIndex] RETURNS [EPIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[FGIToEPIX[t.e, fgi]];
t: SymbolTableBase.y => RETURN[FGIToEPIY[t.e, fgi]];
ENDCASE => ERROR};
FGIToEPIX: PROC
[stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [epi: EPIndex ← 0] = {
returns first fine grain index for the given procedure
(0 for start proc OR invalid fgi)
bti: bx.BodyIndex;
IF fgi = FGNull THEN RETURN;
bti ← FGItoBTIX[stb, fgi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH ext: body^ SELECT FROM
Callable => epi ← ext.entryIndex;
ENDCASE => RETURN;
};
};
FGIToEPIY: PROC
[stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [epi: EPIndex ← 0] = {
returns first fine grain index for the given procedure
(0 for start proc OR invalid fgi)
bti: by.BodyIndex;
IF fgi = FGNull THEN RETURN;
bti ← FGItoBTIY[stb, fgi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH ext: body^ SELECT FROM
Callable => epi ← ext.entryIndex;
ENDCASE => RETURN;
};
};
EPIToFirstFGI: PUBLIC PROC
[stb: SymbolTableBase, epi: EPIndex, skipArgs: BOOL] RETURNS [FGIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[EPIToFirstFGIX[t.e, epi, skipArgs]];
t: SymbolTableBase.y => RETURN[EPIToFirstFGIY[t.e, epi, skipArgs]];
ENDCASE => ERROR};
EPIToFirstFGIX: PROC
[stb: bx.SymbolTableBase, epi: EPIndex, skipArgs: BOOL]
RETURNS [fgi: FGIndex ← FGNull] = {
returns first fine grain index for the given procedure (FGNull for invalid epi)
bti: bx.BodyIndex ← EPItoBTIX[stb, epi];
IF bti = bx.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External => fgi ← [fgCard: info.startIndex, fudge: FALSE];
ENDCASE;
IF skipArgs AND fgi # FGNull THEN {
pc: PCOffset ← FGIToFirstPC[[x[stb]], fgi];
DO
nfgi: FGIndex ← NextFGIX[stb, fgi, epi];
npc: PCOffset;
IF nfgi = FGNull THEN RETURN [fgi];
npc ← FGIToFirstPCX[stb, nfgi];
IF npc # pc THEN RETURN [nfgi];
fgi ← nfgi;
ENDLOOP};
};
EPIToFirstFGIY: PROC
[stb: by.SymbolTableBase, epi: EPIndex, skipArgs: BOOL]
RETURNS [fgi: FGIndex ← FGNull] = {
returns first fine grain index for the given procedure (FGNull for invalid epi)
bti: by.BodyIndex ← EPItoBTIY[stb, epi];
IF bti = by.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External => fgi ← [fgCard: info.startIndex, fudge: FALSE];
ENDCASE;
IF skipArgs AND fgi # FGNull THEN {
pc: PCOffset ← FGIToFirstPC[[y[stb]], fgi];
DO
nfgi: FGIndex ← NextFGIY[stb, fgi, epi];
npc: PCOffset;
IF nfgi = FGNull THEN RETURN [fgi];
npc ← FGIToFirstPCY[stb, nfgi];
IF npc # pc THEN RETURN [nfgi];
fgi ← nfgi;
ENDLOOP};
};
EPIToLastFGI: PUBLIC PROC
[stb: SymbolTableBase, epi: EPIndex] RETURNS [FGIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[EPIToLastFGIX[t.e, epi]];
t: SymbolTableBase.y => RETURN[EPIToLastFGIY[t.e, epi]];
ENDCASE => ERROR};
EPIToLastFGIX: PROC
[stb: bx.SymbolTableBase, epi: EPIndex]
RETURNS [fgi: FGIndex ← FGNull] = {
returns last fine grain index for the given procedure
(FGNull for invalid epi)
bti: bx.BodyIndex ← EPItoBTIX[stb, epi];
IF bti = bx.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External =>
fgi ← [fgCard: info.startIndex + MAX[info.indexLength, 1] - 1, fudge: TRUE];
ENDCASE;
};
EPIToLastFGIY: PROC
[stb: by.SymbolTableBase, epi: EPIndex]
RETURNS [fgi: FGIndex ← FGNull] = {
returns last fine grain index for the given procedure
(FGNull for invalid epi)
bti: by.BodyIndex ← EPItoBTIY[stb, epi];
IF bti = by.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External =>
fgi ← [fgCard: info.startIndex + MAX[info.indexLength, 1] - 1, fudge: TRUE];
ENDCASE;
};
EPIToFirstPC: PUBLIC PROC
[stb: SymbolTableBase, epi: EPIndex, skipArgs: BOOL]
RETURNS [pc: PCOffset ← NullPCOffset] = {
fgi: FGIndex ← EPIToFirstFGI[stb, epi, skipArgs];
IF fgi = FGNull THEN RETURN;
pc ← FGIToFirstPC[stb, fgi];
};
EPIToLastPC: PUBLIC PROC
[stb: SymbolTableBase, epi: EPIndex] RETURNS [PCOffset] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[EPIToLastPCX[t.e, epi]];
t: SymbolTableBase.y => RETURN[EPIToLastPCY[t.e, epi]];
ENDCASE => ERROR};
EPIToLastPCX: PROC
[stb: bx.SymbolTableBase, epi: EPIndex]
RETURNS [pc: PCOffset ← NullPCOffset] = {
returns offset of last byte in the procedure (may be padding byte)
bti: bx.BodyIndex ← EPItoBTIX[stb, epi];
IF bti = bx.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External => {pc ← info.bytes; pc ← pc - 1};
ENDCASE;
};
EPIToLastPCY: PROC
[stb: by.SymbolTableBase, epi: EPIndex]
RETURNS [pc: PCOffset ← NullPCOffset] = {
returns offset of last byte in the procedure (may be padding byte)
bti: by.BodyIndex ← EPItoBTIY[stb, epi];
IF bti = by.nullBodyIndex THEN RETURN;
WITH info: stb.bb[bti].info SELECT FROM
External => {pc ← info.bytes; pc ← pc - 1};
ENDCASE;
};
CharIndexToFGI: PUBLIC PROC
[stb: SymbolTableBase, ci: CharIndex] RETURNS [FGIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[CharIndexToFGIX[t.e, ci]];
t: SymbolTableBase.y => RETURN[CharIndexToFGIY[t.e, ci]];
ENDCASE => ERROR};
CharIndexToFGIX: PROC
[stb: bx.SymbolTableBase, ci: CharIndex] RETURNS [fgi: FGIndex ← FGNull] = {
returns the "best" fine grain index for the given character position
(FGNull for invalid position)
bti: bx.BodyIndex ← bx.nullBodyIndex;
bti ← CItoBTIX[stb, ci];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
thisCI: CharIndex ← body.sourceIndex;
fgi ← [fgCard: firstFGI, fudge: FALSE];
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
nextCI: CharIndex ← thisCI;
fgi.fgCard ← tfgi;
we try not to stop at a source step, because source steps usually come
just before the pc step for the statement (sigh)
WITH fp^ SELECT FROM
normal =>
nextCI ← nextCI + deltaSource;
step =>
IF which = source THEN {
thisCI ← nextCI + delta;
LOOP};
ENDCASE;
IF nextCI > ci THEN RETURN;
thisCI ← nextCI;
ENDLOOP;
fgi.fudge ← TRUE;
};
ENDCASE;
};
};
CharIndexToFGIY: PROC
[stb: by.SymbolTableBase, ci: CharIndex] RETURNS [fgi: FGIndex ← FGNull] = {
returns the "best" fine grain index for the given character position
(FGNull for invalid position)
bti: by.BodyIndex ← by.nullBodyIndex;
bti ← CItoBTIY[stb, ci];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
thisCI: CharIndex ← body.sourceIndex;
fgi ← [fgCard: firstFGI, fudge: FALSE];
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
nextCI: CharIndex ← thisCI;
fgi.fgCard ← tfgi;
we try not to stop at a source step, because source steps usually come
just before the pc step for the statement (sigh)
WITH fp^ SELECT FROM
normal =>
nextCI ← nextCI + deltaSource;
step =>
IF which = source THEN {
thisCI ← nextCI + delta;
LOOP};
ENDCASE;
IF nextCI > ci THEN RETURN;
thisCI ← nextCI;
ENDLOOP;
fgi.fudge ← TRUE;
};
ENDCASE;
};
};
PCToFGI: PUBLIC PROC
[stb: SymbolTableBase, epi: EPIndex, pc: PCOffset] RETURNS [FGIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[PCToFGIX[t.e, epi, pc]];
t: SymbolTableBase.y => RETURN[PCToFGIY[t.e, epi, pc]];
ENDCASE => ERROR};
PCToFGIX: PROC
[stb: bx.SymbolTableBase, epi: EPIndex, pc: PCOffset]
RETURNS [fgi: FGIndex ← FGNull] = {
returns the "best" fine grain index for the given pc offset in the given procedure
(FGNull for invalid epi or invalid pc)
bti: bx.BodyIndex ← EPItoBTIX[stb, epi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
rem: INT ← pc;
IF pc >= info.bytes THEN RETURN [FGNull];
fgi ← [fgCard: firstFGI, fudge: FALSE];
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
fgi.fgCard ← tfgi;
IF rem = 0 THEN RETURN;
WITH fp^ SELECT FROM
normal => rem ← rem - deltaObject;
step => IF which = object THEN rem ← rem - delta;
ENDCASE;
IF rem < 0 THEN RETURN;
ENDLOOP;
fgi.fudge ← TRUE;
};
ENDCASE;
};
};
PCToFGIY: PROC
[stb: by.SymbolTableBase, epi: EPIndex, pc: PCOffset]
RETURNS [fgi: FGIndex ← FGNull] = {
returns the "best" fine grain index for the given pc offset in the given procedure
(FGNull for invalid epi or invalid pc)
bti: by.BodyIndex ← EPItoBTIY[stb, epi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
rem: INT ← pc;
IF pc >= info.bytes THEN RETURN [FGNull];
fgi ← [fgCard: firstFGI, fudge: FALSE];
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
fgi.fgCard ← tfgi;
IF rem = 0 THEN RETURN;
WITH fp^ SELECT FROM
normal => rem ← rem - deltaObject;
step => IF which = object THEN rem ← rem - delta;
ENDCASE;
IF rem < 0 THEN RETURN;
ENDLOOP;
fgi.fudge ← TRUE;
};
ENDCASE;
};
};
NextFGI: PUBLIC PROC
[stb: SymbolTableBase, fgi: FGIndex, epi: EPIndex] RETURNS [FGIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[NextFGIX[t.e, fgi, epi]];
t: SymbolTableBase.y => RETURN[NextFGIY[t.e, fgi, epi]];
ENDCASE => ERROR};
NextFGIX: PROC
[stb: bx.SymbolTableBase, fgi: FGIndex, epi: EPIndex]
RETURNS [nfgi: FGIndex ← FGNull] = {
takes a FGIndex & entry point, returns the next FGIndex
returns FGNull if next fgi is in a different proc than entryPointIndex
OR the given FGIndex or entry point was not valid
bti: bx.BodyIndex;
IF fgi = FGNull THEN RETURN;
bti ← EPItoBTIX[stb, epi];
IF bti # bx.nullBodyIndex THEN
WITH info: stb.bb[bti].info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
IF fgi.fudge OR fgi.fgCard NOT IN [firstFGI..lastFGI] THEN RETURN;
IF fgi.fgCard = lastFGI
THEN fgi.fudge ← TRUE
ELSE fgi.fgCard ← fgi.fgCard + 1;
nfgi ← fgi;
};
ENDCASE;
};
NextFGIY: PROC
[stb: by.SymbolTableBase, fgi: FGIndex, epi: EPIndex]
RETURNS [nfgi: FGIndex ← FGNull] = {
takes a FGIndex & entry point, returns the next FGIndex
returns FGNull if next fgi is in a different proc than entryPointIndex
OR the given FGIndex or entry point was not valid
bti: by.BodyIndex;
IF fgi = FGNull THEN RETURN;
bti ← EPItoBTIY[stb, epi];
IF bti # by.nullBodyIndex THEN
WITH info: stb.bb[bti].info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
IF fgi.fudge OR fgi.fgCard NOT IN [firstFGI..lastFGI] THEN RETURN;
IF fgi.fgCard = lastFGI
THEN fgi.fudge ← TRUE
ELSE fgi.fgCard ← fgi.fgCard + 1;
nfgi ← fgi;
};
ENDCASE;
};
FGIToFirstChar: PUBLIC PROC
[stb: SymbolTableBase, fgi: FGIndex] RETURNS [ci: CharIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[FGIToFirstCharX[t.e, fgi]];
t: SymbolTableBase.y => RETURN[FGIToFirstCharY[t.e, fgi]];
ENDCASE => ERROR};
FGIToFirstCharX: PROC
[stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [ci: CharIndex ← -1] = {
takes a FGIndex, returns the first character position
-1 for invalid fgi
bti: bx.BodyIndex ← FGItoBTIX[stb, fgi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
ci ← body.sourceIndex;
FOR tfgi: FGCard ← info.startIndex, tfgi + 1 DO
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => IF tfgi # fgi.fgCard THEN ci ← ci + deltaSource ELSE EXIT;
step => {-- think of the step fgi as part of the next real fgi
IF tfgi = fgi.fgCard THEN EXIT;
IF which = object THEN LOOP;
IF which # source THEN ERROR;
IF tfgi + 1 = fgi.fgCard THEN EXIT;
IF stb.fgTable[tfgi+1].tag = step AND tfgi + 2 = fgi.fgCard THEN EXIT;
ci ← ci + delta;
};
ENDCASE;
ENDLOOP;
};
ENDCASE;
};
};
FGIToFirstCharY: PROC
[stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [ci: CharIndex ← -1] = {
takes a FGIndex, returns the first character position
-1 for invalid fgi
bti: by.BodyIndex ← FGItoBTIY[stb, fgi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
ci ← body.sourceIndex;
FOR tfgi: FGCard ← info.startIndex, tfgi + 1 DO
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => IF tfgi # fgi.fgCard THEN ci ← ci + deltaSource ELSE EXIT;
step => {-- think of the step fgi as part of the next real fgi
IF tfgi = fgi.fgCard THEN EXIT;
IF which = object THEN LOOP;
IF which # source THEN ERROR;
IF tfgi + 1 = fgi.fgCard THEN EXIT;
IF stb.fgTable[tfgi+1].tag = step AND tfgi + 2 = fgi.fgCard THEN EXIT;
ci ← ci + delta;
};
ENDCASE;
ENDLOOP;
};
ENDCASE;
};
};
FGIToLastChar: PUBLIC PROC
[stb: SymbolTableBase, fgi: FGIndex] RETURNS [ci: CharIndex] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[FGIToLastCharX[t.e, fgi]];
t: SymbolTableBase.y => RETURN[FGIToLastCharY[t.e, fgi]];
ENDCASE => ERROR};
FGIToLastCharX: PROC
[stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [ci: CharIndex ← -1] = {
takes a FGIndex, returns the last character position
-1 for invalid fgi
bti: bx.BodyIndex ← FGItoBTIX[stb, fgi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
ci ← body.sourceIndex;
FOR tfgi: FGCard IN [firstFGI..fgi.fgCard] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => ci ← ci + deltaSource;
step => IF which = source THEN ci ← ci + delta;
ENDCASE;
ENDLOOP;
IF fgi.fudge
THEN ci ← ci + fudge --XXX
ELSE ci ← ci - 1;
};
ENDCASE;
};
};
FGIToLastCharY: PROC
[stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [ci: CharIndex ← -1] = {
takes a FGIndex, returns the last character position
-1 for invalid fgi
bti: by.BodyIndex ← FGItoBTIY[stb, fgi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
ci ← body.sourceIndex;
FOR tfgi: FGCard IN [firstFGI..fgi.fgCard] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => ci ← ci + deltaSource;
step => IF which = source THEN ci ← ci + delta;
ENDCASE;
ENDLOOP;
IF fgi.fudge
THEN ci ← ci + fudge --XXX
ELSE ci ← ci - 1;
};
ENDCASE;
};
};
FGIToFirstPC: PUBLIC PROC
[stb: SymbolTableBase, fgi: FGIndex] RETURNS [pc: PCOffset] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[FGIToFirstPCX[t.e, fgi]];
t: SymbolTableBase.y => RETURN[FGIToFirstPCY[t.e, fgi]];
ENDCASE => ERROR};
FGIToFirstPCX: PROC
[stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [pc: PCOffset ← NullPCOffset] = {
takes a FGIndex, returns the first PC (NullPCOffset for invalid fgi)
bti: bx.BodyIndex ← FGItoBTIX[stb, fgi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
pc ← 0;
FOR tfgi: FGCard ← info.startIndex, tfgi + 1 DO
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => IF tfgi # fgi.fgCard THEN pc ← pc + deltaObject ELSE EXIT;
step => {-- think of the step fgi as part of the next real fgi
IF tfgi = fgi.fgCard THEN EXIT;
IF which = source THEN LOOP;
IF which # object THEN ERROR;
IF tfgi + 1 = fgi.fgCard THEN EXIT;
IF stb.fgTable[tfgi+1].tag = step AND tfgi + 2 = fgi.fgCard THEN EXIT;
pc ← pc + delta;
};
ENDCASE;
ENDLOOP;
};
ENDCASE;
};
};
FGIToFirstPCY: PROC
[stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [pc: PCOffset ← NullPCOffset] = {
takes a FGIndex, returns the first PC (NullPCOffset for invalid fgi)
bti: by.BodyIndex ← FGItoBTIY[stb, fgi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
pc ← 0;
FOR tfgi: FGCard ← info.startIndex, tfgi + 1 DO
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => IF tfgi # fgi.fgCard THEN pc ← pc + deltaObject ELSE EXIT;
step => {-- think of the step fgi as part of the next real fgi
IF tfgi = fgi.fgCard THEN EXIT;
IF which = source THEN LOOP;
IF which # object THEN ERROR;
IF tfgi + 1 = fgi.fgCard THEN EXIT;
IF stb.fgTable[tfgi+1].tag = step AND tfgi + 2 = fgi.fgCard THEN EXIT;
pc ← pc + delta;
};
ENDCASE;
ENDLOOP;
};
ENDCASE;
};
};
FGIToLastPC: PUBLIC PROC
[stb: SymbolTableBase, fgi: FGIndex] RETURNS [pc: PCOffset] = {
WITH stb SELECT FROM
t: SymbolTableBase.x => RETURN[FGIToLastPCX[t.e, fgi]];
t: SymbolTableBase.y => RETURN[FGIToLastPCY[t.e, fgi]];
ENDCASE => ERROR};
FGIToLastPCX: PROC
[stb: bx.SymbolTableBase, fgi: FGIndex] RETURNS [pc: PCOffset ← NullPCOffset] = {
returns offset of last byte in the fine grain entry
(NullPCOffset for invalid fgi)
bti: bx.BodyIndex ← FGItoBTIX[stb, fgi];
IF bti # bx.nullBodyIndex THEN {
body: XBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
IF fgi.fudge THEN {
pc ← info.bytes;
pc ← pc - 1;
RETURN};
pc ← 0;
FOR tfgi: FGCard IN [firstFGI..fgi.fgCard] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => pc ← pc + deltaObject;
step => IF which = object THEN pc ← pc + delta;
ENDCASE;
ENDLOOP;
pc ← pc - 1;
};
ENDCASE;
};
};
FGIToLastPCY: PROC
[stb: by.SymbolTableBase, fgi: FGIndex] RETURNS [pc: PCOffset ← NullPCOffset] = {
returns offset of last byte in the fine grain entry
(NullPCOffset for invalid fgi)
bti: by.BodyIndex ← FGItoBTIY[stb, fgi];
IF bti # by.nullBodyIndex THEN {
body: YBodyPtr ← @stb.bb[bti];
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
IF fgi.fudge THEN {
pc ← info.bytes;
pc ← pc - 1;
RETURN};
pc ← 0;
FOR tfgi: FGCard IN [firstFGI..fgi.fgCard] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => pc ← pc + deltaObject;
step => IF which = object THEN pc ← pc + delta;
ENDCASE;
ENDLOOP;
pc ← pc - 1;
};
ENDCASE;
};
};
implementation procedures
EPItoBTIX: PROC[stb: bx.SymbolTableBase, epi: EPIndex]
RETURNS [outerBti: bx.BodyIndex ← bx.nullBodyIndex] = {
takes a SymbolTableBase & entry point
returns a Callable BTI for the entry point
or nullBodyIndex if that can't be done
innerEPItoBTI: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: XBodyPtr ← @stb.bb[bti];
thisEPI: EPIndex ← 0;
WITH ext: body^ SELECT FROM
Callable => thisEPI ← ext.entryIndex;
ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External =>
IF epi = thisEPI THEN {outerBti ← bti; stop ← TRUE};
ENDCASE;
};
[] ← stb.EnumerateBodies[bx.rootBodyIndex, innerEPItoBTI];
};
EPItoBTIY: PROC[stb: by.SymbolTableBase, epi: EPIndex]
RETURNS [outerBti: by.BodyIndex ← by.nullBodyIndex] = {
takes a SymbolTableBase & entry point
returns a Callable BTI for the entry point
or nullBodyIndex if that can't be done
innerEPItoBTI: PROC [bti: by.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: YBodyPtr ← @stb.bb[bti];
thisEPI: EPIndex ← 0;
WITH ext: body^ SELECT FROM
Callable => thisEPI ← ext.entryIndex;
ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External =>
IF epi = thisEPI THEN {outerBti ← bti; stop ← TRUE};
ENDCASE;
};
[] ← stb.EnumerateBodies[by.rootBodyIndex, innerEPItoBTI];
};
FGItoBTIX: PROC[stb: bx.SymbolTableBase, fgi: FGIndex]
RETURNS [outerBti: bx.BodyIndex ← bx.nullBodyIndex] = {
takes a SymbolTableBase & FGIndex
returns a Callable BTI containing the FGIndex
or nullBodyIndex if that can't be done
innerFGItoBTI: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: XBodyPtr ← @stb.bb[bti];
thisEPI: EPIndex ← 0;
WITH ext: body^ SELECT FROM
Callable => thisEPI ← ext.entryIndex;
ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
IF fgi.fgCard IN [firstFGI..lastFGI] THEN {
outerBti ← bti;
stop ← TRUE};
};
ENDCASE;
};
[] ← stb.EnumerateBodies[bx.rootBodyIndex, innerFGItoBTI];
};
FGItoBTIY: PROC[stb: by.SymbolTableBase, fgi: FGIndex]
RETURNS [outerBti: by.BodyIndex ← by.nullBodyIndex] = {
takes a SymbolTableBase & FGIndex
returns a Callable BTI containing the FGIndex
or nullBodyIndex if that can't be done
innerFGItoBTI: PROC [bti: by.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: YBodyPtr ← @stb.bb[bti];
thisEPI: EPIndex ← 0;
WITH ext: body^ SELECT FROM
Callable => thisEPI ← ext.entryIndex;
ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
IF fgi.fgCard IN [firstFGI..lastFGI] THEN {
outerBti ← bti;
stop ← TRUE};
};
ENDCASE;
};
[] ← stb.EnumerateBodies[by.rootBodyIndex, innerFGItoBTI];
};
CItoBTIX: PROC[stb: bx.SymbolTableBase, ci: CharIndex]
RETURNS [bestBTI: bx.BodyIndex ← bx.nullBodyIndex] = {
takes a SymbolTableBase & character position
returns a Callable BTI containing the FGIndex or nullBodyIndex if that can't be done
bestCI: CharIndex ← 0;
the start CharIndex of the smallest enclosing (of ci) Callable body, initialized to the start CharIndex of the module
bti1: bx.BodyIndex ← bx.nullBodyIndex;
fgi1: FGCard ← 0;
ci1: CharIndex ← 0;
bti2: bx.BodyIndex ← bx.nullBodyIndex;
fgi2: FGCard ← 0;
ci2: CharIndex ← 0;
preliminaries: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: XBodyPtr ← @stb.bb[bti];
WITH ext: body^ SELECT FROM Callable => NULL; ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
thisCI: CharIndex ← body.sourceIndex; -- the first sourceIndex of this Callable body
lastCI: CharIndex ← thisCI; -- the first sourceIndex of the current statement
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
Compute (fgt1) the largest fgt entry startIndex that is smaller than ci
IF (bti1 = bx.nullBodyIndex OR lastCI >= ci1) AND lastCI <= ci
THEN {bti1 ← bti; fgi1 ← tfgi; ci1 ← lastCI};
Compute (fgt2) the smallest fgt entry startIndex that is larger than ci
IF (bti2 = bx.nullBodyIndex OR lastCI <= ci2) AND lastCI >= ci
THEN {bti2 ← bti; fgi2 ← tfgi; ci2 ← lastCI};
WITH fp^ SELECT FROM
normal => lastCI ← lastCI + deltaSource;
step => IF which = source THEN lastCI ← lastCI + delta;
ENDCASE;
ENDLOOP;
};
ENDCASE;
}; -- end preliminaries
innerCItoBTI: PROC [bti: bx.BodyIndex] RETURNS [stop: BOOLFALSE] = {
NOTE: we assume that the character ranges covered by the Callable BTI's are disjoint or nested and the smallest source range containing the index is the one desired
body: XBodyPtr ← @stb.bb[bti];
WITH ext: body^ SELECT FROM Callable => NULL; ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
thisCI: CharIndex ← body.sourceIndex; -- the first sourceIndex of this Callable body
IF bestCI <= thisCI AND thisCI <= ci THEN { -- this body might be a smaller encloser
Here if (this body is the first examined OR the best body seen so far precedes this body) AND this body precedes ci
lastCI: CharIndex ← thisCI;
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: XFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => lastCI ← lastCI + deltaSource;
step => IF which = source THEN lastCI ← lastCI + delta;
ENDCASE;
IF lastCI >= ci
THEN {bestBTI ← bti; bestCI ← thisCI; RETURN};
a statement (not the last) in this body encloses ci
ENDLOOP;
Here to examine the last statement in this body to determine whether it encloses this ci: search thru ALL Callable bodies to find
1. (fgt1) the largest fgt entry startIndex that is smaller than ci, and
2. (fgt2) the smallest fgt entry startIndex that is larger than ci
If the last statement in this block is (fgt1) the largest fgt entry startIndex that is smaller than ci then ...
IF fgi1 = lastFGI THEN {bestBTI ← bti; bestCI ← thisCI; RETURN[stop: TRUE]};
};
};
ENDCASE;
}; -- end innerCItoBTI
START CItoBTIX HERE
[] ← stb.EnumerateBodies[bx.rootBodyIndex, preliminaries];
[] ← stb.EnumerateBodies[bx.rootBodyIndex, innerCItoBTI];
}; -- end CItoBTIX
CItoBTIY: PROC[stb: by.SymbolTableBase, ci: CharIndex]
RETURNS [bestBTI: by.BodyIndex ← by.nullBodyIndex] = {
takes a SymbolTableBase & character position
returns a Callable BTI containing the FGIndex or nullBodyIndex if that can't be done
bestCI: CharIndex ← 0;
the start CharIndex of the smallest enclosing (of ci) Callable body, initialized to the start CharIndex of the module
bti1: by.BodyIndex ← by.nullBodyIndex;
fgi1: FGCard ← 0;
ci1: CharIndex ← 0;
bti2: by.BodyIndex ← by.nullBodyIndex;
fgi2: FGCard ← 0;
ci2: CharIndex ← 0;
preliminaries: PROC [bti: by.BodyIndex] RETURNS [stop: BOOLFALSE] = {
body: YBodyPtr ← @stb.bb[bti];
WITH ext: body^ SELECT FROM Callable => NULL; ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
thisCI: CharIndex ← body.sourceIndex; -- the first sourceIndex of this Callable body
lastCI: CharIndex ← thisCI; -- the first sourceIndex of the current statement
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
Compute (fgt1) the largest fgt entry startIndex that is smaller than ci
IF (bti1 = by.nullBodyIndex OR lastCI >= ci1) AND lastCI <= ci
THEN {bti1 ← bti; fgi1 ← tfgi; ci1 ← lastCI};
Compute (fgt2) the smallest fgt entry startIndex that is larger than ci
IF (bti2 = by.nullBodyIndex OR lastCI <= ci2) AND lastCI >= ci
THEN {bti2 ← bti; fgi2 ← tfgi; ci2 ← lastCI};
WITH fp^ SELECT FROM
normal => lastCI ← lastCI + deltaSource;
step => IF which = source THEN lastCI ← lastCI + delta;
ENDCASE;
ENDLOOP;
};
ENDCASE;
}; -- end preliminaries
innerCItoBTI: PROC [bti: by.BodyIndex] RETURNS [stop: BOOLFALSE] = {
NOTE: we assume that the character ranges covered by the Callable BTI's are disjoint or nested and the smallest source range containing the index is the one desired
body: YBodyPtr ← @stb.bb[bti];
WITH ext: body^ SELECT FROM Callable => NULL; ENDCASE => RETURN;
WITH info: body.info SELECT FROM
External => {
firstFGI: FGCard ← info.startIndex;
lastFGI: FGCard ← firstFGI + MAX[info.indexLength, 1] - 1;
thisCI: CharIndex ← body.sourceIndex; -- the first sourceIndex of this Callable body
IF bestCI <= thisCI AND thisCI <= ci THEN { -- this body might be a smaller encloser
Here if (this body is the first examined OR the best body seen so far precedes this body) AND this body precedes ci
lastCI: CharIndex ← thisCI;
FOR tfgi: FGCard IN [firstFGI..lastFGI] DO
fp: YFGPtr ← @stb.fgTable[tfgi];
WITH fp^ SELECT FROM
normal => lastCI ← lastCI + deltaSource;
step => IF which = source THEN lastCI ← lastCI + delta;
ENDCASE;
IF lastCI >= ci
THEN {bestBTI ← bti; bestCI ← thisCI; RETURN};
a statement (not the last) in this body encloses ci
ENDLOOP;
Here to examine the last statement in this body to determine whether it encloses this ci: search thru ALL Callable bodies to find
1. (fgt1) the largest fgt entry startIndex that is smaller than ci, and
2. (fgt2) the smallest fgt entry startIndex that is larger than ci
If the last statement in this block is (fgt1) the largest fgt entry startIndex that is smaller than ci then ...
IF fgi1 = lastFGI THEN {bestBTI ← bti; bestCI ← thisCI; RETURN[stop: TRUE]};
};
};
ENDCASE;
}; -- end innerCItoBTI
START CItoBTIY HERE
[] ← stb.EnumerateBodies[by.rootBodyIndex, preliminaries];
[] ← stb.EnumerateBodies[by.rootBodyIndex, innerCItoBTI];
}; -- end CItoBTIY
END.