1745Speter /* Copyright (c) 1979 Regents of the University of California */ 2745Speter 3*1195Speter static char sccsid[] = "@(#)call.c 1.3 10/03/80"; 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*1195Speter bool slenflag = 0; 16*1195Speter bool floatflag = 0; 17*1195Speter 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 35*1195Speter # ifdef OBJ 36*1195Speter int cnt; 37*1195Speter # endif OBJ 38745Speter # ifdef PC 39745Speter long temp; 40745Speter int firsttime; 41745Speter int rettype; 42745Speter # endif PC 43745Speter 44745Speter # ifdef OBJ 45*1195Speter if (p->class == FFUNC || p->class == FPROC) 46*1195Speter put(2, PTR_RV | cbn << 8+INDX, p->value[NL_OFFS]); 47745Speter if (porf == FUNC) 48745Speter /* 49745Speter * Push some space 50745Speter * for the function return type 51745Speter */ 52745Speter put2(O_PUSH, even(-width(p->type))); 53745Speter # endif OBJ 54745Speter # ifdef PC 55745Speter if ( porf == FUNC ) { 56745Speter switch( classify( p -> type ) ) { 57745Speter case TSTR: 58745Speter case TSET: 59745Speter case TREC: 60745Speter case TFILE: 61745Speter case TARY: 62745Speter temp = sizes[ cbn ].om_off -= width( p -> type ); 63745Speter putlbracket( ftnno , -sizes[cbn].om_off ); 64745Speter if (sizes[cbn].om_off < sizes[cbn].om_max) { 65745Speter sizes[cbn].om_max = sizes[cbn].om_off; 66745Speter } 67745Speter putRV( 0 , cbn , temp , P2STRTY ); 68745Speter } 69745Speter } 70*1195Speter switch ( p -> class ) { 71*1195Speter case FUNC: 72*1195Speter case PROC: 73*1195Speter { 74*1195Speter char extname[ BUFSIZ ]; 75*1195Speter char *starthere; 76*1195Speter int funcbn; 77*1195Speter int i; 78745Speter 79*1195Speter starthere = &extname[0]; 80*1195Speter funcbn = p -> nl_block & 037; 81*1195Speter for ( i = 1 ; i < funcbn ; i++ ) { 82*1195Speter sprintf( starthere , EXTFORMAT , enclosing[ i ] ); 83*1195Speter starthere += strlen( enclosing[ i ] ) + 1; 84*1195Speter } 85*1195Speter sprintf( starthere , EXTFORMAT , p -> symbol ); 86*1195Speter starthere += strlen( p -> symbol ) + 1; 87*1195Speter if ( starthere >= &extname[ BUFSIZ ] ) { 88*1195Speter panic( "call namelength" ); 89*1195Speter } 90*1195Speter putleaf( P2ICON , 0 , 0 , p2type( p ) , extname ); 91*1195Speter } 92*1195Speter break; 93*1195Speter case FFUNC: 94*1195Speter case FPROC: 95*1195Speter /* 96*1195Speter * start one of these: 97*1195Speter * FRTN( frtn , ( *FCALL( frtn ) )(...args...) ) 98*1195Speter */ 99*1195Speter putleaf( P2ICON , 0 , 0 , p2type( p ) , "_FRTN" ); 100*1195Speter putRV( 0 , cbn , p -> value[NL_OFFS] , P2PTR|P2STRTY ); 101*1195Speter putleaf( P2ICON , 0 , 0 102*1195Speter , ADDTYPE( P2PTR , ADDTYPE( P2FTN , p2type( p ) ) ) 103*1195Speter , "_FCALL" ); 104*1195Speter putRV( 0 , cbn , p -> value[NL_OFFS] , P2PTR|P2STRTY ); 105*1195Speter putop( P2CALL , p2type( p ) ); 106*1195Speter break; 107*1195Speter default: 108*1195Speter panic("call class"); 109745Speter } 110745Speter firsttime = TRUE; 111745Speter # endif PC 112745Speter /* 113745Speter * Loop and process each of 114745Speter * arguments to the proc/func. 115745Speter */ 116*1195Speter if ( p -> class == FUNC || p -> class == PROC ) { 117*1195Speter for (p1 = p->chain; p1 != NIL; p1 = p1->chain) { 118*1195Speter if (argv == NIL) { 119*1195Speter error("Not enough arguments to %s", p->symbol); 120*1195Speter return (NIL); 121*1195Speter } 122*1195Speter switch (p1->class) { 123*1195Speter case REF: 124*1195Speter /* 125*1195Speter * Var parameter 126*1195Speter */ 127*1195Speter r = argv[1]; 128*1195Speter if (r != NIL && r[0] != T_VAR) { 129*1195Speter error("Expression given (variable required) for var parameter %s of %s", p1->symbol, p->symbol); 130*1195Speter break; 131*1195Speter } 132*1195Speter q = lvalue( (int *) argv[1], MOD , LREQ ); 133*1195Speter if (q == NIL) 134*1195Speter break; 135*1195Speter if (q != p1->type) { 136*1195Speter error("Parameter type not identical to type of var parameter %s of %s", p1->symbol, p->symbol); 137*1195Speter break; 138*1195Speter } 139*1195Speter break; 140*1195Speter case VAR: 141*1195Speter /* 142*1195Speter * Value parameter 143*1195Speter */ 144745Speter # ifdef OBJ 145*1195Speter q = rvalue(argv[1], p1->type , RREQ ); 146745Speter # endif OBJ 147745Speter # ifdef PC 148*1195Speter /* 149*1195Speter * structure arguments require lvalues, 150*1195Speter * scalars use rvalue. 151*1195Speter */ 152*1195Speter switch( classify( p1 -> type ) ) { 153*1195Speter case TFILE: 154*1195Speter case TARY: 155*1195Speter case TREC: 156*1195Speter case TSET: 157*1195Speter case TSTR: 158*1195Speter q = rvalue( argv[1] , p1 -> type , LREQ ); 159*1195Speter break; 160*1195Speter case TINT: 161*1195Speter case TSCAL: 162*1195Speter case TBOOL: 163*1195Speter case TCHAR: 164*1195Speter precheck( p1 -> type , "_RANG4" , "_RSNG4" ); 165*1195Speter q = rvalue( argv[1] , p1 -> type , RREQ ); 166*1195Speter postcheck( p1 -> type ); 167*1195Speter break; 168*1195Speter default: 169*1195Speter q = rvalue( argv[1] , p1 -> type , RREQ ); 170*1195Speter if ( isa( p1 -> type , "d" ) 171*1195Speter && isa( q , "i" ) ) { 172*1195Speter putop( P2SCONV , P2DOUBLE ); 173*1195Speter } 174*1195Speter break; 175*1195Speter } 176*1195Speter # endif PC 177*1195Speter if (q == NIL) 178745Speter break; 179*1195Speter if (incompat(q, p1->type, argv[1])) { 180*1195Speter cerror("Expression type clashed with type of value parameter %s of %s", p1->symbol, p->symbol); 181745Speter break; 182745Speter } 183745Speter # ifdef OBJ 184*1195Speter if (isa(p1->type, "bcsi")) 185*1195Speter rangechk(p1->type, q); 186*1195Speter if (q->class != STR) 187*1195Speter convert(q, p1->type); 188745Speter # endif OBJ 189745Speter # ifdef PC 190*1195Speter switch( classify( p1 -> type ) ) { 191*1195Speter case TFILE: 192*1195Speter case TARY: 193*1195Speter case TREC: 194*1195Speter case TSET: 195*1195Speter case TSTR: 196*1195Speter putstrop( P2STARG 197*1195Speter , p2type( p1 -> type ) 198*1195Speter , lwidth( p1 -> type ) 199*1195Speter , align( p1 -> type ) ); 200*1195Speter } 201*1195Speter # endif PC 202*1195Speter break; 203*1195Speter case FFUNC: 204*1195Speter /* 205*1195Speter * function parameter 206*1195Speter */ 207*1195Speter q = flvalue( (int *) argv[1] , FFUNC ); 208*1195Speter if (q == NIL) 209*1195Speter break; 210*1195Speter if (q != p1->type) { 211*1195Speter error("Function type not identical to type of function parameter %s of %s", p1->symbol, p->symbol); 212*1195Speter break; 213745Speter } 214*1195Speter break; 215*1195Speter case FPROC: 216*1195Speter /* 217*1195Speter * procedure parameter 218*1195Speter */ 219*1195Speter q = flvalue( (int *) argv[1] , FPROC ); 220*1195Speter if (q != NIL) { 221*1195Speter error("Procedure parameter %s of %s cannot have a type", p1->symbol, p->symbol); 222*1195Speter } 223*1195Speter break; 224*1195Speter default: 225*1195Speter panic("call"); 226*1195Speter } 227745Speter # ifdef PC 228*1195Speter /* 229*1195Speter * if this is the nth (>1) argument, 230*1195Speter * hang it on the left linear list of arguments 231*1195Speter */ 232*1195Speter if ( firsttime ) { 233*1195Speter firsttime = FALSE; 234*1195Speter } else { 235*1195Speter putop( P2LISTOP , P2INT ); 236*1195Speter } 237745Speter # endif PC 238*1195Speter argv = argv[2]; 239*1195Speter } 240*1195Speter if (argv != NIL) { 241*1195Speter error("Too many arguments to %s", p->symbol); 242*1195Speter rvlist(argv); 243*1195Speter return (NIL); 244*1195Speter } 245*1195Speter } else if ( p -> class == FFUNC || p -> class == FPROC ) { 246*1195Speter /* 247*1195Speter * formal routines can only have by-value parameters. 248*1195Speter * this will lose for integer actuals passed to real 249*1195Speter * formals, and strings which people want blank padded. 250*1195Speter */ 251*1195Speter # ifdef OBJ 252*1195Speter cnt = 0; 253*1195Speter # endif OBJ 254*1195Speter for ( ; argv != NIL ; argv = argv[2] ) { 255*1195Speter # ifdef OBJ 256*1195Speter q = rvalue(argv[1], NIL, RREQ ); 257*1195Speter cnt += even(lwidth(q)); 258*1195Speter # endif OBJ 259*1195Speter # ifdef PC 260*1195Speter /* 261*1195Speter * structure arguments require lvalues, 262*1195Speter * scalars use rvalue. 263*1195Speter */ 264*1195Speter codeoff(); 265*1195Speter p1 = rvalue( argv[1] , NIL , RREQ ); 266*1195Speter codeon(); 267*1195Speter switch( classify( p1 ) ) { 268*1195Speter case TSTR: 269*1195Speter if ( p1 -> class == STR && slenflag == 0 ) { 270*1195Speter if ( opt( 's' ) ) { 271*1195Speter standard(); 272*1195Speter } else { 273*1195Speter warning(); 274*1195Speter } 275*1195Speter error("Implementation can't construct equal length strings"); 276*1195Speter slenflag++; 277*1195Speter } 278*1195Speter /* and fall through */ 279*1195Speter case TFILE: 280*1195Speter case TARY: 281*1195Speter case TREC: 282*1195Speter case TSET: 283*1195Speter q = rvalue( argv[1] , p1 , LREQ ); 284*1195Speter break; 285*1195Speter case TINT: 286*1195Speter if ( floatflag == 0 ) { 287*1195Speter if ( opt( 's' ) ) { 288*1195Speter standard(); 289*1195Speter } else { 290*1195Speter warning(); 291*1195Speter } 292*1195Speter error("Implementation can't coerice integer to real"); 293*1195Speter floatflag++; 294*1195Speter } 295*1195Speter /* and fall through */ 296*1195Speter case TSCAL: 297*1195Speter case TBOOL: 298*1195Speter case TCHAR: 299*1195Speter default: 300*1195Speter q = rvalue( argv[1] , p1 , RREQ ); 301*1195Speter break; 302*1195Speter } 303*1195Speter switch( classify( p1 ) ) { 304*1195Speter case TFILE: 305*1195Speter case TARY: 306*1195Speter case TREC: 307*1195Speter case TSET: 308*1195Speter case TSTR: 309*1195Speter putstrop( P2STARG , p2type( p1 ) , 310*1195Speter lwidth( p1 ) , align( p1 ) ); 311*1195Speter } 312*1195Speter /* 313*1195Speter * if this is the nth (>1) argument, 314*1195Speter * hang it on the left linear list of arguments 315*1195Speter */ 316*1195Speter if ( firsttime ) { 317*1195Speter firsttime = FALSE; 318*1195Speter } else { 319*1195Speter putop( P2LISTOP , P2INT ); 320*1195Speter } 321*1195Speter # endif PC 322*1195Speter } 323*1195Speter } else { 324*1195Speter panic("call class"); 325745Speter } 326745Speter # ifdef OBJ 327*1195Speter if ( p -> class == FFUNC || p -> class == FPROC ) { 328*1195Speter put(2, PTR_RV | cbn << 8+INDX, p->value[NL_OFFS]); 329*1195Speter put(2, O_FCALL, cnt); 330*1195Speter put(2, O_FRTN, even(lwidth(p->type))); 331*1195Speter } else { 332*1195Speter put2(O_CALL | psbn << 8+INDX, p->entloc); 333*1195Speter } 334745Speter # endif OBJ 335745Speter # ifdef PC 336745Speter if ( porf == FUNC ) { 337745Speter rettype = p2type( p -> type ); 338745Speter switch ( classify( p -> type ) ) { 339745Speter case TBOOL: 340745Speter case TCHAR: 341745Speter case TINT: 342745Speter case TSCAL: 343745Speter case TDOUBLE: 344745Speter case TPTR: 345*1195Speter if ( firsttime ) { 346745Speter putop( P2UNARY P2CALL , rettype ); 347745Speter } else { 348745Speter putop( P2CALL , rettype ); 349745Speter } 350*1195Speter if (p -> class == FFUNC || p -> class == FPROC ) { 351*1195Speter putop( P2LISTOP , P2INT ); 352*1195Speter putop( P2CALL , rettype ); 353*1195Speter } 354745Speter break; 355745Speter default: 356*1195Speter if ( firsttime ) { 357745Speter putstrop( P2UNARY P2STCALL 358745Speter , ADDTYPE( rettype , P2PTR ) 359745Speter , lwidth( p -> type ) 360745Speter , align( p -> type ) ); 361745Speter } else { 362745Speter putstrop( P2STCALL 363745Speter , ADDTYPE( rettype , P2PTR ) 364745Speter , lwidth( p -> type ) 365745Speter , align( p -> type ) ); 366745Speter } 367*1195Speter if (p -> class == FFUNC || p -> class == FPROC ) { 368*1195Speter putop( P2LISTOP , P2INT ); 369*1195Speter putop( P2CALL , ADDTYPE( rettype , P2PTR ) ); 370*1195Speter } 371745Speter putstrop( P2STASG , rettype , lwidth( p -> type ) 372745Speter , align( p -> type ) ); 373745Speter putLV( 0 , cbn , temp , rettype ); 374745Speter putop( P2COMOP , P2INT ); 375745Speter break; 376745Speter } 377745Speter } else { 378*1195Speter if ( firsttime ) { 379745Speter putop( P2UNARY P2CALL , P2INT ); 380745Speter } else { 381745Speter putop( P2CALL , P2INT ); 382745Speter } 383*1195Speter if (p -> class == FFUNC || p -> class == FPROC ) { 384*1195Speter putop( P2LISTOP , P2INT ); 385*1195Speter putop( P2CALL , P2INT ); 386*1195Speter } 387745Speter putdot( filename , line ); 388745Speter } 389745Speter # endif PC 390745Speter return (p->type); 391745Speter } 392745Speter 393745Speter rvlist(al) 394745Speter register int *al; 395745Speter { 396745Speter 397745Speter for (; al != NIL; al = al[2]) 398745Speter rvalue( (int *) al[1], NLNIL , RREQ ); 399745Speter } 400