DIRECTORY
Alloc: TYPE USING [Notifier],
Code:
TYPE
USING [
bodyRecurLabel, CodePassInconsistency, codeptr, tailJumpOK],
CodeDefs:
TYPE
USING [
Base, CCIndex, CCInfoType, CCNull, codeType, JumpCCIndex, JumpCCNull,
JumpType, LabelCCIndex, LabelCCNull, RelativePC, TableCodeBytes],
ComData: TYPE USING [bodyIndex, switches],
FOpCodes: TYPE USING [qADD, qDIS, qLFC, qLI, qLL, qRET, qSELFC, qSFC],
OpTableDefs: TYPE USING [InstLength],
P5: TYPE USING [C0, C1, PeepHole],
P5F: TYPE USING [BindJump, CodeJump, CPass5, FillInPCEstimates],
P5U: TYPE USING [DeleteCell, OutJump],
PeepholeDefs:
TYPE
USING [
CJump, NextInteresting, PrevInteresting, RemoveThisPop, SetRealInst],
PrincOps: TYPE USING [framelink],
Symbols: TYPE USING [Base, CBTIndex, BTIndex, bodyType];
Final:
PROGRAM
IMPORTS CPtr: Code, MPtr: ComData, OpTableDefs, P5U, P5, P5F, PeepholeDefs
EXPORTS CodeDefs, P5, P5F =
BEGIN
OPEN PeepholeDefs, CodeDefs;
Fixup:
PUBLIC
PROC [start: CCIndex, ownEntry:
CARDINAL] =
BEGIN -- a final pass over the code to fix up jumps
jumpsbefore, jumpsafter, totalJumps: CARDINAL;
crossJump: BOOL = MPtr.switches['j];
ccInfo ← generating;
DidSomething ← TRUE;
SeenSwitch ← TRUE;
StartIndex ← start;
PeepholeDefs.SetRealInst[FALSE];
TailJump[crossJump AND CPtr.tailJumpOK];
CPtr.bodyRecurLabel ← LabelCCNull; -- avoid dangling ref if deleted
DO
pass 0: distinguish forward and backward jumps
CPass0[];
IF ~DidSomething THEN EXIT;
DidSomething ← FALSE;
SeenSwitch ← ~SeenSwitch;
pass 1: eliminate multiple labels
CPass1[];
pass 2: eliminate jump to jumps
CPass2[];
pass 3: eliminate unreachable code
CPass3[];
pass 4: replace cj-j seq. with ccj
CPass4[];
pass 5: cross jumping
IF crossJump THEN P5F.CPass5[];
ENDLOOP; -- end of the meta-pass consisting of passes 0-5
pass 6: do some peephole optimization: load-store, EXCH-commutative op.
P5.PeepHole[StartIndex];
jump threads are now pc's, debug output take note
ccInfo ← binding;
pass 7: set length and alignment, count jumps
totalJumps ← jumpsafter ← CPass7[];
jumpsbefore ← jumpsafter+1;
pass 8: resolve (most) jump instructions
THROUGH [1..3]
WHILE jumpsafter # 0
AND jumpsafter < jumpsbefore
DO
jumpsbefore ← jumpsafter;
jumpsafter ← CPass8[];
ENDLOOP;
pass 9: resolve (remaining) jump instructions
IF jumpsafter # 0 THEN CPass9[];
pass 10: code jumps
ccInfo ← coding;
IF totalJumps # 0 THEN CPass10[];
pass 11: Remove extra source chunks
CPass11[];
END;
TailJump:
PROC [jumpOK:
BOOL] =
BEGIN -- remove simple tail recursion
enableLevel: CARDINAL ← 0;
next: CCIndex;
FOR c: CCIndex ← cb[StartIndex].flink, next
WHILE c # CCNull
DO
next ← cb[c].flink;
WITH cc: cb[c]
SELECT
FROM
code =>
IF ~cc.realinst
AND cc.inst = FOpCodes.qSELFC
THEN {
CPtr.codeptr ← cb[c].blink;
IF jumpOK
AND enableLevel = 0
AND UCreturn[next]
THEN
BEGIN
P5U.OutJump[Jump, CPtr.bodyRecurLabel];
P5U.DeleteCell[c]
END
ELSE
BEGIN
bti: Symbols.CBTIndex = MPtr.bodyIndex;
WITH body: bb[bti]
SELECT
FROM
Outer => {P5.C1[FOpCodes.qLFC, body.entryIndex]; P5U.DeleteCell[c]};
Inner => {
P5.C1[FOpCodes.qLL, PrincOps.framelink];
P5.C1[FOpCodes.qLI, body.frameOffset];
P5.C0[FOpCodes.qADD];
P5.C0[FOpCodes.qSFC];
P5U.DeleteCell[c]};
ENDCASE => ERROR;
END};
other =>
WITH oc: cc
SELECT
FROM
markbody => {
index: Symbols.BTIndex = oc.index;
WITH bb[index]
SELECT
FROM
Callable => EXIT;
ENDCASE};
markCatch =>
IF oc.start THEN enableLevel ← enableLevel + 1
ELSE enableLevel← enableLevel - 1;
ENDCASE;
ENDCASE;
ENDLOOP;
END;