MDScanImpl.mesa
Copyright © 1986 by Xerox Corporation. All rights reserved.
Willie-Sue, May 7, 1986 4:26:15 pm PDT
taken from mdScan.bcpl
DIRECTORY
IO,
Rope,
MDDefs,
MDGlobalVars,
MDOps,
MDUtils;
MDScanImpl: CEDAR PROGRAM
IMPORTS
IO,
MDGlobalVars, MDOps, MDUtils
EXPORTS
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.