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