MDScanImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Willie-Sue, May 7, 1986 4:26:15 pm PDT
taken from mdScan.bcpl
MDScanImpl:
CEDAR
PROGRAM
IMPORTS
IO,
MDGlobalVars, MDOps, MDUtils
= BEGIN OPEN MDDefs, MDGlobalVars;
-- Mark IFU entries, check common errors
InitialScan:
PUBLIC
PROC
RETURNS[ok:
BOOL] = {
MDOps.Report[infoOnly, " Checking for errors...\n"];
IF ~PreScan[] THEN RETURN[FALSE];
RETURN[RealScan[]];
};
PreScan:
PROC
RETURNS[ok:
BOOL] =
TRUSTED {
Miscellaneous checking and cleanup:
Remove onPage if appropriate
Remove calls if oddcall set (since call does not return)
If callerMask=-1, remove oddcall as well (i.e. RCALL=GOTO
Remove iscond if returns set (for "conditional" IFU jumps)
Prohibit conditional and FF-busy branches to external symbols
Reset IFUE bit for IFU entry loop
nIFUE: INTEGER ← 0;
FOR i:
CARDINAL
IN [0..nInstructions)
DO
imPtr: MDDefs.IMRecordPtr = MDUtils.IMPtr[i];
IF ignoreOnPage THEN imPtr.word0.onPageAndPlaced ← 0;
IF imPtr.word1.W1AddrAndGroupLink = WExt
OR
imPtr.word2.W2AddrAndbLink = WExt THEN {
IF imPtr.word2.iscond = 1
THEN {
MDOps.Report[infoOnly,
"%g ....Conditional branch to external symbol\n", IO.int[i] ];
RETURN[FALSE];
}
ELSE
IF imPtr.word1.usesFN = 1
THEN {
MDOps.Report[infoOnly,
"%g ....Branches to external symbol, but FF is busy\n", IO.int[i] ];
RETURN[FALSE];
};
};
IF imPtr.word1.returns = 1 THEN imPtr.word2.iscond ← 0;
imPtr.word0.brkPAndIFUE ← 0;
ENDLOOP;
Indicate IFU entries
FOR k:
CARDINAL
IN [0..nIFUInstructions)
DO
ifumPtr: IFUMRecordPtr = MDUtils.IFUMPtr[k];
imPtr: IMRecordPtr;
iAddr: CARDINAL = ifumPtr.ifumWord0.ifad;
IF iAddr = 7777B THEN LOOP;
imPtr ← MDUtils.IMPtr[iAddr];
IF imPtr.word0.brkPAndIFUE = 0
THEN {
iAddrLast: CARDINAL;
nIFUE ← nIFUE + 1;
iAddrLast ← iAddr + ifumPtr.ifumWord0.nEnt;
FOR j:
CARDINAL
IN [iAddr .. iAddrLast]
DO
-- checking multiple entry points
imP: MDDefs.IMRecordPtr = IMPtr[j];
IF imP.word0.brkPAndIFUE = 1 THEN RETURN[IFUErr[j]]; -- return[false]
IF imP.word0.globalAndIFUSeq = 1
THEN {
MDOps.Report[infoOnly,
"%g ....Both IFU entry and global\n", IO.int[j]];
RETURN[FALSE];
};
imP.word0.brkPAndIFUE ← 1;
IF j # iAddr THEN imP.word0.globalAndIFUSeq ← 1;
ENDLOOP;
}
ELSE IF imPtr.word0.globalAndIFUSeq = 1 THEN RETURN[IFUErr[iAddr]];
ENDLOOP;
IF nIFUE > IFUMsize
THEN {
MDOps.Report[infoOnly,
"Too many (%g) IFU entries - max is %g\n", IO.int[nIFUE], IO.int[IFUMsize]];
RETURN[FALSE];
};
change .+1 encoding to actual value
FOR i:
CARDINAL
IN [0 .. nInstructions)
DO
imPtr: IMRecordPtr = IMPtr[i];
IF imPtr.word1.W1AddrAndGroupLink = WNext
THEN
imPtr.word1.W1AddrAndGroupLink ← i+1;
IF imPtr.word2.W2AddrAndbLink = WNext THEN imPtr.word2.W2AddrAndbLink ← i+1;
ENDLOOP;
RETURN[TRUE];
};
RealScan:
PROC
RETURNS[ok:
BOOL] =
TRUSTED {
Check constraints:
Forbid branches beyond end of program
FOR i:
CARDINAL
IN [0 .. nInstructions)
DO
imPtr: IMRecordPtr ← IMPtr[i];
addr1, addr2: CARDINAL;
addr1 ← imPtr.word1.W1AddrAndGroupLink;
IF addr1 > nInstructions
AND UsesW1[imPtr]
THEN
IF
NOT (imPtr.word1.returns # 0
AND imPtr.word1.calls = 0)
THEN {
MDOps.Report[infoOnly, "%g....successor (%g) is beyond end of program\n",
IO.card[i], IO.card[addr1] ];
RETURN[FALSE];
};
IF (addr2 ← imPtr.word2.W2AddrAndbLink) > nInstructions
AND UsesW2[imPtr]
THEN {
IF imPtr.word2.iscond = 1
THEN
MDOps.Report[infoOnly, "%g....one successor (%g) is beyond end of program\n",
IO.card[i], IO.card[addr2] ]
ELSE
MDOps.Report[infoOnly, "%g....successor (%g) is beyond end of program\n",
IO.card[i], IO.card[addr2] ];
RETURN[FALSE];
};
ENDLOOP;
RETURN[TRUE];
};
IFUErr:
PROC[addr:
CARDINAL]
RETURNS[
BOOL] = {
MDOps.Report[infoOnly,
"%g ....Overlapping IFU entry sequences\n", IO.card[addr]];
RETURN[FALSE];
};
IMPtr:
PUBLIC
PROC[offset:
CARDINAL]
RETURNS[IMRecordPtr] =
{ RETURN[LOOPHOLE[imArrayHead + offset*SIZE[IMRecord]]] };
UsesW1:
PROC[imPtr: MDDefs.IMRecordPtr]
RETURNS[
BOOL] =
TRUSTED {
RETURN[
((imPtr.word1.returns = 0)
OR (imPtr.word1.calls # 0))
AND
(imPtr.word1.W1AddrAndGroupLink # WExt)]
};
UsesW2:
PROC[imPtr: MDDefs.IMRecordPtr]
RETURNS[
BOOL] =
TRUSTED {
RETURN[
((imPtr.word2.iscond # 0)
OR (imPtr.word1.calls # 0))
AND
(imPtr.word1.W1AddrAndGroupLink # WExt)]
};
END.