[ivy]<Satterthwaite>CrossCompiler>tCrossJump.mesa!2

CrossJump.mesa,
last modified by Sweet, 4-Dec-81 14:20:33
last modified by Satterthwaite, December 1, 1985 3:57:27 pm PST
DIRECTORY
Alloc: TYPE USING [Notifier],
Code: TYPE USING [codeptr],
CodeDefs: TYPE USING [
Base, CCIndex, CCNull, CJItem, codeType, EINull, EnableIndex,
JumpCCIndex, JumpCCNull, LabelCCIndex, LabelCCNull],
OpTableDefs: TYPE USING [InstLength],
P5F: TYPE USING [DidSomething, StartIndex, UCjump, UnthreadJump],
P5U: TYPE USING [CreateLabel, DeleteCell, OutJump, ParamCount];
CrossJump: PROGRAM
IMPORTS CPtr: Code, OpTableDefs, P5U, P5F
EXPORTS CodeDefs, P5F =
BEGIN
OPEN CodeDefs;
cb: CodeDefs.Base;-- code base (local copy)
CrossJumpNotify: PUBLIC Alloc.Notifier =
BEGIN -- called by allocator whenever table area is repacked
cb ← base[codeType];
END;
CJcheck: PUBLIC BOOL ← FALSE;
CJNull: CJItem = [CCNull, fallIn[LabelCCNull]];
FunnyJump: SIGNAL [c: CCIndex] = CODE;
CPass5: PUBLIC PROC =
BEGIN
CPass5a[];
CPass5b[];
END;
CPass5a: PROC =
BEGIN -- set enable index in jumps and labels
stack: ARRAY [0..15) OF EnableIndex;
sptr: CARDINAL ← 0;
curEi: EnableIndex ← EINull;
c: CCIndex;
Push: PROC [new: EnableIndex] =
BEGIN
stack[sptr] ← curEi;
curEi ← new;
sptr ← sptr + 1;
END;
Pop: PROC =
BEGIN
sptr ← sptr - 1;
curEi ← stack[sptr];
END;
FOR c ← cb[P5F.StartIndex].flink, cb[c].flink WHILE c # CCNull DO
WITH cc: cb[c] SELECT FROM
label => cc.ei ← curEi;
jump => cc.ei ← curEi;
other => WITH cc SELECT FROM
markCatch => IF start THEN Push[index] ELSE Pop[];
ENDCASE;
ENDCASE;
ENDLOOP;
END;
CPass5b: PROC =
BEGIN -- pass 5: cross jumping
i1, i2, next2: CJItem;
nextc, c: CCIndex;
CJed: BOOL;
FOR c ← cb[P5F.StartIndex].flink, nextc WHILE c # CCNull DO
WITH cc: cb[c] SELECT FROM
label =>
BEGIN
lc: LabelCCIndex = LOOPHOLE[c];
i1 ← FirstItem[lc];
CJed ← FALSE;
UNTIL i1.inst = CCNull DO
i2 ← NextItem[i1];
UNTIL i2.inst = CCNull DO
next2 ← NextItem[i2];
IF i1.inst # i2.inst AND EqualItems[i1, i2] THEN
BEGIN
CrossJumpIt[i1, i2];
P5F.DidSomething ← CJed ← TRUE;
END;
i2 ← next2;
ENDLOOP;
IF CJed THEN EXIT;
i1 ← NextItem[i1];
ENDLOOP;
nextc ← cc.flink;
END;
ENDCASE => nextc ← cc.flink;
ENDLOOP;
END;
EqualItems: PROC [i1, i2: CJItem] RETURNS [BOOL] =
BEGIN -- can't cross jump into different enable scopes
ei1, ei2: EnableIndex;
IF ~EqualInst[i1.inst, i2.inst] THEN RETURN[FALSE];
WITH i1 SELECT FROM
fallIn => ei1 ← cb[lc].ei;
jumpIn => ei1 ← cb[jc].ei;
ENDCASE;
WITH i2 SELECT FROM
fallIn => ei2 ← cb[lc].ei;
jumpIn => ei2 ← cb[jc].ei;
ENDCASE;
RETURN [ei1 = ei2];
END;
Executable: PROC [c: CCIndex] RETURNS [BOOL] =
BEGIN
RETURN [WITH cb[c] SELECT FROM
code => TRUE,
jump => ~(P5F.UCjump[c] OR FunnyUCjump[c]),
ENDCASE => FALSE]
END;
FirstItem: PROC[lc: LabelCCIndex] RETURNS [item: CJItem] =
BEGIN
j: JumpCCIndex ← cb[lc].jumplist;
pred: CCIndex;
IF j = JumpCCNull THEN RETURN [CJNull];
IF (pred←PrevInst[lc]) = CCNull THEN RETURN [CJNull];
item ← [pred, fallIn[lc]];
IF Executable[pred] THEN RETURN [item];
RETURN [NextItem[item]]
END;
NextItem: PROC [item: CJItem] RETURNS [CJItem] =
BEGIN
j: JumpCCIndex;
inst: CCIndex;
DO
WITH ii: item SELECT FROM
fallIn => j ← cb[ii.lc].jumplist;
jumpIn => j ← cb[ii.jc].thread;
ENDCASE;
IF j = CCNull THEN RETURN [CJNull];
IF FunnyUCjump[j] THEN {item ← [CCNull, jumpIn[j]]; LOOP};
IF Executable[j] THEN {inst ← j; EXIT};
inst ← PrevInst[j];
IF inst # CCNull AND Executable[inst] THEN EXIT;
item ← [CCNull, jumpIn[j]];
ENDLOOP;
RETURN [[inst, jumpIn[j]]]
END;
FunnyUCjump: PROC [j: CCIndex] RETURNS [BOOL] =
BEGIN -- predicate testing if c is not interesting jump for crossjumping
RETURN [WITH cb[j] SELECT FROM
jump => (jtype = JumpC) OR (jtype = JumpA)
OR (jtype = JumpCA) OR (jtype = JumpRet),
ENDCASE => FALSE]
END;
EqualInst: PROC [c, cc: CCIndex] RETURNS [BOOL] =
BEGIN
np: CARDINAL;
WITH c1: cb[c] SELECT FROM
code =>
WITH c2 : cb[cc] SELECT FROM
code =>
BEGIN
IF c1.realinst # c2.realinst THEN RETURN [FALSE];
IF c1.inst # c2.inst THEN RETURN [FALSE];
np ← IF c1.realinst THEN OpTableDefs.InstLength[c1.inst]-1
ELSE P5U.ParamCount[LOOPHOLE[c]];
FOR i: CARDINAL IN [1..np] DO
IF c1.parameters[i] # c2.parameters[i] THEN RETURN [FALSE];
ENDLOOP;
RETURN [TRUE]
END;
ENDCASE;
jump =>
WITH c2 : cb[cc] SELECT FROM
jump =>
BEGIN
c1fwd, c2fwd: CCIndex;
IF c1.jtype # c2.jtype THEN RETURN [FALSE];
IF c1.destlabel # c2.destlabel THEN RETURN [FALSE];
c1fwd ← NextInst[c]; c2fwd ← NextInst[cc];
WITH c1f : cb[c1fwd] SELECT FROM
jump =>
WITH c2f : cb[c2fwd] SELECT FROM
jump => IF c1f.destlabel = c2f.destlabel THEN RETURN [TRUE];
label => IF c1f.destlabel = c2fwd THEN RETURN [TRUE];
ENDCASE;
label =>
WITH c2f : cb[c2fwd] SELECT FROM
jump => IF c2f.destlabel = c1fwd THEN RETURN [TRUE];
ENDCASE;
ENDCASE;
END;
ENDCASE;
ENDCASE;
RETURN [FALSE]
END;
CrossJumpIt: PROC [i1, i2: CJItem] =
BEGIN
l: LabelCCIndex;
fb: CCIndex = PrevInst[i1.inst];
WITH cb[fb] SELECT FROM
label => l ← LOOPHOLE[fb];
ENDCASE => {CPtr.codeptr ← fb; l ← P5U.CreateLabel[]};
CPtr.codeptr ← cb[i2.inst].blink; -- don't skip over source here
P5U.OutJump[Jump,l];
WITH cb[i2.inst] SELECT FROM
jump => P5F.UnthreadJump[LOOPHOLE[i2.inst]];
ENDCASE;
P5U.DeleteCell[i2.inst];
WITH ii: i2 SELECT FROM
jumpIn => IF ii.jc # i2.inst THEN
{P5F.UnthreadJump[ii.jc]; P5U.DeleteCell[ii.jc]};
ENDCASE;
END;
the following two procs are like NextInteresting and PrevInteresting
in PeepholeU, only they won't skip over a MarkCatch
NextInst: PROC [c: CCIndex] RETURNS [CCIndex] =
BEGIN -- skip over startbody, endbody, and source other CCItems
WHILE (c ← cb[c].flink) # CCNull DO
WITH cc: cb[c] SELECT FROM
other => WITH cc SELECT FROM
table, markCatch => EXIT;
ENDCASE;
ENDCASE => EXIT;
ENDLOOP;
RETURN [c]
END;
PrevInst: PROC [c: CCIndex] RETURNS [CCIndex] =
BEGIN -- skip over startbody, endbody, and source other CCItems
WHILE (c ← cb[c].blink) # CCNull DO
WITH cc: cb[c] SELECT FROM
other => WITH cc SELECT FROM
table, markCatch => EXIT;
ENDCASE;
ENDCASE => EXIT;
ENDLOOP;
RETURN [c]
END;
END.