1745Speter /* Copyright (c) 1979 Regents of the University of California */ 2745Speter 3*3063Smckusic static char sccsid[] = "@(#)call.c 1.4.1.1 03/08/81"; 4745Speter 5745Speter #include "whoami.h" 6745Speter #include "0.h" 7745Speter #include "tree.h" 8745Speter #include "opcode.h" 9745Speter #include "objfmt.h" 10745Speter #ifdef PC 11745Speter # include "pc.h" 12745Speter # include "pcops.h" 13745Speter #endif PC 14745Speter 15*3063Smckusic bool slenflag = 0; 16*3063Smckusic bool floatflag = 0; 171195Speter 18745Speter /* 19745Speter * Call generates code for calls to 20745Speter * user defined procedures and functions 21745Speter * and is called by proc and funccod. 22745Speter * P is the result of the lookup 23745Speter * of the procedure/function symbol, 24745Speter * and porf is PROC or FUNC. 25745Speter * Psbn is the block number of p. 26745Speter */ 27745Speter struct nl * 28745Speter call(p, argv, porf, psbn) 29745Speter struct nl *p; 30745Speter int *argv, porf, psbn; 31745Speter { 32745Speter register struct nl *p1, *q; 33745Speter int *r; 34745Speter 351195Speter # ifdef OBJ 361195Speter int cnt; 371195Speter # endif OBJ 38745Speter # ifdef PC 39*3063Smckusic long temp; 40*3063Smckusic int firsttime; 41*3063Smckusic int rettype; 42745Speter # endif PC 43745Speter 44745Speter # ifdef OBJ 451195Speter if (p->class == FFUNC || p->class == FPROC) 46*3063Smckusic put(2, PTR_RV | cbn << 8+INDX, (int)p->value[NL_OFFS]); 47745Speter if (porf == FUNC) 48745Speter /* 49745Speter * Push some space 50745Speter * for the function return type 51745Speter */ 52*3063Smckusic put(2, O_PUSH, leven(-lwidth(p->type))); 53745Speter # endif OBJ 54745Speter # ifdef PC 55745Speter if ( porf == FUNC ) { 56*3063Smckusic switch( classify( p -> type ) ) { 57745Speter case TSTR: 58745Speter case TSET: 59745Speter case TREC: 60745Speter case TFILE: 61745Speter case TARY: 62*3063Smckusic temp = sizes[ cbn ].om_off -= width( p -> type ); 63*3063Smckusic putlbracket( ftnno , -sizes[cbn].om_off ); 64*3063Smckusic if (sizes[cbn].om_off < sizes[cbn].om_max) { 65*3063Smckusic sizes[cbn].om_max = sizes[cbn].om_off; 66745Speter } 67*3063Smckusic putRV( 0 , cbn , temp , P2STRTY ); 68745Speter } 69745Speter } 701195Speter switch ( p -> class ) { 711195Speter case FUNC: 721195Speter case PROC: 731195Speter { 741195Speter char extname[ BUFSIZ ]; 751195Speter char *starthere; 761195Speter int funcbn; 771195Speter int i; 78745Speter 791195Speter starthere = &extname[0]; 801195Speter funcbn = p -> nl_block & 037; 811195Speter for ( i = 1 ; i < funcbn ; i++ ) { 821195Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 831195Speter starthere += strlen( enclosing[ i ] ) + 1; 841195Speter } 851195Speter sprintf( starthere , EXTFORMAT , p -> symbol ); 861195Speter starthere += strlen( p -> symbol ) + 1; 871195Speter if ( starthere >= &extname[ BUFSIZ ] ) { 881195Speter panic( "call namelength" ); 891195Speter } 901195Speter putleaf( P2ICON , 0 , 0 , p2type( p ) , extname ); 911195Speter } 921195Speter break; 931195Speter case FFUNC: 941195Speter case FPROC: 951195Speter /* 96*3063Smckusic * start one of these: 97*3063Smckusic * FRTN( frtn , ( *FCALL( frtn ) )(...args...) ) 981195Speter */ 99*3063Smckusic putleaf( P2ICON , 0 , 0 , p2type( p ) , "_FRTN" ); 100*3063Smckusic putRV( 0 , cbn , p -> value[NL_OFFS] , P2PTR|P2STRTY ); 1011195Speter putleaf( P2ICON , 0 , 0 102*3063Smckusic , ADDTYPE( P2PTR , ADDTYPE( P2FTN , p2type( p ) ) ) 1031195Speter , "_FCALL" ); 1041195Speter putRV( 0 , cbn , p -> value[NL_OFFS] , P2PTR|P2STRTY ); 105*3063Smckusic putop( P2CALL , p2type( p ) ); 1061195Speter break; 1071195Speter default: 1081195Speter panic("call class"); 109745Speter } 110*3063Smckusic firsttime = TRUE; 111745Speter # endif PC 112745Speter /* 113745Speter * Loop and process each of 114745Speter * arguments to the proc/func. 115745Speter */ 1161195Speter if ( p -> class == FUNC || p -> class == PROC ) { 1171195Speter for (p1 = p->chain; p1 != NIL; p1 = p1->chain) { 1181195Speter if (argv == NIL) { 1191195Speter error("Not enough arguments to %s", p->symbol); 1201195Speter return (NIL); 1211195Speter } 1221195Speter switch (p1->class) { 1231195Speter case REF: 1241195Speter /* 1251195Speter * Var parameter 1261195Speter */ 1271195Speter r = argv[1]; 1281195Speter if (r != NIL && r[0] != T_VAR) { 1291195Speter error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol); 1301195Speter break; 1311195Speter } 1321195Speter q = lvalue( (int *) argv[1], MOD , LREQ ); 1331195Speter if (q == NIL) 1341195Speter break; 1351195Speter if (q != p1->type) { 1361195Speter error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol); 1371195Speter break; 1381195Speter } 1391195Speter break; 1401195Speter case VAR: 1411195Speter /* 1421195Speter * Value parameter 1431195Speter */ 144745Speter # ifdef OBJ 1451195Speter q = rvalue(argv[1], p1->type , RREQ ); 146745Speter # endif OBJ 147745Speter # ifdef PC 1481195Speter /* 1491195Speter * structure arguments require lvalues, 1501195Speter * scalars use rvalue. 1511195Speter */ 1521195Speter switch( classify( p1 -> type ) ) { 1531195Speter case TFILE: 1541195Speter case TARY: 1551195Speter case TREC: 1561195Speter case TSET: 1571195Speter case TSTR: 1581195Speter q = rvalue( argv[1] , p1 -> type , LREQ ); 1591195Speter break; 1601195Speter case TINT: 1611195Speter case TSCAL: 1621195Speter case TBOOL: 1631195Speter case TCHAR: 1641195Speter precheck( p1 -> type , "_RANG4" , "_RSNG4" ); 1651195Speter q = rvalue( argv[1] , p1 -> type , RREQ ); 1661195Speter postcheck( p1 -> type ); 1671195Speter break; 1681195Speter default: 1691195Speter q = rvalue( argv[1] , p1 -> type , RREQ ); 1701195Speter if ( isa( p1 -> type , "d" ) 1711195Speter && isa( q , "i" ) ) { 1721195Speter putop( P2SCONV , P2DOUBLE ); 1731195Speter } 1741195Speter break; 1751195Speter } 1761195Speter # endif PC 1771195Speter if (q == NIL) 178745Speter break; 1791195Speter if (incompat(q, p1->type, argv[1])) { 1801195Speter cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol); 181745Speter break; 182745Speter } 183745Speter # ifdef OBJ 1841195Speter if (isa(p1->type, "bcsi")) 1851195Speter rangechk(p1->type, q); 1861195Speter if (q->class != STR) 1871195Speter convert(q, p1->type); 188745Speter # endif OBJ 189745Speter # ifdef PC 1901195Speter switch( classify( p1 -> type ) ) { 1911195Speter case TFILE: 1921195Speter case TARY: 1931195Speter case TREC: 1941195Speter case TSET: 1951195Speter case TSTR: 1961195Speter putstrop( P2STARG 1971195Speter , p2type( p1 -> type ) 1981195Speter , lwidth( p1 -> type ) 1991195Speter , align( p1 -> type ) ); 2001195Speter } 2011195Speter # endif PC 2021195Speter break; 2031195Speter case FFUNC: 2041195Speter /* 2051195Speter * function parameter 2061195Speter */ 2071195Speter q = flvalue( (int *) argv[1] , FFUNC ); 2081195Speter if (q == NIL) 2091195Speter break; 2101195Speter if (q != p1->type) { 2111195Speter error("Function type not identical to type of function parameter %s of %s", p1->symbol, p->symbol); 2121195Speter break; 213745Speter } 2141195Speter break; 2151195Speter case FPROC: 2161195Speter /* 2171195Speter * procedure parameter 2181195Speter */ 2191195Speter q = flvalue( (int *) argv[1] , FPROC ); 2201195Speter if (q != NIL) { 2211195Speter error("Procedure parameter %s of %s cannot have a type", p1->symbol, p->symbol); 2221195Speter } 2231195Speter break; 2241195Speter default: 2251195Speter panic("call"); 2261195Speter } 227745Speter # ifdef PC 2281195Speter /* 2291195Speter * if this is the nth (>1) argument, 2301195Speter * hang it on the left linear list of arguments 2311195Speter */ 232*3063Smckusic if ( firsttime ) { 233*3063Smckusic firsttime = FALSE; 2341195Speter } else { 2351195Speter putop( P2LISTOP , P2INT ); 2361195Speter } 237745Speter # endif PC 2381195Speter argv = argv[2]; 2391195Speter } 2401195Speter if (argv != NIL) { 2411195Speter error("Too many arguments to %s", p->symbol); 2421195Speter rvlist(argv); 2431195Speter return (NIL); 2441195Speter } 2451195Speter } else if ( p -> class == FFUNC || p -> class == FPROC ) { 2461195Speter /* 2471195Speter * formal routines can only have by-value parameters. 2481195Speter * this will lose for integer actuals passed to real 2491195Speter * formals, and strings which people want blank padded. 2501195Speter */ 2511195Speter # ifdef OBJ 2521195Speter cnt = 0; 2531195Speter # endif OBJ 2541195Speter for ( ; argv != NIL ; argv = argv[2] ) { 2551195Speter # ifdef OBJ 2561195Speter q = rvalue(argv[1], NIL, RREQ ); 257*3063Smckusic cnt += leven(lwidth(q)); 2581195Speter # endif OBJ 2591195Speter # ifdef PC 2601195Speter /* 2611195Speter * structure arguments require lvalues, 2621195Speter * scalars use rvalue. 2631195Speter */ 2641195Speter codeoff(); 2651195Speter p1 = rvalue( argv[1] , NIL , RREQ ); 2661195Speter codeon(); 2671195Speter switch( classify( p1 ) ) { 2681195Speter case TSTR: 269*3063Smckusic if ( p1 -> class == STR && slenflag == 0 ) { 270*3063Smckusic if ( opt( 's' ) ) { 271*3063Smckusic standard(); 272*3063Smckusic } else { 273*3063Smckusic warning(); 274*3063Smckusic } 2751195Speter error("Implementation can't construct equal length strings"); 276*3063Smckusic slenflag++; 2771195Speter } 2781195Speter /* and fall through */ 2791195Speter case TFILE: 2801195Speter case TARY: 2811195Speter case TREC: 2821195Speter case TSET: 2831195Speter q = rvalue( argv[1] , p1 , LREQ ); 2841195Speter break; 2851195Speter case TINT: 286*3063Smckusic if ( floatflag == 0 ) { 287*3063Smckusic if ( opt( 's' ) ) { 288*3063Smckusic standard(); 289*3063Smckusic } else { 290*3063Smckusic warning(); 291*3063Smckusic } 2921195Speter error("Implementation can't coerice integer to real"); 293*3063Smckusic floatflag++; 2941195Speter } 2951195Speter /* and fall through */ 2961195Speter case TSCAL: 2971195Speter case TBOOL: 2981195Speter case TCHAR: 2991195Speter default: 3001195Speter q = rvalue( argv[1] , p1 , RREQ ); 3011195Speter break; 3021195Speter } 3031195Speter switch( classify( p1 ) ) { 3041195Speter case TFILE: 3051195Speter case TARY: 3061195Speter case TREC: 3071195Speter case TSET: 3081195Speter case TSTR: 3091195Speter putstrop( P2STARG , p2type( p1 ) , 3101195Speter lwidth( p1 ) , align( p1 ) ); 3111195Speter } 3121195Speter /* 3131195Speter * if this is the nth (>1) argument, 3141195Speter * hang it on the left linear list of arguments 3151195Speter */ 316*3063Smckusic if ( firsttime ) { 317*3063Smckusic firsttime = FALSE; 3181195Speter } else { 3191195Speter putop( P2LISTOP , P2INT ); 3201195Speter } 3211195Speter # endif PC 3221195Speter } 3231195Speter } else { 3241195Speter panic("call class"); 325745Speter } 326745Speter # ifdef OBJ 3271195Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 328*3063Smckusic put(2, PTR_RV | cbn << 8+INDX, (int)p->value[NL_OFFS]); 329*3063Smckusic put(2, O_FCALL, (long)cnt); 330*3063Smckusic put(2, O_FRTN, even(width(p->type))); 3311195Speter } else { 332*3063Smckusic /* put(2, O_CALL | psbn << 8+INDX, (long)p->entloc); */ 333*3063Smckusic put(2, O_CALL | psbn << 8, (long)p->entloc); 3341195Speter } 335745Speter # endif OBJ 336745Speter # ifdef PC 337745Speter if ( porf == FUNC ) { 338*3063Smckusic rettype = p2type( p -> type ); 339*3063Smckusic switch ( classify( p -> type ) ) { 340745Speter case TBOOL: 341745Speter case TCHAR: 342745Speter case TINT: 343745Speter case TSCAL: 344745Speter case TDOUBLE: 345745Speter case TPTR: 346*3063Smckusic if ( firsttime ) { 347*3063Smckusic putop( P2UNARY P2CALL , rettype ); 348*3063Smckusic } else { 349*3063Smckusic putop( P2CALL , rettype ); 350745Speter } 351*3063Smckusic if (p -> class == FFUNC || p -> class == FPROC ) { 352*3063Smckusic putop( P2LISTOP , P2INT ); 353*3063Smckusic putop( P2CALL , rettype ); 354*3063Smckusic } 355745Speter break; 356745Speter default: 357*3063Smckusic if ( firsttime ) { 358*3063Smckusic putstrop( P2UNARY P2STCALL 359*3063Smckusic , ADDTYPE( rettype , P2PTR ) 360*3063Smckusic , lwidth( p -> type ) 361*3063Smckusic , align( p -> type ) ); 362*3063Smckusic } else { 363*3063Smckusic putstrop( P2STCALL 364*3063Smckusic , ADDTYPE( rettype , P2PTR ) 365*3063Smckusic , lwidth( p -> type ) 366*3063Smckusic , align( p -> type ) ); 367*3063Smckusic } 368*3063Smckusic if (p -> class == FFUNC || p -> class == FPROC ) { 369*3063Smckusic putop( P2LISTOP , P2INT ); 370*3063Smckusic putop( P2CALL , ADDTYPE( rettype , P2PTR ) ); 371*3063Smckusic } 372*3063Smckusic putstrop( P2STASG , rettype , lwidth( p -> type ) 373745Speter , align( p -> type ) ); 374*3063Smckusic putLV( 0 , cbn , temp , rettype ); 375*3063Smckusic putop( P2COMOP , P2INT ); 376745Speter break; 377745Speter } 378745Speter } else { 379*3063Smckusic if ( firsttime ) { 380*3063Smckusic putop( P2UNARY P2CALL , P2INT ); 381745Speter } else { 382*3063Smckusic putop( P2CALL , P2INT ); 383745Speter } 384*3063Smckusic if (p -> class == FFUNC || p -> class == FPROC ) { 385*3063Smckusic putop( P2LISTOP , P2INT ); 386*3063Smckusic putop( P2CALL , P2INT ); 387*3063Smckusic } 388745Speter putdot( filename , line ); 389745Speter } 390745Speter # endif PC 391745Speter return (p->type); 392745Speter } 393745Speter 394745Speter rvlist(al) 395745Speter register int *al; 396745Speter { 397745Speter 398745Speter for (; al != NIL; al = al[2]) 399745Speter rvalue( (int *) al[1], NLNIL , RREQ ); 400745Speter } 401