Google
 

Trailing-Edge - PDP-10 Archives - BB-4157E-BM - fortran-compiler/defpt.bli
There are 26 other files named defpt.bli in the archive. Click here to see a list.
!THIS SOFTWARE IS FURNISHED UNDER A LICENSE AND MAY ONLY BE USED
!  OR COPIED IN ACCORDANCE WITH THE TERMS OF SUCH LICENSE.

!COPYRIGHT (C) 1972,1981 BY DIGITAL EQUIPMENT CORPORATION
!AUTHOR NORMA ABEL/HPW/JNG/DCE/TFV/EGM/CKS/AHM

MODULE DEFPT(RESERVE(0,1,2,3),SREG=#17,VREG=#15,FREG=#16,DREGS=4)=
BEGIN

GLOBAL BIND DEFPTV = 6^24 + 0^18 + 126;	! Version Date:	24-Sep-81

%(

***** Begin Revision History *****

92	-----	-----	GENERATE DEFPTS IN I/O LISTS
93	-----	-----	REMOVE 2ND PARAMTER TO GETDEF
94	-----	-----	MAKE SETGTRD GLOBAL AND RETURN A VALUE INSTEAD
			OF SETTING GOTVAL
95	-----	-----	ADD ELIST HANDLING TO ALL LEVELS
96	-----	-----	PUT PARAMETER TO GETDEF BACK
97	-----	-----	FIX DEF1 TO PREVENT MOTION INTO DO LOOPS
			THAT HAPPEN TO BE TOP[BUSY] = TOP[SRCLINK]
98	-----	-----	CALL IOSTDFPT FOR ENCODE/DECODE/READ/WRITE
99	-----	-----	EXTRACT CASE STATEMENT FROM SETGTRD AND
			MAKE A GLOBAL ROUTINE READHERE
100	-----	-----	ADD REREDID TO I/O OPTIMIZATIONS
101	-----	-----	FIX SETONSUC SERIOUS CONCEPT PROBLEM
			CAUSING INCORRECT MOTION
102	-----	-----	FIXES TO LOKELIST, READHERE, AND SETGTRD
			FOR I/O OPTIMIZATION
103	-----	-----	SELECT AND SET VARIABLES ASSIGNED ON
			THE I/O LIST
104	-----	-----	CLEAN UP AND CREATE DEFWORK
105	-----	-----	FIX 104
106	-----	-----	ADD CODE FOR MOTION OF SIMPLE ASSIGNMENTS
107	-----	-----	FIX 106
108	-----	-----	ADD CODE FOR ARRAY COMMON SUB EXPRESSIONS
109	-----	-----	MOVE CALL TO CLEABUP OUT OF DEFDRI INTO
			PROPAGATE
110	-----	-----	FIX LABEL TEST IN SPECBRCHK
111	-----	-----	SORT MULTIPLY NODES FOR BETTER REDUCTION
112	-----	-----	MAKE DEF PT STUFF IN GENERAL AWARE OF THE
			FACT THAT AN IMPLIED DO LOOP CHANGES THE
			VALUE OF THE DO LOOP INDEX
113	-----	-----	SELECTIT, ETC. IS MISHANDLING LABELS
114	-----	-----	DEFWORK NOT TAKING ACCOUNT OF ASSIGN
			STATEMENTS
115	235		FIX NAMELIST PROBLEM, (MD)
116	252	14967	SELECTIT NOT CHECKING FOR SPECOP AND POSSIBLY OTHER OPS,
			(JNT)
117	315	16667	FIX VDEFPT TO RECOGNIZE ARRAYREFS WITH CONSTANT
			SUBSCRIPTS, NOT OPTIMALLY, BUT AT LEAST NOT WRONG, (JNT)
118	453	19695	DON'T CONSIDER THE DEFPT OF VARIABLES MODIFIED
			INSIDE LOOPS TO BE THE DO STATEMENT., (JNG)

***** Begin Version 5A *****

119	575	22820	MAKE ZAPLEVEL MORE CLEVER IN USE OF THE STACK
			TO PREVENT STACK OVERFLOWS., (DCE)
120	671	NVT	WHEN SWAPPING ARGS, SWAP DEF PTS TOO, (DCE)

***** Begin Version 6 *****

121	760	TFV	1-Oct-79	------
	Add handling for IOSTAT variable, it's an implicit assignment
	Include all I/O statements in test for END/ERR= branching

122	763	EGM	24-Apr-80	13913
	Cause ENTRY formals to take part in definition point determination

123	1010	EGM	12-Aug-80	10-29839
	Make sure CHKNAML passes only the address of a NAMELIST entry, not the
	full argument word.

124	1034	DCE	4-Dec-80	-----
	Fix function call arguments so that arguments (especially nested
	ones) which change get noticed.  Example F(G(X)) may change X.

125	1113	CKS	17-Jun-81
	Prevent code motion from moving CSEs to statements which have more
	than one successor.  To do this, modify SETONSUC to set ACC bits for
	variables which are assigned in statement STMT in STMT's successors
	and postdominator.  See comments in SPECBRCHK.

126	1126	AHM	22-Sep-81	Q20-01654
	Remove last vestiges of CALL DEFINE FILE in a comment.

***** End Revision History *****

)%

SWITCHES NOLIST;
REQUIRE FIRST.BLI;
REQUIRE TABLES.BLI;
REQUIRE OPTMAC.BLI;
SWITCHES LIST;

!THE CONTROLLING ROUTINE IN THIS MODULE IS DEFDRIV. IT IS
!CALLED FROM PHA2. IT DIRECTS THE CALLING OF ALL THE OTHER
!(LOCAL) ROUTINES IN THIS MODULE. THE READER SHOULD START WITH
!THE ROUTINE DEFDRIV. IT APPEARS AT THE END OF THE MODULE
!(SAVE FOR INITDEF).


EXTERNAL LENTRY,QQ;
EXTERNAL ASSOCPT;
OWN PCE;
MAP BASE ASSOCPT;		!USED FOR LINKED LIST OF ASSOCIATE VARIABLES
MAP PEXPRNODE PCE;
OWN P,PA,PB,PC,HEAD,PAE;
OWN MOREFLG,LSTVAR,T;
EXTERNAL TOP,BOTTOM,CHOSEN,LOOPNO,LOOKUP;
MAP PHAZ2 P:QQ:PA:PB:PC:HEAD:PAE;
OWN MASK,CHNGLST;
OWN DISPIX;		!PLIT DISPATCH INDEX
FORWARD CHKNAML,CHKUNIQ;
FORWARD DEFWORK;

OWN GOTVAL;		!FLAG FOR ASSIGNED HERE
			!THAT IT GIT IT VALUE HERE

!DISPATCH TO USE FCNLOK TO BOTH SELECT AND SET BITS.
!A SPACE ECONOMY AT A SLIGHT TRADE OFF IN TIME.

FORWARD SELECTIT,SETIT,SETGOTVAL,FCNLOK;
BIND SETSEL = PLIT (
			SELECTIT,
			SETIT,
			SETGOTVAL);



ROUTINE LOKELIST(EPTR)=
BEGIN
	!EXAMINE E1 AND E2 LISTS AND CALL THE CORRECT
	!SELSEL ROUTINE.
	!EPTR POINTS TO THE ELIST NODE.

	MAP BASE EPTR;

	REGISTER BASE ELEM;

	WHILE .EPTR NEQ 0 DO
	BEGIN
		ELEM_.EPTR[E2ARREFPTR];
		IF .ELEM[OPRCLS] EQL DATAOPR THEN
			(.SETSEL[.DISPIX])(.ELEM)
		ELSE
			(.SETSEL[.DISPIX])(.ELEM[ARG1PTR]);
		EPTR_.EPTR[CLINK];
	END;
END;

!
!
!*****************************************************
!
!
ROUTINE SELECTIT(VAR)=
BEGIN
EXTERNAL CORMAN,UNIQVAL,UNLIST,SAVSPACE;
MAP PHAZ2 CHNGLST:TOP:UNIQVAL;
MAP PEXPRNODE VAR;
!SELECT VARIABLES TO PARTICIPATE IN THE DEFINITION POINT 
!THE FIELD IDCHOS (IN THE SYMBOL TABLE) IS SET TO THE
!LOOP NUMBER TO INDICATE THAT THIS VARIABLE WAS CONSIDERED IN THIS
!LOOP. IDDEF INDICATES THAT THE VARAIBLE HAS PARTICIPATED IN THE
!DEFINITION POINT COMPUTATION.
!32 VARIABLES ARE SELECTED. THERE ADDRESS ARE PUT INTO THE VECTOR CHOSEN.

!AS A VARIABLE IS CHOSEN IT IS ALSO ADDED TO THE LIST OF VARIABLES
!THAT ARE CHANGED IN THIS LOOP WHICH IS KEPT WITH THE DO LOOP
!AFTER PROCESSING AS IT GOES FORTH INTO THE OUTSIDE WORLD.

!THE VARIABLE LSTVAR IS USED TO HOLD THE PLACE OF THE ALGORITHM IN
!PROCESSING STATEMENTS IN CASE MORE THAN 32 EXIST.
!ALGORTHM
	!FIRST CHECK VALIDITY OF PARAMETER. IT SHOULD BE A DATAOPR
	!OR AN ARRAYREF
	IF .VAR[OPRCLS] EQL LABOP THEN
		RETURN
	ELSE
	IF .VAR[OPRCLS] EQL DATAOPR THEN
	BEGIN
		IF .VAR[OPERSP] EQL CONSTANT OR .VAR[OPERSP] EQL FORMLFN THEN
			RETURN;
	END ELSE
	IF .VAR[OPRCLS] EQL ARRAYREF THEN
	BEGIN
		SELECTIT(.VAR[ARG1PTR]);
		RETURN;
	END ELSE	!IF NONE OF THE ABOVE
	RETURN;		!THEN GET OUT

	!HERE WE HAVE A SYMBOL TABLE ENTRY
	!SO WE WILL PROCESS IT.

	VAR[IDCHOS]_.LOOPNO;
	IF .T LSS 32 AND NOT .VAR[IDDEF] THEN
	BEGIN

		!EQUIVALENCED VARIABLES ARE NOT HANDLED
		IF .VAR[IDATTRIBUT(INEQV)] THEN RETURN;

		IF .VAR[IDATTRIBUT(INCOM)] THEN 
			PC_.VAR[IDCOMMON] ELSE
			PC_.VAR;
		INCR K FROM 0 TO 31 DO
			IF .CHOSEN[.K] EQL .PC THEN
			BEGIN
				CHKUNIQ(.PC);
				RETURN;
			END;

		!IF WE ARE HERE THE VARIBALE IS NOT ALREADY
		!SELECTED. SO WE WILL DO THAT NOW
			CHOSEN[.T]_.PC;
			VAR[IDDEF]_1;
			T_.T+1;
			!ADD THIS VARIABLE TO THE LIST OF
			!CHANGED IN THIS LOOP
			PC_.CHNGLST;
			NAME<LEFT>_CHNGSIZ;
			CHNGLST_CORMAN();
			IF .PC NEQ 0 THEN
				PC[RIGHTP]_.CHNGLST
			ELSE
				TOP[DOCHNGL]_.CHNGLST;
			CHNGLST[LEFTP]_.VAR;
			IF .T EQL 32 THEN LSTVAR_.P;

			!BUILD ITEM ON UNIQUE VALUE LIST TOO.

			PC_.UNIQVAL;
			NAME<LEFT>_UNIQSIZ;
			UNIQVAL_CORMAN();
			UNIQVAL[RIGHTP]_.PC;
			!PUT VARIABLE IN IN ALL CASES
			UNIQVAL[LEFTP]_.VAR;
			!SAVE ISN
			UNIQVAL[OPTISNVAL]_.ISN;
	END ELSE
	!THIS IS POTENTIALLY AN ADDITIONAL ASSIGNMENT AND WE NEED
	!TO TAKE IT OFF THE UNIQUE VALUR LIST
	CHKUNIQ(.VAR);
END;


ROUTINE CHKUNIQ(VAR)=
BEGIN

	EXTERNAL UNIQVAL,SAVSPACE,UNLIST;
	MAP PHAZ2 UNIQVAL:PC:VAR;

	!REMOVE VAR FROM UNIQUE VALUE LIST

		PC_.UNIQVAL;
		WHILE .PC NEQ 0 DO
		BEGIN
			!IF ITS ON THE LIST AND THE ISNS DO NOT MATCH
			!TAKE IT OFF
			IF .PC[LEFTP] EQL .VAR THEN
			BEGIN
				IF .PC[OPTISNVAL] NEQ .ISN THEN
					IF UNLIST(.UNIQVAL,.VAR,UNIQSIZ)
					THEN
					BEGIN
						PC_.UNIQVAL;
						UNIQVAL_.UNIQVAL[RIGHTP];
						SAVSPACE(UNIQSIZ-1,.PC);
					END;
					RETURN;
			END;
			PC_.PC[RIGHTP];
		END;
END;

!*****************************************************
ROUTINE THROINCOMMON=
BEGIN
	!PUT COMMON VARIABLES ON THE CHOOSEN LIST

	MAP BASE PCE;

		!DONT DO IT FOR HEARVALUED STUFF (DISPIX=2)
		IF .DISPIX EQL 2 THEN RETURN;

		INCR K FROM 0 TO SSIZ-1 DO
		BEGIN
			PCE_.SYMTBL[.K];
			WHILE .PCE NEQ 0 DO
			BEGIN
				IF .PCE[IDATTRIBUT(INCOM)] THEN
					(.SETSEL[.DISPIX])(.PCE);
				PCE_.PCE[CLINK];
			END;
		END;
END;
ROUTINE ANPARMS(ARGLSTPT)=
BEGIN
	!PUT THE PARAMETERS ON THE PARAMTER LIST (ARGLSTPT)
	!ON THE CHOSEN LIST
	!If we are in hot pursuit of a variable which may change as a
	!result of a function call, we must be careful to track all
	!possible nested function calls for occurrences of the variable.
	!Therefore, we make recursive calls to FCNLOK to catch all the
	!blankety nested function call cases!
	!This catches cases like F(G(X)) where X gets changed in G.
	!This entire routine was rewritten for edit 1034.

	MAP ARGUMENTLIST ARGLSTPT;

	LOCAL BASE ARGPTR; ! MUST be a local since this routine is recursive...


			INCR K FROM 1 TO .ARGLSTPT[ARGCOUNT] DO
			BEGIN
				ARGPTR_.ARGLSTPT[.K,ARGNPTR];	! Get the argument
				(.SETSEL[.DISPIX])(.ARGPTR);	! Do simple case

				IF .ARGPTR[OPRCLS] NEQ DATAOPR THEN
				IF .DISPIX EQL 2 THEN
				BEGIN	! Much harder - check array ref, and recur
					IF .ARGPTR[OPRCLS] EQL ARRAYREF
						THEN SETGOTVAL(.ARGPTR[ARG1PTR]);
					FCNLOK(.ARGPTR)
				END
			END;
END;

ROUTINE RSORT(CNODE)=
BEGIN

	!SORT THIS MULTIPLY NODE SO THAT THE DO LOOP
	!INDUCTION VARIABLE (INDVAR) IS ON THE TOP
	!OF ANY NARY TREE. IT WILL ALSO PUT IT TO THE
	!RIGHT ON BINARY TREES.

	EXTERNAL SWAP2DOWN,INDVAR;

	MAP BASE CNODE;

	REGISTER BASE T;

	!IS IT A BOTTOM MOST TREE
	IF .CNODE[A1VALFLG] AND .CNODE[A2VALFLG] THEN
	BEGIN
		!SWITCH ARGS IF THE DO LOOP VARIABLE IS
		!ARG1
		IF .CNODE[ARG1PTR] EQL .INDVAR THEN
![671] WHEN SWAPPING ARGS, SWAP DEF PTS TOO
%[671]%		(SWAPARGS(CNODE);
%[671]%		T_.CNODE[DEFPT2];
%[671]%		CNODE[DEFPT2]_.CNODE[DEFPT1];
%[671]%		CNODE[DEFPT1]_.T);
	END ELSE
	BEGIN
		!IT IS NOT A BOTTOM-MOST TREE. CHECK FOR NARY
		!DOWNWARD

		T_.CNODE[ARG1PTR];

		IF NARYNODE(T,CNODE) THEN
		BEGIN
			!IF THE LOWER BRANCH IS A LEAF AND THE INDUCION
			!VARIABLE THEN SWITCH THEM
			IF .T[ARG2PTR] EQL .INDVAR THEN
				SWAP2DOWN(.CNODE,.T);
		END;
	END;
END;

ROUTINE FCNLOK(EXPR)=
BEGIN
	!EXAMINE EXPRESSION EXPR FOR FUNCTION REFERENCES
	!IF ANY ARE FOUND PUT COMMON AND THE PARAMETERS ON THE
	!SELECTED LIST (THE VECTOR CHOSEN).

	MAP BASE EXPR;

	CASE .EXPR[OPRCLS] OF SET
	!BOOLEAN
	BEGIN
		FCNLOK(.EXPR[ARG1PTR]);
		FCNLOK(.EXPR[ARG2PTR]);
	END;
	!DATAOPR
		RETURN;
	!RELATIONAL
	BEGIN
		FCNLOK(.EXPR[ARG1PTR]);
		FCNLOK(.EXPR[ARG2PTR]);
	END;
	!FNCALL
	BEGIN
		IF .EXPR[OPERSP] NEQ LIBARY THEN
		BEGIN
			THROINCOMMON();
			ANPARMS(.EXPR[ARG2PTR]);
		END;
	END;
	!ARITHMETIC
	BEGIN
		FCNLOK(.EXPR[ARG1PTR]);
		FCNLOK(.EXPR[ARG2PTR]);

		!IF WE ARE SELECTING (DISPIX=0) THEN
		!SORT MULTIPLIES TO IMPROVE REDUCTIONS

		IF .DISPIX EQL 0 THEN
			CASE .EXPR[OPERSP] OF SET
			%ADD% ;
			%SUB% ;
			%MULTIPLY%
			RSORT(.EXPR);
			%DIV% ;
			%EXP% BEGIN END
			TES;
	END;
	!TYPECNV
		FCNLOK(.EXPR[ARG2PTR]);
	!ARRAYREF
		IF .EXPR[ARG2PTR] NEQ 0 THEN
			FCNLOK(.EXPR[ARG2PTR]);
	!CMNSUB
		RETURN;
	!NEGNOT
		FCNLOK(.EXPR[ARG2PTR]);
	!SPECOP
		FCNLOK(.EXPR[ARG1PTR]);
	!FIELDREF
		RETURN;
	!STORECLS
		RETURN;
	!REGCONTENTS
		RETURN;
	!LABOP
		RETURN;
	!STATEMENT
		RETURN;
	!IOLSCLS
		RETURN;
	!INLINFIN
	BEGIN
		FCNLOK(.EXPR[ARG1PTR]);
		IF .EXPR[ARG2PTR] NEQ 0 THEN
		FCNLOK(.EXPR[ARG2PTR]);
	END
	TES;
END;

ROUTINE ASSOCIA=
BEGIN
![1126]	!LOOK AT LINKED LIST OF ASSOCIATE VARIABLES (FROM OPENS)
![1126]	!AND SELECT SET OF INDICATE SET HERE FOR
	!THESE VARIABLES. THE MODULE OWN DISPIX IS SET TO CALL THE
	!CORRECT ROUTINE BY THE CALLER OF THIS ROUITNE.

	REGISTER BASE LP;

	LP_.ASSOCPT;
	WHILE .LP NEQ 0 DO
	BEGIN
		(.SETSEL[.DISPIX])(.LP[LEFTP]);
		LP_.LP[RIGHTP];
	END;
END;

!MACRO TO TEST RANDOM ACCESS PROPERTY OF AN I/O STATEMENT
!POINTED TO BY P AND CALL THE CORRECT SETSEL ROUTINE

MACRO RANDIO(P)=
BEGIN
	IF .P[IORECORD] NEQ 0 THEN
	BEGIN
		ASSOCIA();
		THROINCOMMON();
	END;
END$;

ROUTINE DEF0 =

BEGIN
	!LOOK AT STATEMENTS THAT POTENTAILLY ASSIGN A VALUE TO A
	!VARIABLE. CALL THE ROUTINE SELECTIT TO SELECT THE
	!VARIABLE. FUNCTIONS WITH SIDE EFFECTS WILL PRODUCE
	!BAD RESULTS.

	EXTERNAL CSTMNT,ISN;
	MAP BASE CSTMNT;

	MAP BASE PCE;

	MAP PHAZ2 TOP;

	!SET DISPATCH INDEX TO EXECUTE SELECTIT
	DISPIX_0;
	LSTVAR_-1;		!INITIALIZE LSTVAR
	!ALSO INITIALIZE CHOSEN
	DECR I FROM 31 TO 0 DO
		CHOSEN[.I]_0;
	!MAKE SURE WE GET THE INDUCTION VARIABLE
	IF .TOP[SRCID] EQL DOID THEN
		SELECTIT(.TOP[DOSYM]);

	!PICK FIRST 32 UNIQUE LHS TO PROCESS
	DO
	BEGIN
		CSTMNT_.P;
		ISN_.P[SRCISN];
		DEFWORK(.P);

		!TEST FOR JUST HAVING FILLED UP THE 32
		!IF WE DONT TEST NOW BY THE TIME WE UPDATE
		!P WE WILL HAVE PASTED LSTVAR

		IF .P EQL .LSTVAR THEN
		BEGIN
			MOREFLG_1;
			RETURN;
		END;

		P_.P[BUSY];
	END UNTIL  .P EQL 0 OR .P EQL .LSTVAR;
	IF .P EQL 0 THEN MOREFLG_0;
END;

!*******************************************************
!

ROUTINE SETIT(VAR)=
BEGIN
	!SET THE BIT IN THE ACC FIELD OF THE MODULE-OWN,P,
	!TO INDICATE THAT THE VARIABLE VAR IS DEFINED AT
	!SOME PREDECESSOR OF P.

	MAP BASE VAR; MAP PHAZ2 P;

	LOCAL I;

	IF .VAR[IDDEF] THEN		!THIS VARIABLE IS ELIGIBLE FOR
					!CONSIDERATION
	BEGIN
		I_LOOKUP(.VAR);

		IF .I LSS 32 THEN
			P[ACC]_SETBIT(.P[ACC],.I);
	END;
END;

ROUTINE DEFCHANGE(STMT)=
BEGIN
	!EXAMINE STATEMENTS THAT CAUSE VALUES OF VARAIBLES TO CHANGE
	!AND CALL SETIT OR SETREAD TO SET BITS IN THE MASK FOR THAT
	!WORD. MASK EXPLAINED IN COMMENTS THAT GO WITH DEF1.
	!NOTE:
	!THE BIT WILL BE SET IN THE MASK ASSOCIATED WITH THE MODULE
	!OWN P WI;HICH POINTS TO A STATEMENT.
	MAP PHAZ2 STMT;
	IF .STMT[SRCID] GTR REREDID THEN RETURN;

	!NOTHING ABOVE REREAD IS OF CONCERN

		!SET MODULE OWN THAT IS INDEX TO DISPATCH
		DISPIX_1;

	DEFWORK(.STMT);
END;


ROUTINE ONLYONEPRED(NODE)=
BEGIN
	!A VERSION TWO ROUTINE TO CHECK IF A NODE
	!HAS ONLY ONE PREDECESSOR. CURRENTLY ONLY USED IN
	!CONJUNCTION WITH ZAPLEVEL (IMMEDIATELY FOLLOWING)
	!IF THE NODE HAS A SINGLE PREDECOSSOR A POINTER
	!TO THAT PREDECESSOR IS RETURN ELSE 0 IS RETURNED.

	!THE GLOBAL QQ IS USED AS A TEMP.

	EXTERNAL QQ;
	REGISTER PHAZ2 T;
	MAP PHAZ2 NODE:QQ;

	T_.NODE[PREDPTR];		!START OF PREDECESSOR CHAIN
	QQ_.T[CESLNK];			!LINK TO NEXT ON CHAIN
	!IF QQ IS POINTING TO A ZERO WORD THERE IS ONLY ONE PREDECESSOR
	IF .QQ[CESLNK] EQL 0 THEN
		RETURN (.T[CESSOR])  	!RETURN THAT PREDECESSOR
	ELSE
		RETURN 0
END;

ROUTINE ZAPLEVEL(PRED)=
BEGIN
	!ROUTINE ZEROES THE LEVEL FIELD FOR ALL NODES ON ALL
	!PATHS BETWEEN PRED (A STATEMENT NODE) AND .P[PREDOM].
	!P IS SET UP EXTERNALLY TO THIS ROUTINE. AN EFFORT
	!IS MADE NOT TO RECURSE FOR STRAIGHT LINE PATHS,
	!THUS MINIMIZING THE STACK REQUIRED.

	MAP PHAZ2 PRED;
	OWN NODE,SINGLPRED;
	MAP PHAZ2 NODE;
![575] REMOVE THE LOCAL SYMBOL PLSTPTR SO THAT LESS STACK SPACE
![575] WILL BE USED DURING RECURSIVE CALLS OF THIS ROUTINE.  THE
![575] VARIABLE PRED WILL NOW DO DOUBLE DUTY - COMING IN AS THE
![575] STATEMENT NODE, AND BEING USED TO CYCLE THROUGH ALL OF THE
![575] PREDECESSORS OF THE ORIGINAL PARAMETER.  THIS CHANGE
![575] REDUCES THE STACK SPACE USED FROM 4 TO 3 LOCATIONS PER CALL
![575] TO THIS ROUTINE.


%[575]%	PRED_.PRED[PREDPTR];
![575] PRED IS NOW THE PTR TO THE PREDECESSOR LIST OF THE ORIGINAL PRED

	!FOR EACH PREDECESSOR ON THE LIST
%[575]%	WHILE .PRED[CESLNK] NEQ 0 DO
	BEGIN
		!POINTER TO AN ACTUAL PREDECESSOR
%[575]%		NODE_.PRED[CESSOR];

		!SET THE FLAG THAT HELPS US ITERATE INSTEAD OF RECURSING
		SINGLPRED_1;

		!NOW ITERATE
		WHILE .SINGLPRED DO
		BEGIN
			!IS THIS NODE ELIGIBLE, I.E.
			!	IS IT NOT P[PREDOM]
			!	DOES THE LEVEL FIELD NEED TO BE  ZEROED
			IF .NODE NEQ .P[PREDOM] AND .NODE[LEVEL] NEQ 0 THEN
			BEGIN
				!YES TEH NODE IS ELIGIBLE
				!ZERO THE LEVEL FIELD
				NODE[LEVEL]_0;
				!NOW SEE IF IT HAS A SINGLE PREDECESSOR
				IF (QQ_ONLYONEPRED(.NODE)) NEQ 0 THEN
					!SET NODE TO THE PREDECESSOR
					!RETURNED BY ONLYONEPRED AND
					!ITERATE
					NODE_.QQ
				ELSE
				BEGIN
					!THERE IS MORE THAN ONE
					!PREDECESSOR, SO WE MUST RECURSE
					ZAPLEVEL(.NODE);
					!RESET THE FLAG INDICATING ITERATION
					!RATHER THAN RECURSION.
					SINGLPRED_0;
				END;
			END ELSE
				!THE NODE IS NOT ELIGIBLE
				!RESET FLAG TO STOP LOOP
				SINGLPRED_0;
		END;		!WHILE ON SONGLPRED

		!NOW LOOK AT THE NEXT PREDECESSOR ON THE LIST
%[575]%		PRED_.PRED[CESLNK];
	END;		!WHILE THERE ARE PREDECESSORS
END;	!ROUTINE ZAPLEVEL


ROUTINE SWAMP=
BEGIN
	!MAKE AND FOLLOW A MOORE FLOOD ORDERING OF NODES BETWEEN
	!P AND P[PREDOM] SETTING BITS IN THE MASK AT P FOR
	!VARIABLES CHANGED AT ANY OF THE NODES TRAVERSED.

	MAP PHAZ2 P:T;
	OWN PHAZ2 TAIL;

	TAIL_HEAD_.P;

	!WHILE CONDITION WILL STOP ON ZERO OR THE FIELD SET TO 1 (PROCESSED MARK).
	WHILE .HEAD GTR #1000 DO
	BEGIN
		!PROCESS THE PREDECESSORS OF HEAD
		T_.HEAD[PREDPTR];
		WHILE .T[CESLNK] NEQ 0 DO
		BEGIN
			PA_.T[CESSOR];
			!PA IS NOW A REAL SUCCESSOR
			!IF IT IS NOT ALREADY DONE OR THE PREDOMINAATOR OF P
			!PROCESS IT
			IF .PA NEQ .P[PREDOM] THEN
			BEGIN
				IF .PA[LEVEL] EQL 0 THEN
				BEGIN
					!NOTE PA PROCESSED BY SETTING LEVEL NON-ZERO
					PA[LEVEL]_1;
					!ADD IT TO THE END OF THE CHAIN
					TAIL[LEVEL]_.PA;
					!UPDATE THE TAIL OF THE CHAIN
					TAIL_.PA;
					!SET THE %&$#% BIT
					DEFCHANGE(.PA);
				END;
			END;
			T_.T[CESLNK];
		END;
		HEAD_.HEAD[LEVEL];
	END;		!WHILE ON HEAD;
	!IF P'S PREDOMINATOR IS A DO STATEMENT WHICH ISN'T TOP, THEN
	!SET THE BITS IN P FOR ALL VARS CHANGED IN THE LOOP.
	PA_.P[PREDOM];
	IF (.PA NEQ .TOP) AND (.PA[SRCID] EQL DOID) THEN
		DEFCHANGE(.PA);
END;

FORWARD SPECBRCHK;
ROUTINE DEF1 =
BEGIN
	 MAP PHAZ2 T;
	!
	!INITIALIZE ACC FOR DEFINITION POINT CALCULATION
	!DETERMINE IF THERE IS AN INTERFERRING
	!ASSIGNMENT BETWEEN NODE AND IMMEDIATE
	!PREDOMINATOR

	!THE INITIALIZATION ALGORITHM IS:
	!1.	LOOK AT ALL IMMEDIATE PREDECESSORS OF A NODE
	!2.	IF THE PREDECESSOR IS NOT THE PREDOMINATOR THEN
	!	SET THE BIT IN THE MASK WHICH CORRESPOND TO ANY
	!	VARIABLE ASSIGNED A VALUE AT THAT PREDECESSOR.

	!A SPECIAL CASE IS THE FIRST STATEMENT AFTER THE DO LOOP
	!TO PREVENT COMPUTATIONS THAT ARE COMPOSED OF VARIABLES
	!ASSIGNED IN THE LOOP FROM ERRONEOUSLY MOVING OUTSIDE THE LOOP
	!THIS STATEMENT WILL HAVE THE BITS SET FOR ALL THE VARIABLES
	!ON THE DOCHNGL LIST TOO.

	MAP PHAZ2 TOP;
	EXTERNAL CSTMNT,ISN;
	LOCAL BASE ITM;
	MAP BASE CSTMNT;
	!
	P_.TOP;
	P[ACC]_0;
	P_.TOP[BUSY];
	!THE SPECIAL CASE

	IF .P EQL .TOP[SRCLINK] THEN
	BEGIN
		LOCAL SAVP;

		SAVP_.P;

		!A SPECAIL CASE OF THE SPECIAL CASE
		!IF THIS IS A DO LOOP SET THE BITS ON THE
		!CONTINUE AND NOT ON THE LOOP

		IF .P[SRCID] EQL DOID THEN
		BEGIN
			P_.P[DOLBL];
			P_.P[SNHDR];
		END;

		ITM_.TOP[DOCHNGL];
		WHILE .ITM NEQ 0 DO
		BEGIN
			!DOCHNGL IS A LINKED LIST
			!THE LEFT HALF OF THE WORD
			!POINTS TO THE VARIABLE, THE RIGHT
			!HALF TO THE NEXT LIST ITEM. IT IS
			!TERMINATED WITH A ZERO

			SETIT(.ITM[LEFTP]);
			ITM_.ITM[RIGHTP];
		END;
	IF .TOP[SRCID] EQL DOID THEN SETIT(.TOP[DOSYM]);
	!RESTORE SAVED VALUE OF P AND PROCEED
	P_.SAVP;
	END;

	!THE CAST OF CHARACTERS FOR THE NEXT WHILE LOOP IS
	!P THE STATEMENT ON WHICH MASK BITS ARE INITIALIZED
	!IF THE PREDECESSOR IS THE PREDOMINATOR SET NO BITS
	!IF  NOT ZERO THE LEVEL FIELD OF THE
	!OPTIMIZERS WORDS AND USE IT TO FLOOD AND SET BITS
	!FOR ALL VARIABLES ASSIGNED AT ALL NON_PREDOMINATING
	!PREDECESORS.
	!FOR ALL STATEMENTS
	DO
	BEGIN
		!FOR A DO LOOP THAT IS NOT TOP SET THE BITS ON THE
		!DO LOOP TOO INCASE SOMETHING BELOW THE TERMINATOR
		!IS NOT PREDOMINATED BY THE YERMINATOR

		IF .P NEQ .TOP AND .P[SRCID] EQL DOID THEN
		BEGIN
			ITM_.P[DOCHNGL];
			WHILE .ITM NEQ 0 DO
			BEGIN
				!DOCHNGL IS A LINKED LIST
				!THE LEFT HALF OF THE WORD
				!POINTS TO THE VARIABLE, THE RIGHT
				!HALF TO THE NEXT LIST ITEM. IT IS
				!TERMINATED WITH A ZERO
	
				SETIT(.ITM[LEFTP]);
				ITM_.ITM[RIGHTP];
			END;
		END;

		!TRY TO ELIMINATE SOME TIME AND EFFORT BY NOT
		!DOING THIS FOR A NODE IF IT HAS 1 PREDECESSOR
		!WHICH (BY DEFINITION) IS ITS PREDOMINATOR
		!SET THE LEVEL FIELD OF P[PREDOM] TO BE NON-ZERO
		T_.P[PREDOM];
		T[LEVEL]_1;
		!NOW START CHECKING ON PREDECESSORS
		T_.P[PREDPTR];
		!T IS A POINTER TO THE PREDECESSOR LIST
		PA_.T[CESLNK];
		!PA POINTS TO THE NEXT LINK
		T_.T[CESSOR];
		!T POINTS TO FIRST PREDECESSOR
		!MAKE SURE THERE ARE NONE OTHERS
		!PA POINTS TO NEXT LINK WORD. IF THERE IS ONLY ONE
		!PA IS A POINTER TO A WORD OF ZEROES.
		!THIS IS A DOUBLE SAFE CHECK. IF BLISS EVER DOES BETTER
		!ON BOOLEANS IT WILL ELIMINATE BUMMERS FAST.
		IF .T NEQ .P[PREDOM] OR .PA[CESLNK] NEQ 0  THEN
		BEGIN
			!TO INSURE AGAINST A FLUKE
			P[LEVEL]_0;
			ZAPLEVEL(.P);
			SWAMP();
		END
		!ON THE OTHERHAND IF THIS IS A SINGLE  PREDECESSOR
		!AND IT IS THE PREDOMINATOR AND IT IS A DO LOOP
		!WE WANT TO SET THE BITS FOR ALL VARIABLES IN THE LOOP
		ELSE
			IF .PA[CESLNK] EQL 0 AND .T[SRCID] EQL DOID THEN
				DEFCHANGE(.T);
		P_.P[BUSY];
	END UNTIL .P EQL 0;

	!CALL ROUTINE TO CHECK BRANCHES THAT SET VALUES
	!SEE COMMENTS IN CALLED ROUTINE FOR DETAILS

	SPECBRCHK();
END;


!*******************************************************
!
!*******************************************************
!
MAP PHAZ2 PB;
ROUTINE SETGOTVAL(VAR)=
BEGIN
	!THE GLOBAL TREEPTR POINTS TO S SYMBOL TABLES ENTRY.
	!IF  IT EQUALS VAR THEN SET GOTVAL TO 1
	EXTERNAL TREEPTR;

	IF .VAR EQL .TREEPTR THEN GOTVAL_1;
END;

GLOBAL ROUTINE READHERE(IOLSTT)=
%(**********************************************************************

	ROUTINE TO DETERMINE IF A VARIABLE WAS INITIALIZED
	AT THE IOLSCLS ELEMENT IOLSTT

**********************************************************************)%
BEGIN
EXTERNAL TREEPTR,INPFLAG;
MAP BASE IOLSTT;
	CASE .IOLSTT[OPERSP] OF SET
%DATACALL%	BEGIN
		LOCAL BASE ELEM;
		ELEM_.IOLSTT[DCALLELEM];
![1034] Do not overlook nested function calls.
%[1034]%		IF .INPFLAG THEN
%[1034]%		IF .ELEM[OPRCLS] EQL DATAOPR THEN
%[1034]%			(.SETSEL[.DISPIX])(.ELEM)
%[1034]%		ELSE IF .ELEM[OPRCLS] EQL ARRAYREF THEN
%[1034]%			(.SETSEL[.DISPIX])(.ELEM[ARG1PTR]);
%[1034]%		IF .DISPIX EQL 2 THEN FCNLOK(.ELEM)
		END;
%SLISTCALL%	BEGIN
		LOCAL BASE ELEM;
%[1034]%	IF NOT .INPFLAG THEN RETURN;
		ELEM_.IOLSTT[SCALLELEM];
		IF .ELEM[OPRCLS] EQL DATAOPR THEN
			(.SETSEL[.DISPIX])(.ELEM)
		ELSE
			(.SETSEL[.DISPIX])(.ELEM[ARG1PTR])
		END;
%IOLSTCALL%	BEGIN
		LOCAL BASE IOELEM;
%[1034]%		IF NOT .INPFLAG THEN RETURN;
		IOELEM_.IOLSTT[IOLSTPTR];
		WHILE .IOELEM NEQ 0 DO
		BEGIN
			READHERE(.IOELEM);
			IOELEM_.IOELEM[CLINK]
		END
		END;
%E1LISTCALL%	BEGIN
%[1034]%		IF NOT .INPFLAG THEN RETURN;
		LOKELIST(.IOLSTT[ELSTPTR])
		END;
%E2LISTCALL%	BEGIN
%[1034]%		IF NOT .INPFLAG THEN RETURN;
		LOKELIST(.IOLSTT[ELSTPTR])
		END
	TES
END;


GLOBAL ROUTINE SETGTRD(IOLSTT)=
BEGIN
	!EXAMINE THE IOLIST POINTED TO BY IOLSTT FOR
	!A SINGLE VARIABLE TREEPTR.

	EXTERNAL INPFLAG;

	MAP BASE IOLSTT;

	WHILE .IOLSTT NEQ 0 DO
	BEGIN
		IF .IOLSTT[OPRCLS] NEQ STATEMENT THEN 
![1034] Don't forget function calls in I/O statements
%[1034]%		READHERE(.IOLSTT)
		ELSE
		IF .IOLSTT[OPRS] EQL ASGNOS THEN
		BEGIN
			LOCAL BASE ELEM;
			ELEM_.IOLSTT[LHEXP];
			IF .ELEM[OPRCLS] EQL DATAOPR THEN
			(.SETSEL[.DISPIX])(.ELEM)
			ELSE
			(.SETSEL[.DISPIX])(.ELEM[ARG1PTR])
		END ELSE
		!TAKE NOTE OF THE FACT THAT THE DO LOOP
		!INDEX CHANGES IF THIS IS A LOOP

		IF .IOLSTT[OPRS] EQL DOOS THEN
			(.SETSEL[.DISPIX])(.IOLSTT[DOSYM]);
		IOLSTT_.IOLSTT[CLINK];
	END
END;	!SETGTRD


ROUTINE HEREVALUED(STMT, VAR)=
BEGIN
		!SEE IF THE VARIABLE VAR GETS A VALUE AT STATEMENT STMT.
		!IF SO RETURN 1 ELSE RETURN 0


	EXTERNAL TREEPTR;
	MAP BASE VAR:STMT;

	IF .STMT[SRCID] GTR REREDID THEN RETURN 0;

	!SET TREEPTR TO VAR FOR USE IN DEEPER ROUTINES
	TREEPTR_.VAR;
	!INITIALIZE GOTVAL TO 0
	GOTVAL_0;

	!SET DISPIX
	DISPIX_2;

	DEFWORK(.STMT);

	.GOTVAL
END;

GLOBAL ROUTINE GETDEF(CNODE,STMT,CDEFPT)=
BEGIN
EXTERNAL INDVAR;	!THE DO INDUCTION VARIABLE
LOCAL PDE;		!A TEMPORARY

REGISTER PHAZ2 TSTMT;

!COMPUTE ACTUAL DEFINITION POINT OF A LEAF NODE
!THIS ALGORITHM IS:
	!LOOK UP THE VARIABLE IN QUESTION (CNODE)
	!IF IT IS IN CHOSEN THEN CREATE A 36 BIT MASK WHICH HAS
	!THE BIT CORRESPONDING TO THE VARIABLE ON IN THE MASK.
	!STARTING WITH THE ACC OF THE CURRENT STATEMENT AND
	!THIS MASK WITH SUCCESSIVE ACC FIELDS ON THE PREDOMINATOR
	!CHAIN OF THE STATEMENT UNTIL THE MASK IS NOT ZERO. THIS
	!INDICATES AN INTERFERRING ASSIGNMENT IN THAT INTERVAL.
	!RETURN THE DEFINITION POINT AS THIS PLACE.

EXTERNAL PHAZ2 TOP;
MAP PHAZ2 CNODE;
!
	IF .CNODE[OPRCLS] EQL REGCONTENTS THEN RETURN(.TOP);
	IF .CNODE[OPRCLS] NEQ DATAOPR THEN RETURN(0)
	ELSE

	!IT SHOULD NOT BE A CONSTANT OR FORMAL FUNCTION

	IF .CNODE[OPERSP] EQL CONSTANT OR
	   .CNODE[OPERSP] EQL FORMLFN THEN RETURN(.LENTRY);


	IF .CNODE EQL .INDVAR THEN RETURN(.TOP);
	IF NOT .CNODE[IDDEF] THEN
	BEGIN
		IF NOT .MOREFLG THEN
		BEGIN
			CNODE[IDUSED]_1;
			IF .CNODE[IDATTRIBUT(INCOM)] OR
			   .CNODE[IDATTRIBUT(INEQV)] THEN
			RETURN(.STMT)
			ELSE
			!IF THE DO STATEMENT IS LABELED
			!WE MIGHT BE IN ROUTBLE IF WE SAY LENTRY
			!SPECIALLY IF LENTRY IS AN ASSIGNMENT OF THAT
			!VARIABLE TO A CONSTANT (I.E. IT WILL
			!GET PROPAGATED.
			RETURN(IF .TOP[SRCLBL] NEQ 0 THEN .TOP ELSE .LENTRY);
		END;
	END ELSE
	BEGIN
	!JUST TO MAKE SURE AVOID EQUIVALENCE LIKE THE PLAQUE.
	!EQUIVALENCE LISTS ARE NOT PROCESSED UNTIL REGISTER
	!ALLOCATION
	IF .CNODE[IDATTRIBUT(INCOM)] THEN RETURN(.STMT);
	IF .CNODE[IDATTRIBUT(INEQV)] THEN RETURN(.STMT);
	PDE_LOOKUP(.CNODE);
	IF .PDE GTR 32 THEN RETURN .CDEFPT;
	MASK_0;
	MASK_SETBIT(.MASK,.PDE);
	TSTMT_.STMT;			!PT TO STATEMENT
	WHILE 1 DO
	BEGIN
		IF (.TSTMT[ACC] AND .MASK) NEQ 0 THEN RETURN(.TSTMT);
		IF .TSTMT EQL .TOP THEN RETURN(.LENTRY);
		IF HEREVALUED(.TSTMT,.CNODE) THEN RETURN(.TSTMT);
		TSTMT_.TSTMT[PREDOM];
	END;
	END;
	.CDEFPT		!JUST IN CASE
END;
!**********************************************************
!
ROUTINE VDEFPT(PNODE)=
BEGIN
!WALK AN EXPRESSION TREE COMPUTING DEFINITION POINTS OF LEAFS (VARIABLES)
EXTERNAL ARGCONE;
REGISTER PHAZ2 P;
P_.PNODE;
		CASE .P[OPRCLS] OF SET

			!BOOLEAN
			BEGIN
			IF .P[A1VALFLG] THEN
				P[DEFPT1]_GETDEF(.P[ARG1PTR],.PAE,.P[DEFPT1])
			ELSE
			VDEFPT(.P[ARG1PTR]);
			IF .P[A2VALFLG] THEN
				P[DEFPT2]_GETDEF(.P[ARG2PTR],.PAE,.P[DEFPT2])
			ELSE
			VDEFPT(.P[ARG2PTR]);
			END;

			!DATAOPR
				RETURN;

			!RELATIONAL
			BEGIN
			IF .P[A1VALFLG] THEN
				P[DEFPT1]_GETDEF(.P[ARG1PTR],.PAE,.P[DEFPT1])
			ELSE
			VDEFPT(.P[ARG1PTR]);
			IF .P[A2VALFLG] THEN
				P[DEFPT2]_GETDEF(.P[ARG2PTR],.PAE,.P[DEFPT2])
			ELSE
			VDEFPT(.P[ARG2PTR]);
			END;

			!FNCALL
			BEGIN
				LOCAL ARGUMENTLIST AG;
				AG_.P[ARG2PTR];
				INCR I FROM 1 TO .AG[ARGCOUNT] DO
					VDEFPT(.AG[.I,ARGNPTR]);
				!GIVE ARG A DEFPT ON SINGLE
				!ARGUMENT LIBRARY FUNCTIONS
				IF ARGCONE(.P) THEN
					P[DEFPT2]_GETDEF(.AG[1,ARGNPTR],.PAE,.P[DEFPT2]);
			END;

			!ARITHMETIC
			BEGIN
			IF .P[A1VALFLG] THEN
				P[DEFPT1]_GETDEF(.P[ARG1PTR],.PAE,.P[DEFPT1])
			ELSE
			VDEFPT(.P[ARG1PTR]);
			IF .P[A2VALFLG] THEN
				P[DEFPT2]_GETDEF(.P[ARG2PTR],.PAE,.P[DEFPT2])
			ELSE
			VDEFPT(.P[ARG2PTR]);
			END;

			!TYPCNV
			IF .P[A2VALFLG] THEN
				P[DEFPT2]_GETDEF(.P[ARG2PTR],.PAE,.P[DEFPT2])
			ELSE
			VDEFPT(.P[ARG2PTR]);

			!ARRAYREF
			BEGIN
				IF .P[A2VALFLG] THEN
					IF .P[ARG2PTR] EQL 0	!IF ITS A CONSTANT SS
					THEN	!WE WOULD LIKE IT TO BE LENTRY
					!BUT THAT BOMBS AND WE WANT THIS IN V4A
						P[DEFPT2]_.PAE	!SO SETTLE FOR WHAT WORKS
					ELSE
						P[DEFPT2]_GETDEF(.P[ARG2PTR],.PAE,.P[DEFPT2])
				ELSE
				VDEFPT(.P[ARG2PTR]);
				!LOOK AT ARRAYNAME TOO
				P[DEFPT1]_GETDEF(.P[ARG1PTR],.PAE,.P[DEFPT1]);
			END;

			!CMNSUB
			IF .P[A2VALFLG] THEN
				P[DEFPT2]_GETDEF(.P[ARG2PTR],.PAE,.P[DEFPT2])
			ELSE
			VDEFPT(.P[ARG2PTR]);

			!NEGNOT
			IF .P[A2VALFLG] THEN
				P[DEFPT2]_GETDEF(.P[ARG2PTR],.PAE,.P[DEFPT2])
			ELSE
			VDEFPT(.P[ARG2PTR]);

			!SPECOP
			IF .P[A1VALFLG] THEN
				P[DEFPT1]_GETDEF(.P[ARG1PTR],.PAE,.P[DEFPT1])
			ELSE
			VDEFPT(.P[ARG1PTR]);

			!FIELDREF
			BEGIN END;	!NOT RELEASE 1

			!STORECLS
			BEGIN END;

			!REGCONTENTS
			!IT MUST BE THE INDUCTION VARIABLE
			BEGIN END;	!SHOULDNT GET HERE

			!LABOP
			BEGIN END;

			!STATEMENT
			BEGIN END;

			!IOLSCLS
			BEGIN END;

			!INLINFN
			BEGIN
				IF .P[A1VALFLG] THEN
					P[DEFPT1]_GETDEF(.P[ARG1PTR],.PAE,.P[DEFPT1])
				ELSE
				VDEFPT(.P[ARG1PTR]);
				IF .P[ARG2PTR] NEQ 0 THEN
				BEGIN
					IF .P[A2VALFLG] THEN
					P[DEFPT2]_GETDEF(.P[ARG2PTR],.PAE,.P[DEFPT2])
					ELSE
					VDEFPT(.P[ARG2PTR]);
				END;
			END
			TES;
END;
!************************************************************
!

!TO MAKE CODE LOOK NEATER THIS MACRO IS USED 
MACRO DATAGET=
	IF .P[OPRCLS] EQL DATAOPR THEN RETURN
	ELSE VDEFPT(.P)$;
ROUTINE DEFPT(STMT)=
BEGIN
!AFTER INTERFERING ASSIGNMENT INFORMATION IS COLLECTED
!USE IT TO COMPUTE DEFINITION POINTS FOR LEAVES AND EXPRESIONS
!CONTROL AT THE STATEMENT LEVEL
!THIS IS THE STATEMENT LEVEL ROUTINE AS OPPOSED TO THE
!EXPRESSION LEVEL ROUTINE WHICH IS VDEFPT (VARIABLE DEFPT).

EXTERNAL IOSTDFPT;	!COMPUTE DEFPTS IN I/O LIST <IOPT>
MAP BASE TOP;
MAP PHAZ2 STMT;
PAE_.STMT;		!PAE USED IN LOWER ROUTINES
IF .STMT[SRCID] EQL ASGNID THEN
BEGIN
	P_.STMT[LHEXP];
	IF .P[OPRCLS] EQL ARRAYREF THEN
		VDEFPT(.P);
	P_.STMT[RHEXP];
	IF .P[OPRCLS] EQL DATAOPR THEN STMT[OPDEF]_GETDEF(.P,.STMT,0)
	ELSE
	VDEFPT(.P);
END;
IF .STMT[SRCID] EQL DOID THEN
!SKIP IT IF THIS IS THE CURRENT DO WE ARE PROCESSING
BEGIN
	IF NOT .STMT[FLCWD] AND .STMT[SRCOPT] NEQ 0 THEN
	BEGIN
		P_.STMT[DOLPCTL];
		IF .P[OPR1] EQL CONSTFL THEN
		!STMT[DOPDEF]_.LENTRY
		ELSE
		IF .P[OPRCLS] EQL DATAOPR THEN
		!STMT[DOPDEF]_GETDEF(.P,.STMT)
		ELSE
		VDEFPT(.P);
	END;
END;
IF .STMT[SRCID] EQL IFLID THEN
BEGIN
	P_.STMT[LIFEXPR];
	DATAGET;
	DEFPT(.STMT[LIFSTATE]);
END;
IF .STMT[SRCID] EQL IFAID THEN
BEGIN
	P_.STMT[AIFEXPR];
	DATAGET;
END;
IF .STMT[SRCID] EQL CALLID THEN
BEGIN
	IF .STMT[CALLIST] NEQ 0 THEN
	BEGIN
		LOCAL ARGUMENTLIST AG;
		AG_.STMT[CALLIST];
		INCR K FROM 1 TO .AG[ARGCOUNT] DO
		BEGIN
			PB_.AG[.K,ARGNPTR];
			IF .PB[OPRCLS] NEQ DATAOPR THEN
			VDEFPT(.PB);
		END;
	END;
END;
IF .STMT[SRCID] GEQ READID AND .STMT[SRCID] LEQ REREDID THEN
BEGIN
	IF .STMT[IOLIST] NEQ 0 THEN
	BEGIN
		IOSTDFPT(.STMT)
	END
END;
END;
!
!***************************************
!
GLOBAL ROUTINE DEFDRIV=
BEGIN

!CONTROLER FOR THE DEFINITION POINT ALGORITHM

	EXTERNAL CSTMNT,ISN;
	EXTERNAL UNIQVAL;
	MAP PHAZ2 CSTMNT:TOP;

	UNIQVAL_0;
	CHNGLST_0;
	MOREFLG_1;
	P_.TOP[BUSY];
	WHILE .MOREFLG DO
	BEGIN
		T_0;
		!EACH ROUTINE IS A SEPARATE PASS OVER THE
		!ENCODED SOURCE FOR THE CURRENT LOOP
		DEF0();		!PICK 32 VARIALES
		!IF THERE WERE NO VARIABLES (WRITE STATEMENT ONLY,
		!FOR EXAMPLE, QUIT HERE

		IF .T EQL 0 THEN
			MOREFLG_0
		ELSE
		BEGIN
			DEF1();		!INITIALIZE THE MASK
		END;
		!NOW WE ARE READY TO ACRUALLY GET DEFINITION POINTS
		CSTMNT_.TOP[BUSY];		!SKIP CURRENT LOOP
		WHILE .CSTMNT NEQ 0 DO
		BEGIN
			ISN_.CSTMNT[SRCISN];
			DEFPT(.CSTMNT);
			CSTMNT_.CSTMNT[BUSY];
		END;
		P_.LSTVAR;
	END;
END;
!
!*************************************************
!
ROUTINE CHKNAML(NLPTR)=
BEGIN
	!ROUTINE TO CHECK A NAME LIST.
	!IT:
	!	1. DETERMINES IF NLPTR POINTS TO A NAMELIST NAME
	!	   SYMBOL TABLE ENTRY
	!	2. IF SO, IT SEARCHS THE LINKED LIST OF NAMELIST
	!	  STATEMENTS FOR THE MATCHING NAMELIST
	!	3. IT THEN SETS THE BITS (SELECTIT,SETIT,SETGOTVAL)
	!	   USING THE DISPIX SET UP BY THE CALLER
	OWN BASE NPTR;
	LABEL NLLOK;
	MAP BASE NLPTR;

	EXTERNAL NAMLPTR;

	BIND M1RH=#000000777777;	!-1 IN RIGHT HALF WORD

	!FIRST SEE IF NLPTR POINTS TO A NAMELIST SYMBOL TABLE ENTRY

	IF .NLPTR NEQ 0 AND .NLPTR NEQ M1RH THEN
	BEGIN
		IF .NLPTR[IDATTRIBUT(NAMNAM)] THEN
		BEGIN
			NPTR_.NLPTR[IDCOLINK];	!GET POINTER

			!WE HAVE LOOKED AT LIST WE HAVE TO QUIT IF
			!NPTR IS ZERO
			IF .NPTR EQL 0 THEN RETURN;
			!NPTR POINTS TO THE NAME LIST STATEMENT ENTRY
			INCR I FROM 0 TO .NPTR[NAMCNT]-1 DO
%[1010]%			(.SETSEL[.DISPIX])(.(.NPTR[NAMLIST]+.I)<RIGHT>);
		END;
		!ITS NOT A NAME LIST NAME
	END;
END;
ROUTINE SETONSUC(STMT)=
BEGIN
	!COMPANION ROUITNE TO SPECBRCHK
	!OR THE MASK OF STMT INTO EACH OF ITS SUCCESSORS IF IT IS NOT ZERO
	REGISTER SUCLSTPTR,T;
	MAP PHAZ2 STMT:SUCLSTPTR:T;
	LOCAL PHAZ2 SAVEP;
	LOCAL ACCSAVE;

%[1113]%	ACCSAVE _ .STMT[ACC];		! SAVE ACC BITS
%[1113]%	T _ .STMT[SUCPTR];              ! GET SUCCESSOR LIST
%[1113]%	IF .T[CESLNK] NEQ 0             ! IF STMT HAS MULTIPLE SUCCESSORS
%[1113]%	THEN
%[1113]%	BEGIN
%[1113]%		SAVEP _ .P;               ! SAVE P, ARG TO DEFCHANGE
%[1113]%		P _ .STMT;                ! SET ACC BITS IN STMT FOR EACH
%[1113]%		DEFCHANGE(.STMT);         !   VARIABLE ASSIGNED BY STMT
%[1113]%		P _ .SAVEP;               ! RESTORE P
%[1113]%	END;

	IF .STMT[ACC] NEQ 0 THEN
	BEGIN

		!SET IT ON THE POST DOMINATOR JUST TO BE 10000000%
		!SURE

		T_.STMT[POSTDOM];
		T[ACC]_.T[ACC] OR .STMT[ACC];

		SUCLSTPTR_.STMT[SUCPTR];
		!FOLLOW SUCCESSOR CHAIN
		WHILE .SUCLSTPTR[CESLNK] NEQ 0 DO
		BEGIN
			!LOOK AT ACTUAL SUCCESSOR
			T_.SUCLSTPTR[CESSOR];
			T[ACC]_.T[ACC] OR .STMT[ACC];

			!NEXT SUCCESSOR
			SUCLSTPTR_.SUCLSTPTR[CESLNK];
		END;	!WHILE
	END;
%[1113]%	STMT[ACC] _ .ACCSAVE;
END %SETONSUC%;

ROUTINE SPECBRCHK=
BEGIN
	!ROUTINE CHECKS ALL BRANCHING STATEMENTS.
	!IF SOMETHING IS DEFINED AT A BRANCHING STATEMENT
	!THE APPROPRIATE BIT MUST BE SET ON THE IMMEDIATE
	!SUCCESSORS OF THE BRANCH IN ORDER TO ASSURE THAT
	!CASES SUCH AS THE FOLLOWING DO NOT
	!CAUSE INCORRECT CODE.
	!EXAMPLE:
	!	A LOGICAL IF (CONTAINING A FUNCTION) CALL IS THE
	!	DEFINITION POINT OF AN ARGUMENT TO THE FUNCTION CALL.
	!	WITHOUT THIS ADDITIONAL PROCESSING, IF THE
	!	MOTION PLACE OF AN EXPRESSION WAS THE LOGICAL IF
	!	THE COMPUTATION WOULD BE INSERTED ONLY ON THE
	!	FALSE BRANCH. SETTING THE BITS ON THE SUCCESSORS
	!	INSURES THAT THE LOGICAL IF WILL NOT TURN OUT TO
	!	BE THE MOTION PLACE.
        !
        ![1113] ADDITIONALLY, SET ACC BITS FOR EACH VARIABLE ASSIGNED
        !BY THE BRANCHING STATEMENT ITSELF.
	!       
        !THIS BUSINESS IS NECESSARY TO PREVENT A STATEMENT WHICH BOTH
	!BRANCHES AND ASSIGNS VALUES FROM BECOMING THE DEF POINT FOR ANY
	!VARIABLE.  IF SUCH A STATEMENT WERE CHOSEN AS THE MOTION PLACE FOR A
	!CSE, THE CSE CALCULATION WOULD HAVE TO BE PUT ON EACH SUCCESSOR OF THE
	!STATEMENT.  INSTEAD, THIS SCHEME PREVENTS A STATEMENT WITH MULTIPLE
	!SUCCESSORS FROM BEING IDENTIFIED AS THE DEF POINT OF THE VARIABLES
	!WHICH IT ASSIGNS.  ACC BITS ARE SET IN EACH SUCCESSOR (SO THAT CSE
	!MOVEMENT WILL STOP WHEN IT HITS THE SUCCESSOR) AND THE POSTDOMINATOR
	!(SO THAT MOVEMENT OF CSES WHICH OCCUR AFTER THE POSTDOMINATOR WILL HIT
	!THE POSTDOMINATOR AND STOP THERE).

	LABEL L1;
	MAP PHAZ2 P:TOP;

	P_.TOP[BUSY];

	WHILE .P NEQ 0 DO
	BEGIN
		!FIRST A GENERAL BRANCH
		IF .P[SRCID] GEQ GOTOID AND .P[SRCID] LEQ IFLID THEN
			SETONSUC(.P)
		ELSE
		!A CALL
		!WITH LABLE ARGUMENTS
		IF .P[SRCID]  EQL CALLID THEN
		BEGIN
			LOCAL ARGUMENTLIST AG;
			L1:
			IF .P[CALLIST] NEQ 0 THEN
			BEGIN
				AG_.P[CALLIST];
				INCR I FROM 1 TO .AG[ARGCOUNT] DO
				BEGIN
					REGISTER BASE T;

					T_.AG[.I,ARGNPTR];
					IF .T[OPRCLS] EQL LABOP THEN
					BEGIN
						SETONSUC(.P);
						LEAVE L1;
					END;
				END;
			END;
		END ELSE
%[760]%		IF (.P[SRCID] GEQ READID AND .P[SRCID] LEQ ENDFID) OR
%[760]%		    (.P[SRCID] EQL OPENID)
%[760]%		THEN
		!ITS AN I/O STATEMENT. IT IS A BRANCH IF THERE IS AN
		!END OR ERR SPECIFIED
			IF .P[IOERR] NEQ 0 OR .P[IOEND] NEQ 0 THEN
				SETONSUC(.P);

		!NEXT STATEMENT
		P_.P[BUSY];
	END;			!WHILE
END;


ROUTINE DEFWORK(P)=
BEGIN
	!MAIN ROUITN;INE TO DO ALL THE DEFPOINT WORK.
	!CALLED BY HEREVALUES, DEF0 AND DEFCHANGE

	REGISTER BASE TMP;
%[763]%	REGISTER ARGUMENTLIST ALST;	! FOR ENTRY FORMALS
	MAP PHAZ2 P;

	EXTERNAL CSTMNT,INPFLAG;
	MAP BASE CSTMNT;


![760] Check iostat= for all I/O statements - it's an implicit assignment
%[760]%	IF (.P[SRCID] GEQ READID AND .P[SRCID] LEQ ENDFID) OR  .P[SRCID] EQL OPENID
%[760]%	THEN
%[760]%	BEGIN
%[760]%		IF .P[IOIOSTAT] NEQ 0
%[760]%		THEN
%[760]%		BEGIN
%[760]%			TMP_.P[IOIOSTAT];
%[760]%			IF .TMP[OPRCLS] EQL DATAOPR
%[760]%			THEN (.SETSEL[.DISPIX])(.P[IOIOSTAT])
%[760]%			ELSE (.SETSEL[.DISPIX])(.TMP[ARG1PTR]);
%[760]%		END;
%[760]%	END;

	IF .P[SRCID] GEQ CLOSID THEN RETURN;

	CASE .P[SRCID] OF SET

%ASGNID%
	BEGIN
		TMP_.P[LHEXP];
		IF .TMP[OPRCLS] EQL DATAOPR THEN
			 (.SETSEL[.DISPIX])(.TMP)
		ELSE
			(.SETSEL[.DISPIX])(.TMP[ARG1PTR]);
		FCNLOK(.P[RHEXP]);
	END;
%ASSIID%
	BEGIN
		TMP_.P[ASISYM];
		IF .TMP[OPRCLS] EQL DATAOPR THEN
			(.SETSEL[.DISPIX])(.TMP)
		ELSE
		IF .TMP[OPRCLS] EQL ARRAYREF THEN
			(.SETSEL[.DISPIX])(.TMP[ARG1PTR]);
	END;
%CALLID%
	BEGIN
		!PUT COMMONIN THE LIST
		THROINCOMMON();
		!PUT PARAMETERS ON THE LIST
		IF .P[CALLIST] NEQ 0 THEN
			ANPARMS(.P[CALLIST]);
	END;

%CONTID%
	BEGIN END;
%DOID%
	BEGIN
		FCNLOK(.P[DOLPCTL]);
		!THIS MUST BE INNER TO THE ONE CURRENTLY BEING
		!PROCESSED
		!MAKE SURE THAT WE NOTE THE VARIABLES CHANGED IN IT
		!IN THE ALGORITHM
		TMP_.P[DOCHNGL];
		WHILE .TMP NEQ 0 DO
		BEGIN
			(.SETSEL[.DISPIX])(.TMP[LEFTP]);
			TMP_.TMP[RIGHTP];
		END;
	END;
%ENTRID%
%[763]%	BEGIN
%[763]%		IF (ALST _ .P[ENTLIST]) NEQ 0 THEN
%[763]%		BEGIN
%[763]%			INCR K FROM 1 TO .ALST[ARGCOUNT] DO
%[763]%			BEGIN
%[763]%				IF (TMP _ .ALST[.K,ARGNPTR]) NEQ 0 THEN
%[763]%					IF .TMP[OPRCLS] EQL DATAOPR THEN
%[763]%						(.SETSEL[.DISPIX])(.TMP)
%[763]%					ELSE
%[763]%						(.SETSEL[.DISPIX])(.TMP[ARG1PTR])
%[763]%			END;
%[763]%		END;
%[763]%	END;
%COMNSUB%
	BEGIN END;
%GOTOID%
	BEGIN END;
%AGOID%
	FCNLOK(.P[AGOTOLBL]);
%CGOTOID%
	FCNLOK(.P[CGOTOLBL]);
%IFAID%
	FCNLOK(.P[AIFEXPR]);
%IFLID%
	FCNLOK(.P[LIFEXPR]);
%RETUID%
	IF .P[RETEXPR] NEQ 0 THEN
		FCNLOK(.P[RETEXPR]);
%STOPID%
	BEGIN END;
%READID%
	BEGIN
		INPFLAG_1;
		IF .P[IOLIST] NEQ 0 THEN
		BEGIN
			SETGTRD(.P[IOLIST]);
			RANDIO(P);
		END ELSE
			CHKNAML(.P[IONAME]);
	END;
%WRITID%
	BEGIN

	!YOU ARE SURPRISED TO FIND A WRITE HERE. IT IS RELEVANT 
	!IF IT IS RANDOM ACCESS; IN THAT CASE ANY ASSOCIATE VAIABLES
	!MUST BE CONSIDERED. ALSO COMMON.
	!ALSO FUNCTION CALL ARGUMENTS MAY CHANGE VALUE - HENCE THE
	!CALL TO SETGTRD.


	SETGTRD(.P[IOLIST]);
	RANDIO(P);
	END;

%DECOID%
	BEGIN
		INPFLAG_1;
		SETGTRD(.P[IOLIST]);
	END;
%ENCOID%
	BEGIN
		IF .P[IOVAR] NEQ 0 THEN
		BEGIN
			TMP_.P[IOVAR];
			IF .TMP[OPRCLS] EQL DATAOPR THEN
				(.SETSEL[.DISPIX])(.P[IOVAR])
			ELSE
				(.SETSEL[.DISPIX])(.TMP[ARG1PTR]);
			SETGTRD(.P[IOLIST]);
		END;
	END;
%REREDID%
	BEGIN
		INPFLAG_1;
		SETGTRD(.P[IOLIST]);
	END;


%FINDID%
	RANDIO(P);
	TES;
	INPFLAG_0;
END;
END
ELUDOM