1 /* 2 * Copyright (c) 1980 Regents of the University of California. 3 * All rights reserved. The Berkeley software License Agreement 4 * specifies the terms and conditions for redistribution. 5 */ 6 7 #ifndef lint 8 static char sccsid[] = "@(#)intr.c 5.1 (Berkeley) 6/7/85"; 9 #endif not lint 10 11 /* 12 * intr.c 13 * 14 * Routines for handling intrinsic functions, f77 compiler pass 1, 4.2 BSD. 15 * 16 * University of Utah CS Dept modification history: 17 * 18 * $Log: intr.c,v $ 19 * Revision 1.4 85/02/22 00:54:59 donn 20 * Mark intrinsic functions as having storage class STGINTR. builtin() 21 * always returns STGEXT nodes. Notice that the reference to the function 22 * in the external symbol table still uses STGEXT... I hope this is right. 23 * 24 * Revision 1.3 85/01/15 21:05:40 donn 25 * Changes to distinguish explicit from implicit conversions with intrconv(). 26 * 27 * Revision 1.2 84/12/15 01:02:33 donn 28 * Added a case for an integer*4 result from len() in inlne(). Previously 29 * only -i2 provoked len() inline, sigh. 30 * 31 */ 32 33 #include "defs.h" 34 35 extern ftnint intcon[14]; 36 extern double realcon[6]; 37 38 union 39 { 40 int ijunk; 41 struct Intrpacked bits; 42 } packed; 43 44 struct Intrbits 45 { 46 int intrgroup /* :3 */; 47 int intrstuff /* result type or number of generics */; 48 int intrno /* :7 */; 49 }; 50 51 LOCAL struct Intrblock 52 { 53 char intrfname[VL]; 54 struct Intrbits intrval; 55 } intrtab[ ] = 56 { 57 "int", { INTRCONV, TYLONG }, 58 "real", { INTRCONV, TYREAL }, 59 "dble", { INTRCONV, TYDREAL }, 60 "dreal", { INTRCONV, TYDREAL }, 61 "cmplx", { INTRCONV, TYCOMPLEX }, 62 "dcmplx", { INTRCONV, TYDCOMPLEX }, 63 "ifix", { INTRCONV, TYLONG }, 64 "idint", { INTRCONV, TYLONG }, 65 "float", { INTRCONV, TYREAL }, 66 "dfloat", { INTRCONV, TYDREAL }, 67 "sngl", { INTRCONV, TYREAL }, 68 "ichar", { INTRCONV, TYLONG }, 69 "iachar", { INTRCONV, TYLONG }, 70 "char", { INTRCONV, TYCHAR }, 71 "achar", { INTRCONV, TYCHAR }, 72 73 "max", { INTRMAX, TYUNKNOWN }, 74 "max0", { INTRMAX, TYLONG }, 75 "amax0", { INTRMAX, TYREAL }, 76 "max1", { INTRMAX, TYLONG }, 77 "amax1", { INTRMAX, TYREAL }, 78 "dmax1", { INTRMAX, TYDREAL }, 79 80 "and", { INTRBOOL, TYUNKNOWN, OPBITAND }, 81 "or", { INTRBOOL, TYUNKNOWN, OPBITOR }, 82 "xor", { INTRBOOL, TYUNKNOWN, OPBITXOR }, 83 "not", { INTRBOOL, TYUNKNOWN, OPBITNOT }, 84 "lshift", { INTRBOOL, TYUNKNOWN, OPLSHIFT }, 85 "rshift", { INTRBOOL, TYUNKNOWN, OPRSHIFT }, 86 87 "min", { INTRMIN, TYUNKNOWN }, 88 "min0", { INTRMIN, TYLONG }, 89 "amin0", { INTRMIN, TYREAL }, 90 "min1", { INTRMIN, TYLONG }, 91 "amin1", { INTRMIN, TYREAL }, 92 "dmin1", { INTRMIN, TYDREAL }, 93 94 "aint", { INTRGEN, 2, 0 }, 95 "dint", { INTRSPEC, TYDREAL, 1 }, 96 97 "anint", { INTRGEN, 2, 2 }, 98 "dnint", { INTRSPEC, TYDREAL, 3 }, 99 100 "nint", { INTRGEN, 4, 4 }, 101 "idnint", { INTRGEN, 2, 6 }, 102 103 "abs", { INTRGEN, 6, 8 }, 104 "iabs", { INTRGEN, 2, 9 }, 105 "dabs", { INTRSPEC, TYDREAL, 11 }, 106 "cabs", { INTRSPEC, TYREAL, 12 }, 107 "zabs", { INTRSPEC, TYDREAL, 13 }, 108 "cdabs", { INTRSPEC, TYDREAL, 13 }, 109 110 "mod", { INTRGEN, 4, 14 }, 111 "amod", { INTRSPEC, TYREAL, 16 }, 112 "dmod", { INTRSPEC, TYDREAL, 17 }, 113 114 "sign", { INTRGEN, 4, 18 }, 115 "isign", { INTRGEN, 2, 19 }, 116 "dsign", { INTRSPEC, TYDREAL, 21 }, 117 118 "dim", { INTRGEN, 4, 22 }, 119 "idim", { INTRGEN, 2, 23 }, 120 "ddim", { INTRSPEC, TYDREAL, 25 }, 121 122 "dprod", { INTRSPEC, TYDREAL, 26 }, 123 124 "len", { INTRSPEC, TYLONG, 27 }, 125 "index", { INTRSPEC, TYLONG, 29 }, 126 127 "imag", { INTRGEN, 2, 31 }, 128 "aimag", { INTRSPEC, TYREAL, 31 }, 129 "dimag", { INTRSPEC, TYDREAL, 32 }, 130 131 "conjg", { INTRGEN, 2, 33 }, 132 "dconjg", { INTRSPEC, TYDCOMPLEX, 34 }, 133 134 "sqrt", { INTRGEN, 4, 35 }, 135 "dsqrt", { INTRSPEC, TYDREAL, 36 }, 136 "csqrt", { INTRSPEC, TYCOMPLEX, 37 }, 137 "zsqrt", { INTRSPEC, TYDCOMPLEX, 38 }, 138 "cdsqrt", { INTRSPEC, TYDCOMPLEX, 38 }, 139 140 "exp", { INTRGEN, 4, 39 }, 141 "dexp", { INTRSPEC, TYDREAL, 40 }, 142 "cexp", { INTRSPEC, TYCOMPLEX, 41 }, 143 "zexp", { INTRSPEC, TYDCOMPLEX, 42 }, 144 "cdexp", { INTRSPEC, TYDCOMPLEX, 42 }, 145 146 "log", { INTRGEN, 4, 43 }, 147 "alog", { INTRSPEC, TYREAL, 43 }, 148 "dlog", { INTRSPEC, TYDREAL, 44 }, 149 "clog", { INTRSPEC, TYCOMPLEX, 45 }, 150 "zlog", { INTRSPEC, TYDCOMPLEX, 46 }, 151 "cdlog", { INTRSPEC, TYDCOMPLEX, 46 }, 152 153 "log10", { INTRGEN, 2, 47 }, 154 "alog10", { INTRSPEC, TYREAL, 47 }, 155 "dlog10", { INTRSPEC, TYDREAL, 48 }, 156 157 "sin", { INTRGEN, 4, 49 }, 158 "dsin", { INTRSPEC, TYDREAL, 50 }, 159 "csin", { INTRSPEC, TYCOMPLEX, 51 }, 160 "zsin", { INTRSPEC, TYDCOMPLEX, 52 }, 161 "cdsin", { INTRSPEC, TYDCOMPLEX, 52 }, 162 163 "cos", { INTRGEN, 4, 53 }, 164 "dcos", { INTRSPEC, TYDREAL, 54 }, 165 "ccos", { INTRSPEC, TYCOMPLEX, 55 }, 166 "zcos", { INTRSPEC, TYDCOMPLEX, 56 }, 167 "cdcos", { INTRSPEC, TYDCOMPLEX, 56 }, 168 169 "tan", { INTRGEN, 2, 57 }, 170 "dtan", { INTRSPEC, TYDREAL, 58 }, 171 172 "asin", { INTRGEN, 2, 59 }, 173 "dasin", { INTRSPEC, TYDREAL, 60 }, 174 175 "acos", { INTRGEN, 2, 61 }, 176 "dacos", { INTRSPEC, TYDREAL, 62 }, 177 178 "atan", { INTRGEN, 2, 63 }, 179 "datan", { INTRSPEC, TYDREAL, 64 }, 180 181 "atan2", { INTRGEN, 2, 65 }, 182 "datan2", { INTRSPEC, TYDREAL, 66 }, 183 184 "sinh", { INTRGEN, 2, 67 }, 185 "dsinh", { INTRSPEC, TYDREAL, 68 }, 186 187 "cosh", { INTRGEN, 2, 69 }, 188 "dcosh", { INTRSPEC, TYDREAL, 70 }, 189 190 "tanh", { INTRGEN, 2, 71 }, 191 "dtanh", { INTRSPEC, TYDREAL, 72 }, 192 193 "lge", { INTRSPEC, TYLOGICAL, 73}, 194 "lgt", { INTRSPEC, TYLOGICAL, 75}, 195 "lle", { INTRSPEC, TYLOGICAL, 77}, 196 "llt", { INTRSPEC, TYLOGICAL, 79}, 197 198 "epbase", { INTRCNST, 4, 0 }, 199 "epprec", { INTRCNST, 4, 4 }, 200 "epemin", { INTRCNST, 2, 8 }, 201 "epemax", { INTRCNST, 2, 10 }, 202 "eptiny", { INTRCNST, 2, 12 }, 203 "ephuge", { INTRCNST, 4, 14 }, 204 "epmrsp", { INTRCNST, 2, 18 }, 205 206 "fpexpn", { INTRGEN, 4, 81 }, 207 "fpabsp", { INTRGEN, 2, 85 }, 208 "fprrsp", { INTRGEN, 2, 87 }, 209 "fpfrac", { INTRGEN, 2, 89 }, 210 "fpmake", { INTRGEN, 2, 91 }, 211 "fpscal", { INTRGEN, 2, 93 }, 212 213 "" }; 214 215 216 LOCAL struct Specblock 217 { 218 char atype; 219 char rtype; 220 char nargs; 221 char spxname[XL]; 222 char othername; /* index into callbyvalue table */ 223 } spectab[ ] = 224 { 225 { TYREAL,TYREAL,1,"r_int" }, 226 { TYDREAL,TYDREAL,1,"d_int" }, 227 228 { TYREAL,TYREAL,1,"r_nint" }, 229 { TYDREAL,TYDREAL,1,"d_nint" }, 230 231 { TYREAL,TYSHORT,1,"h_nint" }, 232 { TYREAL,TYLONG,1,"i_nint" }, 233 234 { TYDREAL,TYSHORT,1,"h_dnnt" }, 235 { TYDREAL,TYLONG,1,"i_dnnt" }, 236 237 { TYREAL,TYREAL,1,"r_abs" }, 238 { TYSHORT,TYSHORT,1,"h_abs" }, 239 { TYLONG,TYLONG,1,"i_abs" }, 240 { TYDREAL,TYDREAL,1,"d_abs" }, 241 { TYCOMPLEX,TYREAL,1,"c_abs" }, 242 { TYDCOMPLEX,TYDREAL,1,"z_abs" }, 243 244 { TYSHORT,TYSHORT,2,"h_mod" }, 245 { TYLONG,TYLONG,2,"i_mod" }, 246 { TYREAL,TYREAL,2,"r_mod" }, 247 { TYDREAL,TYDREAL,2,"d_mod" }, 248 249 { TYREAL,TYREAL,2,"r_sign" }, 250 { TYSHORT,TYSHORT,2,"h_sign" }, 251 { TYLONG,TYLONG,2,"i_sign" }, 252 { TYDREAL,TYDREAL,2,"d_sign" }, 253 254 { TYREAL,TYREAL,2,"r_dim" }, 255 { TYSHORT,TYSHORT,2,"h_dim" }, 256 { TYLONG,TYLONG,2,"i_dim" }, 257 { TYDREAL,TYDREAL,2,"d_dim" }, 258 259 { TYREAL,TYDREAL,2,"d_prod" }, 260 261 { TYCHAR,TYSHORT,1,"h_len" }, 262 { TYCHAR,TYLONG,1,"i_len" }, 263 264 { TYCHAR,TYSHORT,2,"h_indx" }, 265 { TYCHAR,TYLONG,2,"i_indx" }, 266 267 { TYCOMPLEX,TYREAL,1,"r_imag" }, 268 { TYDCOMPLEX,TYDREAL,1,"d_imag" }, 269 { TYCOMPLEX,TYCOMPLEX,1,"r_cnjg" }, 270 { TYDCOMPLEX,TYDCOMPLEX,1,"d_cnjg" }, 271 272 { TYREAL,TYREAL,1,"r_sqrt", 14 }, 273 { TYDREAL,TYDREAL,1,"d_sqrt", 1 }, 274 { TYCOMPLEX,TYCOMPLEX,1,"c_sqrt" }, 275 { TYDCOMPLEX,TYDCOMPLEX,1,"z_sqrt" }, 276 277 { TYREAL,TYREAL,1,"r_exp", 15 }, 278 { TYDREAL,TYDREAL,1,"d_exp", 2 }, 279 { TYCOMPLEX,TYCOMPLEX,1,"c_exp" }, 280 { TYDCOMPLEX,TYDCOMPLEX,1,"z_exp" }, 281 282 { TYREAL,TYREAL,1,"r_log", 16 }, 283 { TYDREAL,TYDREAL,1,"d_log", 3 }, 284 { TYCOMPLEX,TYCOMPLEX,1,"c_log" }, 285 { TYDCOMPLEX,TYDCOMPLEX,1,"z_log" }, 286 287 { TYREAL,TYREAL,1,"r_lg10" }, 288 { TYDREAL,TYDREAL,1,"d_lg10" }, 289 290 { TYREAL,TYREAL,1,"r_sin", 17 }, 291 { TYDREAL,TYDREAL,1,"d_sin", 4 }, 292 { TYCOMPLEX,TYCOMPLEX,1,"c_sin" }, 293 { TYDCOMPLEX,TYDCOMPLEX,1,"z_sin" }, 294 295 { TYREAL,TYREAL,1,"r_cos", 18 }, 296 { TYDREAL,TYDREAL,1,"d_cos", 5 }, 297 { TYCOMPLEX,TYCOMPLEX,1,"c_cos" }, 298 { TYDCOMPLEX,TYDCOMPLEX,1,"z_cos" }, 299 300 { TYREAL,TYREAL,1,"r_tan" }, 301 { TYDREAL,TYDREAL,1,"d_tan", 6 }, 302 303 { TYREAL,TYREAL,1,"r_asin" }, 304 { TYDREAL,TYDREAL,1,"d_asin", 7 }, 305 306 { TYREAL,TYREAL,1,"r_acos" }, 307 { TYDREAL,TYDREAL,1,"d_acos", 8 }, 308 309 { TYREAL,TYREAL,1,"r_atan", 19 }, 310 { TYDREAL,TYDREAL,1,"d_atan", 9 }, 311 312 { TYREAL,TYREAL,2,"r_atn2" }, 313 { TYDREAL,TYDREAL,2,"d_atn2", 10 }, 314 315 { TYREAL,TYREAL,1,"r_sinh" }, 316 { TYDREAL,TYDREAL,1,"d_sinh", 11 }, 317 318 { TYREAL,TYREAL,1,"r_cosh" }, 319 { TYDREAL,TYDREAL,1,"d_cosh", 12 }, 320 321 { TYREAL,TYREAL,1,"r_tanh" }, 322 { TYDREAL,TYDREAL,1,"d_tanh", 13 }, 323 324 { TYCHAR,TYLOGICAL,2,"hl_ge" }, 325 { TYCHAR,TYLOGICAL,2,"l_ge" }, 326 327 { TYCHAR,TYLOGICAL,2,"hl_gt" }, 328 { TYCHAR,TYLOGICAL,2,"l_gt" }, 329 330 { TYCHAR,TYLOGICAL,2,"hl_le" }, 331 { TYCHAR,TYLOGICAL,2,"l_le" }, 332 333 { TYCHAR,TYLOGICAL,2,"hl_lt" }, 334 { TYCHAR,TYLOGICAL,2,"l_lt" }, 335 336 { TYREAL,TYSHORT,1,"hr_expn" }, 337 { TYREAL,TYLONG,1,"ir_expn" }, 338 { TYDREAL,TYSHORT,1,"hd_expn" }, 339 { TYDREAL,TYLONG,1,"id_expn" }, 340 341 { TYREAL,TYREAL,1,"r_absp" }, 342 { TYDREAL,TYDREAL,1,"d_absp" }, 343 344 { TYREAL,TYDREAL,1,"r_rrsp" }, 345 { TYDREAL,TYDREAL,1,"d_rrsp" }, 346 347 { TYREAL,TYREAL,1,"r_frac" }, 348 { TYDREAL,TYDREAL,1,"d_frac" }, 349 350 { TYREAL,TYREAL,2,"r_make" }, 351 { TYDREAL,TYDREAL,2,"d_make" }, 352 353 { TYREAL,TYREAL,2,"r_scal" }, 354 { TYDREAL,TYDREAL,2,"d_scal" } 355 } ; 356 357 LOCAL struct Incstblock 358 { 359 char atype; 360 char rtype; 361 char constno; 362 } consttab[ ] = 363 { 364 { TYSHORT, TYLONG, 0 }, 365 { TYLONG, TYLONG, 1 }, 366 { TYREAL, TYLONG, 2 }, 367 { TYDREAL, TYLONG, 3 }, 368 369 { TYSHORT, TYLONG, 4 }, 370 { TYLONG, TYLONG, 5 }, 371 { TYREAL, TYLONG, 6 }, 372 { TYDREAL, TYLONG, 7 }, 373 374 { TYREAL, TYLONG, 8 }, 375 { TYDREAL, TYLONG, 9 }, 376 377 { TYREAL, TYLONG, 10 }, 378 { TYDREAL, TYLONG, 11 }, 379 380 { TYREAL, TYREAL, 0 }, 381 { TYDREAL, TYDREAL, 1 }, 382 383 { TYSHORT, TYLONG, 12 }, 384 { TYLONG, TYLONG, 13 }, 385 { TYREAL, TYREAL, 2 }, 386 { TYDREAL, TYDREAL, 3 }, 387 388 { TYREAL, TYREAL, 4 }, 389 { TYDREAL, TYDREAL, 5 } 390 }; 391 392 /* For each machine, two arrays must be initialized. 393 intcon contains 394 radix for short int 395 radix for long int 396 radix for single precision 397 radix for double precision 398 precision for short int 399 precision for long int 400 precision for single precision 401 precision for double precision 402 emin for single precision 403 emin for double precision 404 emax for single precision 405 emax for double prcision 406 largest short int 407 largest long int 408 409 realcon contains 410 tiny for single precision 411 tiny for double precision 412 huge for single precision 413 huge for double precision 414 mrsp (epsilon) for single precision 415 mrsp (epsilon) for double precision 416 417 the realcons should probably be filled in in binary if TARGET==HERE 418 */ 419 420 char callbyvalue[ ][XL] = 421 { 422 "sqrt", 423 "exp", 424 "log", 425 "sin", 426 "cos", 427 "tan", 428 "asin", 429 "acos", 430 "atan", 431 "atan2", 432 "sinh", 433 "cosh", 434 "tanh", 435 /* function opcodes */ 436 "@sqrt", 437 "@exp", 438 "@log", 439 "@sin", 440 "@cos", 441 "@atan" 442 }; 443 444 expptr intrcall(np, argsp, nargs) 445 Namep np; 446 struct Listblock *argsp; 447 int nargs; 448 { 449 int i, rettype; 450 Addrp ap; 451 register struct Specblock *sp; 452 register struct Chain *cp; 453 expptr inlne(), mkcxcon(), mkrealcon(); 454 register struct Incstblock *cstp; 455 expptr q, ep; 456 int mtype; 457 int op; 458 int f1field, f2field, f3field; 459 460 packed.ijunk = np->vardesc.varno; 461 f1field = packed.bits.f1; 462 f2field = packed.bits.f2; 463 f3field = packed.bits.f3; 464 if(nargs == 0) 465 goto badnargs; 466 467 mtype = 0; 468 for(cp = argsp->listp ; cp ; cp = cp->nextp) 469 { 470 /* TEMPORARY */ ep = (expptr) (cp->datap); 471 /* TEMPORARY */ if( ISCONST(ep) && ep->headblock.vtype==TYSHORT ) 472 /* TEMPORARY */ cp->datap = (tagptr) mkconv(tyint, ep); 473 mtype = maxtype(mtype, ep->headblock.vtype); 474 } 475 476 switch(f1field) 477 { 478 case INTRBOOL: 479 op = f3field; 480 if( ! ONEOF(mtype, MSKINT|MSKLOGICAL) ) 481 goto badtype; 482 if(op == OPBITNOT) 483 { 484 if(nargs != 1) 485 goto badnargs; 486 q = mkexpr(OPBITNOT, argsp->listp->datap, ENULL); 487 } 488 else 489 { 490 if(nargs != 2) 491 goto badnargs; 492 q = mkexpr(op, argsp->listp->datap, 493 argsp->listp->nextp->datap); 494 } 495 frchain( &(argsp->listp) ); 496 free( (charptr) argsp); 497 return(q); 498 499 case INTRCONV: 500 if (nargs == 1) 501 { 502 if(argsp->listp->datap->headblock.vtype == TYERROR) 503 { 504 free( (charptr) argsp->listp->datap); 505 frchain( &(argsp->listp) ); 506 free( (charptr) argsp); 507 return( errnode() ); 508 } 509 } 510 else if (nargs == 2) 511 { 512 if(argsp->listp->nextp->datap->headblock.vtype == 513 TYERROR || 514 argsp->listp->datap->headblock.vtype == TYERROR) 515 { 516 free( (charptr) argsp->listp->nextp->datap); 517 free( (charptr) argsp->listp->datap); 518 frchain( &(argsp->listp) ); 519 free( (charptr) argsp); 520 return( errnode() ); 521 } 522 } 523 rettype = f2field; 524 if(rettype == TYLONG) 525 rettype = tyint; 526 if( ISCOMPLEX(rettype) && nargs==2) 527 { 528 expptr qr, qi; 529 qr = (expptr) (argsp->listp->datap); 530 qi = (expptr) (argsp->listp->nextp->datap); 531 if(ISCONST(qr) && ISCONST(qi)) 532 q = mkcxcon(qr,qi); 533 else q = mkexpr(OPCONV,intrconv(rettype-2,qr), 534 intrconv(rettype-2,qi)); 535 } 536 else if(nargs == 1) 537 q = intrconv(rettype, argsp->listp->datap); 538 else goto badnargs; 539 540 q->headblock.vtype = rettype; 541 frchain(&(argsp->listp)); 542 free( (charptr) argsp); 543 return(q); 544 545 546 case INTRCNST: 547 cstp = consttab + f3field; 548 for(i=0 ; i<f2field ; ++i) 549 if(cstp->atype == mtype) 550 goto foundconst; 551 else 552 ++cstp; 553 goto badtype; 554 555 foundconst: 556 switch(cstp->rtype) 557 { 558 case TYLONG: 559 return(mkintcon(intcon[cstp->constno])); 560 561 case TYREAL: 562 case TYDREAL: 563 return(mkrealcon(cstp->rtype, 564 realcon[cstp->constno]) ); 565 566 default: 567 fatal("impossible intrinsic constant"); 568 } 569 570 case INTRGEN: 571 sp = spectab + f3field; 572 if(no66flag) 573 if(sp->atype == mtype) 574 goto specfunct; 575 else err66("generic function"); 576 577 for(i=0; i<f2field ; ++i) 578 if(sp->atype == mtype) 579 goto specfunct; 580 else 581 ++sp; 582 goto badtype; 583 584 case INTRSPEC: 585 sp = spectab + f3field; 586 specfunct: 587 if(tyint==TYLONG && ONEOF(sp->rtype,M(TYSHORT)|M(TYLOGICAL)) 588 && (sp+1)->atype==sp->atype) 589 ++sp; 590 591 if(nargs != sp->nargs) 592 goto badnargs; 593 if(mtype != sp->atype) 594 goto badtype; 595 fixargs(YES, argsp); 596 if(q = inlne(sp-spectab, mtype, argsp->listp)) 597 { 598 frchain( &(argsp->listp) ); 599 free( (charptr) argsp); 600 } 601 else if(sp->othername) 602 { 603 ap = builtin(sp->rtype, 604 varstr(XL, callbyvalue[sp->othername-1]) ); 605 ap->vstg = STGINTR; 606 q = fixexpr( mkexpr(OPCCALL, ap, argsp) ); 607 } 608 else 609 { 610 ap = builtin(sp->rtype, varstr(XL, sp->spxname) ); 611 ap->vstg = STGINTR; 612 q = fixexpr( mkexpr(OPCALL, ap, argsp) ); 613 } 614 return(q); 615 616 case INTRMIN: 617 case INTRMAX: 618 if(nargs < 2) 619 goto badnargs; 620 if( ! ONEOF(mtype, MSKINT|MSKREAL) ) 621 goto badtype; 622 argsp->vtype = mtype; 623 q = mkexpr( (f1field==INTRMIN ? OPMIN : OPMAX), argsp, ENULL); 624 625 q->headblock.vtype = mtype; 626 rettype = f2field; 627 if(rettype == TYLONG) 628 rettype = tyint; 629 else if(rettype == TYUNKNOWN) 630 rettype = mtype; 631 return( intrconv(rettype, q) ); 632 633 default: 634 fatali("intrcall: bad intrgroup %d", f1field); 635 } 636 badnargs: 637 errstr("bad number of arguments to intrinsic %s", 638 varstr(VL,np->varname) ); 639 goto bad; 640 641 badtype: 642 errstr("bad argument type to intrinsic %s", varstr(VL, np->varname) ); 643 644 bad: 645 return( errnode() ); 646 } 647 648 649 650 651 intrfunct(s) 652 char s[VL]; 653 { 654 register struct Intrblock *p; 655 char nm[VL]; 656 register int i; 657 658 for(i = 0 ; i<VL ; ++s) 659 nm[i++] = (*s==' ' ? '\0' : *s); 660 661 for(p = intrtab; p->intrval.intrgroup!=INTREND ; ++p) 662 { 663 if( eqn(VL, nm, p->intrfname) ) 664 { 665 packed.bits.f1 = p->intrval.intrgroup; 666 packed.bits.f2 = p->intrval.intrstuff; 667 packed.bits.f3 = p->intrval.intrno; 668 return(packed.ijunk); 669 } 670 } 671 672 return(0); 673 } 674 675 676 677 678 679 Addrp intraddr(np) 680 Namep np; 681 { 682 Addrp q; 683 register struct Specblock *sp; 684 int f3field; 685 686 if(np->vclass!=CLPROC || np->vprocclass!=PINTRINSIC) 687 fatalstr("intraddr: %s is not intrinsic", varstr(VL,np->varname)); 688 packed.ijunk = np->vardesc.varno; 689 f3field = packed.bits.f3; 690 691 switch(packed.bits.f1) 692 { 693 case INTRGEN: 694 /* imag, log, and log10 arent specific functions */ 695 if(f3field==31 || f3field==43 || f3field==47) 696 goto bad; 697 698 case INTRSPEC: 699 sp = spectab + f3field; 700 if(tyint==TYLONG && sp->rtype==TYSHORT) 701 ++sp; 702 q = builtin(sp->rtype, varstr(XL,sp->spxname) ); 703 q->vstg = STGINTR; 704 return(q); 705 706 case INTRCONV: 707 case INTRMIN: 708 case INTRMAX: 709 case INTRBOOL: 710 case INTRCNST: 711 bad: 712 errstr("cannot pass %s as actual", 713 varstr(VL,np->varname)); 714 return( (Addrp) errnode() ); 715 } 716 fatali("intraddr: impossible f1=%d\n", (int) packed.bits.f1); 717 /* NOTREACHED */ 718 } 719 720 721 722 723 724 expptr inlne(fno, type, args) 725 int fno; 726 int type; 727 struct Chain *args; 728 { 729 register expptr q, t, t1; 730 731 switch(fno) 732 { 733 case 8: /* real abs */ 734 case 9: /* short int abs */ 735 case 10: /* long int abs */ 736 case 11: /* double precision abs */ 737 if( addressable(q = (expptr) (args->datap)) ) 738 { 739 t = q; 740 q = NULL; 741 } 742 else 743 t = (expptr) mktemp(type,PNULL); 744 t1 = mkexpr(OPQUEST, 745 mkexpr(OPLE, intrconv(type,ICON(0)), cpexpr(t)), 746 mkexpr(OPCOLON, cpexpr(t), 747 mkexpr(OPNEG, cpexpr(t), ENULL) )); 748 if(q) 749 t1 = mkexpr(OPCOMMA, mkexpr(OPASSIGN, cpexpr(t),q), t1); 750 frexpr(t); 751 return(t1); 752 753 case 26: /* dprod */ 754 q = mkexpr(OPSTAR, intrconv(TYDREAL,args->datap), args->nextp->datap); 755 return(q); 756 757 case 27: /* len of character string */ 758 case 28: 759 q = (expptr) cpexpr(args->datap->headblock.vleng); 760 frexpr(args->datap); 761 return(q); 762 763 case 14: /* half-integer mod */ 764 case 15: /* mod */ 765 return( mkexpr(OPMOD, (expptr) (args->datap), 766 (expptr) (args->nextp->datap) )); 767 } 768 return(NULL); 769 } 770