12187Smckusick /* Copyright (c) 1979 Regents of the University of California */ 22187Smckusick 3*2649Speter static char sccsid[] = "@(#)forop.c 1.2 02/24/81"; 42187Smckusick 52187Smckusick #include "whoami.h" 62187Smckusick #include "0.h" 72187Smckusick #include "opcode.h" 82187Smckusick #include "tree.h" 92187Smckusick #include "objfmt.h" 102187Smckusick #ifdef PC 112187Smckusick # include "pc.h" 122187Smckusick # include "pcops.h" 132187Smckusick #endif PC 142187Smckusick /* 152187Smckusick * forop for pc: 162187Smckusick * this evaluates the initial and termination expressions, 172187Smckusick * checks them to see if the loop executes at all, and then 182187Smckusick * does the assignment and the loop. 192187Smckusick * arg here looks like: 202187Smckusick * arg[0] T_FORU or T_FORD 212187Smckusick * [1] lineof "for" 222187Smckusick * [2] [0] T_ASGN 232187Smckusick * [1] lineof ":=" 242187Smckusick * [2] [0] T_VAR 252187Smckusick * [1] lineof id 262187Smckusick * [2] char * to id 272187Smckusick * [3] qualifications 282187Smckusick * [3] initial expression 292187Smckusick * [3] termination expression 302187Smckusick * [4] statement 312187Smckusick */ 322187Smckusick forop( arg ) 332187Smckusick int *arg; 342187Smckusick { 352187Smckusick int *lhs; 362187Smckusick struct nl *forvar; 372187Smckusick struct nl *fortype; 382187Smckusick int forctype; 392187Smckusick int *init; 402187Smckusick struct nl *inittype; 412187Smckusick int initoff; 422187Smckusick int *term; 432187Smckusick struct nl *termtype; 442187Smckusick int termoff; 452187Smckusick int *stat; 462187Smckusick int goc; /* saved gocnt */ 472187Smckusick int again; /* label at the top of the loop */ 482187Smckusick int after; /* label after the end of the loop */ 492187Smckusick 502187Smckusick goc = gocnt; 512187Smckusick forvar = NIL; 522187Smckusick if ( arg == NIL ) { 532187Smckusick goto byebye; 542187Smckusick } 552187Smckusick if ( arg[2] == NIL ) { 562187Smckusick goto byebye; 572187Smckusick } 582187Smckusick line = arg[1]; 592187Smckusick putline(); 602187Smckusick lhs = ( (int *) arg[2] )[2]; 612187Smckusick init = ( (int *) arg[2] )[3]; 622187Smckusick term = arg[3]; 632187Smckusick stat = arg[4]; 642187Smckusick if ( lhs[3] != NIL ) { 652187Smckusick error("For variable must be unqualified"); 662187Smckusick rvalue( init , NIL , RREQ ); 672187Smckusick rvalue( term , NIL , RREQ ); 682187Smckusick statement( stat ); 692187Smckusick goto byebye; 702187Smckusick } 712187Smckusick /* 722187Smckusick * and this marks the variable as used!!! 732187Smckusick */ 742187Smckusick forvar = lookup( lhs[2] ); 752187Smckusick if ( forvar == NIL ) { 762187Smckusick rvalue( init , NIL , RREQ ); 772187Smckusick rvalue( term , NIL , RREQ ); 782187Smckusick statement( stat ); 792187Smckusick goto byebye; 802187Smckusick } 812187Smckusick /* 822187Smckusick * find out the type of the loop variable 832187Smckusick */ 842187Smckusick codeoff(); 852187Smckusick fortype = lvalue( lhs , MOD , RREQ ); 862187Smckusick codeon(); 872187Smckusick /* 882187Smckusick * mark the forvar so we can't change it during the loop 892187Smckusick */ 902187Smckusick forvar -> value[ NL_FORV ] = 1; 912187Smckusick if ( fortype == NIL ) { 922187Smckusick rvalue( init , NIL , RREQ ); 932187Smckusick rvalue( term , NIL , RREQ ); 942187Smckusick statement( stat ); 952187Smckusick goto byebye; 962187Smckusick } 972187Smckusick if ( isnta( fortype , "bcis" ) ) { 982187Smckusick error("For variables cannot be %ss" , nameof( fortype ) ); 992187Smckusick rvalue( init , NIL , RREQ ); 1002187Smckusick rvalue( term , NIL , RREQ ); 1012187Smckusick statement( stat ); 1022187Smckusick goto byebye; 1032187Smckusick } 1042187Smckusick /* 1052187Smckusick * allocate space for the initial and termination expressions 1062187Smckusick */ 1072187Smckusick sizes[cbn].om_off -= sizeof( long ); 1082187Smckusick initoff = sizes[cbn].om_off; 1092187Smckusick sizes[cbn].om_off -= sizeof( long ); 1102187Smckusick termoff = sizes[cbn].om_off; 1112187Smckusick if ( sizes[cbn].om_off < sizes[cbn].om_max ) { 1122187Smckusick sizes[cbn].om_max = sizes[cbn].om_off; 1132187Smckusick } 1142187Smckusick # ifdef PC 1152187Smckusick putlbracket( ftnno , -sizes[cbn].om_off ); 1162187Smckusick /* 1172187Smckusick * compute and save the initial expression 1182187Smckusick */ 1192187Smckusick forctype = p2type( fortype ); 1202187Smckusick putRV( 0 , cbn , initoff , forctype ); 1212187Smckusick # endif PC 1222187Smckusick # ifdef OBJ 1232187Smckusick put(2, O_LV | cbn<<8+INDX, initoff); 1242187Smckusick # endif OBJ 1252187Smckusick inittype = rvalue( init , fortype , RREQ ); 1262187Smckusick if ( incompat( inittype , fortype , init ) ) { 1272187Smckusick cerror("Type of initial expression clashed with index type in 'for' statement"); 1282187Smckusick rvalue( term , NIL , RREQ ); 1292187Smckusick statement( stat ); 1302187Smckusick goto byebye; 1312187Smckusick } 1322187Smckusick # ifdef PC 1332187Smckusick putop( P2ASSIGN , forctype ); 1342187Smckusick putdot( filename , line ); 1352187Smckusick /* 1362187Smckusick * compute and save the termination expression 1372187Smckusick */ 1382187Smckusick putRV( 0 , cbn , termoff , forctype ); 1392187Smckusick # endif PC 1402187Smckusick # ifdef OBJ 1412187Smckusick put(1, width(inittype) <= 2 ? O_AS24 : O_AS4); 1422187Smckusick /* 1432187Smckusick * compute and save the termination expression 1442187Smckusick */ 1452187Smckusick put(2, O_LV | cbn<<8+INDX, termoff); 1462187Smckusick # endif OBJ 1472187Smckusick termtype = rvalue( term , fortype , RREQ ); 1482187Smckusick if ( incompat( termtype , fortype , term ) ) { 1492187Smckusick cerror("Type of limit expression clashed with index type in 'for' statement"); 1502187Smckusick statement( stat ); 1512187Smckusick goto byebye; 1522187Smckusick } 1532187Smckusick # ifdef PC 1542187Smckusick putop( P2ASSIGN , forctype ); 1552187Smckusick putdot( filename , line ); 1562187Smckusick /* 1572187Smckusick * we can skip the loop altogether if !( init <= term ) 1582187Smckusick */ 1592187Smckusick after = getlab(); 1602187Smckusick putRV( 0 , cbn , initoff , forctype ); 1612187Smckusick putRV( 0 , cbn , termoff , forctype ); 1622187Smckusick putop( ( arg[0] == T_FORU ? P2LE : P2GE ) , forctype ); 1632187Smckusick putleaf( P2ICON , after , 0 , P2INT , 0 ); 1642187Smckusick putop( P2CBRANCH , P2INT ); 1652187Smckusick putdot( filename , line ); 1662187Smckusick /* 1672187Smckusick * okay, then we have to execute the body, but first, 1682187Smckusick * assign the initial expression to the for variable. 1692187Smckusick * see the note in asgnop1 about why this is an rvalue. 1702187Smckusick */ 1712187Smckusick rvalue( lhs , NIL , RREQ ); 1722187Smckusick if ( opt( 't' ) ) { 1732187Smckusick precheck( fortype , "_RANG4" , "_RSNG4" ); 1742187Smckusick } 1752187Smckusick putRV( 0 , cbn , initoff , forctype ); 1762187Smckusick if ( opt( 't' ) ) { 1772187Smckusick postcheck( fortype ); 1782187Smckusick } 1792187Smckusick putop( P2ASSIGN , forctype ); 1802187Smckusick putdot( filename , line ); 1812187Smckusick # endif PC 1822187Smckusick # ifdef OBJ 1832187Smckusick put(1, width(termtype) <= 2 ? O_AS24 : O_AS4); 1842187Smckusick /* 1852187Smckusick * we can skip the loop altogether if !( init <= term ) 1862187Smckusick */ 1872187Smckusick put(2, O_RV4 | cbn<<8+INDX, initoff); 1882187Smckusick put(2, O_RV4 | cbn<<8+INDX, termoff); 1892187Smckusick gen(NIL, arg[0] == T_FORU ? T_LE : T_GE, sizeof(long), 1902187Smckusick sizeof(long)); 1912187Smckusick after = getlab(); 1922187Smckusick put(2, O_IF, after); 1932187Smckusick /* 1942187Smckusick * okay, then we have to execute the body, but first, 1952187Smckusick * assign the initial expression to the for variable. 1962187Smckusick */ 1972187Smckusick lvalue( lhs , NOUSE , LREQ ); 1982187Smckusick put(2, O_RV4 | cbn<<8+INDX, initoff); 1992187Smckusick rangechk(fortype, nl+T4INT); 2002187Smckusick put(1, width(fortype) <= 2 ? O_AS42 : O_AS4); 2012187Smckusick # endif OBJ 2022187Smckusick /* 2032187Smckusick * put down the label at the top of the loop 2042187Smckusick */ 2052187Smckusick again = getlab(); 2062187Smckusick putlab( again ); 2072187Smckusick putcnt(); 2082187Smckusick /* 2092187Smckusick * and don't forget ... 2102187Smckusick */ 2112187Smckusick statement( arg[ 4 ] ); 2122187Smckusick /* 2132187Smckusick * wasn't that fun? do we get to do it again? 2142187Smckusick * we don't do it again if ( !( forvar < limit ) ) 2152187Smckusick * pretend we were doing this at the top of the loop 2162187Smckusick */ 2172187Smckusick line = arg[ 1 ]; 2182187Smckusick # ifdef PC 2192187Smckusick if ( opt( 'p' ) ) { 2202187Smckusick if ( opt('t') ) { 2212187Smckusick putleaf( P2ICON , 0 , 0 , ADDTYPE( P2FTN | P2INT , P2PTR ) 2222187Smckusick , "_LINO" ); 2232187Smckusick putop( P2UNARY P2CALL , P2INT ); 2242187Smckusick putdot( filename , line ); 2252187Smckusick } else { 2262187Smckusick putRV( STMTCOUNT , 0 , 0 , P2INT ); 2272187Smckusick putleaf( P2ICON , 1 , 0 , P2INT , 0 ); 2282187Smckusick putop( P2ASG P2PLUS , P2INT ); 2292187Smckusick putdot( filename , line ); 2302187Smckusick } 2312187Smckusick } 2322187Smckusick rvalue( lhs , NIL , RREQ ); 2332187Smckusick putRV( 0 , cbn , termoff , forctype ); 2342187Smckusick putop( ( arg[ 0 ] == T_FORU ? P2LT : P2GT ) , forctype ); 2352187Smckusick putleaf( P2ICON , after , 0 , P2INT , 0 ); 2362187Smckusick putop( P2CBRANCH , P2INT ); 2372187Smckusick putdot( filename , line ); 2382187Smckusick /* 2392187Smckusick * okay, so we have to do it again, 2402187Smckusick * but first, increment the for variable. 2412187Smckusick * there it is again, an rvalue on the lhs of an assignment. 2422187Smckusick */ 2432187Smckusick rvalue( lhs , NIL , RREQ ); 2442187Smckusick if ( opt( 't' ) ) { 2452187Smckusick precheck( fortype , "_RANG4" , "_RSNG4" ); 2462187Smckusick } 2472187Smckusick rvalue( lhs , NIL , RREQ ); 2482187Smckusick putleaf( P2ICON , 1 , 0 , forctype , 0 ); 2492187Smckusick putop( ( arg[0] == T_FORU ? P2PLUS : P2MINUS ) , forctype ); 2502187Smckusick if ( opt( 't' ) ) { 2512187Smckusick postcheck( fortype ); 2522187Smckusick } 2532187Smckusick putop( P2ASSIGN , forctype ); 2542187Smckusick putdot( filename , line ); 2552187Smckusick /* 2562187Smckusick * and do it all again 2572187Smckusick */ 2582187Smckusick putjbr( again ); 2592187Smckusick /* 2602187Smckusick * and here we are 2612187Smckusick */ 2622187Smckusick putlab( after ); 2632187Smckusick /* 2642187Smckusick * deallocate the initial and limit variables 2652187Smckusick */ 2662187Smckusick sizes[cbn].om_off += 2 * ( sizeof( long ) ); 2672187Smckusick putlbracket( ftnno , -sizes[cbn].om_off ); 2682187Smckusick # endif PC 2692187Smckusick # ifdef OBJ 2702187Smckusick /* 2712187Smckusick * okay, so we have to do it again. 2722187Smckusick * Luckily we have a magic opcode which increments the 2732187Smckusick * index variable, checks the limit falling through if 2742187Smckusick * it has been reached, else range checking the result 2752187Smckusick * updating the index variable, and returning to the top 2762187Smckusick * of the loop. 2772187Smckusick */ 278*2649Speter putline(); 2792187Smckusick put(2, O_RV4 | cbn<<8+INDX, termoff); 2802187Smckusick lvalue(lhs, MOD, LREQ); 2812187Smckusick put(4, (arg[0] == T_FORU ? O_FOR1U : O_FOR1D) + (width(fortype)>>1), 2822187Smckusick fortype->range[0], fortype->range[1], again); 2832187Smckusick /* 2842187Smckusick * and here we are 2852187Smckusick */ 2862187Smckusick patch( after ); 2872187Smckusick /* 2882187Smckusick * deallocate the initial and limit variables 2892187Smckusick */ 2902187Smckusick sizes[cbn].om_off += 2 * ( sizeof( long ) ); 2912187Smckusick # endif OBJ 2922187Smckusick byebye: 2932187Smckusick noreach = 0; 2942187Smckusick if ( forvar != NIL ) { 2952187Smckusick forvar -> value[ NL_FORV ] = 0; 2962187Smckusick } 2972187Smckusick if ( goc != gocnt ) { 2982187Smckusick putcnt(); 2992187Smckusick } 3002187Smckusick } 301