1*2187Smckusick /* Copyright (c) 1979 Regents of the University of California */ 2*2187Smckusick 3*2187Smckusick static char sccsid[] = "@(#)forop.c 1.1 01/16/81"; 4*2187Smckusick 5*2187Smckusick #include "whoami.h" 6*2187Smckusick #include "0.h" 7*2187Smckusick #include "opcode.h" 8*2187Smckusick #include "tree.h" 9*2187Smckusick #include "objfmt.h" 10*2187Smckusick #ifdef PC 11*2187Smckusick # include "pc.h" 12*2187Smckusick # include "pcops.h" 13*2187Smckusick #endif PC 14*2187Smckusick /* 15*2187Smckusick * forop for pc: 16*2187Smckusick * this evaluates the initial and termination expressions, 17*2187Smckusick * checks them to see if the loop executes at all, and then 18*2187Smckusick * does the assignment and the loop. 19*2187Smckusick * arg here looks like: 20*2187Smckusick * arg[0] T_FORU or T_FORD 21*2187Smckusick * [1] lineof "for" 22*2187Smckusick * [2] [0] T_ASGN 23*2187Smckusick * [1] lineof ":=" 24*2187Smckusick * [2] [0] T_VAR 25*2187Smckusick * [1] lineof id 26*2187Smckusick * [2] char * to id 27*2187Smckusick * [3] qualifications 28*2187Smckusick * [3] initial expression 29*2187Smckusick * [3] termination expression 30*2187Smckusick * [4] statement 31*2187Smckusick */ 32*2187Smckusick forop( arg ) 33*2187Smckusick int *arg; 34*2187Smckusick { 35*2187Smckusick int *lhs; 36*2187Smckusick struct nl *forvar; 37*2187Smckusick struct nl *fortype; 38*2187Smckusick int forctype; 39*2187Smckusick int *init; 40*2187Smckusick struct nl *inittype; 41*2187Smckusick int initoff; 42*2187Smckusick int *term; 43*2187Smckusick struct nl *termtype; 44*2187Smckusick int termoff; 45*2187Smckusick int *stat; 46*2187Smckusick int goc; /* saved gocnt */ 47*2187Smckusick int again; /* label at the top of the loop */ 48*2187Smckusick int after; /* label after the end of the loop */ 49*2187Smckusick 50*2187Smckusick goc = gocnt; 51*2187Smckusick forvar = NIL; 52*2187Smckusick if ( arg == NIL ) { 53*2187Smckusick goto byebye; 54*2187Smckusick } 55*2187Smckusick if ( arg[2] == NIL ) { 56*2187Smckusick goto byebye; 57*2187Smckusick } 58*2187Smckusick line = arg[1]; 59*2187Smckusick putline(); 60*2187Smckusick lhs = ( (int *) arg[2] )[2]; 61*2187Smckusick init = ( (int *) arg[2] )[3]; 62*2187Smckusick term = arg[3]; 63*2187Smckusick stat = arg[4]; 64*2187Smckusick if ( lhs[3] != NIL ) { 65*2187Smckusick error("For variable must be unqualified"); 66*2187Smckusick rvalue( init , NIL , RREQ ); 67*2187Smckusick rvalue( term , NIL , RREQ ); 68*2187Smckusick statement( stat ); 69*2187Smckusick goto byebye; 70*2187Smckusick } 71*2187Smckusick /* 72*2187Smckusick * and this marks the variable as used!!! 73*2187Smckusick */ 74*2187Smckusick forvar = lookup( lhs[2] ); 75*2187Smckusick if ( forvar == NIL ) { 76*2187Smckusick rvalue( init , NIL , RREQ ); 77*2187Smckusick rvalue( term , NIL , RREQ ); 78*2187Smckusick statement( stat ); 79*2187Smckusick goto byebye; 80*2187Smckusick } 81*2187Smckusick /* 82*2187Smckusick * find out the type of the loop variable 83*2187Smckusick */ 84*2187Smckusick codeoff(); 85*2187Smckusick fortype = lvalue( lhs , MOD , RREQ ); 86*2187Smckusick codeon(); 87*2187Smckusick /* 88*2187Smckusick * mark the forvar so we can't change it during the loop 89*2187Smckusick */ 90*2187Smckusick forvar -> value[ NL_FORV ] = 1; 91*2187Smckusick if ( fortype == NIL ) { 92*2187Smckusick rvalue( init , NIL , RREQ ); 93*2187Smckusick rvalue( term , NIL , RREQ ); 94*2187Smckusick statement( stat ); 95*2187Smckusick goto byebye; 96*2187Smckusick } 97*2187Smckusick if ( isnta( fortype , "bcis" ) ) { 98*2187Smckusick error("For variables cannot be %ss" , nameof( fortype ) ); 99*2187Smckusick rvalue( init , NIL , RREQ ); 100*2187Smckusick rvalue( term , NIL , RREQ ); 101*2187Smckusick statement( stat ); 102*2187Smckusick goto byebye; 103*2187Smckusick } 104*2187Smckusick /* 105*2187Smckusick * allocate space for the initial and termination expressions 106*2187Smckusick */ 107*2187Smckusick sizes[cbn].om_off -= sizeof( long ); 108*2187Smckusick initoff = sizes[cbn].om_off; 109*2187Smckusick sizes[cbn].om_off -= sizeof( long ); 110*2187Smckusick termoff = sizes[cbn].om_off; 111*2187Smckusick if ( sizes[cbn].om_off < sizes[cbn].om_max ) { 112*2187Smckusick sizes[cbn].om_max = sizes[cbn].om_off; 113*2187Smckusick } 114*2187Smckusick # ifdef PC 115*2187Smckusick putlbracket( ftnno , -sizes[cbn].om_off ); 116*2187Smckusick /* 117*2187Smckusick * compute and save the initial expression 118*2187Smckusick */ 119*2187Smckusick forctype = p2type( fortype ); 120*2187Smckusick putRV( 0 , cbn , initoff , forctype ); 121*2187Smckusick # endif PC 122*2187Smckusick # ifdef OBJ 123*2187Smckusick put(2, O_LV | cbn<<8+INDX, initoff); 124*2187Smckusick # endif OBJ 125*2187Smckusick inittype = rvalue( init , fortype , RREQ ); 126*2187Smckusick if ( incompat( inittype , fortype , init ) ) { 127*2187Smckusick cerror("Type of initial expression clashed with index type in 'for' statement"); 128*2187Smckusick rvalue( term , NIL , RREQ ); 129*2187Smckusick statement( stat ); 130*2187Smckusick goto byebye; 131*2187Smckusick } 132*2187Smckusick # ifdef PC 133*2187Smckusick putop( P2ASSIGN , forctype ); 134*2187Smckusick putdot( filename , line ); 135*2187Smckusick /* 136*2187Smckusick * compute and save the termination expression 137*2187Smckusick */ 138*2187Smckusick putRV( 0 , cbn , termoff , forctype ); 139*2187Smckusick # endif PC 140*2187Smckusick # ifdef OBJ 141*2187Smckusick put(1, width(inittype) <= 2 ? O_AS24 : O_AS4); 142*2187Smckusick /* 143*2187Smckusick * compute and save the termination expression 144*2187Smckusick */ 145*2187Smckusick put(2, O_LV | cbn<<8+INDX, termoff); 146*2187Smckusick # endif OBJ 147*2187Smckusick termtype = rvalue( term , fortype , RREQ ); 148*2187Smckusick if ( incompat( termtype , fortype , term ) ) { 149*2187Smckusick cerror("Type of limit expression clashed with index type in 'for' statement"); 150*2187Smckusick statement( stat ); 151*2187Smckusick goto byebye; 152*2187Smckusick } 153*2187Smckusick # ifdef PC 154*2187Smckusick putop( P2ASSIGN , forctype ); 155*2187Smckusick putdot( filename , line ); 156*2187Smckusick /* 157*2187Smckusick * we can skip the loop altogether if !( init <= term ) 158*2187Smckusick */ 159*2187Smckusick after = getlab(); 160*2187Smckusick putRV( 0 , cbn , initoff , forctype ); 161*2187Smckusick putRV( 0 , cbn , termoff , forctype ); 162*2187Smckusick putop( ( arg[0] == T_FORU ? P2LE : P2GE ) , forctype ); 163*2187Smckusick putleaf( P2ICON , after , 0 , P2INT , 0 ); 164*2187Smckusick putop( P2CBRANCH , P2INT ); 165*2187Smckusick putdot( filename , line ); 166*2187Smckusick /* 167*2187Smckusick * okay, then we have to execute the body, but first, 168*2187Smckusick * assign the initial expression to the for variable. 169*2187Smckusick * see the note in asgnop1 about why this is an rvalue. 170*2187Smckusick */ 171*2187Smckusick rvalue( lhs , NIL , RREQ ); 172*2187Smckusick if ( opt( 't' ) ) { 173*2187Smckusick precheck( fortype , "_RANG4" , "_RSNG4" ); 174*2187Smckusick } 175*2187Smckusick putRV( 0 , cbn , initoff , forctype ); 176*2187Smckusick if ( opt( 't' ) ) { 177*2187Smckusick postcheck( fortype ); 178*2187Smckusick } 179*2187Smckusick putop( P2ASSIGN , forctype ); 180*2187Smckusick putdot( filename , line ); 181*2187Smckusick # endif PC 182*2187Smckusick # ifdef OBJ 183*2187Smckusick put(1, width(termtype) <= 2 ? O_AS24 : O_AS4); 184*2187Smckusick /* 185*2187Smckusick * we can skip the loop altogether if !( init <= term ) 186*2187Smckusick */ 187*2187Smckusick put(2, O_RV4 | cbn<<8+INDX, initoff); 188*2187Smckusick put(2, O_RV4 | cbn<<8+INDX, termoff); 189*2187Smckusick gen(NIL, arg[0] == T_FORU ? T_LE : T_GE, sizeof(long), 190*2187Smckusick sizeof(long)); 191*2187Smckusick after = getlab(); 192*2187Smckusick put(2, O_IF, after); 193*2187Smckusick /* 194*2187Smckusick * okay, then we have to execute the body, but first, 195*2187Smckusick * assign the initial expression to the for variable. 196*2187Smckusick */ 197*2187Smckusick lvalue( lhs , NOUSE , LREQ ); 198*2187Smckusick put(2, O_RV4 | cbn<<8+INDX, initoff); 199*2187Smckusick rangechk(fortype, nl+T4INT); 200*2187Smckusick put(1, width(fortype) <= 2 ? O_AS42 : O_AS4); 201*2187Smckusick # endif OBJ 202*2187Smckusick /* 203*2187Smckusick * put down the label at the top of the loop 204*2187Smckusick */ 205*2187Smckusick again = getlab(); 206*2187Smckusick putlab( again ); 207*2187Smckusick putcnt(); 208*2187Smckusick /* 209*2187Smckusick * and don't forget ... 210*2187Smckusick */ 211*2187Smckusick statement( arg[ 4 ] ); 212*2187Smckusick /* 213*2187Smckusick * wasn't that fun? do we get to do it again? 214*2187Smckusick * we don't do it again if ( !( forvar < limit ) ) 215*2187Smckusick * pretend we were doing this at the top of the loop 216*2187Smckusick */ 217*2187Smckusick line = arg[ 1 ]; 218*2187Smckusick # ifdef PC 219*2187Smckusick if ( opt( 'p' ) ) { 220*2187Smckusick if ( opt('t') ) { 221*2187Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 222*2187Smckusick , "_LINO" ); 223*2187Smckusick putop( P2UNARY P2CALL , P2INT ); 224*2187Smckusick putdot( filename , line ); 225*2187Smckusick } else { 226*2187Smckusick putRV( STMTCOUNT , 0 , 0 , P2INT ); 227*2187Smckusick putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 228*2187Smckusick putop( P2ASG P2PLUS , P2INT ); 229*2187Smckusick putdot( filename , line ); 230*2187Smckusick } 231*2187Smckusick } 232*2187Smckusick rvalue( lhs , NIL , RREQ ); 233*2187Smckusick putRV( 0 , cbn , termoff , forctype ); 234*2187Smckusick putop( ( arg[ 0 ] == T_FORU ? P2LT : P2GT ) , forctype ); 235*2187Smckusick putleaf( P2ICON , after , 0 , P2INT , 0 ); 236*2187Smckusick putop( P2CBRANCH , P2INT ); 237*2187Smckusick putdot( filename , line ); 238*2187Smckusick /* 239*2187Smckusick * okay, so we have to do it again, 240*2187Smckusick * but first, increment the for variable. 241*2187Smckusick * there it is again, an rvalue on the lhs of an assignment. 242*2187Smckusick */ 243*2187Smckusick rvalue( lhs , NIL , RREQ ); 244*2187Smckusick if ( opt( 't' ) ) { 245*2187Smckusick precheck( fortype , "_RANG4" , "_RSNG4" ); 246*2187Smckusick } 247*2187Smckusick rvalue( lhs , NIL , RREQ ); 248*2187Smckusick putleaf( P2ICON , 1 , 0 , forctype , 0 ); 249*2187Smckusick putop( ( arg[0] == T_FORU ? P2PLUS : P2MINUS ) , forctype ); 250*2187Smckusick if ( opt( 't' ) ) { 251*2187Smckusick postcheck( fortype ); 252*2187Smckusick } 253*2187Smckusick putop( P2ASSIGN , forctype ); 254*2187Smckusick putdot( filename , line ); 255*2187Smckusick /* 256*2187Smckusick * and do it all again 257*2187Smckusick */ 258*2187Smckusick putjbr( again ); 259*2187Smckusick /* 260*2187Smckusick * and here we are 261*2187Smckusick */ 262*2187Smckusick putlab( after ); 263*2187Smckusick /* 264*2187Smckusick * deallocate the initial and limit variables 265*2187Smckusick */ 266*2187Smckusick sizes[cbn].om_off += 2 * ( sizeof( long ) ); 267*2187Smckusick putlbracket( ftnno , -sizes[cbn].om_off ); 268*2187Smckusick # endif PC 269*2187Smckusick # ifdef OBJ 270*2187Smckusick /* 271*2187Smckusick * okay, so we have to do it again. 272*2187Smckusick * Luckily we have a magic opcode which increments the 273*2187Smckusick * index variable, checks the limit falling through if 274*2187Smckusick * it has been reached, else range checking the result 275*2187Smckusick * updating the index variable, and returning to the top 276*2187Smckusick * of the loop. 277*2187Smckusick */ 278*2187Smckusick put(2, O_RV4 | cbn<<8+INDX, termoff); 279*2187Smckusick lvalue(lhs, MOD, LREQ); 280*2187Smckusick put(4, (arg[0] == T_FORU ? O_FOR1U : O_FOR1D) + (width(fortype)>>1), 281*2187Smckusick fortype->range[0], fortype->range[1], again); 282*2187Smckusick /* 283*2187Smckusick * and here we are 284*2187Smckusick */ 285*2187Smckusick patch( after ); 286*2187Smckusick /* 287*2187Smckusick * deallocate the initial and limit variables 288*2187Smckusick */ 289*2187Smckusick sizes[cbn].om_off += 2 * ( sizeof( long ) ); 290*2187Smckusick # endif OBJ 291*2187Smckusick byebye: 292*2187Smckusick noreach = 0; 293*2187Smckusick if ( forvar != NIL ) { 294*2187Smckusick forvar -> value[ NL_FORV ] = 0; 295*2187Smckusick } 296*2187Smckusick if ( goc != gocnt ) { 297*2187Smckusick putcnt(); 298*2187Smckusick } 299*2187Smckusick } 300