!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,1977 BY DIGITAL EQUIPMENT CORPORATION !AUTHOR: S. MURPHY/HPW/MD/JNG/SJW MODULE CPLX(SREG=#17,VREG=#15,FREG=#16,DREGS=4,RESERVE(0,1,2,3)) = BEGIN GLOBAL BIND CPLXV = 5^24 + 0^18 + 132; !VERSION DATE: 3-Nov-76 %( REVISION HISTORY 115 ----- ----- ADD ROUTINES CMPE1LIST AND CMPE2LIST TO COMPUTE COMPLEXITY FOR E1LISTCALL AND E2LISTCALL NODES 116 ----- ----- ALLOCATE CONSTANT ZERO IN E1INCR OR E2INCR FIELD OF E1LISTCALL OR E2LISTCALL NODES 117 ----- ----- KEEP VALUE OF "PAIRMODE" CORRECTLY INSIDE OF IOLISTS ("CMPLIOLST" NEEDED MODIFYING) KEEP VALUE OF "FNREF" INSIDE OF IOLISTS SET "FNREF" WHEN A FNCALL IS ENCOUNTERED 118 ----- ----- IN A SYMMETRIC BINARY OPERATION WITH TWO REGISTER ARGUMENTS ONE OF WHICH IS THE FUNCTION RETURN REGISTER, PERFORM CALCULATIONS IN THE OTHER REGISTER 119 ----- ----- IMPROVE COMPLEXITY CALCULATION FOR DATACALL, E1LISTCALL, AND E2LISTCALL NODES 120 ----- ----- SAME FOR FUNCTION AND SUBROUTINE CALLS 121 ----- ----- ADD CMPLEXITY FOR CMPLX IN LINE 122 ----- ----- ALLOW "EXCHARGS" TO BE CALLED FOR IN LINE FNS 123 ----- ----- REMOVE ALL REFERENCES TO SQROP,CUBOP,P4OP (THEY ARE ALL NOW UNDER EXPCIOP) 124 ----- ----- CHANGE REFS TO THE MACRO "POWEROF2" TO "POWOF2" 125 ----- ----- FIX BUG IN CMPILF; DIM CANNOT HAVE AN IMMED MODE 2ND ARG 126 ----- ----- ? 127 301 16154 SET FNCALLSFLG IN CSTMNT WHEN CHANGING ** TO FUNCTION CALL 128 344 17768 PROPAGATE FNCALLSFLG TO NEG/NOT NODE EVEN IF COMPLEXITY OF ARGUMENT IS ZERO. 129 411 19537 DON'T EXCHANGE ARGS TO MAX OR MIN FUNCTION IF FIRST ARG IS NEGATIVE. ** BEGIN VERSION 5 130 412 ----- IN CMPLA FOR DOUBLE ARRAYREF FOR KA10, PARENT COMPLEXITY MUST BE AT LEAST 3 131 426 18816 SET FNCALLSFLG FOR STATEMENTS CONTAINING IMPLICIT FN CALLS SO 0,1, 16 WILL BE SAVED. 132 510 ----- DON'T LOOK FOR ALCRETREGFLG IN DATAOPR NODES. )% EXTERNAL CGERR,NXTTMP,ALOCONST,TBLSEARCH,C1H,C1L,DNEGCNST,MAKEPR, MAKPR1; FORWARD SETCOMPLEXITY(0),CMPLA(0),CMARGS(0),PRCNSTARG(3), ARRNARGBLK(2), CMPVBOOL(0),CMPLBL(0),CMPLREL(0), CMPLFNCALL(0),CMPFNARGS(1),CMPTPCNV(0),CMPLXARRAY(0),CMPILF(0), CMPLIOLST(0),CMPE1LIST(1),CMPE2LIST(1),SNGARGPROP(2), CMPIOCALL(1),EXCHARGS(0),EXPTOFNCALL(0); EXTERNAL TREEPTR,GBSYREGS,RESNAME,CLOBBREGS; EXTERNAL KISNGL; EXTERNAL PROPNEG; !(IN MODULE UTIL - ROUTINE TO PROPAGATE A NEGATE) EXTERNAL SAVREGCONTAINING; !IN BASIC-BLOCK REG ALLOCATOR (MODULE "CMPBLO") ! ROUTINE TO SET FLAG IN THE PREVIOUS REF TO A VAR ! SO THAT THE REG CONTAINING IT WILL BE SAVED; EXTERNAL ADDREGCANDATE; !IN BASIC-BLOCK REG ALLOCATOR - ROUTINE TO ADD ! A VAR TO THE SET OF VARS WHOSE VALS ARE LEFT IN ! REGS BY THE COMPUTATION OF STMNTS IN THE BLOCK EXTERNAL SRCHREGCANDATE; !IN BASIC-BLOCK ALLOCATOR, ROUTINE THAT CHECKS WHETHER OR ! A GIVEN VAR IS IN THE SET OF VARS WHOSE VALS WERE LEFT ! IN REGS BY THE COMPUTATION OF PRECEEDING STMNTS %**;[301],CMPLEX,JNT,13-JUN-75% %**;[301],IN MODULE HEAD @ 61% EXTERNAL CSTMNT; ![301] POINTER TO SOURCE STATEMENT NODE SWITCHES NOLIST; REQUIRE FIRST.BLI; REQUIRE TABLES.BLI; SWITCHES LIST; %(*************************************************************************** LOCAL REGISTER ALLOCATION MODULE. INCLUDES 2 PASSES OVER AN EXPRESSION TREE. ON THE "COMPLEXITY WALK" (IE THE ROUTINE SETCOMPLEXITY AND ALL THE ROUTINES IT CALLS), THE NODES ARE REARRANGED TO REDUCE THE NUMBER OF REGISTERS NECESSARY TO COMPUTE THEM, AND THE MINIMUM NUMBER OF REGS NECESSARY IS SAVED IN EACH NODE. AT THIS TIME CONSTANTS THAT CAN BE USED "IMMED MODE" ARE RECOGNIZED AND SPACE IS ALLOCATED FOR ALL OTHERS. THE CONSTANT PART OF AN ARRAY ADDRESS CALC IS ALSO ADDED IN TO THE INSTRUCTION ADDRESS AT THIS TIME. THE 2ND WALK (THE ROUTINES "ALCINREG" AND "ALCINTMP") ALLOCATES REGISTERS(AND/OR TEMPORARIES) FOR EACH BINARY/UNARY OPERATION TO BE PERFORMED - TARGETING THE VALUE OF AN EXPRESSION TO A PARTICULAR REG/TMP THE GLOBAL "TREEPTR" IS USED IN BOTH THESE WALKS TO POINT TO THE NODE OF THE EXPRESSION TREE BEING PROCESSED. ***************************************************************************)% %**;[301],CMPLEX,JNT,13-JUN-75% %**;[301],IN MODULE HEAD @ 3224% MAP BASE CSTMNT; ![301] MAP PEXPRNODE TREEPTR; GLOBAL ROUTINE SETCOMPLEXITY = %(*************************************************************************** ROUTINE TO COMPUTE THE COMPLEXITY (IE # OF REGS NECESSARY FOR COMPUTATION) OF EXPRESSION NODES AND STORE THAT VALUE INTO THE NODE ITSELF ALSO TRIES TO MAKE ARG1 BE THE ARGUMENT MOST LIKELY TO BE COMPUTED INTO A REGISTER. ALSO SETS THE FLAG FNCALLSFLG WHICH INDICATES THAT REG 0 GETS CLOBBERED UNDER THIS NODE. ALSO, WHEN ARG1 OF A GIVEN NODE WILL BE COMPUTED INTO "RETREG" (IE FN RETURN REG) THEN IF POSSIBLE ASSIGNS THE PARENT TO BE COMPUTED INTO "RETREG" CALLED WITH THE GLOBAL "TREEPTR" POINTING TO THE NODE TO BE PROCESSED RETURNS THE VALUE OF THE COMPLEXITY OF THIS NODE ***************************************************************************)% BEGIN REGISTER PEXPRNODE CNODE:ARGNODE; !PTR TO THE NODE BEING PROCESSED OWN CMPLX1; EXTERNAL PAIRMODE; !GLOBAL FLAG THAT WILL BE SET TO TRUE IF ANY OPERATIONS ! ARE ENCOUNTERED THAT REQUIRE REGISTER PAIRS CNODE_.TREEPTR; IF .CNODE[DBLFLG] !IF THIS NODE IS DP OR COMPLEX THEN PAIRMODE_TRUE; ! THEN REG PAIRS WILL BE NEEDED RETURN BEGIN CASE .CNODE[OPRCLS] OF SET %(*******FOR BOOLEAN OPERATIONS*******)% CNODE[COMPLEXITY]_CMPVBOOL(); %(******FOR DATA ITEMS******************)% %(*******RETURN 0, BUT DO NOT SET ANYTHING IN THE ENTRY***)% 0; %(******FOR RELATIONALS*********************)% %(********NEED 1 MORE REG THAN DO FOR CONTROL-TYPE RELATIONALS****)% %(*******MUST CHECK FOR DOUBLE-PREC ARGS UNDER THIS SINGLE-WD NODE*****)% CNODE[COMPLEXITY]_CMPLREL()+1; %(*******FOR FUNCTION CALLS*****************)% CNODE[COMPLEXITY]_CMPLFNCALL(); %(*******FOR ARITHMETIC EXPRESSIONS**********)% BEGIN CMPLX1_CMPLA(); CNODE[COMPLEXITY]_(IF .CNODE[OPERATOR] EQL INTDIVIDE THEN ( PAIRMODE_TRUE; !A REG PAIR WILL BE NEEDED IF .CMPLX1 GTR 2 !AT LEAST 2 REGS THEN .CMPLX1 !WILL BE NEEDED ELSE 2) ELSE .CMPLX1) END; %(*******FOR TYPE CONVERSION****************)% CNODE[COMPLEXITY]_CMPTPCNV(); %(******FOR ARRAY REFERENCE***************)% %(*******MUST GET THE VALUE OF THE OFFSET INTO A REGISTER - THUS NEED AS MANY REGS AS NEED TO COMPUTE THAT VAL, OR 1 REG IF NO COMPUTATION IS NECESSARY*******)% CNODE[COMPLEXITY]_CMPLXARRAY(); %(*******FOR COMMON SUBEXPRESSION NODE*******)% %(*********RETURN 0 - DO NOT SET FIELD IN NODE*****)% 0; %(*******FOR NEG/NOT NODES (THERE SHOULD BE VERY FEW OF THESE THAT COULDNT BE PROPAGATED OUT*******)% CNODE[COMPLEXITY]_BEGIN ARGNODE_.CNODE[ARG2PTR]; IF .ARGNODE[OPR1] EQL CONSTFL !IF ARG IS A CONST THEN ALOCONST(.ARGNODE); !THIS NODE WILL USUALLY HAVE BEEN ! FOLDED INTO THE CONSTANT, IF NOT ! ALLOCATE CORE FOR THE CONST TREEPTR_.CNODE[ARG2PTR]; CMPLX1_SETCOMPLEXITY(); IF .CMPLX1 EQL 0 THEN BEGIN %(***IF ARG IS EQL TO VAR ON LHS OF ASMNT***)% IF .ARGNODE EQL .RESNAME THEN CNODE[RESRFFLG]_1; %**;[344], SETCOMPLEXITY , MD , 29-JAN-76 % %**;[344], ADD @ LINE 3332 % %[344] (***IF ARG IS A FUNCTION CALL ***)% IF .ARGNODE[OPRCLS] NEQ DATAOPR ![344] AND .ARGNODE[OPRCLS] NEQ CMNSUB ![344] THEN SNGARGPROP(.CNODE,.ARGNODE); ![344] %(***IF ARG COULD HAVE BEEN LEFT IN A REG BY A EARLIER STMNT, DO SO***)% SAVREGCONTAINING(.ARGNODE); %(***VAL OF CMPLX IS 1***)% 1 END ELSE BEGIN %(***IF ARG IS COMPUTED INTO FN-RET REG COMPUTE VAL OF THIS NODE THERE ALSO***)% SNGARGPROP(.CNODE,.ARGNODE); .CMPLX1 END END; %(*****FOR SPECIAL OPS INTRODUCED BY PHASE 2 SKELETON****)% %(*******P2MUL,P2DIV, AND EXPCIOP TO A POWER THAT IS A POWER OF TWO TAKE NO EXTRA REGISTERS OVER THOSE NECESSARY TO GET THE ARG INTO A REG. P2PL1MUL NEEDS 1 REG IF ARG IS A PROGRAM VARIABLE OTHERWISE, EITHER 2 REGS OR AS MANY AS ARE NEEDED TO COMPUTE THE ARG (WHICHEVER IS GREATER) ********)% CNODE[COMPLEXITY]_ BEGIN ARGNODE_.CNODE[ARG1PTR]; IF .CNODE[A1VALFLG] THEN BEGIN %(**IF ARG COULD HAVE BEEN LEFT IN A REG BY AN EARLIER STMNT, DO SO**)% SAVREGCONTAINING(.ARGNODE); %(***IF ARG IS A CONSTANT, DECIDE WHETHER TO ALLOCATE CORE FOR IT**)% IF .ARGNODE[OPR1] EQL CONSTFL THEN PRCNSTARG(.CNODE,.ARGNODE,TRUE) ELSE %(***IF ARG IS THE VARIABLE ON THE LHS OF THE ASSIGNMENT STMNT, SET "RESRFFLG" IN CNODE***)% IF .ARGNODE EQL .RESNAME THEN CNODE[RESRFFLG]_1; 1 END ELSE BEGIN TREEPTR_.ARGNODE; CMPLX1_SETCOMPLEXITY(); %(***IF ARG CONTAINED ANY FNCALLS OR ANY REFERENCES TO THE LHS OF ASMNT, SET FLAGS IN CNODE***)% IF .ARGNODE[RESRFFLG] THEN CNODE[RESRFFLG]_1; IF .ARGNODE[FNCALLSFLG] THEN CNODE[FNCALLSFLG]_1; %(***IF ARG WAS COMPUTED INTO FN-RETURN REG, THEN FOR P2MUL,P2DIV, AND EXPCIOP TO A POWER OF 2 WANT TO COMPUTE THE PARENT IN FN-RETURN REG***)% IF .ARGNODE[ALCRETREGFLG] THEN BEGIN MACRO CMPINRETREG= BEGIN CNODE[TARGTAC]_RETREG; CNODE[INREGFLG]_1; CNODE[A1SAMEFLG]_1; CNODE[ALCRETREGFLG]_1; END$; CASE .CNODE[OPERSP] OF SET CMPINRETREG; !P2MUL CMPINRETREG; !P2DIV BEGIN END; !P2PL1MUL CGERR(); !(SQROP HAS BEEN REMOVED) CGERR(); !CUBOP HAS BEEN REMOVED CGERR(); !P4OP HAS BEEN REMOVED BEGIN !EXPCIOP IF POWOF2(.CNODE[ARG2PTR]) THEN CMPINRETREG; END; TES; END; %(***IF ARG HAS COMPLEXITY 0, STILL NEED 1 REG***)% IF .CMPLX1 EQL 0 THEN 1 ELSE %(***IF ARG HAS COMPLEXITY GEQ 2, THEN NEED SAME NUMBER OF REGS FOR PARENT AS DO FOR ARG***)% IF .CMPLX1 GEQ 2 THEN .CMPLX1 ELSE %(***IF ARG HAS COMPLEXITY 1, THEN FOR P2MUL,P2DIV, AND EXPCIOP TO A POWER OF 2, NEED ONLY 1 REG. FOR P2PL1MUL AND EXPCIOP TO A NUMBER OTHER THAN A POWER OF 2 NEED 2 REGS******)% ( CASE .CNODE[OPERSP] OF SET 1; !FOR P2MUL 1; !FOR P2DIV 2; !FOR P2PL1MUL CGERR(); !FOR SQROP(NO LONGER USED) CGERR(); !FOR CUBOP(NO LONGER USED) CGERR(); !FOR P4OP (POWER OF 4) 2; !FOR EXPCIOP TES ) END END; %(****FOR FIELD-REF: NOT IN RELEASE 1**************)% CGERR(); %(***FOR STORECLS: SHOULD NOT BE ENCOUNTERED BEFORE THE REGISTER-ALLOCATION PASS**)% CGERR(); %(***FOR REGCONTENTS: COMPLEXITY IS 0*****)% 0; %(***FOR LABOP: SHOULD NEVER GET HERE*************)% CGERR(); %(***FOR STATEMENT: SHOULD NEVER GET HERE*****)% CGERR(); %(***FOR IOLIST ELEMENT: SHOULD NEVER GET HERE*******)% CGERR(); %(***FOR IN-LINE FUNCTIONS*************************)% CNODE[COMPLEXITY]_CMPILF(); TES END; END; GLOBAL ROUTINE ARRNARGBLK(REFPNTR,VLUPNTR)= %(********************************************************************** ROUTINE TO DETERMINE IF AN ARRAY REFENCE APPEARING IN AN ARGBLK IS OF THE FORM A(1) WHERE A IS A FORMAL ARRAY IF SO, WE WANT TO SUBSTITUTE THE NAME OF THE FORMAL ARRAY FOR THE ARRAYREFERENCE CALLED WITH REFPNTR POINTING TO THE REFERENCE TO THE ARRAY AND VLUPNTR POINTING TO THE APPRPARIATE VALFLG (REFPNTR AND VLUPNTR ARE BYTE POINTERS) **********************************************************************)% BEGIN EXTERNAL SAVSPACE; TREEPTR_..REFPNTR; !RESET TREEPTR IF .TREEPTR[OPRCLS] EQL ARRAYREF THEN IF .TREEPTR[ARG2PTR] NEQ 0 THEN IF .TREEPTR[IDTARGET] EQL 0 THEN BEGIN LOCAL PEXPRNODE ARROFFSET; ARROFFSET_.TREEPTR[ARG2PTR]; IF .ARROFFSET[OPR1] EQL FMLVARFL THEN BEGIN LOCAL PEXPRNODE ARRNAME; ARRNAME_.TREEPTR[ARG1PTR]; IF .ARRNAME[OPR1] EQL FMLARRFL THEN IF .ARRNAME[IDSYMBOL] EQL .ARROFFSET[IDSYMBOL] THEN BEGIN SAVSPACE(EXSIZ-1,.TREEPTR); .REFPNTR_TREEPTR_.ARRNAME; !SUBSTITUE ARRAY NAME IF .VLUPNTR NEQ 0 THEN .VLUPNTR_1; RETURN TRUE END END END; RETURN FALSE END; GLOBAL ROUTINE CMPLA = %(*************************************************************************** ROUTINE TO COMPUTE THE COMPLEXITY OF AN ARITH OR NON-CONTROL TYPE BOOLEAN RETURNS THE VAL OF THE COMPLEXITY ALSO TRIES TO MAKE ARG1 BE THE ARGUMENT MOST LIKELY TO BE COMPUTED INTO A REGISTER. ALSO SETS THE FLAGS "FNCALLSFLG", "A1IMMEDFLG", "A2IMMEDFLG". ALLOCATES CORE FOR CONSTANTS WHICH ARE NOT IMMED-SIZE AND HENCE MUST BE STORED ALSO, WHEN ARG1 OF A GIVEN NODE WILL BE COMPUTED INTO "RETREG" (IE FN RETURN REG) THEN IF POSSIBLE ASSIGNS THE PARENT TO BE COMPUTED INTO "RETREG" CALLED WITH THE GLOBAL "TREEPTR" POINTING TO THE NODE TO BE PROCESSED ***************************************************************************)% BEGIN LOCAL PEXPRNODE CNODE; !PTR TO THE NODE BEING PROCESSED REGISTER PEXPRNODE ARG1NODE; REGISTER PEXPRNODE ARG2NODE; LOCAL CMPLX1,CMPLX2; !COMPLEXITY OF THE ARGS UNDER CNODE !**[412] CMPLA @3554 SJW 9-JUL-76 %[412]% LOCAL RETVAL; ! RETURN VALUE OWN T1; OWN AADDR; !BASE ADDRESS FOR THE ARRAY %(****TO SWAP THE INFO ABOUT THE 2 ARGS WHEN SWAP THE 2 ARGS***)% MACRO SWPARGDATA = BEGIN T1_.CMPLX1; CMPLX1_.CMPLX2; CMPLX2_.T1; ARG1NODE_.CNODE[ARG1PTR]; ARG2NODE_.CNODE[ARG2PTR]; END$; %(**CHECK WHETHER THIS EXPR WILL BE EVALUATED BY CALLING A LIBRARY FN(EG IF IT IS COMPLEX MUL,DIV OR A DP OP ON THE KA10) SET A GLOBAL FLAG INDICATING WHETHER THIS PROGRAM INCLUDES ANY CALLS TO SUCH FNS**)% !**;[426] Change @ line 3552 in CMPLA JNG 17-Aug-76 %[426]% IF USEFNCALL(TREEPTR) THEN TREEPTR[FNCALLSFLG]_LIBARITHFLG_TRUE; %(****WILL TREAT EXPONENTIATION AS A FUNCTION CALL. THEREFORE TRANSFORM ANY EXPONENTIATION NODES TO FUNCTION-CALL NODES AND CALL THE ROUTIEN TO PERFORM COMPLEXITY OF A FN-CALL ********)% IF .TREEPTR[OPR1] EQL EXPONOPF THEN BEGIN EXPTOFNCALL(); RETURN CMPLFNCALL(); END; CNODE_.TREEPTR; ARG1NODE_.CNODE[ARG1PTR]; ARG2NODE_.CNODE[ARG2PTR]; %(****FIND COMPLEXITIES OF THE 2 ARGS, IF EITHER ARG IS A CONSTANT PROCESS IT ALSO PROPAGATE THE FLAGS FNCALLSFLG, AND RESRFFLG UP FROM THE ARGS***)% CMARGS(); %(***GET COMPLEXITY OF 1ST ARG****)% CMPLX1_(IF .CNODE[A1VALFLG] THEN 0 ELSE .ARG1NODE[COMPLEXITY]); %(**GET COMPLEXITY OF 2ND ARG*******)% CMPLX2_(IF .CNODE[A2VALFLG] THEN 0 ELSE .ARG2NODE[COMPLEXITY]); %(****WILL ALWAYS WANT ARG1 TO BE COMPUTED INTO A REGISTER, THEREFORE IF EITHER ARG 1. MUST BE IN A TEMPORARY 2. IS A SIMPLE DATA ITEM WHICH REQUIRES NO COMPUTATION 3. IS AN ARRAY REFERENCE WHICH MAY BE PICKED UP WITHOUT COMPUTING IT INTO A REG 4. IS A COMMON SUBEXPRESSION LET THAT ARG BE ARG2 IF POSSIBLE ********)% IF NOT .CNODE[A2VALFLG] AND NOT .CNODE[MEMCMPFLG] !DO NOT REORDER THE ARGS OF AN OPERATION ! THAT WILL BE PERFORMED TO MEMORY THEN BEGIN IF .CNODE[A1VALFLG] THEN %(***IF EITHER ARG IS A DATA ITEM OR COMMON SUBEXPR, THAT ARG SHOULD ALWAYS BE ARG2 IF POSSIBLE**********)% BEGIN IF EXCHARGS(.CNODE) THEN %(***IF WERE ABLE TO EXCHANGE ARG1 AND ARG2, THEN EXCHANGE THE DATA ABOUT THEM AS WELL***)% SWPARGDATA; END ELSE IF .ARG2NODE[OPRCLS] NEQ ARRAYREF THEN %(****WHEN NEITHER ARG IS A SIMPLE DATA ITEM, THEN IF EITHER ARG IS AN ARRAY REFERENCE, THAT ARG SHOULD BE ARG2 IF POSSIBLE*****)% BEGIN IF .ARG1NODE[OPRCLS] EQL ARRAYREF OR .CMPLX1 GTR .CMPLX2 THEN %(***IF NEITHER ARG IS AN ARRAYREF NOR A DATA ITEM, LET ARG2 BE THE ARG OF GREATER COMPLEXITY***)% BEGIN IF EXCHARGS(.CNODE) THEN SWPARGDATA; END; END; END; %(***IF 1ST ARG IS NOT A SUBEXPRESSION WHOSE EVALUATION WILL LEAVE A RESULT IN A REGISTER, THEN TRY TO MAKE 1ST ARG BE A VARIABLE WHOSE VALUE MIGHT BE LEFT IN A REG FROM EXECUTION OF A PRECEEDING STMNT***)% IF .ARG1NODE[OPRCLS] EQL DATAOPR !IF ARG1 IS A VAR OR CONST THEN BEGIN IF SAVREGCONTAINING(.ARG1NODE) !IF CAN LEAVE ARG1 IN A REG FROM A THEN BEGIN END ! PRECEEDING STMNT, DO SO ELSE !OTHERWISE, IF .ARG2NODE[RGCANDFLG] !IF ARG2 CAN BE LEFT IN A REG BY AND NOT .CNODE[MEMCMPFLG] THEN ! A PRECEEDING STMNT, BEGIN IF EXCHARGS(.CNODE) !IF CAN SWAP THE ARGS, DO SO THEN BEGIN SWPARGDATA; SAVREGCONTAINING(.ARG1NODE); !SAVE THE REG CONTAINING ! THE NEW ARG1 END; END END ELSE %(*** IF ARG1 IS AN ARRAYREF OR COMMON SUB OR ARG1 RETURNS ITS VALUE IN THE FUNCTION RETURN REGISTER, CHECK IF ARG2 IS ALSO A REGISTER AND, IF SO, PERFORM THE CALCULATION IN THE REGISTER FOR ARG2 ***)% IF .ARG1NODE[OPRCLS] EQL ARRAYREF OR .ARG1NODE[OPRCLS] EQL CMNSUB OR BEGIN !ARG1 RETURNING VALUE IN REGISTER 0? .ARG1NODE[ALCRETREGFLG] AND .ARG1NODE[INREGFLG] AND .ARG1NODE[TARGTAC] EQL RETREG END THEN BEGIN IF .ARG2NODE[RGCANDFLG] !HENCE IF ARG2 WAS LEFT IN A REG AND NOT .CNODE[MEMCMPFLG] THEN ! BY A PRECEEDING STMNT BEGIN IF EXCHARGS(.CNODE) !IF CAN SWAP THE ARGS, DO SO THEN BEGIN SWPARGDATA; SAVREGCONTAINING(.ARG1NODE); !SAVE THE REG CONTAINING ! THE NEW ARG1 END END END; %(***IF ARE COMPUTING TO MEMORY AND THE 1ST ARG IS A SIMPLE VAR OR CONST, THEN THAT VAR OR CONST CAN BE LEFT IN A REG AFTER THIS STMNT IS EVALUATED**)% IF .CNODE[MEMCMPFLG] AND .CNODE[A1VALFLG] THEN ADDREGCANDATE(.ARG1NODE,.CNODE); IF .CMPLX1 LEQ .CMPLX2 THEN CNODE[RVRSFLG]_1; %(***CHECK WHETHER THE VAL OF THE ARG COMPUTED FIRST WILL BE LEFT IN "RETREG" AND THEN CLOBBERRED BY COMPUTATION OF THE ARG THAT IS COMPUTED SECOND. IF SO, UNDO THE ASSIGNMENT OF THAT VAL TO "RETREG" ********)% IF NOT .CNODE[A1VALFLG] AND NOT .CNODE[A2VALFLG] THEN BEGIN IF .CNODE[RVRSFLG] THEN %(***IF ARG2 IS EVALUATED FIRST***)% BEGIN IF .ARG2NODE[ALCRETREGFLG] AND .ARG1NODE[FNCALLSFLG] THEN BEGIN ARG2NODE[ALCRETREGFLG]_0; ARG2NODE[A1SAMEFLG]_0; ARG2NODE[A2SAMEFLG]_0; !(NOTE THAT ARG-SAME-FLGS ! COULD ONLY BE SET AT THIS ! POINT DUE TO ALCRETREG ARG2NODE[INREGFLG]_0; END; END ELSE %(***IF ARG1 IS EVALUATED FIRST***)% BEGIN IF .ARG1NODE[ALCRETREGFLG] AND .ARG2NODE[FNCALLSFLG] THEN BEGIN ARG1NODE[ALCRETREGFLG]_0; ARG1NODE[A1SAMEFLG]_0; ARG1NODE[A2SAMEFLG]_0; ARG1NODE[INREGFLG]_0; END; END; END; %(****IF ARG1 WILL BE COMPUTED INTO "RETREG" (FN RETURN REGISTER) THEN WOULD LIKE TO COMPUTE PARENT IN RETREG ALSO.*******)% IF NOT .CNODE[A1VALFLG] AND .ARG1NODE[ALCRETREGFLG] AND .ARG1NODE[INREGFLG] AND .ARG1NODE[TARGTAC] EQL RETREG !(FOR RELATIONALS, "ALCRETREGFLG" ! INDICATES THAT THE COMPAR IS DONE ! IN RETREG, NOT THAT THE VAL IS LEFT THERE THEN %(***IF VAL OF ARG1 WILL BE LEFT IN "RETREG"***)% BEGIN IF .CNODE[OPRCLS] EQL RELATIONAL THEN CNODE[TARGAUX]_RETREG ELSE BEGIN CNODE[TARGTAC]_RETREG; CNODE[INREGFLG]_1; END; CNODE[ALCRETREGFLG]_1; CNODE[A1SAMEFLG]_1; END; %(***IF CMPLX1 IS STILL 0 (AFTER HAVE ATTEMPTED TO SWAP ARGS), TREAT IT AS IF IT WERE 1 (SINCE IT MUST BE LOADED INTO A REG TO PERFORM THE OPERATION***)% IF .CMPLX1 EQL 0 THEN CMPLX1_1; %(***RETURN THE COMPLEXITY OF CNODE - THIS VALUE IS EQUAL TO THE MAXIMUM OF THE COMPLEXITY OF ARG1(CMPLX1) AND THE COMPLEXITY OF ARG2 (CMPLX2), UNLESS THE TWO ARE EQUAL, IN WHICH CASE IT IS ONE GREATER THAN THE VAL OF THE COMPLEXITY OF THE 2 ARGS *********)% !**[412] CMPLA @3797 SJW 9-JUL-76 %[412]% RETVAL _ %[412]% BEGIN %[412]% IF .CMPLX1 EQL .CMPLX2 %[412]% THEN %[412]% .CMPLX1+1 %[412]% ELSE %[412]% BEGIN %[412]% IF .CMPLX2 GTR .CMPLX1 %[412]% THEN %[412]% .CMPLX2 %[412]% ELSE %[412]% .CMPLX1 %[412]% END %[412]% END; %(*** IF ARG1 IS DOUBLE PREC ARRAYREF FOR KA10 AND ARG2 HAS NON-ZERO COMPLEXITY, THEN PARENT MUST HAVE AT LEAST COMPLEXITY 3 ***)% !**[412] CMPLA @3815 SJW 9-JUL-76 %[412]% IF .ARG1NODE [OPRCLS] EQL ARRAYREF AND %[412]% .ARG1NODE [VALTYPE] EQL DOUBLPREC AND %[412]% .KA10FLG AND %[412]% .CMPLX2 NEQ 0 AND %[412]% .RETVAL LSS 3 %[412]% THEN RETVAL _ 3; %[412]% RETURN .RETVAL; END; GLOBAL ROUTINE CMARGS= %(*************************************************************************** ROUTINE TP PERFORM COMPLEXITY-WALK PROCESSING FOR THE 2 ARGS UNDER THE NODE POINTED TO BY THE GLOBAL "TREEPTR". IF EITHER OF THE ARGS HAS "FNCALLSFLG" SET, SETS IT IN THE PARENT. IF EITHER OF THE ARGS HAS "RESRFFLG" SET, SETS IT IN THE PARENT. IF EITHER ARG IS A CONSTANT, DECIDES WHETHER TO USE IT IMMEDIATE MODE, OR ALLOCATE CORE FOR IT ***************************************************************************)% BEGIN LOCAL PEXPRNODE ARG1NODE:ARG2NODE:CNODE; CNODE_.TREEPTR; ARG1NODE_.CNODE[ARG1PTR]; ARG2NODE_.CNODE[ARG2PTR]; %(*****COMPUTE COMPLEXITY OF 1ST ARG******)% IF NOT .CNODE[A1VALFLG] THEN BEGIN TREEPTR_.CNODE[ARG1PTR]; SETCOMPLEXITY(); END; %(*****COMPUTE COMPLEXITY OF 2ND ARG*****)% IF NOT .CNODE[A2VALFLG] THEN BEGIN TREEPTR_.CNODE[ARG2PTR]; SETCOMPLEXITY(); END; %(***IF EITHER ARG IS THE VAR INTO WHICH THE RESULT OF THIS ASSIGNMENT IS TO BE STORED, SET A FLAG IN THE PARENT***)% IF .ARG1NODE EQL .RESNAME OR .ARG2NODE EQL .RESNAME THEN CNODE[RESRFFLG]_1; %(***IF EITHER ARG IS A CONSTANT- THEN IF IT IS IMMED SIZE, SET IMMEDFLG, IF NOT, ALLOCATE CORE FOR IT*****)% IF .ARG1NODE[OPR1] EQL CONSTFL THEN PRCNSTARG(.CNODE,.ARG1NODE,TRUE); IF .ARG2NODE[OPR1] EQL CONSTFL THEN PRCNSTARG(.CNODE,.ARG2NODE,FALSE); %(***KEEP FLAGS FOR "FNCALL PRESENT SOMEWHERE UNDER THIS NODE" AND "REF TO RESULT VARIABLE PRESENT SOMEWHER UNDER THIS NODE"*****)% IF .ARG1NODE[OPRCLS] NEQ DATAOPR THEN BEGIN IF .ARG1NODE[FNCALLSFLG] THEN CNODE[FNCALLSFLG]_1; IF .ARG1NODE[RESRFFLG] THEN CNODE[RESRFFLG]_1; END; IF .ARG2NODE[OPRCLS] NEQ DATAOPR THEN BEGIN IF .ARG2NODE[FNCALLSFLG] THEN CNODE[FNCALLSFLG]_1; IF .ARG2NODE[RESRFFLG] THEN CNODE[RESRFFLG]_1; END; END; GLOBAL ROUTINE EXPTOFNCALL= %(*************************************************************************** ROUTINE TO TRANSFORM AN EXPONENTIATION NODE INTO A FUNCTION-CALL NODE. CALLED WITH THE GLOBAL "TREEPTR" POINTING TO THE NODE TO BE TRANSFORMED. ***************************************************************************)% BEGIN EXTERNAL CORMAN,NAME,TBLSEARCH,ENTRY; OWN PEXPRNODE FNNMENTRY; OWN PEXPRNODE ARG2NODE; OWN ARGUMENTLIST LST; %(***TABLES OF ROUTINE NAMES TO BE CALLED FOR EXPONENTIATION***)% %(***FOR AN INTEGER EXPONENT***)% BIND IEXPFNTBL= PLIT ( SIXBIT 'EXP1.', !INTEGER**INTEGER SIXBIT 'EXP2.', !REAL**INTEGER SIXBIT 'DEXP2.', !DOUBLE-PREC**INTEGER SIXBIT 'CEXP2.' ); !COMPLEX**INTEGER %(***FOR AN EXPONENT OF SAME TYPE AS BASE***)% BIND EXPFNTBL=PLIT ( SIXBIT 'EXP1.', !INTEGER**INTEGER SIXBIT 'EXP3.', !REAL**REAL SIXBIT 'DEXP3.', !DOUBLE-PREC**DOUBLE-PREC SIXBIT 'CEXP3.' ); !COMPLEX**COMPLEX ARG2NODE_.TREEPTR[ARG2PTR]; %(***GET 4 WDS TO HOLD THE ARG LIST***)% NAME_ARGLSTSIZE(2); LST_CORMAN(); %(***SET ARGCOUNT FIELD IN THE ARGLIST TO 2, SET THE 2 ELEMENTS ON THE ARGLIST TO PTRS TO THE ARGS****)% LST[ARGCOUNT]_2; LST[1,ARGNPTR]_.TREEPTR[ARG1PTR]; LST[2,ARGNPTR]_.ARG2NODE; %(***SET THE VALFLGS FOR THE 2 ARGS***)% LST[1,AVALFLG]_.TREEPTR[A1VALFLG]; LST[2,AVALFLG]_.TREEPTR[A2VALFLG]; !**;[426] Delete edit 301 @ line 3909 in EXPTOFNCALL JNG 17-Aug-76 %(***MAKE THE NODE PTED TO BY TREEPTR BE A FNCALL NODE***)% TREEPTR[OPRCLS]_FNCALL; TREEPTR[OPERSP]_LIBARY; !(A LIBRARY FN) TREEPTR[ARG2PTR]_.LST; TREEPTR[EXPFLAGS]_0; %(***SET ARG1 OF THIS FNCALL TO PT TO THE SYMBOL-TABLE ENTRY FOR THE FUNCTION NAME FOR THE FUNCTION TO BE USED THERE ARE 2 FNS FOR EACH OF THE 4 MAIN VALUE-TYPES. ONE FOR THAT VALTYPE RAISED TO AN INTEGER POWER, ONE FOR THAT VALTYPE RAISED TO A POWER OF SAME VALTYPE. *******)% NAME_IDTAB; ENTRY[0]_ (IF .ARG2NODE[VALTP1] EQL INTEG1 THEN .IEXPFNTBL[.TREEPTR[VALTP1]] ELSE .EXPFNTBL[.TREEPTR[VALTP1]]); FNNMENTRY_TBLSEARCH(); TREEPTR[ARG1PTR]_.FNNMENTRY; FNNMENTRY[OPERSP]_FNNAME; END; GLOBAL ROUTINE PRCNSTARG(PARNODE, CONSTNODE,A1CNSTFLG)= %(*************************************************************************** TO PROCESS A CONSTANT ARG. IF IT IS OF IMMED SIZE, SET IMMEDFLG IN THE PARENT. IF NOT, ALLOCATE CORE FOR IT. CALLED WITH THE ARGS PARNODE - PTR TO THE PARENT NODE CONSTNODE - PTR TO THE CONSTANT TABLE ENTRY FOR THE CONSTANT A1CNSTFLG - FLAG FOR "THE CONSTANT NODE IS THE 1ST ARG UNDER PARENT" ***************************************************************************)% BEGIN MAP PEXPRNODE PARNODE:CONSTNODE; %(***IF THE CONSTANT IS USED AS THE 2ND ARG OF AN OPERATION WHICH IS PERFORMED BY MEANS OF A FN-CALL (IE EXPONENTIATION OR DOUBLE-PREC OPS ON KA10), THEN MUST ALLOCATE CORE FOR THE CONSTANT***)% IF USEFNCALL(PARNODE) AND NOT .A1CNSTFLG THEN ALOCONST(.CONSTNODE) %(***IF THE CONSTANT IS NOT OF TYPE INTEGER OR TYPE LOGICAL, AND A BOOLEAN OPERATOR IS BEING APPLIED TO IT, THEN MUST ALLOCATE CORE FOR IT*****)% ELSE IF .PARNODE[OPRCLS] EQL BOOLEAN AND .CONSTNODE[VALTP1] NEQ INTEG1 THEN ALOCONST(.CONSTNODE) %(***IF CONSTANT IS IMMEDIATE SIZE, DO NOT ALLOCATE CORE FOR IT. INSTEAD, SET IMMEDFLG IN THE PARENT *****)% ELSE IF IMMEDCNST(CONSTNODE) THEN BEGIN (IF .A1CNSTFLG THEN PARNODE[A1IMMEDFLG] ELSE PARNODE[A2IMMEDFLG])_1; IF .CONSTNODE[CONST2] LSS 0 AND .CONSTNODE[VALTP1] EQL INTEG1 THEN %(***IF THE CONSTANT IS A NEG INTEGER, USE A POSITIVE NUMBER NEGATED.***)% BEGIN IF .PARNODE[OPRCLS] EQL BOOLEAN THEN %(***FOR BOOLEANS, USE THE 1S COMPLEMENT AND THE 'NOT' VERSION OF THE INSTRUCTION.*******)% BEGIN IF .A1CNSTFLG !TO PICK UP ARG1 WITH"NOT" THEN BEGIN PARNODE[A1NOTFLG]_NOT .PARNODE[A1NOTFLG]; PARNODE[ARG1PTR]_MAKECNST(.CONSTNODE[VALTYPE],0,NOT .CONSTNODE[CONST2]); END ELSE !TO OPERATE ON ARG2 WITH "NOT" BEGIN PARNODE[A2NOTFLG]_NOT .PARNODE[A2NOTFLG]; PARNODE[ARG2PTR]_ MAKECNST(.CONSTNODE[VALTYPE],0,NOT .CONSTNODE[CONST2]); END; END ELSE IF .PARNODE[OPRCLS] EQL STATEMENT THEN BEGIN %(***FOR ASSIGNMENT STMNTS, IF RHS IS AN IMMED CONSTANT WHEN NEGATED, THEN SET A2NEGFLG AND USE THE NEG***)% IF .PARNODE[SRCID] EQL ASGNID THEN BEGIN PARNODE[A2NEGFLG]_NOT .PARNODE[A2NEGFLG]; PARNODE[RHEXP]_MAKECNST(.CONSTNODE[VALTYPE],0,-.CONSTNODE[CONST2]); END ELSE CGERR(); !SHOULD NEVER CALL PRCNSTARG WITH ! ANY STMNT OTHER THAN ASSIGNMENT END ELSE IF .A1CNSTFLG THEN BEGIN PARNODE[A1NEGFLG]_NOT .PARNODE[A1NEGFLG]; PARNODE[ARG1PTR]_MAKECNST(.CONSTNODE[VALTYPE],0,-.CONSTNODE[CONST2]); END ELSE BEGIN PARNODE[A2NEGFLG]_NOT .PARNODE[A2NEGFLG]; PARNODE[ARG2PTR]_MAKECNST(.CONSTNODE[VALTYPE],0,-.CONSTNODE[CONST2]); END; END END ELSE ALOCONST(.CONSTNODE); END; GLOBAL ROUTINE CMPVBOOL= %(*************************************************************************** ROUTINE PERFORMS COMPLEXITY WALK FOR A BOOLEAN WHOSE VALUE IS TO BE COMPUTED. ***************************************************************************)% BEGIN LOCAL PEXPRNODE CNODE:ARG1NODE:ARG2NODE; %(***FOR EQV AND XOR - TREAT SAME AS ARITH****)% IF .TREEPTR[BOOLCLS] NEQ ANDORCLS THEN CMPLA() ELSE %(***IF VALTYPE OF THIS NODE IS "CONTROL" WILL NEED 1 REG TO HOLD THE VAL IN ADDITION TO THE NUMBER OF REGS NEEDED FOR THE CONTROL BOOLEAN IF IT WERE USED STRICTLY FOR CONTROL PURPOSES****)% IF .TREEPTR[VALTYPE] EQL CONTROL THEN CMPLBL() + 1 ELSE BEGIN CNODE_.TREEPTR; ARG1NODE_.CNODE[ARG1PTR]; ARG2NODE_.CNODE[ARG2PTR]; %(***IF ONE OF THE 2 ARGS HAS VALTYPE CONTROL (AND THE OTHER IS A MASK) ALWAYS MAKE ARG1 BE THE MASK. ********)% IF .ARG1NODE[VALTYPE] EQL CONTROL THEN BEGIN EXCHARGS(.CNODE); ARG1NODE_.CNODE[ARG1PTR]; ARG2NODE_.CNODE[ARG2PTR]; END; %(***IF ONE ARG IS OF TYPE CONTROL, WILL INIT VAL OF BOOLEAN TO THE OTHER ARG, THEN EVALUATE THE CONTROL ARG***)% IF .ARG2NODE[VALTYPE] EQL CONTROL THEN BEGIN %(***PERFORM COMPLEXITY WALK FOR THE 2 ARGS. PROPAGATE FNCALLSFLG AND RESRFFLG UP FROM THE ARGS TO THE PARENT***)% CMARGS(); %(***IF ARG1 IS COMPUTED INTO FN-RETURN-REG***)% !**;[510] Change @ line 4079 in CMPVBOOL JNG 3-Nov-76 %[510]% IF .ARG1NODE[OPRCLS] NEQ DATAOPR %[510]% AND .ARG1NODE[ALCRETREGFLG] THEN BEGIN %(**IF COMP OF ARG2 WILL CLOBBER FN-RET-REG, THEN MUST STORE ARG1 ELSEWHERE***)% IF .ARG2NODE[FNCALLSFLG] THEN BEGIN ARG1NODE[ALCRETREGFLG]_0; ARG1NODE[A1SAMEFLG]_0; ARG1NODE[INREGFLG]_0; END %(***OTHERWISE COMPUTE PARENT IN FN-RET REG***)% ELSE BEGIN CNODE[ALCRETREGFLG]_1; CNODE[A1SAMEFLG]_1; CNODE[INREGFLG]_1; CNODE[TARGTAC]_RETREG; END; END; SAVREGCONTAINING(.ARG1NODE); !IF BB ALLOCATOR CAN LEAVE VAL OF ARG1 IN A REG ! IN SOME PREV STMNT, IT SHOULD DO SO %(***COMPLEXITY OF CNODE IS MAX OF (1+CMPLX OF ARG2) AND CMPLX OF ARG1 ***)% IF .ARG1NODE[COMPLEXITY] GTR .ARG2NODE[COMPLEXITY] THEN .ARG1NODE[COMPLEXITY] ELSE .ARG2NODE[COMPLEXITY] + 1 END ELSE %(***FOR AND OR OR WHEN NEITHER ARG HAS TYPE CONTROL, TREAT LIKE ARITH***)% CMPLA() END END; GLOBAL ROUTINE CMPLBL = %(*************************************************************************** ROUTINE TO COMPUTE THE COMPLEXITY OF A CONTROL-TYPE BOOLEAN CALLED WITH THE GLOBAL TREEPTR POINTING TO THE NODE WHOSE COMPLEXITY IS TO BE RETURNED ***************************************************************************)% BEGIN LOCAL PEXPRNODE CNODE:ARG1NODE:ARG2NODE; LOCAL CMPLX1,CMPLX2; !COMPLEXITY OF ARG1 AND ARG2 CNODE_.TREEPTR; !PTR TO THE NODE BEING PROCESSED ARG1NODE_.CNODE[ARG1PTR]; ARG2NODE_.CNODE[ARG2PTR]; %(****FOR 1ST ARG**************************************)% TREEPTR_.ARG1NODE; %(****ARGS OF A CONTROL-TYPE BOOLEAN CAN BE EITHER CONTROL-TYPE BOOLEANS, OR RELATIONALS************************)% IF .ARG1NODE[OPRCLS] EQL RELATIONAL THEN %(****FOR A RELATIONAL USED FOR CONTROL PURPOSES ONLY***)% ARG1NODE[COMPLEXITY]_(CMPLX1_CMPLREL()) ELSE BEGIN IF .ARG1NODE[OPRCLS] EQL BOOLEAN THEN %(****IF A SUBNODE IS A BOOLEAN, IT MUST BE A CONTROL-TYPE BOOLEAN****)% ARG1NODE[COMPLEXITY]_(CMPLX1_CMPLBL()) ELSE CGERR(5) END; %(****FOR 2ND ARG**************************************)% TREEPTR_.ARG2NODE; %(****ARGS OF A CONTROL-TYPE BOOLEAN CAN BE EITHER CONTROL-TYPE BOOLEANS, OR RELATIONALS************************)% IF .ARG2NODE[OPRCLS] EQL RELATIONAL THEN %(****FOR A RELATIONAL USED FOR CONTROL PURPOSES ONLY***)% ARG2NODE[COMPLEXITY]_(CMPLX2_CMPLREL()) ELSE BEGIN IF .ARG2NODE[OPRCLS] EQL BOOLEAN THEN %(****IF A SUBNODE IS A BOOLEAN, IT MUST BE A CONTROL-TYPE BOOLEAN****)% ARG2NODE[COMPLEXITY]_(CMPLX2_CMPLBL()) ELSE CGERR(5) END; %(****SET THE FLAG "FNCALLSFLG" IN THE PARENT, IF ANY FNCALLS ARE UNDER ANY OF THE ARGS****)% %(****SET THE FLAG "RESRFFLG" IN THE PARENT IF REF TO LOC OF FINAL RESULT OCCURS UNDER EITHER ARG*****)% IF .ARG1NODE[FNCALLSFLG] OR .ARG2NODE[FNCALLSFLG] THEN CNODE[FNCALLSFLG]_1; IF .ARG1NODE[RESRFFLG] OR .ARG2NODE[RESRFFLG] THEN CNODE[RESRFFLG]_1; %(****FOR A CONTROL-TYPE BOOLEAN, COMPLEXITY IS EQUAL TO MAX OF COMPLEXITY OF THE 2 ARGS**********************)% IF .CMPLX2 GTR .CMPLX1 THEN CMPLX1_.CMPLX2; CNODE[COMPLEXITY] _.CMPLX1; RETURN .CMPLX1 END; GLOBAL ROUTINE CMPLREL = %(**************************************************************************** ROUTINE TO COMPUTE THE COMPLEXITY OF A RELATIONAL. COMPUTES THE NUMBER OF REGISTERS NEEDED IF THE REL IS USED FOR CONTROL PURPOSES ONLY. CALLED WITH THE GLOBAL TREEPTR POINTING TO THE NODE FOR THE RELATIONAL. ****************************************************************************)% BEGIN EXTERNAL PAIRMODE; !GLOBAL FLAG THAT GETS SET WHEN PROCESSING ANY STMNT THAT CONTAINS ! ANY OPERATIONS THAT REQUIRE REG PAIRS OWN CMPLX1; LOCAL PEXPRNODE CNODE:ARG1NODE: ARG2NODE; CNODE_.TREEPTR; %(***USE SAME BASIC ALGORITHM FOR COMPLEXITY AS IS USED FOR ARITH NODES***)% CMPLX1_CMPLA(); ARG1NODE_.CNODE[ARG1PTR]; !AFTER CMPLA, GET VALS OF ARG1PTR AND ARG2PTR ARG2NODE_.CNODE[ARG2PTR]; CNODE[INREGFLG]_0; !CMPLA WOULD HAVE SET "INREGFLG" IF IT ALLOCATED ! THIS NODE TO BE COMPUTED IN FN-RET REG - ! BUT FOR A RELATIONAL, THE COMPAR ! IS PERF IN A REG, BUT THE VAL MIGHT BE LEFT ! IN A TEMP %(***IF ARGS ARE DOUBLE-WORD, THEN NEED TWICE AS MANY REGS AS CMPLX1 INDICATES ***)% IF .ARG1NODE[DBLFLG] THEN BEGIN CMPLX1_.CMPLX1^1; PAIRMODE_TRUE !IF THE OPERANDS OF THE RELATIONAL ARE DP OR COMPLEX VARS ! WILL NEED A REG PAIR TO DO THE COMPARISON END; %(***IF ARG2 IS A REAL OR COMPLEX IMMED CONSTANT, WILL HAVE TO ALLOCATE CORE FOR IT (SINCE HAVE NO COMPARE IMMED INSTRUCTION FOR REALS) HANCE IF ONE ARG IS REAL IMMED AND THE OTHER IS A VAR , LET ARG1 BE THE CONST ARG. IF BOTH ARGS ARE REAL IMMED(POSSIBLE ONLY IF P2SKEL NOT USED), ALLOCATE CORE FOR ARG2****)% IF .CNODE[A2IMMEDFLG] THEN BEGIN IF (.ARG2NODE[OPERATOR] EQL REALCONST OR .ARG2NODE[OPERATOR] EQL CPLXCONST) AND (.ARG2NODE[CONST1] NEQ 0) !CAN USE CAI FOR ZERO THEN BEGIN %(***IF ARG1 IS AN EXPRESSION (WHOSE VAL WILL PROBABLY BE LEFT IN A REG) OR IS A VARIABLE WHOSE VAL CAN BE LEFT IN A REG BY A PREV STMNT OR IF ARG1 IS ALSO AN IMMED CONSTANT, ALLOCATE CORE FOR ARG2 ********)% IF .CNODE[A1IMMEDFLG] !IF ARG1 IS AN IMMED CONST OR (.ARG1NODE[OPRCLS] NEQ ARRAYREF !ARG1 NOT AN ARRAY REF AND NOT (.ARG1NODE[OPRCLS] EQL DATAOPR !ARG1 NOT A VAR THAT AND NOT .ARG1NODE[RGCANDFLG]) ! COULD NOT HAVE BEEN LEFT IN A REG ) THEN BEGIN %(***MUST ALLOCATE CORE FOR ARG2***)% ALOCONST(.ARG2NODE); CNODE[A2IMMEDFLG]_0; END %(***IF ARG1 IS A VAR THAT COULD NOT HAVE BEEN LEFT IN A REG BY A PREV STMNT OR IF ARG1 IS AN ARRAYREF (IE IF ARG1 HAS TO BE LOADED INTO A REG) AND IF ARG1 IS NOT ALSO AN IMMED REAL CONST, EXCHANGE THE 2 ARGS***)% ELSE EXCHARGS(.CNODE) END; END; %(***CANNOT GENERATE CODE FOR A RELATIONAL WHICH HAS A NEGFLG OVER ARG2. GET RID OF ANY A2NEGFLG BY: A LT -B = -A GT B A LEQ -B = -A GEQ B A EQ -B = -A EQ B ETC *****)% IF .CNODE[A2NEGFLG] THEN BEGIN CNODE[A1NEGFLG]_NOT .CNODE[A1NEGFLG]; CNODE[A2NEGFLG]_0; IF NOT EQREL(.CNODE[OPERSP]) THEN CNODE[OPERSP]_REVREL(.CNODE[OPERSP]) END; %(***IF A1NEGFLG IS NOW SET AND ARG1 IS AN EXPRESSION, TRY TO PROPAGATE THE NEGATIVE OVER ARG1 *******)% IF .CNODE[A1NEGFLG] AND NOT .CNODE[A1VALFLG] THEN BEGIN IF PROPNEG(.CNODE[ARG1PTR]) THEN CNODE[A1NEGFLG]_0; END; %(***IF ARG1 IS A VAR OR CONST, ADD IT TO THE SET OF VARS WHOSE VALS ARE LEFT IN REGS BY THE EVAL OF STMNTS***)% IF .CNODE[A1VALFLG] THEN BEGIN %(**IF BOTH ARGS ARE VARS/CONSTS THEN PUT ARG2 IN THE SET OF VARS WHOSE VALS CAN BE LEFT IN REGS**)% IF .CNODE[A2VALFLG] THEN BEGIN %(**ONLY PUT ARG2 INTO THE SET OF POTENTIAL REG VARS IF 1. ARG1 IS A CONST OR VAR (NOT A CSB) 2. ARG1 WILL NOT BE AVAILABLE IN A REG FROM SOME EARLIER STMNT *****)% ARG1NODE_.CNODE[ARG1PTR]; IF .ARG1NODE[OPRCLS] EQL DATAOPR AND NOT .ARG1NODE[RGCANDFLG] THEN ADDREGCANDATE(.CNODE[ARG2PTR],.CNODE); END; %(***ADD ARG1 TO SET OF POTENTIAL REG-VARS***)% ADDREGCANDATE(.CNODE[ARG1PTR],.CNODE); END; RETURN .CMPLX1; END; GLOBAL ROUTINE CMPLFNCALL = %(*************************************************************************** COMPUTE THE COMPLEXITY OF A FUNCTION CALL BY EXAMINING ITS LIST OF ARGUMENTS. CALLED WITH THE GLOBAL TREEPTR POINTING TO THE FNCALL NODE ***************************************************************************)% BEGIN EXTERNAL FNREF; !GLOBAL THAT GETS SET WHEN PROCESSING A STMNT THAT ! INCLUDES A FN-CALL LOCAL ARGUMENTLIST ARGLST; LOCAL CMPLX1; LOCAL PEXPRNODE CNODE; LOCAL PEXPRNODE ARGNODE; FNREF_TRUE; !SET GLOBAL FLAG INDICATING THAT THIS STMNT INCLUDES A FN-CALL TREEPTR[FNCALLSFLG]_1; TREEPTR[ALCRETREGFLG]_1; TREEPTR[TARGTAC]_RETREG; TREEPTR[INREGFLG]_1; TREEPTR[TARGADDR]_RETREG; %(***IF HAVE NO ARGS (ARGLST PTR IS 0) THEN COMPLEXITY IS 0***)% IF .TREEPTR[ARG2PTR] EQL 0 THEN RETURN 0; %(**SAVE PTR TO CURRENT NODE***)% CNODE_.TREEPTR; %(***COMPLEXITY WILL BE MAX OF COMPLEXITIES OF ELEMS ON ARGLIST***)% CMPLX1_CMPFNARGS(.TREEPTR[ARG2PTR],.TREEPTR[DBLFLG]); %(***DETERMINE WHETHER ANY ARG UNDER THIS CALL IS EQL TO LHS OF THIS ASMNT OR CONTAINS ANY REFERENCE TO IT***)% ARGLST_.CNODE[ARG2PTR]; %(***WALK DOWN THE ARGLIST***)% INCR CT FROM 1 TO .ARGLST[ARGCOUNT] BY 1 DO BEGIN ARGNODE_.ARGLST[.CT,ARGNPTR]; IF .ARGNODE[OPRCLS] EQL DATAOPR THEN BEGIN IF .ARGNODE EQL .RESNAME THEN CNODE[RESRFFLG]_1; END ELSE IF .ARGNODE[RESRFFLG] THEN CNODE[RESRFFLG]_1; END; RETURN .CMPLX1; END; GLOBAL ROUTINE CMPFNARGS(ARLISTT,PARDBLFLG)= %(************************************************************ COMPUTE THE COMPLEXITY OF AN ARGUMENT LIST. USED FOR FUNCTIONS AND SUBROUTINE CALLS "PARDBLFLG" IS TRUE IFF THE FUNCTION HAD A DOUBLE-WD VALUE AND HENCE ALLOCATION AT THE PARENT LEVEL WAS DONE IN "DOUBLE-WD MODE" ************************************************************:)% BEGIN MAP ARGUMENTLIST ARLISTT; LOCAL CMPLMAX, CMPL1; LOCAL PEXPRNODE ARGNODE; CMPLMAX_0; %(***REPEAT THE FOLLOWING FOR ALL ARGS***)% INCR CT FROM 1 TO .ARLISTT[ARGCOUNT] BY 1 DO BEGIN %(***GET PTR TO EXPRESSION NODE FOR 1ST ARG***)% ARGNODE_.ARLISTT[.CT,ARGNPTR]; TREEPTR_.ARGNODE; %(***IF THIS ARG IS A CONSTANT, ALLOCATE CORE TO STORE THAT CONSTANT (IF NONE HAS YET BEEN ALLOCATED)****)% IF .ARGNODE[OPR1] EQL CONSTFL THEN BEGIN ALOCONST(.TREEPTR); CMPL1_0 END ELSE IF NOT .ARLISTT[.CT,AVALFLG] THEN BEGIN CMPL1_ SETCOMPLEXITY(); %(***CHECK FOR AN ARG THAT REQUIRES A DOUBLE-WD COMPUTATION. IF PARENT WAS NOT ALSO DOUBLE-WD MODE, MUST DOUBLE THE SIZE OF THE NUMBER OF REGS INDICATED***)% IF .ARGNODE[DBLFLG] AND NOT .PARDBLFLG THEN CMPL1_.CMPL1^1 ELSE %(***IF PARENT IS DOUBLE-WD MODE AND ARG IS SINGLE-WD, DIVIDE COMPLEXITY IN HALF***)% IF .PARDBLFLG AND NOT .ARGNODE[DBLFLG] THEN CMPL1_(.CMPL1+1)^(-1); %(***CHECK IF ARG IS FORMAL ARRAY***)% IF ARRNARGBLK(ARLISTT[.CT,ARGNPTR],ARLISTT[.CT,AVALFLG]) THEN CMPL1_0; END ELSE CMPL1_0; IF .CMPL1 GTR .CMPLMAX THEN CMPLMAX_.CMPL1; END; RETURN .CMPLMAX END; GLOBAL ROUTINE CMPTPCNV= %(*************************************************************************** TO COMPUTE THE COMPLEXITY OF A TYPE CONVERSION NODE. IF THE CONVERSION IS BETWEEN SINGLE-WORD AND DOUBLE-WORD VALUES, MUST ADJUST THE COMPLEXITY USED FOR NODES BELOW THIS ONE. IF THE CONVERSION IS BETWEEN FIXED AND FLOAT ON THE KA10, WILL NEED AN EXTRA REG. ***************************************************************************)% BEGIN EXTERNAL PAIRMODE; !GLOBAL FLAG INDICATING THAT STMNT BEING PROCESSED ! REQUIRES REG PAIRS LOCAL PEXPRNODE CNODE:ARGNODE; OWN CMPLX1; CNODE_.TREEPTR; ARGNODE_.CNODE[ARG2PTR]; %(***GET COMPLEXITY OF THE ARG***)% IF .CNODE[A2VALFLG] THEN BEGIN CMPLX1_0; %(***IF ARG IS EQUAL TO THE VARIABLE ON THE LHS OF THIS ASSIGNMENT SET A FLG*****)% IF .CNODE[ARG2PTR] EQL .RESNAME THEN CNODE[RESRFFLG]_1; %(***IF THE ARG UNDER THIS NODE COULD HAVE BEEN LEFT IN A REG BY THE EVAL OF A PRECEEDING STMNT, DO SO***)% SAVREGCONTAINING(.ARGNODE); END ELSE BEGIN ARGNODE_.CNODE[ARG2PTR]; TREEPTR_.CNODE[ARG2PTR]; CMPLX1_SETCOMPLEXITY(); %(***IF VAL OF ARG IS COMPUTED INTO RETREG, COMPUTE VAL OF PARENT INTO RETREG**)% SNGARGPROP(.CNODE,.ARGNODE); END; %(***IF ARG IS A CONSTANT, MUST ALLOCATE CORE FOR IT (THIS WILL ONLY OCCUR IF CALLED THE TYPE CONV ROUTINE EXPLICITLY)***)% IF .ARGNODE[OPR1] EQL CONSTFL THEN ALOCONST(.ARGNODE); %(***UNLESS NO CONVERSION CODE HAS TO BE GENERATED, AT LEAST 1 REGISTER WILL BE NEEDED TO PERFORM THE CONVERSION IN *******)% IF NOT NOCNV(CNODE) THEN BEGIN IF .CMPLX1 EQL 0 THEN CMPLX1_1; %(***FOR CONVERSION BETWEEN FIXED AND FLOAT AND VICE-VERSA, ON THE KA10 NEED A SECOND REGISTER ********)% IF .KA10FLG THEN BEGIN IF NOT .CNODE[DBLFLG] AND NOT .CNODE[SDBLFLG] THEN BEGIN PAIRMODE_TRUE; !A REG PAIR WILL BE NEEDED IF .CMPLX1 LSS 2 THEN CMPLX1_2; END; END END; %(***CHECK FOR CHANGE IN PRECISION ACROSS THIS NODE***)% IF .CNODE[DBLFLG] AND NOT .CNODE[SDBLFLG] THEN %(***IF NODE BELOW IS SINGLE-WD AND THIS NODE IS DOUBLE-WD***)% CMPLX1_(.CMPLX1+1)^(-1) ELSE IF NOT .CNODE[DBLFLG] AND .CNODE[SDBLFLG] THEN %(***IF NODE BELOW IS DOUBLE-WD AND THIS NODE IS SINGLE-WD***)% CMPLX1_.CMPLX1^1; RETURN .CMPLX1; END; GLOBAL ROUTINE CMPLXARRAY = %(*************************************************************************** COMPUTE THE COMPLEXITY OF AN ARRAY REFERENCE. MUST GET THE VALUE OF THE OFFSET INTO A REGISTER (UNLESS IT IS CONSTANT). THEREFORE NEED AS MANY REGS AS ARE NEEDED TO COMPUTE THAT VAL, OR 1 REG IF THAT VAL REQUIRES NO COMPUTATION BUT IS NOT CONSTANT (IE IS A SCALER). SET UP THE TARGET WD OF THIS ARRAYREF NODE SO THAT THE RIGHT-HALF CONTAINS THE CONSTANT PART OF THE REFERENCE TO THIS ELEMENT (IE THE SUM OF THE ADDRESS OF THE ARRAY BASE WITH ANY CONSTANTS INVOLVED IN THE OFFSET CALCULATION. IN ORDER TO DO THIS MUST WALK DOWN THE N-ARY SUM THAT IS THE ADDRESS CALCULATION, TO GET ANY CONSTANT TERM (WHICH THE CANONICALIZER WILL HAVE LEFT AT BOTTOM LEFT). NOTE THAT THE TARGET WORD ALREADY CONTAINS ANY CONSTANT TERMS THAT WERE DETECTED AT THE TIME THAT THE ADDRESS CALCULATION WAS EXPANDED. THIS ROUTINE IS CALLED WITH THE GLOBAL TREEPTR POINTING TO THE ARRAYREF NODE TO BE PROCESSED. ***************************************************************************)% BEGIN OWN T1; OWN AADDR; OWN CMPLX1; OWN PEXPRNODE CONSTTERM; !EVENTUALLY WILL BE SET TO PT TO THE ! CONSTANT TERM IN THE ADDRESS CALC OWN PEXPRNODE PAROFCONST; !PTR TO PARENT OF CONSTTERM OWN PEXPRNODE GPOFCONST; !PTR TO PARENT OF "PAROFCONST" LOCAL PEXPRNODE CNODE:NAME:ADDRNODE; NAME_.TREEPTR[ARG1PTR]; ADDRNODE_.TREEPTR[ARG2PTR]; CNODE_.TREEPTR; %(***IF THE ARRAY NAME IS IDENTICAL TO THE ARRAY NAME ON LEFT HAND SIDE OF ASSIGNMENT OR THE ADDRNODE IS IDENTICAL TO A SIMPLE VAR ON THE LEFT HAND SIDE OF THE ASSIGNMENT, SET FLAGS INDICATING THAT THERE IS A REFERENCE TO LHS UNDER THIS NODE***)% IF (.NAME EQL .RESNAME) OR (.ADDRNODE EQL .RESNAME) THEN TREEPTR[RESRFFLG]_1; %(***FOR AN ARRAY WHICH IS NOT A FORMAL, ADD THE BASE ADDRESS OF THE ARRAY INTO THE CONSTANT PART OF THE ADDRESS CALCULATION***)% AADDR_ (IF .NAME[FORMLFLG] THEN 0 ELSE .NAME[IDADDR] ); %(***IF THERE IS NO ADDRESS CALCULATION TO BE DONE (ADDR IS A CONSTANT WHICH WAS DETECTED AT TIME OF EXPANSION OF THE ARRAY). FILL IN CORRECT VAL FOR TARGET FIELD AND RETURN. *******)% IF .ADDRNODE EQL 0 THEN BEGIN T1_.AADDR + EXTSIGN( .TREEPTR[TARGADDR]); TREEPTR[A2IMMEDFLG]_1; TREEPTR[TARGADDR]_.T1; RETURN 0 END; %(***IF ADDRNODE IS A CONSTANT, THEN NO RUNTIME ADDRESS CALCULATION IS NECESSARY***)% IF .ADDRNODE[OPR1] EQL CONSTFL THEN BEGIN T1_.ADDRNODE[CONST2] + .AADDR + EXTSIGN( .TREEPTR[TARGADDR]); TREEPTR[ARG2PTR]_0; !SET THE "VARIABLE-PART" OF THE ADDRESS CALC ! TO 0 TREEPTR[A2VALFLG]_1; TREEPTR[A2IMMEDFLG]_1; TREEPTR[TARGADDR]_.T1; !PUT THE CONSTANT PART OF THE ADDRESS INTO ! THE TARGET FIELD OF THE ARRAYREF NODE RETURN 0 END; IF .ADDRNODE[OPRCLS] EQL CMNSUB !IF THE VARIABLE PART OF THE ADDRESS IS A COMMON SUB THEN ADDRNODE[CSSSFLG]_1; !SET FLAG INDICATING "THIS CS USED AS A SUBSCRIPT" ! (THIS WILL CAUSE IT TO GET PRIORITY FOR A REGISTER) %(*****IF ADDRESS COMPUTATION IS A SUM, SEARCH DOWN THE N-ARY SUM FOR THE CONSTANT TERM (WHICH THE CANONICALIZER WILL HAVE LEFT AT BOTTOM LEFT). EXTRACT THIS TERM FROM THE TREE AND PUT IT IN THE TARGET FIELD. *********)% IF .ADDRNODE[OPR1] EQL ADDOPF THEN BEGIN CONSTTERM_.ADDRNODE[ARG1PTR]; IF .CONSTTERM[OPR1] EQL CONSTFL THEN BEGIN %(***ADD THE CONSTANT TERM INTO THE ADDRESS FIELD OF THE INSTR (TRUNCATE TO 18 BITS IF NECESSARY) AND REMOVE THE CONSTANT NODE FROM THE TREE***)% T1_.AADDR + EXTSIGN( .TREEPTR[TARGADDR]) + .CONSTTERM[CONST2]; TREEPTR[TARGADDR]_.T1; TREEPTR[A2FLGS]_RAISEFLGS(.TREEPTR[A2FLGS],.ADDRNODE[A2FLGS]); TREEPTR[ARG2PTR]_.ADDRNODE[ARG2PTR]; ADDRNODE_.ADDRNODE[ARG2PTR]; END ELSE %(***IF LH OF TOP-LEVEL SUM IS ALSO A + NODE, SEARCH DOWN IT FOR THE CONSTANT TERM*******)% IF .CONSTTERM[OPR1] EQL ADDOPF THEN BEGIN PAROFCONST_.CONSTTERM; CONSTTERM_.CONSTTERM[ARG1PTR]; WHILE .CONSTTERM[OPR1] EQL ADDOPF DO (PAROFCONST_.CONSTTERM; CONSTTERM_.CONSTTERM[ARG1PTR]); %(***IF THERE IS A CONSTANT-TERM, IT WILL BE THE FIRST NON-PLUS NODE REACHED****)% IF .CONSTTERM[OPR1] EQL CONSTFL THEN BEGIN T1_.AADDR+EXTSIGN(.TREEPTR[TARGADDR])+.CONSTTERM[CONST2]; TREEPTR[TARGADDR]_.T1; %(***REMOVE THE CONSTANT NODE FROM THE TREE, LINKING ITS BROTHER UNDER ITS PARENT PLUS-NODE DIRECTLY TO ITS GRAND-PARENT PLUS-NODE***)% GPOFCONST_.PAROFCONST[PARENT]; GPOFCONST[A1FLGS]_RAISEFLGS(.GPOFCONST[A1FLGS], .PAROFCONST[A2FLGS]); GPOFCONST[ARG1PTR]_.PAROFCONST[ARG2PTR]; END ELSE %(***IF THERE IS NO CONSTANT TERM, JUST ADD THE ARRAY BASE ADDRESS INTO THE TARGET WD***)% TREEPTR[TARGADDR]_.AADDR+EXTSIGN(.TREEPTR[TARGADDR]); END ELSE TREEPTR[TARGADDR]_.AADDR+EXTSIGN(.TREEPTR[TARGADDR]); END ELSE TREEPTR[TARGADDR]_.AADDR+EXTSIGN(.TREEPTR[TARGADDR]); %(***IF THE VARIABLE PART OF THE ADDR IS A SINGLE VAR, THEN IF IT COULD BE LEFT IN A REG EARLIER DO SO AND IF ITS NEEDED LATER THEN LEAVE ITS REG ALONE AFTER EXECUTIOM OF THIS STMNT***)% IF .TREEPTR[A2VALFLG] THEN BEGIN SAVREGCONTAINING(.ADDRNODE); !SAVE THE REG FROM PREV REF ADDREGCANDATE(.ADDRNODE,.TREEPTR); !IF NEED THE REG LATER, CAN USE IT ! FROM THIS REF END; %(***FIND THE NUMBER OF REGISTERS NECESSARY TO COMPUTE THE ADDRESS, THE COMPLEXITY OF THE ARRAYREF NODE IS 1 IF 0 REGS ARE NEEDED, OTHERWISE IT IS EQUAL TO THE NUMBER OF REGS NEEDED*****)% IF .TREEPTR[A2VALFLG] THEN CMPLX1_1 ELSE BEGIN TREEPTR_.ADDRNODE; CMPLX1_SETCOMPLEXITY(); %(**IF THERE IS A REFERENCE TO LHS OF ASSIGNMENT STMNT SOMEWHERE IN THE ADDRESS CALCULATION, SET FLAG IN THE ARRAYREF NODE***)% IF .ADDRNODE[RESRFFLG] THEN CNODE[RESRFFLG]_1; IF .ADDRNODE[FNCALLSFLG] THEN CNODE[FNCALLSFLG]_1; END; IF .CNODE[DBLFLG] THEN BEGIN %(***CONVERT CMPLX1 FROM NUMBER OF REGS TO NUMBER OF PAIRS***)% CMPLX1_(.CMPLX1+1)/2; %(***FOR A DOUBLE-WD ARRAY-REF - ALWAYS NEED AT LEAST 3 REGS TO GET THE VALUE LOADED (SINCE CANT LOAD IT INTO THE REG USED FOR THE INDEX). HENCE NEED AT LEAST 2 PAIRS***)% IF .CMPLX1 LSS 2 THEN CMPLX1_2; END %(***FOR A SINGLE-WD ARRAYREF - ALWAYS NEED AT LEAST 1 REG***)% ELSE IF .CMPLX1 EQL 0 THEN CMPLX1_1; RETURN .CMPLX1 END; GLOBAL ROUTINE CMPILF= %(*************************************************************************** TO PERFORM THE COMPLEXITY PASS FOR AN IN-LINE-FUNCTION NODE. NUMBER OF REGS NEEDED IS MAX OF THE FOLLOWING: 1. NUMBER OF REGS NEEDED TO COMPUTE ARG1 2. 1+NUMBER OF REGS NEEDED FOR COMPUTING ARG2 FOR MOD, NEED 1 MORE REG THAN THAT. ***************************************************************************)% BEGIN LOCAL PEXPRNODE CNODE; LOCAL CMPLX1,CMPLX2; LOCAL PEXPRNODE ARG1NODE:ARG2NODE; CNODE_.TREEPTR; ARG1NODE_.CNODE[ARG1PTR]; ARG2NODE_.CNODE[ARG2PTR]; %(***FOR CMPLX - USE CMPLA***)% IF .CNODE[OPERSP] EQL CMPLXFN THEN RETURN BEGIN IF (CMPLX1_CMPLA()) GTR 2 THEN .CMPLX1 ELSE 2 END; %(***FOR MAX AND MIN - IF ONE OF THE ARGS IS A REAL OR NEGATIVE CONSTANT, LET ARG1 BE THAT ARG (SINCE HAVE PROBS WITH COMPARE-IMMED FOR REAL AN NEG CNSTS)***)% IF .CNODE[OPERSP] EQL MAXFN OR .CNODE[OPERSP] EQL MINFN THEN BEGIN !**;[411] Insert @ 4784 JNG 6-Jul-76 !**;[411] Don't swap args if first neg to prevent bad code. IF .ARG2NODE[OPR1] EQL CONSTFL ![411] AND .ARG1NODE[OPR1] NEQ CONSTFL ![411] AND NOT .CNODE[A1NEGFLG] ![411] THEN BEGIN IF .ARG2NODE[VALTP1] NEQ INTEG1 OR .ARG2NODE[CONST2] LSS 0 THEN BEGIN SWAPARGS(CNODE); !EXCHANGE THE 2 PTRS AND ALSO THE FLAGS THAT GO WITH ! THE 2 ARGS ARG1NODE_.CNODE[ARG1PTR]; ARG2NODE_.CNODE[ARG2PTR]; END END END; %(***PERFORM COMPLEXITY ANALYSIS FOR ARG1***)% TREEPTR_.CNODE[ARG1PTR]; %(***IF ARG1 IS AN IMMED CNST SET A1IMMEDFLG, IF IT IS A NON-IMMED CNST, ALLOCATE CORE FOR IT***)% IF .ARG1NODE[OPR1] EQL CONSTFL THEN (PRCNSTARG(.CNODE,.CNODE[ARG1PTR],TRUE); CMPLX1_0) ELSE IF .CNODE[A1VALFLG] THEN BEGIN %(***IF ARG IS RESULT NAME, SET RESRFFLG***)% IF .ARG1NODE EQL .RESNAME THEN CNODE[RESRFFLG]_1; CMPLX1_0 END ELSE BEGIN CMPLX1_SETCOMPLEXITY(); %(***SET FLAGS FOR "FNCALLS PRESENT UNDER THIS NODE" AND FOR REF TO RESULT UNDER THIS NODE***)% IF .ARG1NODE[FNCALLSFLG] THEN CNODE[FNCALLSFLG]_1; IF .ARG1NODE[RESRFFLG] THEN CNODE[RESRFFLG]_1; END; IF .CNODE[OPERSP] NEQ ABSFN !FOR FNS OTHER THAN ABS THEN SAVREGCONTAINING(.ARG1NODE); ! IF VAL OF ARG1 CAN BE LEFT IN A REG IN A PREV ! STMNT, BB ALLOCATOR SHOULD DO SO %(***PROCESS 2ND ARG**************)% IF .ARG2NODE NEQ 0 THEN BEGIN TREEPTR_.CNODE[ARG2PTR]; %(***FOR ARG2 AN IMMED CNST, SET A2IMMEDFLG EXCEPT IN THE CASES OF AMAX AND AMIN (SINCE CANT DO COMPARE IMMED FOR A REAL) AND IN THE (UNLIKELY!) CASE OF SIGN***)% IF .ARG2NODE[OPR1] EQL CONSTFL THEN BEGIN IF .CNODE[OPERATOR] EQL AMAXFNOP OR .CNODE[OPERATOR] EQL AMINFNOP OR .CNODE[OPERATOR] EQL DIMFNOP OR .CNODE[OPERSP] EQL SIGNFN THEN ALOCONST(.ARG2NODE) ELSE IF IMMEDCNST(ARG2NODE) THEN BEGIN IF .ARG2NODE[VALTP1] EQL INTEG1 AND .ARG2NODE[CONST2] LSS 0 THEN ALOCONST(.ARG2NODE) ELSE CNODE[A2IMMEDFLG]_1; END ELSE ALOCONST(.ARG2NODE); CMPLX2_1; END ELSE IF .CNODE[A2VALFLG] THEN BEGIN IF .ARG2NODE EQL .RESNAME THEN .CNODE[RESRFFLG]_1; CMPLX2_1; END ELSE BEGIN CMPLX2_SETCOMPLEXITY()+1; IF .ARG2NODE[RESRFFLG] THEN CNODE[RESRFFLG]_1; IF .ARG2NODE[FNCALLSFLG] THEN CNODE[FNCALLSFLG]_1; END; END ELSE CMPLX2_1; %(***IF ARG1 WILL BE COMPUTED INTO RETREG (FN RETURN REGISTER), THEN 1. IF ARG2 INCLUDES FN CALLS, THEN CANNOT COMPUTE ARG1 INTO RETREG. UNDO THE ALLOCATION. 2. OTHERWISE, COMPUTE THE PARENT INTO RETREG ALSO **********)% IF NOT .CNODE[A1VALFLG] AND .ARG1NODE[ALCRETREGFLG] THEN BEGIN IF NOT .CNODE[A2VALFLG] AND .ARG2NODE[FNCALLSFLG] THEN BEGIN %(***UNDO THE ALLOCATION OF ARG1 TO RETREG (SINCE RETREG WILL BE CLOBBERED WHILE COMPUTING ARG2)***)% ARG1NODE[ALCRETREGFLG]_0; ARG1NODE[A1SAMEFLG]_0; ARG1NODE[A2SAMEFLG]_0; ARG1NODE[INREGFLG]_0; END ELSE BEGIN %(***ALLOCATE CNODE TO BE COMPUTED IN RETREG***)% CNODE[TARGTAC]_RETREG; CNODE[INREGFLG]_1; CNODE[A1SAMEFLG]_1; CNODE[ALCRETREGFLG]_1; END; END; IF .CMPLX2 GTR .CMPLX1 THEN CMPLX1_.CMPLX2; IF .CNODE[OPERSP] EQL MODFN THEN RETURN .CMPLX1+1 ELSE RETURN .CMPLX1; END; GLOBAL ROUTINE CMPLIOLST= %(*************************************************************************** ROUTINE TO PERFORM THE COMPLEXITY WALK FOR AN IOLIST CALLED WITH THE GLOBAL CSTMNT POINTING TO A STATEMENT THAT HAS AN IOLIST ASSOCIATED WITH IT. CALLED WITH THE GLOBALS STBSYR AND STRGCT INDICATING WHICH REGS ARE AVAILABLE FOR USE THE COMPLEXITY OF AN IOLIST IS EQUAL TO THE COMPLEXITY OF ITS MOST COMPLEX ELEMENT. ***************************************************************************)% BEGIN EXTERNAL PAIRMODE; !GLOBAL FLAG FOR "THIS STMNT USES A REG PAIR" EXTERNAL FNREF; !GLOBAL FLAG FOR "THIS STMNT INCLUDES A FN CALL" EXTERNAL STCMCSB; EXTERNAL CSTMNT,STBSYR,STRGCT; EXTERNAL CMSTMN; MAP BASE CSTMNT; LOCAL CMPLXMAX,CMPLX1; LOCAL BASE IOLELEM; LOCAL SAVSTMNT; LOCAL SAVPAIRMODE,SAVFNREF; %(***GET PTR TO 1ST ELEMENT ON THE IOLIST TO BE PROCESSED***)% IOLELEM_.CSTMNT[IOLIST]; %(***SAVE PTR TO CURRENT STATEMENT (IF THERE ARE DO-STMNTS IN THE IOLIST WILL CLOBBER CSTMNT) ***)% SAVSTMNT_.CSTMNT; %(***INIT THE COMPLEXITY OF THE IOLOIST TO 0****)% CMPLXMAX_0; %(****WALK THRU THE ELEMENTS ON THE IOLOIST*****)% UNTIL .IOLELEM EQL 0 DO BEGIN IF .IOLELEM[OPRCLS] EQL STATEMENT THEN BEGIN CSTMNT_.IOLELEM; SAVPAIRMODE_.PAIRMODE; SAVFNREF_.FNREF; !(THE GLOBALS "PAIRMODE" AND "FNREF" WILL ! DESCRIBE THIS SUBSTMNT WHEN WE RETURN FROM CMSTMN - SAVE THEIR ! OLD VALUES CMSTMN(); PAIRMODE_.SAVPAIRMODE OR .PAIRMODE; !RESTORE "PAIRMODE" - IT SHOULD ! GET SET TO "TRUE" IF THIS SUBSTMNT USED ANY PAIRS FNREF_.SAVFNREF OR .FNREF; !RESTORE "FNREF" - IT SHOULD ! GET SET TO "TRUE" IF THIS SUBSTMNT INCLUDED ANY FN CALLS CMPLX1_.CSTMNT[SRCCMPLX]; END ELSE IF .IOLELEM[OPRCLS] EQL IOLSCLS THEN BEGIN CASE .IOLELEM[OPERSP] OF SET %(***FOR A DATACALL NODE*******)% BEGIN TREEPTR_.IOLELEM[DCALLELEM]; CMPLX1_SETCOMPLEXITY(); IF ARRNARGBLK(IOLELEM[DCALLELEM],0) THEN CMPLX1_0; END; %(***FOR AN SLISTCALL NODE***)% BEGIN %(***PERFORM COMPLEXITY PASS FOR THE EXPRESSION TO COMPUTE THE NUMBER OF ELEMENTS***)% TREEPTR_.IOLELEM[SCALLCT]; CMPLX1_SETCOMPLEXITY(); IF ARRNARGBLK(IOLELEM[SCALLCT],0) THEN CMPLX1_0; END; %(***FOR AN IOLSTCALL NODE***)% CMPLX1_CMPIOCALL(.IOLELEM); %(***FOR AN E1LISTCALL - OPTIMIZED CODE ONLY***)% BEGIN LOCAL BASE SAVCSTMNT; CMPE1LIST(.IOLELEM); !SET COMPLEXITY SAVCSTMNT_.CSTMNT; !INCLUDE COMMON SUBS CSTMNT_.IOLELEM; !SET STATEMENT STCMCSB(); !INCLUDE COMMON SUBS CMPLX1_.IOLELEM[SRCCMPLX]; !SET COMPLEXITY CSTMNT_.SAVCSTMNT END; %(***FOR AN E2LISTCALL - OPTIMIZED CODE ONLY***)% BEGIN LOCAL BASE SAVCSTMNT; CMPE2LIST(.IOLELEM); !SET COMPLEXITY SAVCSTMNT_.CSTMNT; !INCLUDE COMMON SUBS CSTMNT_.IOLELEM; !SET STATEMENT STCMCSB(); !INCLUDE COMMON SUBS CMPLX1_.IOLELEM[SRCCMPLX]; !SET COMPLEXITY CSTMNT_.SAVCSTMNT END TES; %(***IF THIS ELEMENT OF THE LIST REQUIRES MORE REGS TO COMPUTE THAN ANY EARLIER ELEMENTS, SET CMPLXMAX TO INDICATE THE NUMBER OF REGS THAT THIS ELEM NEEDS***)% IF .CMPLXMAX LSS .CMPLX1 THEN CMPLXMAX_.CMPLX1; END; %(***GO ON TO NEXT ELEMENT***)% IOLELEM_.IOLELEM[CLINK]; END; CSTMNT_.SAVSTMNT; CSTMNT[SRCCMPLX]_.CMPLXMAX; END; GLOBAL ROUTINE CMPIOCALL(IOLSNODE)= %(*************************************************************************** ROUTINE TO PERFORM THE COMPLEXITY WALK FOR AN IOLSTCALL NODE. THE ARG IOLSNODE POINTS TO THE IOLSTCALL NODE. THE NUMBER OF REGS THAT CAN BE USED FOR AN IOLSTCALL NODE IS DETERMINED BY: 1. THE NUMBER OF ITEMS LEFT IN REGS ACROSS THE CALL TO THE OPERATING SYSTEM 2. THE NUMBER OF REGS NEEDED TO COMPUTE THE EXPRESSIONS WHICH MUST BE COMPUTED PRIOR TO CALLING THE OPERATING SYSTEM THE COMPLEXITY OF THIS NODE IS THE MAXIMUM VALUE OF THE SUM OF: 1. THE NUMBER OF REGS NECESSARY TO COMPUTE A GIVEN EXPRESSION 2. THE NUMBER OF ITEMS PRECEEDING THIS EXPRESSION THAT WERE LEFT IN REGS ***************************************************************************)% BEGIN MAP BASE IOLSNODE; EXTERNAL CSTMNT,STCMCSB; OWN SAVSTMNT; OWN CMPLX,REGSINUSE; OWN CMPLX1,REG1; OWN BASE IOLELEM; %(***SAVE PTR TO CSTMNT***)% SAVSTMNT_.CSTMNT; CMPLX_0; REGSINUSE_0; IOLELEM_.IOLSNODE[IOLSTPTR]; %(***WALK THRU THE ELEMENTS OF THE IOLST, KEEPING TRACK OF THE MAX VALUE OF THE SUM OF THE COMPLEXITY OF A GIVEN ELEMENT WITH THE NUMBER OF REGS BEING USED TO HOLD ELEMS BEFORE IT***)% UNTIL .IOLELEM EQL 0 DO BEGIN CASE .IOLELEM[OPERSP] OF SET %(***FOR A DATACALL NODE***)% BEGIN OWN PEXPRNODE DELEM; !EXPRESSION FOR DATA ELEMENT DELEM_.IOLELEM[DCALLELEM]; TREEPTR_.DELEM; CMPLX1_SETCOMPLEXITY(); IF ARRNARGBLK(IOLELEM[DCALLELEM],0) THEN CMPLX1_0; REG1_(IF .CMPLX1 EQL 0 THEN 0 ELSE IF .DELEM[DBLFLG] !IF THE VAL MUST BE LEFT ! IN AN EVEN-ODD PAIR THEN 2 ! TAKE 2 REGS OUT OF SET ELSE 1); END; %(***FOR A SLISTCALL NODE***)% BEGIN TREEPTR_.IOLELEM[SCALLCT]; CMPLX1_SETCOMPLEXITY(); IF ARRNARGBLK(IOLELEM[SCALLCT],0) EQL 0 THEN CMPLX1_0; %(***NEVER BOTHER TO TRY TO LEAVE THIS CT IN A REG (STORE IT IN A TMP BEFORE CALLING FOROTS)***)% REG1_0; END; %(***IOLSTCALL NODE WITHIN AN IOLSTCALL NODE IS ILLEGAL***)% CGERR(); %(***FOR AN E1LISTCALL NODE - OPTIMIZED CODE ONLY***)% BEGIN CMPLX1_CMPE1LIST(.IOLELEM); REG1_0 !NO REGISTERS END; %(***FOR AN E2LISTCALL NODE - OPTIMIZED CODE ONLY***)% BEGIN CMPLX1_CMPE2LIST(.IOLELEM); REG1_0 END TES; IF .REGSINUSE+.CMPLX1 GTR .CMPLX THEN CMPLX_.REGSINUSE+.CMPLX1; REGSINUSE_.REGSINUSE+.REG1; IOLELEM_.IOLELEM[CLINK]; END; IOLSNODE[SRCCMPLX]_.CMPLX; %(***PERFORM COMPLEXITY ANALYSIS FOR COMMON SUBEXPRS UNDER THIS IOLSTCALL***)% CSTMNT_.IOLSNODE; STCMCSB(); %(***RESTORE CSTMNT****)% CSTMNT_.SAVSTMNT; RETURN .IOLSNODE[SRCCMPLX]; END; GLOBAL ROUTINE CMPE1LIST(IOLELEM)= %(********************************************************************** COMPUTE THE COMPLEXITY OF AN E1LISTCALL NODE (EXCEPT FOR COMMON SUBEXPRESSIONS) **********************************************************************)% BEGIN MAP BASE IOLELEM; LOCAL BASE IOARRAY; OWN CMPLX,REGSINUSE,CMPLX1,REG1; %(***COMPUTE COMPLEXITY OF COUNT EXPRESSION***)% TREEPTR_.IOLELEM[ECNTPTR]; !LOCATE EXPRESSION CMPLX_SETCOMPLEXITY(); !INITIALIZE COMPLEXITY IF ARRNARGBLK(IOLELEM[ECNTPTR],0) THEN CMPLX_0; !RESET IF ARRAYREF IS REPLACED REGSINUSE_0; !INITIALIZE REGISTER COUNT %(***ADD IN COMPLEXITY OF INCREMENT EXPRESSION***)% TREEPTR_.IOLELEM[E1INCR]; !LOCATE EXPRESSION IF .TREEPTR[OPR1] EQL CONSTFL THEN IF .TREEPTR[CONST1] EQL 0 AND .TREEPTR[CONST2] EQL 0 THEN ALOCONST(.TREEPTR); CMPLX1_SETCOMPLEXITY(); !COMPUTE COMPLEXITY IF ARRNARGBLK(IOLELEM[E1INCR],0) THEN CMPLX1_0; !RESET OF ARRAYREG IS REPLACED REG1_0; !NEVER SAVE IN A REG IF .REGSINUSE +.CMPLX1 GTR .CMPLX THEN CMPLX_.REGSINUSE+.CMPLX1; !UPDATE COMPLEXITY REGSINUSE_.REGSINUSE+.REG1; !UPDATE REGISTER COUNT %(***ADD IN COMPLEXITY OF EACH ARRAYREF ON THE LIST***)% IOARRAY_.IOLELEM[ELSTPTR]; !LOCATE LIST WHILE .IOARRAY NEQ 0 DO BEGIN TREEPTR_.IOARRAY[E2ARREFPTR]; !LOCATE EXPRESSION CMPLX1_SETCOMPLEXITY(); !COMPUTE COMPLEXITY IF ARRNARGBLK(IOARRAY[E2ARREFPTR],0) THEN CMPLX1_0; REG1_0; !NEVER IN A REG IF .REGSINUSE+.CMPLX1 GTR .CMPLX THEN CMPLX_.REGSINUSE+.CMPLX1; !UPDATE COMPLEXITY REGSINUSE_.REGSINUSE+.REG1; !UPDATE REGISTER COUNT IOARRAY_.IOARRAY[CLINK] !NEXT ARRAYREF END; %(***RETURN COMPLEXITY OF E1LISTCALL NODE***)% RETURN (IOLELEM[SRCCMPLX]_.CMPLX) END; GLOBAL ROUTINE CMPE2LIST(IOLELEM)= %(********************************************************************** COMPUTE THE COMPEXITY OF AN E2LISTCALL NODE (EXCEPT FOR COMMON SUBEXPRESSIONS) **********************************************************************)% BEGIN MAP BASE IOLELEM; LOCAL BASE IOARRAY; OWN CMPLX,REGSINUSE,CMPLX1,REG1; %(***COMPUTE COMPLEXITY OF COUNT EXPRESSION***)% TREEPTR_.IOLELEM[ECNTPTR]; !LOCATE EXPRESSION CMPLX_SETCOMPLEXITY(); !INITIALIZE COMPLEXITY COUNTER IF ARRNARGBLK(IOLELEM[ECNTPTR],0) THEN CMPLX_0; REGSINUSE_0; !INITIALIZE REGSISTER COUNTER %(***COMPUTE COMPLEXITY OF EACH INCREMENT EXPRESSION***)% IOARRAY_.IOLELEM[ELSTPTR]; !INITIALIZE POINTER WHILE .IOARRAY NEQ 0 DO BEGIN TREEPTR_.IOARRAY[E2INCR]; !LOCATE EXPRESSION IF .TREEPTR[OPR1] EQL CONSTFL THEN IF .TREEPTR[CONST1] EQL 0 AND .TREEPTR[CONST2] EQL 0 THEN ALOCONST(.TREEPTR); CMPLX1_SETCOMPLEXITY(); !COMPUTE COMPLEXITY IF ARRNARGBLK(IOARRAY[E2INCR],0) THEN CMPLX1_0; REG1_0; !NEVER SAVE IN A REG IF .REGSINUSE+.CMPLX1 GTR .CMPLX THEN .CMPLX_.REGSINUSE+.CMPLX1; !UPDATE CMPLEXITY REGSINUSE_.REGSINUSE+.REG1; !UPDATE REGISTER COUNT IOARRAY_.IOARRAY[CLINK] !ADVANCE TO NEXT ARRAYREF END; %(***COMPUTE COMPLEXITY FOR ARRAYREFS***)% IOARRAY_.IOLELEM[ELSTPTR]; !INITIALIZE POINTER WHILE .IOARRAY NEQ 0 DO BEGIN TREEPTR_.IOARRAY[E2ARREFPTR]; !LOCATE EXPRESSION CMPLX1_SETCOMPLEXITY(); !COMPUTE COMPLEXITY IF ARRNARGBLK(IOARRAY[E2ARREFPTR],0) THEN CMPLX1_0; REG1_0; !NEVER SAVE IN A REG IF .REGSINUSE+.CMPLX1 GTR .CMPLX THEN .CMPLX_.REGSINUSE+.CMPLX1; !UPDATE CMPLEXITY REGSINUSE_.REGSINUSE+.REG1; !UPDATE REGISTER COUNT IOARRAY_.IOARRAY[CLINK] !ADVANCE TO NEXT ARRAYREF END; %(***RETURN COMPLEXITY***)% RETURN (IOLELEM[SRCCMPLX]_.CMPLX) END; GLOBAL ROUTINE SNGARGPROP(PARENTNODE,SON)= %(*************************************************************************** FOR NODES THAT HAVE ONLY ONE ARGUMENT (TYPE-CONVERSION,NEGNOT, SPECIAL OPERATORS), SET RESRFFLG,FNCALLSFLG IN THE PARENT IF THEY ARE SET IN THE SON. ALSO, IF THE ARG IS COMPUTED INTO THE FN-RESULT REGISTER ("RETREG"), THEN WILL WANT TO COMPUTE THE PARENT INTO THE SAME REGISTER (IN MOST CASES). ***************************************************************************)% BEGIN MAP PEXPRNODE PARENTNODE:SON; IF .SON[ALCRETREGFLG] AND .SON[INREGFLG] AND .SON[TARGTAC] EQL RETREG THEN BEGIN PARENTNODE[TARGTAC]_RETREG; PARENTNODE[INREGFLG]_1; PARENTNODE[ALCRETREGFLG]_1; %(***SET FLAG IN PARENT INDICATING WHICH ARG IS IN THE SAME REG***)% IF .PARENTNODE[ARG1PTR] EQL .SON THEN PARENTNODE[A1SAMEFLG]_1 ELSE PARENTNODE[A2SAMEFLG]_1; END; IF .SON[RESRFFLG] THEN PARENTNODE[RESRFFLG]_1; IF .SON[FNCALLSFLG] THEN PARENTNODE[FNCALLSFLG]_1; END ; GLOBAL ROUTINE EXCHARGS(CNODE) = %(*************************************************************************** ROUTINE TO SWAP THE 1ST AND 2ND ARGS UNDER AN EXPRESSION NODE IF POSSIBLE CALLED WITH THE ARG "CNODE" POINTING TO THE NODE IN QUESTION RETURNS "TRUE" IF A SWAP WAS POSSIBLE, "FALSE" IF NOT ***************************************************************************)% BEGIN MAP PEXPRNODE CNODE; %(***SHOULD ONLY CALL THIS ROUTINE FOR NODES OF OPRCLS RELATIONAL, BOOLEAN, ARITHMETIC, OR IN LINE FN*****)% IF .CNODE[OPRCLS] GTR ARITHMETIC THEN BEGIN IF .CNODE[OPRCLS] EQL INLINFN !FOR IN LINE FNS THEN BEGIN IF .CNODE[OPERSP] EQL MAXFN OR .CNODE[OPERSP] EQL MINFN !FOR MAX/MIN ! CAN SWAP ARGS THEN (SWAPARGS(CNODE); RETURN TRUE) !EXCHANGE THE PTRS AND THE FLAGS ELSE RETURN FALSE !FOR OTHER IN LINE FNS CANNOT END ELSE CGERR() !IF OPERATOR IS NOT BOOLEAN,REL,ARITH OR IN LINE FN HAVE AN ERROR END; IF .CNODE[OPR1] EQL DIVOPF OR .CNODE[OPR1] EQL EXPONOPF THEN RETURN FALSE; %(***CANNOT SWAP THE ARGS IF HAVE SUB AND THE NOT FLAG IS ON FOR ARG2 (WHICH WOULD NOW NEED TO BE NEGATED) ***)% IF .CNODE[OPR1] EQL MULOPF AND .CNODE[A2NOTFLG] THEN RETURN FALSE; %(***SWAP THE 2 POINTERS*****)% %(****ALSO THE FLAGS CORRESPONDING TO THE 2 ARGS (IE A1NEGFLG WITH A2NEGFLG ETC) ****)% SWAPARGS(CNODE); %(****FOR SUBTRACTION,COMPLEMENT NEGFLG FOR THE ARG THAT WAS MOVED FROM 2ND TO 1ST AND CHANGE OPERSP FROM "SUB2 TO "ADD"*******)% IF .CNODE[OPR1] EQL SUBOPF THEN BEGIN CNODE[OPR1]_ADDOPF; CNODE[A1NEGFLG]_NOT .CNODE[A1NEGFLG]; END; %(****FOR RELATIONALS(EXCEPT EQ AND NE) REVERSE THE MODE OF THE RELATIONAL (EG SET LT TO GT, LE TO GE, ETC)*****)% IF .CNODE[OPRCLS] EQL RELATIONAL THEN BEGIN IF NOT EQREL(.CNODE[OPERSP]) THEN CNODE[OPERSP]_REVREL(.CNODE[OPERSP]); END; RETURN TRUE; END; END ELUDOM