Annotation of cci/usr/src/usr.bin/f77/f77pass1/putpcc.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.