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[] = "@(#)putpcc.c 5.1 (Berkeley) 6/7/85"; 9 #endif not lint 10 11 /* 12 * putpcc.c 13 * 14 * Intermediate code generation for S. C. Johnson C compilers 15 * New version using binary polish postfix intermediate 16 * 17 * University of Utah CS Dept modification history: 18 * 19 * $Header: putpcc.c,v 3.2 85/03/25 09:35:57 root Exp $ 20 * $Log: putpcc.c,v $ 21 * Revision 3.2 85/03/25 09:35:57 root 22 * fseek return -1 on error. 23 * 24 * Revision 3.1 85/02/27 19:06:55 donn 25 * Changed to use pcc.h instead of pccdefs.h. 26 * 27 * Revision 2.12 85/02/22 01:05:54 donn 28 * putaddr() didn't know about intrinsic functions... 29 * 30 * Revision 2.11 84/11/28 21:28:49 donn 31 * Hacked putop() to handle any character expression being converted to int, 32 * not just function calls. Previously it bombed on concatenations. 33 * 34 * Revision 2.10 84/11/01 22:07:07 donn 35 * Yet another try at getting putop() to work right. It appears that the 36 * second pass can't abide certain explicit conversions (e.g. short to long) 37 * so the conversion code in putop() tries to remove them. I think this 38 * version (finally) works. 39 * 40 * Revision 2.9 84/10/29 02:30:57 donn 41 * Earlier fix to putop() for conversions was insufficient -- we NEVER want to 42 * see the type of the left operand of the thing left over from stripping off 43 * conversions... 44 * 45 * Revision 2.8 84/09/18 03:09:21 donn 46 * Fixed bug in putop() where the left operand of an addrblock was being 47 * extracted... This caused an extremely obscure conversion error when 48 * an array of longs was subscripted by a short. 49 * 50 * Revision 2.7 84/08/19 20:10:19 donn 51 * Removed stuff in putbranch that treats STGARG parameters specially -- the 52 * bug in the code generation pass that motivated it has been fixed. 53 * 54 * Revision 2.6 84/08/07 21:32:23 donn 55 * Bumped the size of the buffer for the intermediate code file from 0.5K 56 * to 4K on a VAX. 57 * 58 * Revision 2.5 84/08/04 20:26:43 donn 59 * Fixed a goof in the new putbranch() -- it now calls mkaltemp instead of 60 * mktemp(). Correction due to Jerry Berkman. 61 * 62 * Revision 2.4 84/07/24 19:07:15 donn 63 * Fixed bug reported by Craig Leres in which putmnmx() mistakenly assumed 64 * that mkaltemp() returns tempblocks, and tried to free them with frtemp(). 65 * 66 * Revision 2.3 84/07/19 17:22:09 donn 67 * Changed putch1() so that OPPAREN expressions of type CHARACTER are legal. 68 * 69 * Revision 2.2 84/07/19 12:30:38 donn 70 * Fixed a type clash in Bob Corbett's new putbranch(). 71 * 72 * Revision 2.1 84/07/19 12:04:27 donn 73 * Changed comment headers for UofU. 74 * 75 * Revision 1.8 84/07/19 11:38:23 donn 76 * Replaced putbranch() routine so that you can ASSIGN into argument variables. 77 * The code is from Bob Corbett, donated by Jerry Berkman. 78 * 79 * Revision 1.7 84/05/31 00:48:32 donn 80 * Fixed an extremely obscure bug dealing with the comparison of CHARACTER*1 81 * expressions -- a foulup in the order of COMOP and the comparison caused 82 * one operand of the comparison to be garbage. 83 * 84 * Revision 1.6 84/04/16 09:54:19 donn 85 * Backed out earlier fix for bug where items in the argtemplist were 86 * (incorrectly) being given away; this is now fixed in mkargtemp(). 87 * 88 * Revision 1.5 84/03/23 22:49:48 donn 89 * Took out the initialization of the subroutine argument temporary list in 90 * putcall() -- it needs to be done once per statement instead of once per call. 91 * 92 * Revision 1.4 84/03/01 06:48:05 donn 93 * Fixed bug in Bob Corbett's code for argument temporaries that caused an 94 * addrblock to get thrown out inadvertently when it was needed for recycling 95 * purposes later on. 96 * 97 * Revision 1.3 84/02/26 06:32:38 donn 98 * Added Berkeley changes to move data definitions around and reduce offsets. 99 * 100 * Revision 1.2 84/02/26 06:27:45 donn 101 * Added code to catch TTEMP values passed to putx(). 102 * 103 */ 104 105 #if FAMILY != PCC 106 WRONG put FILE !!!! 107 #endif 108 109 #include "defs.h" 110 #include <pcc.h> 111 112 Addrp putcall(), putcxeq(), putcx1(), realpart(); 113 expptr imagpart(); 114 ftnint lencat(); 115 116 #define FOUR 4 117 extern int ops2[]; 118 extern int types2[]; 119 120 #if HERE==VAX || HERE == TAHOE 121 #define PCC_BUFFMAX 1024 122 #else 123 #define PCC_BUFFMAX 128 124 #endif 125 static long int p2buff[PCC_BUFFMAX]; 126 static long int *p2bufp = &p2buff[0]; 127 static long int *p2bufend = &p2buff[PCC_BUFFMAX]; 128 129 130 puthead(s, class) 131 char *s; 132 int class; 133 { 134 char buff[100]; 135 #if TARGET == VAX || TARGET == TAHOE 136 if(s) 137 p2ps("\t.globl\t_%s", s); 138 #endif 139 /* put out fake copy of left bracket line, to be redone later */ 140 if( ! headerdone ) 141 { 142 #if FAMILY == PCC 143 p2flush(); 144 #endif 145 headoffset = ftell(textfile); 146 prhead(textfile); 147 headerdone = YES; 148 p2triple(PCCF_FEXPR, (strlen(infname)+ALILONG-1)/ALILONG, 0); 149 p2str(infname); 150 #if TARGET == PDP11 151 /* fake jump to start the optimizer */ 152 if(class != CLBLOCK) 153 putgoto( fudgelabel = newlabel() ); 154 #endif 155 156 #if TARGET == VAX || TARGET == TAHOE 157 /* jump from top to bottom */ 158 if(s!=CNULL && class!=CLBLOCK) 159 { 160 int proflab = newlabel(); 161 p2pass("\t.align\t1"); 162 p2ps("_%s:", s); 163 p2pi("\t.word\tLWM%d", procno); 164 prsave(proflab); 165 #if TARGET == VAX 166 p2pi("\tjbr\tL%d", 167 #else 168 putgoto( 169 #endif 170 fudgelabel = newlabel()); 171 } 172 #endif 173 } 174 } 175 176 177 178 179 180 /* It is necessary to precede each procedure with a "left bracket" 181 * line that tells pass 2 how many register variables and how 182 * much automatic space is required for the function. This compiler 183 * does not know how much automatic space is needed until the 184 * entire procedure has been processed. Therefore, "puthead" 185 * is called at the begining to record the current location in textfile, 186 * then to put out a placeholder left bracket line. This procedure 187 * repositions the file and rewrites that line, then puts the 188 * file pointer back to the end of the file. 189 */ 190 191 putbracket() 192 { 193 long int hereoffset; 194 195 #if FAMILY == PCC 196 p2flush(); 197 #endif 198 hereoffset = ftell(textfile); 199 if(fseek(textfile, headoffset, 0) == -1) 200 fatal("fseek failed"); 201 prhead(textfile); 202 if(fseek(textfile, hereoffset, 0) == -1) 203 fatal("fseek failed 2"); 204 } 205 206 207 208 209 putrbrack(k) 210 int k; 211 { 212 p2op(PCCF_FRBRAC, k); 213 } 214 215 216 217 putnreg() 218 { 219 } 220 221 222 223 224 225 226 puteof() 227 { 228 p2op(PCCF_FEOF, 0); 229 p2flush(); 230 } 231 232 233 234 putstmt() 235 { 236 p2triple(PCCF_FEXPR, 0, lineno); 237 } 238 239 240 241 242 /* put out code for if( ! p) goto l */ 243 putif(p,l) 244 register expptr p; 245 int l; 246 { 247 register int k; 248 249 if( ( k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL) 250 { 251 if(k != TYERROR) 252 err("non-logical expression in IF statement"); 253 frexpr(p); 254 } 255 else 256 { 257 putex1(p); 258 p2icon( (long int) l , PCCT_INT); 259 p2op(PCC_CBRANCH, 0); 260 putstmt(); 261 } 262 } 263 264 265 266 267 268 /* put out code for goto l */ 269 putgoto(label) 270 int label; 271 { 272 p2triple(PCC_GOTO, 1, label); 273 putstmt(); 274 } 275 276 277 /* branch to address constant or integer variable */ 278 putbranch(p) 279 register Addrp p; 280 { 281 putex1((expptr) p); 282 p2op(PCC_GOTO, PCCT_INT); 283 putstmt(); 284 } 285 286 287 288 /* put out label l: */ 289 putlabel(label) 290 int label; 291 { 292 p2op(PCCF_FLABEL, label); 293 } 294 295 296 297 298 putexpr(p) 299 expptr p; 300 { 301 putex1(p); 302 putstmt(); 303 } 304 305 306 307 308 putcmgo(index, nlab, labs) 309 expptr index; 310 int nlab; 311 struct Labelblock *labs[]; 312 { 313 int i, labarray, skiplabel; 314 315 if(! ISINT(index->headblock.vtype) ) 316 { 317 execerr("computed goto index must be integer", CNULL); 318 return; 319 } 320 321 #if TARGET == VAX || TARGET == TAHOE 322 /* use special case instruction */ 323 casegoto(index, nlab, labs); 324 #else 325 labarray = newlabel(); 326 preven(ALIADDR); 327 prlabel(asmfile, labarray); 328 prcona(asmfile, (ftnint) (skiplabel = newlabel()) ); 329 for(i = 0 ; i < nlab ; ++i) 330 if( labs[i] ) 331 prcona(asmfile, (ftnint)(labs[i]->labelno) ); 332 prcmgoto(index, nlab, skiplabel, labarray); 333 putlabel(skiplabel); 334 #endif 335 } 336 337 putx(p) 338 expptr p; 339 { 340 char *memname(); 341 int opc; 342 int ncomma; 343 int type, k; 344 345 if (!p) 346 return; 347 348 switch(p->tag) 349 { 350 case TERROR: 351 free( (charptr) p ); 352 break; 353 354 case TCONST: 355 switch(type = p->constblock.vtype) 356 { 357 case TYLOGICAL: 358 type = tyint; 359 case TYLONG: 360 case TYSHORT: 361 p2icon(p->constblock.constant.ci, types2[type]); 362 free( (charptr) p ); 363 break; 364 365 case TYADDR: 366 p2triple(PCC_ICON, 1, PCCT_INT|PCCTM_PTR); 367 p2word(0L); 368 p2name(memname(STGCONST, 369 (int) p->constblock.constant.ci) ); 370 free( (charptr) p ); 371 break; 372 373 default: 374 putx( putconst(p) ); 375 break; 376 } 377 break; 378 379 case TEXPR: 380 switch(opc = p->exprblock.opcode) 381 { 382 case OPCALL: 383 case OPCCALL: 384 if( ISCOMPLEX(p->exprblock.vtype) ) 385 putcxop(p); 386 else putcall(p); 387 break; 388 389 case OPMIN: 390 case OPMAX: 391 putmnmx(p); 392 break; 393 394 395 case OPASSIGN: 396 if(ISCOMPLEX(p->exprblock.leftp->headblock.vtype) 397 || ISCOMPLEX(p->exprblock.rightp->headblock.vtype) ) 398 frexpr( putcxeq(p) ); 399 else if( ISCHAR(p) ) 400 putcheq(p); 401 else 402 goto putopp; 403 break; 404 405 case OPEQ: 406 case OPNE: 407 if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) || 408 ISCOMPLEX(p->exprblock.rightp->headblock.vtype) ) 409 { 410 putcxcmp(p); 411 break; 412 } 413 case OPLT: 414 case OPLE: 415 case OPGT: 416 case OPGE: 417 if(ISCHAR(p->exprblock.leftp)) 418 { 419 putchcmp(p); 420 break; 421 } 422 goto putopp; 423 424 case OPPOWER: 425 putpower(p); 426 break; 427 428 case OPSTAR: 429 #if FAMILY == PCC 430 /* m * (2**k) -> m<<k */ 431 if(INT(p->exprblock.leftp->headblock.vtype) && 432 ISICON(p->exprblock.rightp) && 433 ( (k = log2(p->exprblock.rightp->constblock.constant.ci))>0) ) 434 { 435 p->exprblock.opcode = OPLSHIFT; 436 frexpr(p->exprblock.rightp); 437 p->exprblock.rightp = ICON(k); 438 goto putopp; 439 } 440 #endif 441 442 case OPMOD: 443 goto putopp; 444 case OPPLUS: 445 case OPMINUS: 446 case OPSLASH: 447 case OPNEG: 448 if( ISCOMPLEX(p->exprblock.vtype) ) 449 putcxop(p); 450 else goto putopp; 451 break; 452 453 case OPCONV: 454 if( ISCOMPLEX(p->exprblock.vtype) ) 455 putcxop(p); 456 else if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) ) 457 { 458 ncomma = 0; 459 putx( mkconv(p->exprblock.vtype, 460 realpart(putcx1(p->exprblock.leftp, 461 &ncomma)))); 462 putcomma(ncomma, p->exprblock.vtype, NO); 463 free( (charptr) p ); 464 } 465 else goto putopp; 466 break; 467 468 case OPNOT: 469 case OPOR: 470 case OPAND: 471 case OPEQV: 472 case OPNEQV: 473 case OPADDR: 474 case OPPLUSEQ: 475 case OPSTAREQ: 476 case OPCOMMA: 477 case OPQUEST: 478 case OPCOLON: 479 case OPBITOR: 480 case OPBITAND: 481 case OPBITXOR: 482 case OPBITNOT: 483 case OPLSHIFT: 484 case OPRSHIFT: 485 putopp: 486 putop(p); 487 break; 488 489 case OPPAREN: 490 putx (p->exprblock.leftp); 491 break; 492 default: 493 badop("putx", opc); 494 } 495 break; 496 497 case TADDR: 498 putaddr(p, YES); 499 break; 500 501 case TTEMP: 502 /* 503 * This type is sometimes passed to putx when errors occur 504 * upstream, I don't know why. 505 */ 506 frexpr(p); 507 break; 508 509 default: 510 badtag("putx", p->tag); 511 } 512 } 513 514 515 516 LOCAL putop(p) 517 expptr p; 518 { 519 int k; 520 expptr lp, tp; 521 int pt, lt, tt; 522 int comma; 523 Addrp putch1(); 524 525 switch(p->exprblock.opcode) /* check for special cases and rewrite */ 526 { 527 case OPCONV: 528 tt = pt = p->exprblock.vtype; 529 lp = p->exprblock.leftp; 530 lt = lp->headblock.vtype; 531 #if TARGET == VAX 532 if (pt == TYREAL && lt == TYDREAL) 533 { 534 putx(lp); 535 p2op(PCC_SCONV, PCCT_FLOAT); 536 return; 537 } 538 #endif 539 while(p->tag==TEXPR && p->exprblock.opcode==OPCONV && ( 540 #if TARGET != TAHOE 541 (ISREAL(pt)&&ISREAL(lt)) || 542 #endif 543 (INT(pt)&&(ONEOF(lt,MSKINT|MSKADDR|MSKCHAR|M(TYSUBR)))) )) 544 { 545 #if SZINT < SZLONG 546 if(lp->tag != TEXPR) 547 { 548 if(pt==TYINT && lt==TYLONG) 549 break; 550 if(lt==TYINT && pt==TYLONG) 551 break; 552 } 553 #endif 554 555 #if TARGET == VAX 556 if(pt==TYDREAL && lt==TYREAL) 557 { 558 if(lp->tag==TEXPR && 559 lp->exprblock.opcode==OPCONV && 560 lp->exprblock.leftp->headblock.vtype==TYDREAL) 561 { 562 putx(lp->exprblock.leftp); 563 p2op(PCC_SCONV, PCCT_FLOAT); 564 p2op(PCC_SCONV, PCCT_DOUBLE); 565 free( (charptr) p ); 566 return; 567 } 568 else break; 569 } 570 #endif 571 if(lt==TYCHAR && lp->tag==TEXPR) 572 { 573 int ncomma = 0; 574 p->exprblock.leftp = (expptr) putch1(lp, &ncomma); 575 putop(p); 576 putcomma(ncomma, pt, NO); 577 free( (charptr) p ); 578 return; 579 } 580 free( (charptr) p ); 581 p = lp; 582 pt = lt; 583 if (p->tag == TEXPR) 584 { 585 lp = p->exprblock.leftp; 586 lt = lp->headblock.vtype; 587 } 588 } 589 if(p->tag==TEXPR && p->exprblock.opcode==OPCONV) 590 break; 591 putx(p); 592 if (types2[tt] != types2[pt] && 593 ! ( (ISREAL(tt)&&ISREAL(pt)) || 594 (INT(tt)&&(ONEOF(pt,MSKINT|MSKADDR|MSKCHAR|M(TYSUBR)))) )) 595 p2op(PCC_SCONV,types2[tt]); 596 return; 597 598 case OPADDR: 599 comma = NO; 600 lp = p->exprblock.leftp; 601 if(lp->tag != TADDR) 602 { 603 tp = (expptr) mkaltemp 604 (lp->headblock.vtype,lp->headblock.vleng); 605 putx( mkexpr(OPASSIGN, cpexpr(tp), lp) ); 606 lp = tp; 607 comma = YES; 608 } 609 putaddr(lp, NO); 610 if(comma) 611 putcomma(1, TYINT, NO); 612 free( (charptr) p ); 613 return; 614 #if TARGET == VAX || TARGET == TAHOE 615 /* take advantage of a glitch in the code generator that does not check 616 the type clash in an assignment or comparison of an integer zero and 617 a floating left operand, and generates optimal code for the correct 618 type. (The PCC has no floating-constant node to encode this correctly.) 619 */ 620 case OPASSIGN: 621 case OPLT: 622 case OPLE: 623 case OPGT: 624 case OPGE: 625 case OPEQ: 626 case OPNE: 627 if(ISREAL(p->exprblock.leftp->headblock.vtype) && 628 ISREAL(p->exprblock.rightp->headblock.vtype) && 629 ISCONST(p->exprblock.rightp) && 630 p->exprblock.rightp->constblock.constant.cd[0]==0) 631 { 632 p->exprblock.rightp->constblock.vtype = TYINT; 633 p->exprblock.rightp->constblock.constant.ci = 0; 634 } 635 #endif 636 } 637 638 if( (k = ops2[p->exprblock.opcode]) <= 0) 639 badop("putop", p->exprblock.opcode); 640 putx(p->exprblock.leftp); 641 if(p->exprblock.rightp) 642 putx(p->exprblock.rightp); 643 p2op(k, types2[p->exprblock.vtype]); 644 645 if(p->exprblock.vleng) 646 frexpr(p->exprblock.vleng); 647 free( (charptr) p ); 648 } 649 650 putforce(t, p) 651 int t; 652 expptr p; 653 { 654 p = mkconv(t, fixtype(p)); 655 putx(p); 656 p2op(PCC_FORCE, 657 #if TARGET == TAHOE 658 (t==TYLONG ? PCCT_LONG : (t==TYREAL ? PCCT_FLOAT : PCCT_DOUBLE)) ); 659 #else 660 (t==TYSHORT ? PCCT_SHORT : (t==TYLONG ? PCCT_LONG : PCCT_DOUBLE)) ); 661 #endif 662 putstmt(); 663 } 664 665 666 667 LOCAL putpower(p) 668 expptr p; 669 { 670 expptr base; 671 Addrp t1, t2; 672 ftnint k; 673 int type; 674 int ncomma; 675 676 if(!ISICON(p->exprblock.rightp) || 677 (k = p->exprblock.rightp->constblock.constant.ci)<2) 678 fatal("putpower: bad call"); 679 base = p->exprblock.leftp; 680 type = base->headblock.vtype; 681 682 if ((k == 2) && base->tag == TADDR && ISCONST(base->addrblock.memoffset)) 683 { 684 putx( mkexpr(OPSTAR,cpexpr(base),cpexpr(base))); 685 686 return; 687 } 688 t1 = mkaltemp(type, PNULL); 689 t2 = NULL; 690 ncomma = 1; 691 putassign(cpexpr(t1), cpexpr(base) ); 692 693 for( ; (k&1)==0 && k>2 ; k>>=1 ) 694 { 695 ++ncomma; 696 putsteq(t1, t1); 697 } 698 699 if(k == 2) 700 putx( mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) ); 701 else 702 { 703 t2 = mkaltemp(type, PNULL); 704 ++ncomma; 705 putassign(cpexpr(t2), cpexpr(t1)); 706 707 for(k>>=1 ; k>1 ; k>>=1) 708 { 709 ++ncomma; 710 putsteq(t1, t1); 711 if(k & 1) 712 { 713 ++ncomma; 714 putsteq(t2, t1); 715 } 716 } 717 putx( mkexpr(OPSTAR, cpexpr(t2), 718 mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) )); 719 } 720 putcomma(ncomma, type, NO); 721 frexpr(t1); 722 if(t2) 723 frexpr(t2); 724 frexpr(p); 725 } 726 727 728 729 730 LOCAL Addrp intdouble(p, ncommap) 731 Addrp p; 732 int *ncommap; 733 { 734 register Addrp t; 735 736 t = mkaltemp(TYDREAL, PNULL); 737 ++*ncommap; 738 putassign(cpexpr(t), p); 739 return(t); 740 } 741 742 743 744 745 746 LOCAL Addrp putcxeq(p) 747 register expptr p; 748 { 749 register Addrp lp, rp; 750 int ncomma; 751 752 if(p->tag != TEXPR) 753 badtag("putcxeq", p->tag); 754 755 ncomma = 0; 756 lp = putcx1(p->exprblock.leftp, &ncomma); 757 rp = putcx1(p->exprblock.rightp, &ncomma); 758 putassign(realpart(lp), realpart(rp)); 759 if( ISCOMPLEX(p->exprblock.vtype) ) 760 { 761 ++ncomma; 762 putassign(imagpart(lp), imagpart(rp)); 763 } 764 putcomma(ncomma, TYREAL, NO); 765 frexpr(rp); 766 free( (charptr) p ); 767 return(lp); 768 } 769 770 771 772 LOCAL putcxop(p) 773 expptr p; 774 { 775 Addrp putcx1(); 776 int ncomma; 777 778 ncomma = 0; 779 putaddr( putcx1(p, &ncomma), NO); 780 putcomma(ncomma, TYINT, NO); 781 } 782 783 784 785 LOCAL Addrp putcx1(p, ncommap) 786 register expptr p; 787 int *ncommap; 788 { 789 expptr q; 790 Addrp lp, rp; 791 register Addrp resp; 792 int opcode; 793 int ltype, rtype; 794 expptr mkrealcon(); 795 796 if(p == NULL) 797 return(NULL); 798 799 switch(p->tag) 800 { 801 case TCONST: 802 if( ISCOMPLEX(p->constblock.vtype) ) 803 p = (expptr) putconst(p); 804 return( (Addrp) p ); 805 806 case TADDR: 807 if( ! addressable(p) ) 808 { 809 ++*ncommap; 810 resp = mkaltemp(tyint, PNULL); 811 putassign( cpexpr(resp), p->addrblock.memoffset ); 812 p->addrblock.memoffset = (expptr)resp; 813 } 814 return( (Addrp) p ); 815 816 case TEXPR: 817 if( ISCOMPLEX(p->exprblock.vtype) ) 818 break; 819 ++*ncommap; 820 resp = mkaltemp(TYDREAL, NO); 821 putassign( cpexpr(resp), p); 822 return(resp); 823 824 default: 825 badtag("putcx1", p->tag); 826 } 827 828 opcode = p->exprblock.opcode; 829 if(opcode==OPCALL || opcode==OPCCALL) 830 { 831 ++*ncommap; 832 return( putcall(p) ); 833 } 834 else if(opcode == OPASSIGN) 835 { 836 ++*ncommap; 837 return( putcxeq(p) ); 838 } 839 resp = mkaltemp(p->exprblock.vtype, PNULL); 840 if(lp = putcx1(p->exprblock.leftp, ncommap) ) 841 ltype = lp->vtype; 842 if(rp = putcx1(p->exprblock.rightp, ncommap) ) 843 rtype = rp->vtype; 844 845 switch(opcode) 846 { 847 case OPPAREN: 848 frexpr (resp); 849 resp = lp; 850 lp = NULL; 851 break; 852 853 case OPCOMMA: 854 frexpr(resp); 855 resp = rp; 856 rp = NULL; 857 break; 858 859 case OPNEG: 860 putassign( realpart(resp), mkexpr(OPNEG, realpart(lp), ENULL) ); 861 putassign( imagpart(resp), mkexpr(OPNEG, imagpart(lp), ENULL) ); 862 *ncommap += 2; 863 break; 864 865 case OPPLUS: 866 case OPMINUS: 867 putassign( realpart(resp), 868 mkexpr(opcode, realpart(lp), realpart(rp) )); 869 if(rtype < TYCOMPLEX) 870 putassign( imagpart(resp), imagpart(lp) ); 871 else if(ltype < TYCOMPLEX) 872 { 873 if(opcode == OPPLUS) 874 putassign( imagpart(resp), imagpart(rp) ); 875 else putassign( imagpart(resp), 876 mkexpr(OPNEG, imagpart(rp), ENULL) ); 877 } 878 else 879 putassign( imagpart(resp), 880 mkexpr(opcode, imagpart(lp), imagpart(rp) )); 881 882 *ncommap += 2; 883 break; 884 885 case OPSTAR: 886 if(ltype < TYCOMPLEX) 887 { 888 if( ISINT(ltype) ) 889 lp = intdouble(lp, ncommap); 890 putassign( realpart(resp), 891 mkexpr(OPSTAR, cpexpr(lp), realpart(rp) )); 892 putassign( imagpart(resp), 893 mkexpr(OPSTAR, cpexpr(lp), imagpart(rp) )); 894 } 895 else if(rtype < TYCOMPLEX) 896 { 897 if( ISINT(rtype) ) 898 rp = intdouble(rp, ncommap); 899 putassign( realpart(resp), 900 mkexpr(OPSTAR, cpexpr(rp), realpart(lp) )); 901 putassign( imagpart(resp), 902 mkexpr(OPSTAR, cpexpr(rp), imagpart(lp) )); 903 } 904 else { 905 putassign( realpart(resp), mkexpr(OPMINUS, 906 mkexpr(OPSTAR, realpart(lp), realpart(rp)), 907 mkexpr(OPSTAR, imagpart(lp), imagpart(rp)) )); 908 putassign( imagpart(resp), mkexpr(OPPLUS, 909 mkexpr(OPSTAR, realpart(lp), imagpart(rp)), 910 mkexpr(OPSTAR, imagpart(lp), realpart(rp)) )); 911 } 912 *ncommap += 2; 913 break; 914 915 case OPSLASH: 916 /* fixexpr has already replaced all divisions 917 * by a complex by a function call 918 */ 919 if( ISINT(rtype) ) 920 rp = intdouble(rp, ncommap); 921 putassign( realpart(resp), 922 mkexpr(OPSLASH, realpart(lp), cpexpr(rp)) ); 923 putassign( imagpart(resp), 924 mkexpr(OPSLASH, imagpart(lp), cpexpr(rp)) ); 925 *ncommap += 2; 926 break; 927 928 case OPCONV: 929 putassign( realpart(resp), realpart(lp) ); 930 if( ISCOMPLEX(lp->vtype) ) 931 q = imagpart(lp); 932 else if(rp != NULL) 933 q = (expptr) realpart(rp); 934 else 935 q = mkrealcon(TYDREAL, 0.0); 936 putassign( imagpart(resp), q); 937 *ncommap += 2; 938 break; 939 940 default: 941 badop("putcx1", opcode); 942 } 943 944 frexpr(lp); 945 frexpr(rp); 946 free( (charptr) p ); 947 return(resp); 948 } 949 950 951 952 953 LOCAL putcxcmp(p) 954 register expptr p; 955 { 956 int opcode; 957 int ncomma; 958 register Addrp lp, rp; 959 expptr q; 960 961 if(p->tag != TEXPR) 962 badtag("putcxcmp", p->tag); 963 964 ncomma = 0; 965 opcode = p->exprblock.opcode; 966 lp = putcx1(p->exprblock.leftp, &ncomma); 967 rp = putcx1(p->exprblock.rightp, &ncomma); 968 969 q = mkexpr( opcode==OPEQ ? OPAND : OPOR , 970 mkexpr(opcode, realpart(lp), realpart(rp)), 971 mkexpr(opcode, imagpart(lp), imagpart(rp)) ); 972 putx( fixexpr(q) ); 973 putcomma(ncomma, TYINT, NO); 974 975 free( (charptr) lp); 976 free( (charptr) rp); 977 free( (charptr) p ); 978 } 979 980 LOCAL Addrp putch1(p, ncommap) 981 register expptr p; 982 int * ncommap; 983 { 984 register Addrp t; 985 986 switch(p->tag) 987 { 988 case TCONST: 989 return( putconst(p) ); 990 991 case TADDR: 992 return( (Addrp) p ); 993 994 case TEXPR: 995 ++*ncommap; 996 997 switch(p->exprblock.opcode) 998 { 999 expptr q; 1000 1001 case OPCALL: 1002 case OPCCALL: 1003 t = putcall(p); 1004 break; 1005 1006 case OPPAREN: 1007 --*ncommap; 1008 t = putch1(p->exprblock.leftp, ncommap); 1009 break; 1010 1011 case OPCONCAT: 1012 t = mkaltemp(TYCHAR, ICON(lencat(p)) ); 1013 q = (expptr) cpexpr(p->headblock.vleng); 1014 putcat( cpexpr(t), p ); 1015 /* put the correct length on the block */ 1016 frexpr(t->vleng); 1017 t->vleng = q; 1018 1019 break; 1020 1021 case OPCONV: 1022 if(!ISICON(p->exprblock.vleng) 1023 || p->exprblock.vleng->constblock.constant.ci!=1 1024 || ! INT(p->exprblock.leftp->headblock.vtype) ) 1025 fatal("putch1: bad character conversion"); 1026 t = mkaltemp(TYCHAR, ICON(1) ); 1027 putop( mkexpr(OPASSIGN, cpexpr(t), p) ); 1028 break; 1029 default: 1030 badop("putch1", p->exprblock.opcode); 1031 } 1032 return(t); 1033 1034 default: 1035 badtag("putch1", p->tag); 1036 } 1037 /* NOTREACHED */ 1038 } 1039 1040 1041 1042 1043 LOCAL putchop(p) 1044 expptr p; 1045 { 1046 int ncomma; 1047 1048 ncomma = 0; 1049 putaddr( putch1(p, &ncomma) , NO ); 1050 putcomma(ncomma, TYCHAR, YES); 1051 } 1052 1053 1054 1055 1056 LOCAL putcheq(p) 1057 register expptr p; 1058 { 1059 int ncomma; 1060 expptr lp, rp; 1061 1062 if(p->tag != TEXPR) 1063 badtag("putcheq", p->tag); 1064 1065 ncomma = 0; 1066 lp = p->exprblock.leftp; 1067 rp = p->exprblock.rightp; 1068 if( rp->tag==TEXPR && rp->exprblock.opcode==OPCONCAT ) 1069 putcat(lp, rp); 1070 else if( ISONE(lp->headblock.vleng) && ISONE(rp->headblock.vleng) ) 1071 { 1072 putaddr( putch1(lp, &ncomma) , YES ); 1073 putaddr( putch1(rp, &ncomma) , YES ); 1074 putcomma(ncomma, TYINT, NO); 1075 p2op(PCC_ASSIGN, PCCT_CHAR); 1076 } 1077 else 1078 { 1079 putx( call2(TYINT, "s_copy", lp, rp) ); 1080 putcomma(ncomma, TYINT, NO); 1081 } 1082 1083 frexpr(p->exprblock.vleng); 1084 free( (charptr) p ); 1085 } 1086 1087 1088 1089 1090 LOCAL putchcmp(p) 1091 register expptr p; 1092 { 1093 int ncomma; 1094 expptr lp, rp; 1095 1096 if(p->tag != TEXPR) 1097 badtag("putchcmp", p->tag); 1098 1099 ncomma = 0; 1100 lp = p->exprblock.leftp; 1101 rp = p->exprblock.rightp; 1102 1103 if(ISONE(lp->headblock.vleng) && ISONE(rp->headblock.vleng) ) 1104 { 1105 putaddr( putch1(lp, &ncomma) , YES ); 1106 putcomma(ncomma, TYINT, NO); 1107 ncomma = 0; 1108 putaddr( putch1(rp, &ncomma) , YES ); 1109 putcomma(ncomma, TYINT, NO); 1110 p2op(ops2[p->exprblock.opcode], PCCT_CHAR); 1111 free( (charptr) p ); 1112 } 1113 else 1114 { 1115 p->exprblock.leftp = call2(TYINT,"s_cmp", lp, rp); 1116 p->exprblock.rightp = ICON(0); 1117 putop(p); 1118 } 1119 } 1120 1121 1122 1123 1124 1125 LOCAL putcat(lhs, rhs) 1126 register Addrp lhs; 1127 register expptr rhs; 1128 { 1129 int n, ncomma; 1130 Addrp lp, cp; 1131 1132 ncomma = 0; 1133 n = ncat(rhs); 1134 lp = mkaltmpn(n, TYLENG, PNULL); 1135 cp = mkaltmpn(n, TYADDR, PNULL); 1136 1137 n = 0; 1138 putct1(rhs, lp, cp, &n, &ncomma); 1139 1140 putx( call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n)) ) ); 1141 putcomma(ncomma, TYINT, NO); 1142 } 1143 1144 1145 1146 1147 1148 LOCAL putct1(q, lp, cp, ip, ncommap) 1149 register expptr q; 1150 register Addrp lp, cp; 1151 int *ip, *ncommap; 1152 { 1153 int i; 1154 Addrp lp1, cp1; 1155 1156 if(q->tag==TEXPR && q->exprblock.opcode==OPCONCAT) 1157 { 1158 putct1(q->exprblock.leftp, lp, cp, ip, ncommap); 1159 putct1(q->exprblock.rightp, lp, cp , ip, ncommap); 1160 frexpr(q->exprblock.vleng); 1161 free( (charptr) q ); 1162 } 1163 else 1164 { 1165 i = (*ip)++; 1166 lp1 = (Addrp) cpexpr(lp); 1167 lp1->memoffset = mkexpr(OPPLUS,lp1->memoffset, ICON(i*SZLENG)); 1168 cp1 = (Addrp) cpexpr(cp); 1169 cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR)); 1170 putassign( lp1, cpexpr(q->headblock.vleng) ); 1171 putassign( cp1, addrof(putch1(q,ncommap)) ); 1172 *ncommap += 2; 1173 } 1174 } 1175 1176 LOCAL putaddr(p, indir) 1177 register Addrp p; 1178 int indir; 1179 { 1180 int type, type2, funct; 1181 ftnint offset, simoffset(); 1182 expptr offp, shorten(); 1183 1184 if( p->tag==TERROR || (p->memoffset!=NULL && ISERROR(p->memoffset)) ) 1185 { 1186 frexpr(p); 1187 return; 1188 } 1189 if (p->tag != TADDR) badtag ("putaddr",p->tag); 1190 1191 type = p->vtype; 1192 type2 = types2[type]; 1193 funct = (p->vclass==CLPROC ? PCCTM_FTN<<2 : 0); 1194 1195 offp = (p->memoffset ? (expptr) cpexpr(p->memoffset) : (expptr)NULL ); 1196 1197 1198 #if (FUDGEOFFSET != 1) 1199 if(offp) 1200 offp = mkexpr(OPSTAR, ICON(FUDGEOFFSET), offp); 1201 #endif 1202 1203 offset = simoffset( &offp ); 1204 #if SZINT < SZLONG 1205 if(offp) 1206 if(shortsubs) 1207 offp = shorten(offp); 1208 else 1209 offp = mkconv(TYINT, offp); 1210 #else 1211 if(offp) 1212 offp = mkconv(TYINT, offp); 1213 #endif 1214 1215 if (p->vclass == CLVAR 1216 && (p->vstg == STGBSS || p->vstg == STGEQUIV) 1217 && SMALLVAR(p->varsize) 1218 && offset >= -32768 && offset <= 32767) 1219 { 1220 anylocals = YES; 1221 if (indir && !offp) 1222 p2ldisp(offset, memname(p->vstg, p->memno), type2); 1223 else 1224 { 1225 p2reg(LVARREG, type2 | PCCTM_PTR); 1226 p2triple(PCC_ICON, 1, PCCT_INT); 1227 p2word(offset); 1228 p2ndisp(memname(p->vstg, p->memno)); 1229 p2op(PCC_PLUS, type2 | PCCTM_PTR); 1230 if (offp) 1231 { 1232 putx(offp); 1233 p2op(PCC_PLUS, type2 | PCCTM_PTR); 1234 } 1235 if (indir) 1236 p2op(PCC_DEREF, type2); 1237 } 1238 frexpr((tagptr) p); 1239 return; 1240 } 1241 1242 switch(p->vstg) 1243 { 1244 case STGAUTO: 1245 if(indir && !offp) 1246 { 1247 p2oreg(offset, AUTOREG, type2); 1248 break; 1249 } 1250 1251 if(!indir && !offp && !offset) 1252 { 1253 p2reg(AUTOREG, type2 | PCCTM_PTR); 1254 break; 1255 } 1256 1257 p2reg(AUTOREG, type2 | PCCTM_PTR); 1258 if(offp) 1259 { 1260 putx(offp); 1261 if(offset) 1262 p2icon(offset, PCCT_INT); 1263 } 1264 else 1265 p2icon(offset, PCCT_INT); 1266 if(offp && offset) 1267 p2op(PCC_PLUS, type2 | PCCTM_PTR); 1268 p2op(PCC_PLUS, type2 | PCCTM_PTR); 1269 if(indir) 1270 p2op(PCC_DEREF, type2); 1271 break; 1272 1273 case STGARG: 1274 p2oreg( 1275 #ifdef ARGOFFSET 1276 ARGOFFSET + 1277 #endif 1278 (ftnint) (FUDGEOFFSET*p->memno), 1279 ARGREG, type2 | PCCTM_PTR | funct ); 1280 1281 based: 1282 if(offset) 1283 { 1284 p2icon(offset, PCCT_INT); 1285 p2op(PCC_PLUS, type2 | PCCTM_PTR); 1286 } 1287 if(offp) 1288 { 1289 putx(offp); 1290 p2op(PCC_PLUS, type2 | PCCTM_PTR); 1291 } 1292 if(indir) 1293 p2op(PCC_DEREF, type2); 1294 break; 1295 1296 case STGLENG: 1297 if(indir) 1298 { 1299 p2oreg( 1300 #ifdef ARGOFFSET 1301 ARGOFFSET + 1302 #endif 1303 (ftnint) (FUDGEOFFSET*p->memno), 1304 ARGREG, type2 ); 1305 } 1306 else { 1307 p2reg(ARGREG, type2 | PCCTM_PTR ); 1308 p2icon( 1309 #ifdef ARGOFFSET 1310 ARGOFFSET + 1311 #endif 1312 (ftnint) (FUDGEOFFSET*p->memno), PCCT_INT); 1313 p2op(PCC_PLUS, type2 | PCCTM_PTR ); 1314 } 1315 break; 1316 1317 1318 case STGBSS: 1319 case STGINIT: 1320 case STGEXT: 1321 case STGINTR: 1322 case STGCOMMON: 1323 case STGEQUIV: 1324 case STGCONST: 1325 if(offp) 1326 { 1327 putx(offp); 1328 putmem(p, PCC_ICON, offset); 1329 p2op(PCC_PLUS, type2 | PCCTM_PTR); 1330 if(indir) 1331 p2op(PCC_DEREF, type2); 1332 } 1333 else 1334 putmem(p, (indir ? PCC_NAME : PCC_ICON), offset); 1335 1336 break; 1337 1338 case STGREG: 1339 if(indir) 1340 p2reg(p->memno, type2); 1341 else 1342 fatal("attempt to take address of a register"); 1343 break; 1344 1345 case STGPREG: 1346 if(indir && !offp) 1347 p2oreg(offset, p->memno, type2); 1348 else 1349 { 1350 p2reg(p->memno, type2 | PCCTM_PTR); 1351 goto based; 1352 } 1353 break; 1354 1355 default: 1356 badstg("putaddr", p->vstg); 1357 } 1358 frexpr(p); 1359 } 1360 1361 1362 1363 1364 LOCAL putmem(p, class, offset) 1365 expptr p; 1366 int class; 1367 ftnint offset; 1368 { 1369 int type2; 1370 int funct; 1371 char *name, *memname(); 1372 1373 funct = (p->headblock.vclass==CLPROC ? PCCTM_FTN<<2 : 0); 1374 type2 = types2[p->headblock.vtype]; 1375 if(p->headblock.vclass == CLPROC) 1376 type2 |= (PCCTM_FTN<<2); 1377 name = memname(p->addrblock.vstg, p->addrblock.memno); 1378 if(class == PCC_ICON) 1379 { 1380 p2triple(PCC_ICON, name[0]!='\0', type2|PCCTM_PTR); 1381 p2word(offset); 1382 if(name[0]) 1383 p2name(name); 1384 } 1385 else 1386 { 1387 p2triple(PCC_NAME, offset!=0, type2); 1388 if(offset != 0) 1389 p2word(offset); 1390 p2name(name); 1391 } 1392 } 1393 1394 1395 1396 LOCAL Addrp putcall(p) 1397 register Exprp p; 1398 { 1399 chainp arglist, charsp, cp; 1400 int n, first; 1401 Addrp t; 1402 register expptr q; 1403 Addrp fval, mkargtemp(); 1404 int type, type2, ctype, qtype, indir; 1405 1406 type2 = types2[type = p->vtype]; 1407 charsp = NULL; 1408 indir = (p->opcode == OPCCALL); 1409 n = 0; 1410 first = YES; 1411 1412 if(p->rightp) 1413 { 1414 arglist = p->rightp->listblock.listp; 1415 free( (charptr) (p->rightp) ); 1416 } 1417 else 1418 arglist = NULL; 1419 1420 for(cp = arglist ; cp ; cp = cp->nextp) 1421 { 1422 q = (expptr) cp->datap; 1423 if(indir) 1424 ++n; 1425 else { 1426 q = (expptr) (cp->datap); 1427 if( ISCONST(q) ) 1428 { 1429 q = (expptr) putconst(q); 1430 cp->datap = (tagptr) q; 1431 } 1432 if( ISCHAR(q) && q->headblock.vclass!=CLPROC ) 1433 { 1434 charsp = hookup(charsp, 1435 mkchain(cpexpr(q->headblock.vleng), 1436 CHNULL)); 1437 n += 2; 1438 } 1439 else 1440 n += 1; 1441 } 1442 } 1443 1444 if(type == TYCHAR) 1445 { 1446 if( ISICON(p->vleng) ) 1447 { 1448 fval = mkargtemp(TYCHAR, p->vleng); 1449 n += 2; 1450 } 1451 else { 1452 err("adjustable character function"); 1453 return; 1454 } 1455 } 1456 else if( ISCOMPLEX(type) ) 1457 { 1458 fval = mkargtemp(type, PNULL); 1459 n += 1; 1460 } 1461 else 1462 fval = NULL; 1463 1464 ctype = (fval ? PCCT_INT : type2); 1465 putaddr(p->leftp, NO); 1466 1467 if(fval) 1468 { 1469 first = NO; 1470 putaddr( cpexpr(fval), NO); 1471 if(type==TYCHAR) 1472 { 1473 putx( mkconv(TYLENG,p->vleng) ); 1474 p2op(PCC_CM, type2); 1475 } 1476 } 1477 1478 for(cp = arglist ; cp ; cp = cp->nextp) 1479 { 1480 q = (expptr) (cp->datap); 1481 if(q->tag==TADDR && (indir || q->addrblock.vstg!=STGREG) ) 1482 putaddr(q, indir && q->addrblock.vtype!=TYCHAR); 1483 else if( ISCOMPLEX(q->headblock.vtype) ) 1484 putcxop(q); 1485 else if (ISCHAR(q) ) 1486 putchop(q); 1487 else if( ! ISERROR(q) ) 1488 { 1489 if(indir) 1490 putx(q); 1491 else { 1492 t = mkargtemp(qtype = q->headblock.vtype, 1493 q->headblock.vleng); 1494 putassign( cpexpr(t), q ); 1495 putaddr(t, NO); 1496 putcomma(1, qtype, YES); 1497 } 1498 } 1499 if(first) 1500 first = NO; 1501 else 1502 p2op(PCC_CM, type2); 1503 } 1504 1505 if(arglist) 1506 frchain(&arglist); 1507 for(cp = charsp ; cp ; cp = cp->nextp) 1508 { 1509 putx( mkconv(TYLENG,cp->datap) ); 1510 p2op(PCC_CM, type2); 1511 } 1512 frchain(&charsp); 1513 #if TARGET == TAHOE 1514 if(indir && ctype==PCCT_FLOAT) /* function opcodes */ 1515 p2op(PCC_FORTCALL, ctype); 1516 else 1517 #endif 1518 p2op(n>0 ? PCC_CALL : PCC_UCALL , ctype); 1519 free( (charptr) p ); 1520 return(fval); 1521 } 1522 1523 1524 1525 LOCAL putmnmx(p) 1526 register expptr p; 1527 { 1528 int op, type; 1529 int ncomma; 1530 expptr qp; 1531 chainp p0, p1; 1532 Addrp sp, tp; 1533 1534 if(p->tag != TEXPR) 1535 badtag("putmnmx", p->tag); 1536 1537 type = p->exprblock.vtype; 1538 op = (p->exprblock.opcode==OPMIN ? OPLT : OPGT ); 1539 p0 = p->exprblock.leftp->listblock.listp; 1540 free( (charptr) (p->exprblock.leftp) ); 1541 free( (charptr) p ); 1542 1543 sp = mkaltemp(type, PNULL); 1544 tp = mkaltemp(type, PNULL); 1545 qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp)); 1546 qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp); 1547 qp = fixexpr(qp); 1548 1549 ncomma = 1; 1550 putassign( cpexpr(sp), p0->datap ); 1551 1552 for(p1 = p0->nextp ; p1 ; p1 = p1->nextp) 1553 { 1554 ++ncomma; 1555 putassign( cpexpr(tp), p1->datap ); 1556 if(p1->nextp) 1557 { 1558 ++ncomma; 1559 putassign( cpexpr(sp), cpexpr(qp) ); 1560 } 1561 else 1562 putx(qp); 1563 } 1564 1565 putcomma(ncomma, type, NO); 1566 frexpr(sp); 1567 frexpr(tp); 1568 frchain( &p0 ); 1569 } 1570 1571 1572 1573 1574 LOCAL putcomma(n, type, indir) 1575 int n, type, indir; 1576 { 1577 type = types2[type]; 1578 if(indir) 1579 type |= PCCTM_PTR; 1580 while(--n >= 0) 1581 p2op(PCC_COMOP, type); 1582 } 1583 1584 1585 1586 1587 ftnint simoffset(p0) 1588 expptr *p0; 1589 { 1590 ftnint offset, prod; 1591 register expptr p, lp, rp; 1592 1593 offset = 0; 1594 p = *p0; 1595 if(p == NULL) 1596 return(0); 1597 1598 if( ! ISINT(p->headblock.vtype) ) 1599 return(0); 1600 1601 if(p->tag==TEXPR && p->exprblock.opcode==OPSTAR) 1602 { 1603 lp = p->exprblock.leftp; 1604 rp = p->exprblock.rightp; 1605 if(ISICON(rp) && lp->tag==TEXPR && 1606 lp->exprblock.opcode==OPPLUS && ISICON(lp->exprblock.rightp)) 1607 { 1608 p->exprblock.opcode = OPPLUS; 1609 lp->exprblock.opcode = OPSTAR; 1610 prod = rp->constblock.constant.ci * 1611 lp->exprblock.rightp->constblock.constant.ci; 1612 lp->exprblock.rightp->constblock.constant.ci = rp->constblock.constant.ci; 1613 rp->constblock.constant.ci = prod; 1614 } 1615 } 1616 1617 if(p->tag==TEXPR && p->exprblock.opcode==OPPLUS && 1618 ISICON(p->exprblock.rightp)) 1619 { 1620 rp = p->exprblock.rightp; 1621 lp = p->exprblock.leftp; 1622 offset += rp->constblock.constant.ci; 1623 frexpr(rp); 1624 free( (charptr) p ); 1625 *p0 = lp; 1626 } 1627 1628 if( ISCONST(p) ) 1629 { 1630 offset += p->constblock.constant.ci; 1631 frexpr(p); 1632 *p0 = NULL; 1633 } 1634 1635 return(offset); 1636 } 1637 1638 1639 1640 1641 1642 p2op(op, type) 1643 int op, type; 1644 { 1645 p2triple(op, 0, type); 1646 } 1647 1648 p2icon(offset, type) 1649 ftnint offset; 1650 int type; 1651 { 1652 p2triple(PCC_ICON, 0, type); 1653 p2word(offset); 1654 } 1655 1656 1657 1658 1659 p2oreg(offset, reg, type) 1660 ftnint offset; 1661 int reg, type; 1662 { 1663 p2triple(PCC_OREG, reg, type); 1664 p2word(offset); 1665 p2name(""); 1666 } 1667 1668 1669 1670 1671 p2reg(reg, type) 1672 int reg, type; 1673 { 1674 p2triple(PCC_REG, reg, type); 1675 } 1676 1677 1678 1679 p2pi(s, i) 1680 char *s; 1681 int i; 1682 { 1683 char buff[100]; 1684 sprintf(buff, s, i); 1685 p2pass(buff); 1686 } 1687 1688 1689 1690 p2pij(s, i, j) 1691 char *s; 1692 int i, j; 1693 { 1694 char buff[100]; 1695 sprintf(buff, s, i, j); 1696 p2pass(buff); 1697 } 1698 1699 1700 1701 1702 p2ps(s, t) 1703 char *s, *t; 1704 { 1705 char buff[100]; 1706 sprintf(buff, s, t); 1707 p2pass(buff); 1708 } 1709 1710 1711 1712 1713 p2pass(s) 1714 char *s; 1715 { 1716 p2triple(PCCF_FTEXT, (strlen(s) + ALILONG-1)/ALILONG, 0); 1717 p2str(s); 1718 } 1719 1720 1721 1722 1723 p2str(s) 1724 register char *s; 1725 { 1726 union { long int word; char str[SZLONG]; } u; 1727 register int i; 1728 1729 i = 0; 1730 u.word = 0; 1731 while(*s) 1732 { 1733 u.str[i++] = *s++; 1734 if(i == SZLONG) 1735 { 1736 p2word(u.word); 1737 u.word = 0; 1738 i = 0; 1739 } 1740 } 1741 if(i > 0) 1742 p2word(u.word); 1743 } 1744 1745 1746 1747 1748 p2triple(op, var, type) 1749 int op, var, type; 1750 { 1751 register long word; 1752 word = PCCM_TRIPLE(op, var, type); 1753 p2word(word); 1754 } 1755 1756 1757 1758 1759 1760 p2name(s) 1761 register char *s; 1762 { 1763 register int i; 1764 1765 #ifdef UCBPASS2 1766 /* arbitrary length names, terminated by a null, 1767 padded to a full word */ 1768 1769 # define WL sizeof(long int) 1770 union { long int word; char str[WL]; } w; 1771 1772 w.word = 0; 1773 i = 0; 1774 while(w.str[i++] = *s++) 1775 if(i == WL) 1776 { 1777 p2word(w.word); 1778 w.word = 0; 1779 i = 0; 1780 } 1781 if(i > 0) 1782 p2word(w.word); 1783 #else 1784 /* standard intermediate, names are 8 characters long */ 1785 1786 union { long int word[2]; char str[8]; } u; 1787 1788 u.word[0] = u.word[1] = 0; 1789 for(i = 0 ; i<8 && *s ; ++i) 1790 u.str[i] = *s++; 1791 p2word(u.word[0]); 1792 p2word(u.word[1]); 1793 1794 #endif 1795 1796 } 1797 1798 1799 1800 1801 p2word(w) 1802 long int w; 1803 { 1804 *p2bufp++ = w; 1805 if(p2bufp >= p2bufend) 1806 p2flush(); 1807 } 1808 1809 1810 1811 p2flush() 1812 { 1813 if(p2bufp > p2buff) 1814 write(fileno(textfile), p2buff, (p2bufp-p2buff)*sizeof(long int)); 1815 p2bufp = p2buff; 1816 } 1817 1818 1819 1820 LOCAL 1821 p2ldisp(offset, vname, type) 1822 ftnint offset; 1823 char *vname; 1824 int type; 1825 { 1826 char buff[100]; 1827 1828 sprintf(buff, "%s-v.%d", vname, bsslabel); 1829 p2triple(PCC_OREG, LVARREG, type); 1830 p2word(offset); 1831 p2name(buff); 1832 } 1833 1834 1835 1836 p2ndisp(vname) 1837 char *vname; 1838 { 1839 char buff[100]; 1840 1841 sprintf(buff, "%s-v.%d", vname, bsslabel); 1842 p2name(buff); 1843 } 1844