140230Sdonn /* 240230Sdonn * Copyright (c) 1980 Regents of the University of California. 340230Sdonn * All rights reserved. The Berkeley software License Agreement 440230Sdonn * specifies the terms and conditions for redistribution. 540230Sdonn */ 640230Sdonn 740230Sdonn #ifndef lint 840230Sdonn static char *sccsid[] = "@(#)expr.c 5.3 (Berkeley) 6/23/85"; 940230Sdonn #endif not lint 1040230Sdonn 1140230Sdonn /* 1240230Sdonn * expr.c 1340230Sdonn * 1440230Sdonn * Routines for handling expressions, f77 compiler pass 1. 1540230Sdonn * 1640230Sdonn * University of Utah CS Dept modification history: 1740230Sdonn * 1840230Sdonn * $Log: expr.c,v $ 1940230Sdonn * Revision 1.3 86/02/26 17:13:37 rcs 2040230Sdonn * Correct COFR 411. 2140230Sdonn * P. Wong 2240230Sdonn * 2340230Sdonn * Revision 3.16 85/06/21 16:38:09 donn 2440230Sdonn * The fix to mkprim() didn't handle null substring parameters (sigh). 2540230Sdonn * 2640230Sdonn * Revision 3.15 85/06/04 04:37:03 donn 2740230Sdonn * Changed mkprim() to force substring parameters to be integral types. 2840230Sdonn * 2940230Sdonn * Revision 3.14 85/06/04 03:41:52 donn 3040230Sdonn * Change impldcl() to handle functions of type 'undefined'. 3140230Sdonn * 3240230Sdonn * Revision 3.13 85/05/06 23:14:55 donn 3340230Sdonn * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get 3440230Sdonn * a temporary when converting character strings to integers; previously we 3540230Sdonn * were having problems because mkconv() was called after tempalloc(). 3640230Sdonn * 3740230Sdonn * Revision 3.12 85/03/18 08:07:47 donn 3840230Sdonn * Fixes to help out with short integers -- if integers are by default short, 3940230Sdonn * then so are constants; and if addresses can't be stored in shorts, complain. 4040230Sdonn * 4140230Sdonn * Revision 3.11 85/03/16 22:31:27 donn 4240230Sdonn * Added hack to mkconv() to allow character values of length > 1 to be 4340230Sdonn * converted to numeric types, for Helge Skrivervik. Note that this does 4440230Sdonn * not affect use of the intrinsic ichar() conversion. 4540230Sdonn * 4640230Sdonn * Revision 3.10 85/01/15 21:06:47 donn 4740230Sdonn * Changed mkconv() to comment on implicit conversions; added intrconv() for 4840230Sdonn * use with explicit conversions by intrinsic functions. 4940230Sdonn * 5040230Sdonn * Revision 3.9 85/01/11 21:05:49 donn 5140230Sdonn * Added changes to implement SAVE statements. 5240230Sdonn * 5340230Sdonn * Revision 3.8 84/12/17 02:21:06 donn 5440230Sdonn * Added a test to prevent constant folding from being done on expressions 5540230Sdonn * whose type is not known at that point in mkexpr(). 5640230Sdonn * 5740230Sdonn * Revision 3.7 84/12/11 21:14:17 donn 5840230Sdonn * Removed obnoxious 'excess precision' warning. 5940230Sdonn * 6040230Sdonn * Revision 3.6 84/11/23 01:00:36 donn 6140230Sdonn * Added code to trim excess precision from single-precision constants, and 6240230Sdonn * to warn the user when this occurs. 6340230Sdonn * 6440230Sdonn * Revision 3.5 84/11/23 00:10:39 donn 6540230Sdonn * Changed stfcall() to remark on argument type clashes in 'calls' to 6640230Sdonn * statement functions. 6740230Sdonn * 6840230Sdonn * Revision 3.4 84/11/22 21:21:17 donn 6940230Sdonn * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics. 7040230Sdonn * 7140230Sdonn * Revision 3.3 84/11/12 18:26:14 donn 7240230Sdonn * Shuffled some code around so that the compiler remembers to free some vleng 7340230Sdonn * structures which used to just sit around. 7440230Sdonn * 7540230Sdonn * Revision 3.2 84/10/16 19:24:15 donn 7640230Sdonn * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent 7740230Sdonn * core dumps by replacing bad subscripts with good ones. 7840230Sdonn * 7940230Sdonn * Revision 3.1 84/10/13 01:31:32 donn 8040230Sdonn * Merged Jerry Berkman's version into mine. 8140230Sdonn * 8240230Sdonn * Revision 2.7 84/09/27 15:42:52 donn 8340230Sdonn * The last fix for multiplying undeclared variables by 0 isn't sufficient, 8440230Sdonn * since the type of the 0 may not be the (implicit) type of the variable. 8540230Sdonn * I added a hack to check the implicit type of implicitly declared 8640230Sdonn * variables... 8740230Sdonn * 8840230Sdonn * Revision 2.6 84/09/14 19:34:03 donn 8940230Sdonn * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert 9040230Sdonn * 0 to type UNKNOWN, which is illegal. Fix is to use native type instead. 9140230Sdonn * Not sure how correct (or important) this is... 9240230Sdonn * 9340230Sdonn * Revision 2.5 84/08/05 23:05:27 donn 9440230Sdonn * Added fixes to prevent fixexpr() from slicing and dicing complex conversions 9540230Sdonn * with two operands. 9640230Sdonn * 9740230Sdonn * Revision 2.4 84/08/05 17:34:48 donn 9840230Sdonn * Added an optimization to mklhs() to detect substrings of the form ch(i:i) 9940230Sdonn * and assign constant length 1 to them. 10040230Sdonn * 10140230Sdonn * Revision 2.3 84/07/19 19:38:33 donn 10240230Sdonn * Added a typecast to the last fix. Somehow I missed it the first time... 10340230Sdonn * 10440230Sdonn * Revision 2.2 84/07/19 17:19:57 donn 10540230Sdonn * Caused OPPAREN expressions to inherit the length of their operands, so 10640230Sdonn * that parenthesized character expressions work correctly. 10740230Sdonn * 10840230Sdonn * Revision 2.1 84/07/19 12:03:02 donn 10940230Sdonn * Changed comment headers for UofU. 11040230Sdonn * 11140230Sdonn * Revision 1.2 84/04/06 20:12:17 donn 11240230Sdonn * Fixed bug which caused programs with mixed-type multiplications involving 11340230Sdonn * the constant 0 to choke the compiler. 11440230Sdonn * 11540230Sdonn */ 11640230Sdonn 11740230Sdonn #include "defs.h" 11840230Sdonn 11940230Sdonn 12040230Sdonn /* little routines to create constant blocks */ 12140230Sdonn 12240230Sdonn Constp mkconst(t) 12340230Sdonn register int t; 12440230Sdonn { 12540230Sdonn register Constp p; 12640230Sdonn 12740230Sdonn p = ALLOC(Constblock); 12840230Sdonn p->tag = TCONST; 12940230Sdonn p->vtype = t; 13040230Sdonn return(p); 13140230Sdonn } 13240230Sdonn 13340230Sdonn 13440230Sdonn expptr mklogcon(l) 13540230Sdonn register int l; 13640230Sdonn { 13740230Sdonn register Constp p; 13840230Sdonn 13940230Sdonn p = mkconst(TYLOGICAL); 14040230Sdonn p->const.ci = l; 14140230Sdonn return( (expptr) p ); 14240230Sdonn } 14340230Sdonn 14440230Sdonn 14540230Sdonn 14640230Sdonn expptr mkintcon(l) 14740230Sdonn ftnint l; 14840230Sdonn { 14940230Sdonn register Constp p; 15040230Sdonn int usetype; 15140230Sdonn 15240230Sdonn if(tyint == TYSHORT) 15340230Sdonn { 15440230Sdonn short s = l; 15540230Sdonn if(l != s) 15640230Sdonn usetype = TYLONG; 15740230Sdonn else 15840230Sdonn usetype = TYSHORT; 15940230Sdonn } 16040230Sdonn else 16140230Sdonn usetype = tyint; 16240230Sdonn p = mkconst(usetype); 16340230Sdonn p->const.ci = l; 16440230Sdonn return( (expptr) p ); 16540230Sdonn } 16640230Sdonn 16740230Sdonn 16840230Sdonn 16940230Sdonn expptr mkaddcon(l) 17040230Sdonn register int l; 17140230Sdonn { 17240230Sdonn register Constp p; 17340230Sdonn 17440230Sdonn p = mkconst(TYADDR); 17540230Sdonn p->const.ci = l; 17640230Sdonn return( (expptr) p ); 17740230Sdonn } 17840230Sdonn 17940230Sdonn 18040230Sdonn 18140230Sdonn expptr mkrealcon(t, d) 18240230Sdonn register int t; 18340230Sdonn double d; 18440230Sdonn { 18540230Sdonn register Constp p; 18640230Sdonn 18740230Sdonn p = mkconst(t); 18840230Sdonn p->const.cd[0] = d; 18940230Sdonn return( (expptr) p ); 19040230Sdonn } 19140230Sdonn 19240230Sdonn expptr mkbitcon(shift, leng, s) 19340230Sdonn int shift; 19440230Sdonn register int leng; 19540230Sdonn register char *s; 19640230Sdonn { 19740230Sdonn Constp p; 19840230Sdonn register int i, j, k; 19940230Sdonn register char *bp; 20040230Sdonn int size; 20140230Sdonn 20240230Sdonn size = (shift*leng + BYTESIZE -1)/BYTESIZE; 20340230Sdonn bp = (char *) ckalloc(size); 20440230Sdonn 20540230Sdonn i = 0; 20640230Sdonn 20740230Sdonn #if (HERE == PDP11 || HERE == VAX) 20840230Sdonn j = 0; 20940230Sdonn #else 21040230Sdonn j = size; 21140230Sdonn #endif 21240230Sdonn 21340230Sdonn k = 0; 21440230Sdonn 21540230Sdonn while (leng > 0) 21640230Sdonn { 21740230Sdonn k |= (hextoi(s[--leng]) << i); 21840230Sdonn i += shift; 21940230Sdonn if (i >= BYTESIZE) 22040230Sdonn { 22140230Sdonn #if (HERE == PDP11 || HERE == VAX) 22240230Sdonn bp[j++] = k & MAXBYTE; 22340230Sdonn #else 22440230Sdonn bp[--j] = k & MAXBYTE; 22540230Sdonn #endif 22640230Sdonn k = k >> BYTESIZE; 22740230Sdonn i -= BYTESIZE; 22840230Sdonn } 22940230Sdonn } 23040230Sdonn 23140230Sdonn if (k != 0) 23240230Sdonn #if (HERE == PDP11 || HERE == VAX) 23340230Sdonn bp[j++] = k; 23440230Sdonn #else 23540230Sdonn bp[--j] = k; 23640230Sdonn #endif 23740230Sdonn 23840230Sdonn p = mkconst(TYBITSTR); 23940230Sdonn p->vleng = ICON(size); 24040230Sdonn p->const.ccp = bp; 24140230Sdonn 24240230Sdonn return ((expptr) p); 24340230Sdonn } 24440230Sdonn 24540230Sdonn 24640230Sdonn 24740230Sdonn expptr mkstrcon(l,v) 24840230Sdonn int l; 24940230Sdonn register char *v; 25040230Sdonn { 25140230Sdonn register Constp p; 25240230Sdonn register char *s; 25340230Sdonn 25440230Sdonn p = mkconst(TYCHAR); 25540230Sdonn p->vleng = ICON(l); 25640230Sdonn p->const.ccp = s = (char *) ckalloc(l); 25740230Sdonn while(--l >= 0) 25840230Sdonn *s++ = *v++; 25940230Sdonn return( (expptr) p ); 26040230Sdonn } 26140230Sdonn 26240230Sdonn 26340230Sdonn expptr mkcxcon(realp,imagp) 26440230Sdonn register expptr realp, imagp; 26540230Sdonn { 26640230Sdonn int rtype, itype; 26740230Sdonn register Constp p; 26840230Sdonn 26940230Sdonn rtype = realp->headblock.vtype; 27040230Sdonn itype = imagp->headblock.vtype; 27140230Sdonn 27240230Sdonn if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) ) 27340230Sdonn { 27440230Sdonn p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX); 27540230Sdonn if( ISINT(rtype) ) 27640230Sdonn p->const.cd[0] = realp->constblock.const.ci; 27740230Sdonn else p->const.cd[0] = realp->constblock.const.cd[0]; 27840230Sdonn if( ISINT(itype) ) 27940230Sdonn p->const.cd[1] = imagp->constblock.const.ci; 28040230Sdonn else p->const.cd[1] = imagp->constblock.const.cd[0]; 28140230Sdonn } 28240230Sdonn else 28340230Sdonn { 28440230Sdonn err("invalid complex constant"); 28540230Sdonn p = (Constp) errnode(); 28640230Sdonn } 28740230Sdonn 28840230Sdonn frexpr(realp); 28940230Sdonn frexpr(imagp); 29040230Sdonn return( (expptr) p ); 29140230Sdonn } 29240230Sdonn 29340230Sdonn 29440230Sdonn expptr errnode() 29540230Sdonn { 29640230Sdonn struct Errorblock *p; 29740230Sdonn p = ALLOC(Errorblock); 29840230Sdonn p->tag = TERROR; 29940230Sdonn p->vtype = TYERROR; 30040230Sdonn return( (expptr) p ); 30140230Sdonn } 30240230Sdonn 30340230Sdonn 30440230Sdonn 30540230Sdonn 30640230Sdonn 30740230Sdonn expptr mkconv(t, p) 30840230Sdonn register int t; 30940230Sdonn register expptr p; 31040230Sdonn { 31140230Sdonn register expptr q; 31240230Sdonn Addrp r, s; 31340230Sdonn register int pt; 31440230Sdonn expptr opconv(); 31540230Sdonn 31640230Sdonn if(t==TYUNKNOWN || t==TYERROR) 31740230Sdonn badtype("mkconv", t); 31840230Sdonn pt = p->headblock.vtype; 31940230Sdonn if(t == pt) 32040230Sdonn return(p); 32140230Sdonn 32240230Sdonn if( pt == TYCHAR && ISNUMERIC(t) ) 32340230Sdonn { 32440230Sdonn warn("implicit conversion of character to numeric type"); 32540230Sdonn 32640230Sdonn /* 32740230Sdonn * Ugly kluge to copy character values into numerics. 32840230Sdonn */ 32940230Sdonn s = mkaltemp(t, ENULL); 33040230Sdonn r = (Addrp) cpexpr(s); 33140230Sdonn r->vtype = TYCHAR; 33240230Sdonn r->varleng = typesize[t]; 33340230Sdonn r->vleng = mkintcon(r->varleng); 33440230Sdonn q = mkexpr(OPASSIGN, r, p); 33540230Sdonn q = mkexpr(OPCOMMA, q, s); 33640230Sdonn return(q); 33740230Sdonn } 33840230Sdonn 33940230Sdonn #if SZADDR > SZSHORT 34040230Sdonn if( pt == TYADDR && t == TYSHORT) 34140230Sdonn { 34240230Sdonn err("insufficient precision to hold address type"); 34340230Sdonn return( errnode() ); 34440230Sdonn } 34540230Sdonn #endif 34640230Sdonn if( pt == TYADDR && ISNUMERIC(t) ) 34740230Sdonn warn("implicit conversion of address to numeric type"); 34840230Sdonn 34940230Sdonn if( ISCONST(p) && pt!=TYADDR) 35040230Sdonn { 35140230Sdonn q = (expptr) mkconst(t); 35240230Sdonn consconv(t, &(q->constblock.const), 35340230Sdonn p->constblock.vtype, &(p->constblock.const) ); 35440230Sdonn frexpr(p); 35540230Sdonn } 35640230Sdonn #if TARGET == PDP11 35740230Sdonn else if(ISINT(t) && pt==TYCHAR) 35840230Sdonn { 35940230Sdonn q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255)); 36040230Sdonn if(t == TYLONG) 36140230Sdonn q = opconv(q, TYLONG); 36240230Sdonn } 36340230Sdonn #endif 36440230Sdonn else 36540230Sdonn q = opconv(p, t); 36640230Sdonn 36740230Sdonn if(t == TYCHAR) 36840230Sdonn q->constblock.vleng = ICON(1); 36940230Sdonn return(q); 37040230Sdonn } 37140230Sdonn 37240230Sdonn 37340230Sdonn 37440230Sdonn /* intrinsic conversions */ 37540230Sdonn expptr intrconv(t, p) 37640230Sdonn register int t; 37740230Sdonn register expptr p; 37840230Sdonn { 37940230Sdonn register expptr q; 38040230Sdonn register int pt; 38140230Sdonn expptr opconv(); 38240230Sdonn 38340230Sdonn if(t==TYUNKNOWN || t==TYERROR) 38440230Sdonn badtype("intrconv", t); 38540230Sdonn pt = p->headblock.vtype; 38640230Sdonn if(t == pt) 38740230Sdonn return(p); 38840230Sdonn 38940230Sdonn else if( ISCONST(p) && pt!=TYADDR) 39040230Sdonn { 39140230Sdonn q = (expptr) mkconst(t); 39240230Sdonn consconv(t, &(q->constblock.const), 39340230Sdonn p->constblock.vtype, &(p->constblock.const) ); 39440230Sdonn frexpr(p); 39540230Sdonn } 39640230Sdonn #if TARGET == PDP11 39740230Sdonn else if(ISINT(t) && pt==TYCHAR) 39840230Sdonn { 39940230Sdonn q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255)); 40040230Sdonn if(t == TYLONG) 40140230Sdonn q = opconv(q, TYLONG); 40240230Sdonn } 40340230Sdonn #endif 40440230Sdonn else 40540230Sdonn q = opconv(p, t); 40640230Sdonn 40740230Sdonn if(t == TYCHAR) 40840230Sdonn q->constblock.vleng = ICON(1); 40940230Sdonn return(q); 41040230Sdonn } 41140230Sdonn 41240230Sdonn 41340230Sdonn 41440230Sdonn expptr opconv(p, t) 41540230Sdonn expptr p; 41640230Sdonn int t; 41740230Sdonn { 41840230Sdonn register expptr q; 41940230Sdonn 42040230Sdonn q = mkexpr(OPCONV, p, PNULL); 42140230Sdonn q->headblock.vtype = t; 42240230Sdonn return(q); 42340230Sdonn } 42440230Sdonn 42540230Sdonn 42640230Sdonn 42740230Sdonn expptr addrof(p) 42840230Sdonn expptr p; 42940230Sdonn { 43040230Sdonn return( mkexpr(OPADDR, p, PNULL) ); 43140230Sdonn } 43240230Sdonn 43340230Sdonn 43440230Sdonn 43540230Sdonn tagptr cpexpr(p) 43640230Sdonn register tagptr p; 43740230Sdonn { 43840230Sdonn register tagptr e; 43940230Sdonn int tag; 44040230Sdonn register chainp ep, pp; 44140230Sdonn tagptr cpblock(); 44240230Sdonn 44340230Sdonn static int blksize[ ] = 44440230Sdonn { 0, 44540230Sdonn sizeof(struct Nameblock), 44640230Sdonn sizeof(struct Constblock), 44740230Sdonn sizeof(struct Exprblock), 44840230Sdonn sizeof(struct Addrblock), 44940230Sdonn sizeof(struct Tempblock), 45040230Sdonn sizeof(struct Primblock), 45140230Sdonn sizeof(struct Listblock), 45240230Sdonn sizeof(struct Errorblock) 45340230Sdonn }; 45440230Sdonn 45540230Sdonn if(p == NULL) 45640230Sdonn return(NULL); 45740230Sdonn 45840230Sdonn if( (tag = p->tag) == TNAME) 45940230Sdonn return(p); 46040230Sdonn 46140230Sdonn e = cpblock( blksize[p->tag] , p); 46240230Sdonn 46340230Sdonn switch(tag) 46440230Sdonn { 46540230Sdonn case TCONST: 46640230Sdonn if(e->constblock.vtype == TYCHAR) 46740230Sdonn { 46840230Sdonn e->constblock.const.ccp = 46940230Sdonn copyn(1+strlen(e->constblock.const.ccp), 47040230Sdonn e->constblock.const.ccp); 47140230Sdonn e->constblock.vleng = 47240230Sdonn (expptr) cpexpr(e->constblock.vleng); 47340230Sdonn } 47440230Sdonn case TERROR: 47540230Sdonn break; 47640230Sdonn 47740230Sdonn case TEXPR: 47840230Sdonn e->exprblock.leftp = (expptr) cpexpr(p->exprblock.leftp); 47940230Sdonn e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp); 48040230Sdonn break; 48140230Sdonn 48240230Sdonn case TLIST: 48340230Sdonn if(pp = p->listblock.listp) 48440230Sdonn { 48540230Sdonn ep = e->listblock.listp = 48640230Sdonn mkchain( cpexpr(pp->datap), CHNULL); 48740230Sdonn for(pp = pp->nextp ; pp ; pp = pp->nextp) 48840230Sdonn ep = ep->nextp = 48940230Sdonn mkchain( cpexpr(pp->datap), CHNULL); 49040230Sdonn } 49140230Sdonn break; 49240230Sdonn 49340230Sdonn case TADDR: 49440230Sdonn e->addrblock.vleng = (expptr) cpexpr(e->addrblock.vleng); 49540230Sdonn e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset); 49640230Sdonn e->addrblock.istemp = NO; 49740230Sdonn break; 49840230Sdonn 49940230Sdonn case TTEMP: 50040230Sdonn e->tempblock.vleng = (expptr) cpexpr(e->tempblock.vleng); 50140230Sdonn e->tempblock.istemp = NO; 50240230Sdonn break; 50340230Sdonn 50440230Sdonn case TPRIM: 50540230Sdonn e->primblock.argsp = (struct Listblock *) 50640230Sdonn cpexpr(e->primblock.argsp); 50740230Sdonn e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp); 50840230Sdonn e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp); 50940230Sdonn break; 51040230Sdonn 51140230Sdonn default: 51240230Sdonn badtag("cpexpr", tag); 51340230Sdonn } 51440230Sdonn 51540230Sdonn return(e); 51640230Sdonn } 51740230Sdonn 51840230Sdonn frexpr(p) 51940230Sdonn register tagptr p; 52040230Sdonn { 52140230Sdonn register chainp q; 52240230Sdonn 52340230Sdonn if(p == NULL) 52440230Sdonn return; 52540230Sdonn 52640230Sdonn switch(p->tag) 52740230Sdonn { 52840230Sdonn case TCONST: 52940230Sdonn switch (p->constblock.vtype) 53040230Sdonn { 53140230Sdonn case TYBITSTR: 53240230Sdonn case TYCHAR: 53340230Sdonn case TYHOLLERITH: 53440230Sdonn free( (charptr) (p->constblock.const.ccp) ); 53540230Sdonn frexpr(p->constblock.vleng); 53640230Sdonn } 53740230Sdonn break; 53840230Sdonn 53940230Sdonn case TADDR: 54040230Sdonn if (!optimflag && p->addrblock.istemp) 54140230Sdonn { 54240230Sdonn frtemp(p); 54340230Sdonn return; 54440230Sdonn } 54540230Sdonn frexpr(p->addrblock.vleng); 54640230Sdonn frexpr(p->addrblock.memoffset); 54740230Sdonn break; 54840230Sdonn 54940230Sdonn case TTEMP: 55040230Sdonn frexpr(p->tempblock.vleng); 55140230Sdonn break; 55240230Sdonn 55340230Sdonn case TERROR: 55440230Sdonn break; 55540230Sdonn 55640230Sdonn case TNAME: 55740230Sdonn return; 55840230Sdonn 55940230Sdonn case TPRIM: 56040230Sdonn frexpr(p->primblock.argsp); 56140230Sdonn frexpr(p->primblock.fcharp); 56240230Sdonn frexpr(p->primblock.lcharp); 56340230Sdonn break; 56440230Sdonn 56540230Sdonn case TEXPR: 56640230Sdonn frexpr(p->exprblock.leftp); 56740230Sdonn if(p->exprblock.rightp) 56840230Sdonn frexpr(p->exprblock.rightp); 56940230Sdonn break; 57040230Sdonn 57140230Sdonn case TLIST: 57240230Sdonn for(q = p->listblock.listp ; q ; q = q->nextp) 57340230Sdonn frexpr(q->datap); 57440230Sdonn frchain( &(p->listblock.listp) ); 57540230Sdonn break; 57640230Sdonn 57740230Sdonn default: 57840230Sdonn badtag("frexpr", p->tag); 57940230Sdonn } 58040230Sdonn 58140230Sdonn free( (charptr) p ); 58240230Sdonn } 58340230Sdonn 58440230Sdonn /* fix up types in expression; replace subtrees and convert 58540230Sdonn names to address blocks */ 58640230Sdonn 58740230Sdonn expptr fixtype(p) 58840230Sdonn register tagptr p; 58940230Sdonn { 59040230Sdonn 59140230Sdonn if(p == 0) 59240230Sdonn return(0); 59340230Sdonn 59440230Sdonn switch(p->tag) 59540230Sdonn { 59640230Sdonn case TCONST: 59740230Sdonn return( (expptr) p ); 59840230Sdonn 59940230Sdonn case TADDR: 60040230Sdonn p->addrblock.memoffset = fixtype(p->addrblock.memoffset); 60140230Sdonn return( (expptr) p); 60240230Sdonn 60340230Sdonn case TTEMP: 60440230Sdonn return( (expptr) p); 60540230Sdonn 60640230Sdonn case TERROR: 60740230Sdonn return( (expptr) p); 60840230Sdonn 60940230Sdonn default: 61040230Sdonn badtag("fixtype", p->tag); 61140230Sdonn 61240230Sdonn case TEXPR: 61340230Sdonn return( fixexpr(p) ); 61440230Sdonn 61540230Sdonn case TLIST: 61640230Sdonn return( (expptr) p ); 61740230Sdonn 61840230Sdonn case TPRIM: 61940230Sdonn if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR) 62040230Sdonn { 62140230Sdonn if(p->primblock.namep->vtype == TYSUBR) 62240230Sdonn { 62340230Sdonn err("function invocation of subroutine"); 62440230Sdonn return( errnode() ); 62540230Sdonn } 62640230Sdonn else 62740230Sdonn return( mkfunct(p) ); 62840230Sdonn } 62940230Sdonn else return( mklhs(p) ); 63040230Sdonn } 63140230Sdonn } 63240230Sdonn 63340230Sdonn 63440230Sdonn 63540230Sdonn 63640230Sdonn 63740230Sdonn /* special case tree transformations and cleanups of expression trees */ 63840230Sdonn 63940230Sdonn expptr fixexpr(p) 64040230Sdonn register Exprp p; 64140230Sdonn { 64240230Sdonn expptr lp; 64340230Sdonn register expptr rp; 64440230Sdonn register expptr q; 64540230Sdonn int opcode, ltype, rtype, ptype, mtype; 64640230Sdonn expptr lconst, rconst; 64740230Sdonn expptr mkpower(); 64840230Sdonn 64940230Sdonn if( ISERROR(p) ) 65040230Sdonn return( (expptr) p ); 65140230Sdonn else if(p->tag != TEXPR) 65240230Sdonn badtag("fixexpr", p->tag); 65340230Sdonn opcode = p->opcode; 65440230Sdonn if (ISCONST(p->leftp)) 65540230Sdonn lconst = (expptr) cpexpr(p->leftp); 65640230Sdonn else 65740230Sdonn lconst = NULL; 65840230Sdonn if (p->rightp && ISCONST(p->rightp)) 65940230Sdonn rconst = (expptr) cpexpr(p->rightp); 66040230Sdonn else 66140230Sdonn rconst = NULL; 66240230Sdonn lp = p->leftp = fixtype(p->leftp); 66340230Sdonn ltype = lp->headblock.vtype; 66440230Sdonn if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP) 66540230Sdonn { 66640230Sdonn err("left side of assignment must be variable"); 66740230Sdonn frexpr(p); 66840230Sdonn return( errnode() ); 66940230Sdonn } 67040230Sdonn 67140230Sdonn if(p->rightp) 67240230Sdonn { 67340230Sdonn rp = p->rightp = fixtype(p->rightp); 67440230Sdonn rtype = rp->headblock.vtype; 67540230Sdonn } 67640230Sdonn else 67740230Sdonn { 67840230Sdonn rp = NULL; 67940230Sdonn rtype = 0; 68040230Sdonn } 68140230Sdonn 68240230Sdonn if(ltype==TYERROR || rtype==TYERROR) 68340230Sdonn { 68440230Sdonn frexpr(p); 68540230Sdonn frexpr(lconst); 68640230Sdonn frexpr(rconst); 68740230Sdonn return( errnode() ); 68840230Sdonn } 68940230Sdonn 69040230Sdonn /* force folding if possible */ 69140230Sdonn if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) ) 69240230Sdonn { 69340230Sdonn q = mkexpr(opcode, lp, rp); 69440230Sdonn if( ISCONST(q) ) 69540230Sdonn { 69640230Sdonn frexpr(lconst); 69740230Sdonn frexpr(rconst); 69840230Sdonn return(q); 69940230Sdonn } 70040230Sdonn free( (charptr) q ); /* constants did not fold */ 70140230Sdonn } 70240230Sdonn 70340230Sdonn if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR) 70440230Sdonn { 70540230Sdonn frexpr(p); 70640230Sdonn frexpr(lconst); 70740230Sdonn frexpr(rconst); 70840230Sdonn return( errnode() ); 70940230Sdonn } 71040230Sdonn 71140230Sdonn switch(opcode) 71240230Sdonn { 71340230Sdonn case OPCONCAT: 71440230Sdonn if(p->vleng == NULL) 71540230Sdonn p->vleng = mkexpr(OPPLUS, 71640230Sdonn cpexpr(lp->headblock.vleng), 71740230Sdonn cpexpr(rp->headblock.vleng) ); 71840230Sdonn break; 71940230Sdonn 72040230Sdonn case OPASSIGN: 72140230Sdonn case OPPLUSEQ: 72240230Sdonn case OPSTAREQ: 72340230Sdonn if(ltype == rtype) 72440230Sdonn break; 72540230Sdonn #if TARGET == VAX 72640230Sdonn if( ! rconst && ISREAL(ltype) && ISREAL(rtype) ) 72740230Sdonn break; 72840230Sdonn #endif 72940230Sdonn if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) ) 73040230Sdonn break; 73140230Sdonn if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT) 73240230Sdonn #if FAMILY==PCC 73340230Sdonn && typesize[ltype]>=typesize[rtype] ) 73440230Sdonn #else 73540230Sdonn && typesize[ltype]==typesize[rtype] ) 73640230Sdonn #endif 73740230Sdonn break; 73840230Sdonn if (rconst) 73940230Sdonn { 74040230Sdonn p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) ); 74140230Sdonn frexpr(rp); 74240230Sdonn } 74340230Sdonn else 74440230Sdonn p->rightp = fixtype(mkconv(ptype, rp)); 74540230Sdonn break; 74640230Sdonn 74740230Sdonn case OPSLASH: 74840230Sdonn if( ISCOMPLEX(rtype) ) 74940230Sdonn { 75040230Sdonn p = (Exprp) call2(ptype, 75140230Sdonn ptype==TYCOMPLEX? "c_div" : "z_div", 75240230Sdonn mkconv(ptype, lp), mkconv(ptype, rp) ); 75340230Sdonn break; 75440230Sdonn } 75540230Sdonn case OPPLUS: 75640230Sdonn case OPMINUS: 75740230Sdonn case OPSTAR: 75840230Sdonn case OPMOD: 75940230Sdonn #if TARGET == VAX 76040230Sdonn if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) || 76140230Sdonn (rtype==TYREAL && ! rconst ) )) 76240230Sdonn break; 76340230Sdonn #endif 76440230Sdonn if( ISCOMPLEX(ptype) ) 76540230Sdonn break; 76640230Sdonn if(ltype != ptype) 76740230Sdonn if (lconst) 76840230Sdonn { 76940230Sdonn p->leftp = fixtype(mkconv(ptype, 77040230Sdonn cpexpr(lconst))); 77140230Sdonn frexpr(lp); 77240230Sdonn } 77340230Sdonn else 77440230Sdonn p->leftp = fixtype(mkconv(ptype,lp)); 77540230Sdonn if(rtype != ptype) 77640230Sdonn if (rconst) 77740230Sdonn { 77840230Sdonn p->rightp = fixtype(mkconv(ptype, 77940230Sdonn cpexpr(rconst))); 78040230Sdonn frexpr(rp); 78140230Sdonn } 78240230Sdonn else 78340230Sdonn p->rightp = fixtype(mkconv(ptype,rp)); 78440230Sdonn break; 78540230Sdonn 78640230Sdonn case OPPOWER: 78740230Sdonn return( mkpower(p) ); 78840230Sdonn 78940230Sdonn case OPLT: 79040230Sdonn case OPLE: 79140230Sdonn case OPGT: 79240230Sdonn case OPGE: 79340230Sdonn case OPEQ: 79440230Sdonn case OPNE: 79540230Sdonn if(ltype == rtype) 79640230Sdonn break; 79740230Sdonn mtype = cktype(OPMINUS, ltype, rtype); 79840230Sdonn #if TARGET == VAX 79940230Sdonn if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) || 80040230Sdonn (rtype==TYREAL && ! rconst) )) 80140230Sdonn break; 80240230Sdonn #endif 80340230Sdonn if( ISCOMPLEX(mtype) ) 80440230Sdonn break; 80540230Sdonn if(ltype != mtype) 80640230Sdonn if (lconst) 80740230Sdonn { 80840230Sdonn p->leftp = fixtype(mkconv(mtype, 80940230Sdonn cpexpr(lconst))); 81040230Sdonn frexpr(lp); 81140230Sdonn } 81240230Sdonn else 81340230Sdonn p->leftp = fixtype(mkconv(mtype,lp)); 81440230Sdonn if(rtype != mtype) 81540230Sdonn if (rconst) 81640230Sdonn { 81740230Sdonn p->rightp = fixtype(mkconv(mtype, 81840230Sdonn cpexpr(rconst))); 81940230Sdonn frexpr(rp); 82040230Sdonn } 82140230Sdonn else 82240230Sdonn p->rightp = fixtype(mkconv(mtype,rp)); 82340230Sdonn break; 82440230Sdonn 82540230Sdonn 82640230Sdonn case OPCONV: 82740230Sdonn if(ISCOMPLEX(p->vtype)) 82840230Sdonn { 82940230Sdonn ptype = cktype(OPCONV, p->vtype, ltype); 83040230Sdonn if(p->rightp) 83140230Sdonn ptype = cktype(OPCONV, ptype, rtype); 83240230Sdonn break; 83340230Sdonn } 83440230Sdonn ptype = cktype(OPCONV, p->vtype, ltype); 83540230Sdonn if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA) 83640230Sdonn { 83740230Sdonn lp->exprblock.rightp = 83840230Sdonn fixtype( mkconv(ptype, lp->exprblock.rightp) ); 83940230Sdonn free( (charptr) p ); 84040230Sdonn p = (Exprp) lp; 84140230Sdonn } 84240230Sdonn break; 84340230Sdonn 84440230Sdonn case OPADDR: 84540230Sdonn if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR) 84640230Sdonn fatal("addr of addr"); 84740230Sdonn break; 84840230Sdonn 84940230Sdonn case OPCOMMA: 85040230Sdonn case OPQUEST: 85140230Sdonn case OPCOLON: 85240230Sdonn break; 85340230Sdonn 85440230Sdonn case OPPAREN: 85540230Sdonn p->vleng = (expptr) cpexpr( lp->headblock.vleng ); 85640230Sdonn break; 85740230Sdonn 85840230Sdonn case OPMIN: 85940230Sdonn case OPMAX: 86040230Sdonn ptype = p->vtype; 86140230Sdonn break; 86240230Sdonn 86340230Sdonn default: 86440230Sdonn break; 86540230Sdonn } 86640230Sdonn 86740230Sdonn p->vtype = ptype; 86840230Sdonn frexpr(lconst); 86940230Sdonn frexpr(rconst); 87040230Sdonn return((expptr) p); 87140230Sdonn } 87240230Sdonn 87340230Sdonn #if SZINT < SZLONG 87440230Sdonn /* 87540230Sdonn for efficient subscripting, replace long ints by shorts 87640230Sdonn in easy places 87740230Sdonn */ 87840230Sdonn 87940230Sdonn expptr shorten(p) 88040230Sdonn register expptr p; 88140230Sdonn { 88240230Sdonn register expptr q; 88340230Sdonn 88440230Sdonn if(p->headblock.vtype != TYLONG) 88540230Sdonn return(p); 88640230Sdonn 88740230Sdonn switch(p->tag) 88840230Sdonn { 88940230Sdonn case TERROR: 89040230Sdonn case TLIST: 89140230Sdonn return(p); 89240230Sdonn 89340230Sdonn case TCONST: 89440230Sdonn case TADDR: 89540230Sdonn return( mkconv(TYINT,p) ); 89640230Sdonn 89740230Sdonn case TEXPR: 89840230Sdonn break; 89940230Sdonn 90040230Sdonn default: 90140230Sdonn badtag("shorten", p->tag); 90240230Sdonn } 90340230Sdonn 90440230Sdonn switch(p->exprblock.opcode) 90540230Sdonn { 90640230Sdonn case OPPLUS: 90740230Sdonn case OPMINUS: 90840230Sdonn case OPSTAR: 90940230Sdonn q = shorten( cpexpr(p->exprblock.rightp) ); 91040230Sdonn if(q->headblock.vtype == TYINT) 91140230Sdonn { 91240230Sdonn p->exprblock.leftp = shorten(p->exprblock.leftp); 91340230Sdonn if(p->exprblock.leftp->headblock.vtype == TYLONG) 91440230Sdonn frexpr(q); 91540230Sdonn else 91640230Sdonn { 91740230Sdonn frexpr(p->exprblock.rightp); 91840230Sdonn p->exprblock.rightp = q; 91940230Sdonn p->exprblock.vtype = TYINT; 92040230Sdonn } 92140230Sdonn } 92240230Sdonn break; 92340230Sdonn 92440230Sdonn case OPNEG: 92540230Sdonn case OPPAREN: 92640230Sdonn p->exprblock.leftp = shorten(p->exprblock.leftp); 92740230Sdonn if(p->exprblock.leftp->headblock.vtype == TYINT) 92840230Sdonn p->exprblock.vtype = TYINT; 92940230Sdonn break; 93040230Sdonn 93140230Sdonn case OPCALL: 93240230Sdonn case OPCCALL: 93340230Sdonn p = mkconv(TYINT,p); 93440230Sdonn break; 93540230Sdonn default: 93640230Sdonn break; 93740230Sdonn } 93840230Sdonn 93940230Sdonn return(p); 94040230Sdonn } 94140230Sdonn #endif 94240230Sdonn /* fix an argument list, taking due care for special first level cases */ 94340230Sdonn 94440230Sdonn fixargs(doput, p0) 94540230Sdonn int doput; /* doput is true if the function is not intrinsic; 94640230Sdonn was used to decide whether to do a putconst, 94740230Sdonn but this is no longer done here (Feb82)*/ 94840230Sdonn struct Listblock *p0; 94940230Sdonn { 95040230Sdonn register chainp p; 95140230Sdonn register tagptr q, t; 95240230Sdonn register int qtag; 95340230Sdonn int nargs; 95440230Sdonn Addrp mkscalar(); 95540230Sdonn 95640230Sdonn nargs = 0; 95740230Sdonn if(p0) 95840230Sdonn for(p = p0->listp ; p ; p = p->nextp) 95940230Sdonn { 96040230Sdonn ++nargs; 96140230Sdonn q = p->datap; 96240230Sdonn qtag = q->tag; 96340230Sdonn if(qtag == TCONST) 96440230Sdonn { 96540230Sdonn 96640230Sdonn /* 96740230Sdonn if(q->constblock.vtype == TYSHORT) 96840230Sdonn q = (tagptr) mkconv(tyint, q); 96940230Sdonn */ 97040230Sdonn p->datap = q ; 97140230Sdonn } 97240230Sdonn else if(qtag==TPRIM && q->primblock.argsp==0 && 97340230Sdonn q->primblock.namep->vclass==CLPROC) 97440230Sdonn p->datap = (tagptr) mkaddr(q->primblock.namep); 97540230Sdonn else if(qtag==TPRIM && q->primblock.argsp==0 && 97640230Sdonn q->primblock.namep->vdim!=NULL) 97740230Sdonn p->datap = (tagptr) mkscalar(q->primblock.namep); 97840230Sdonn else if(qtag==TPRIM && q->primblock.argsp==0 && 97940230Sdonn q->primblock.namep->vdovar && 98040230Sdonn (t = (tagptr) memversion(q->primblock.namep)) ) 98140230Sdonn p->datap = (tagptr) fixtype(t); 98240230Sdonn else 98340230Sdonn p->datap = (tagptr) fixtype(q); 98440230Sdonn } 98540230Sdonn return(nargs); 98640230Sdonn } 98740230Sdonn 98840230Sdonn 98940230Sdonn Addrp mkscalar(np) 99040230Sdonn register Namep np; 99140230Sdonn { 99240230Sdonn register Addrp ap; 99340230Sdonn 99440230Sdonn vardcl(np); 99540230Sdonn ap = mkaddr(np); 99640230Sdonn 99740230Sdonn #if TARGET == VAX || TARGET == TAHOE 99840230Sdonn /* on the VAX, prolog causes array arguments 99940230Sdonn to point at the (0,...,0) element, except when 100040230Sdonn subscript checking is on 100140230Sdonn */ 100240230Sdonn #ifdef SDB 100340230Sdonn if( !checksubs && !sdbflag && np->vstg==STGARG) 100440230Sdonn #else 100540230Sdonn if( !checksubs && np->vstg==STGARG) 100640230Sdonn #endif 100740230Sdonn { 100840230Sdonn register struct Dimblock *dp; 100940230Sdonn dp = np->vdim; 101040230Sdonn frexpr(ap->memoffset); 101140230Sdonn ap->memoffset = mkexpr(OPSTAR, 101240230Sdonn (np->vtype==TYCHAR ? 101340230Sdonn cpexpr(np->vleng) : 101440230Sdonn (tagptr)ICON(typesize[np->vtype]) ), 101540230Sdonn cpexpr(dp->baseoffset) ); 101640230Sdonn } 101740230Sdonn #endif 101840230Sdonn return(ap); 101940230Sdonn } 102040230Sdonn 102140230Sdonn 102240230Sdonn 102340230Sdonn 102440230Sdonn 102540230Sdonn expptr mkfunct(p) 102640230Sdonn register struct Primblock *p; 102740230Sdonn { 102840230Sdonn struct Entrypoint *ep; 102940230Sdonn Addrp ap; 103040230Sdonn struct Extsym *extp; 103140230Sdonn register Namep np; 103240230Sdonn register expptr q; 103340230Sdonn expptr intrcall(), stfcall(); 103440230Sdonn int k, nargs; 103540230Sdonn int class; 103640230Sdonn 103740230Sdonn if(p->tag != TPRIM) 103840230Sdonn return( errnode() ); 103940230Sdonn 104040230Sdonn np = p->namep; 104140230Sdonn class = np->vclass; 104240230Sdonn 104340230Sdonn if(class == CLUNKNOWN) 104440230Sdonn { 104540230Sdonn np->vclass = class = CLPROC; 104640230Sdonn if(np->vstg == STGUNKNOWN) 104740230Sdonn { 104840230Sdonn if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) ) 104940230Sdonn { 105040230Sdonn np->vstg = STGINTR; 105140230Sdonn np->vardesc.varno = k; 105240230Sdonn np->vprocclass = PINTRINSIC; 105340230Sdonn } 105440230Sdonn else 105540230Sdonn { 105640230Sdonn extp = mkext( varunder(VL,np->varname) ); 105740230Sdonn if(extp->extstg == STGCOMMON) 105840230Sdonn warn("conflicting declarations", np->varname); 105940230Sdonn extp->extstg = STGEXT; 106040230Sdonn np->vstg = STGEXT; 106140230Sdonn np->vardesc.varno = extp - extsymtab; 106240230Sdonn np->vprocclass = PEXTERNAL; 106340230Sdonn } 106440230Sdonn } 106540230Sdonn else if(np->vstg==STGARG) 106640230Sdonn { 106740230Sdonn if(np->vtype!=TYCHAR && !ftn66flag) 106840230Sdonn warn("Dummy procedure not declared EXTERNAL. Code may be wrong."); 106940230Sdonn np->vprocclass = PEXTERNAL; 107040230Sdonn } 107140230Sdonn } 107240230Sdonn 107340230Sdonn if(class != CLPROC) 107440230Sdonn fatali("invalid class code %d for function", class); 107540230Sdonn if(p->fcharp || p->lcharp) 107640230Sdonn { 107740230Sdonn err("no substring of function call"); 107840230Sdonn goto error; 107940230Sdonn } 108040230Sdonn impldcl(np); 108140230Sdonn nargs = fixargs( np->vprocclass!=PINTRINSIC, p->argsp); 108240230Sdonn 108340230Sdonn switch(np->vprocclass) 108440230Sdonn { 108540230Sdonn case PEXTERNAL: 108640230Sdonn ap = mkaddr(np); 108740230Sdonn call: 108840230Sdonn q = mkexpr(OPCALL, ap, p->argsp); 108940230Sdonn if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN) 109040230Sdonn { 109140230Sdonn err("attempt to use untyped function"); 109240230Sdonn goto error; 109340230Sdonn } 109440230Sdonn if(np->vleng) 109540230Sdonn q->exprblock.vleng = (expptr) cpexpr(np->vleng); 109640230Sdonn break; 109740230Sdonn 109840230Sdonn case PINTRINSIC: 109940230Sdonn q = intrcall(np, p->argsp, nargs); 110040230Sdonn break; 110140230Sdonn 110240230Sdonn case PSTFUNCT: 110340230Sdonn q = stfcall(np, p->argsp); 110440230Sdonn break; 110540230Sdonn 110640230Sdonn case PTHISPROC: 110740230Sdonn warn("recursive call"); 110840230Sdonn for(ep = entries ; ep ; ep = ep->entnextp) 110940230Sdonn if(ep->enamep == np) 111040230Sdonn break; 111140230Sdonn if(ep == NULL) 111240230Sdonn fatal("mkfunct: impossible recursion"); 111340230Sdonn ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) ); 111440230Sdonn goto call; 111540230Sdonn 111640230Sdonn default: 111740230Sdonn fatali("mkfunct: impossible vprocclass %d", 111840230Sdonn (int) (np->vprocclass) ); 111940230Sdonn } 112040230Sdonn free( (charptr) p ); 112140230Sdonn return(q); 112240230Sdonn 112340230Sdonn error: 112440230Sdonn frexpr(p); 112540230Sdonn return( errnode() ); 112640230Sdonn } 112740230Sdonn 112840230Sdonn 112940230Sdonn 113040230Sdonn LOCAL expptr stfcall(np, actlist) 113140230Sdonn Namep np; 113240230Sdonn struct Listblock *actlist; 113340230Sdonn { 113440230Sdonn register chainp actuals; 113540230Sdonn int nargs; 113640230Sdonn chainp oactp, formals; 113740230Sdonn int type; 113840230Sdonn expptr q, rhs, ap; 113940230Sdonn Namep tnp; 114040230Sdonn register struct Rplblock *rp; 114140230Sdonn struct Rplblock *tlist; 114240230Sdonn 114340230Sdonn if(actlist) 114440230Sdonn { 114540230Sdonn actuals = actlist->listp; 114640230Sdonn free( (charptr) actlist); 114740230Sdonn } 114840230Sdonn else 114940230Sdonn actuals = NULL; 115040230Sdonn oactp = actuals; 115140230Sdonn 115240230Sdonn nargs = 0; 115340230Sdonn tlist = NULL; 115440230Sdonn if( (type = np->vtype) == TYUNKNOWN) 115540230Sdonn { 115640230Sdonn err("attempt to use untyped statement function"); 115740230Sdonn q = errnode(); 115840230Sdonn goto ret; 115940230Sdonn } 116040230Sdonn formals = (chainp) (np->varxptr.vstfdesc->datap); 116140230Sdonn rhs = (expptr) (np->varxptr.vstfdesc->nextp); 116240230Sdonn 116340230Sdonn /* copy actual arguments into temporaries */ 116440230Sdonn while(actuals!=NULL && formals!=NULL) 116540230Sdonn { 116640230Sdonn rp = ALLOC(Rplblock); 116740230Sdonn rp->rplnp = tnp = (Namep) (formals->datap); 116840230Sdonn ap = fixtype(actuals->datap); 116940230Sdonn if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR 117040230Sdonn && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) ) 117140230Sdonn { 117240230Sdonn rp->rplvp = (expptr) ap; 117340230Sdonn rp->rplxp = NULL; 117440230Sdonn rp->rpltag = ap->tag; 117540230Sdonn } 117640230Sdonn else { 117740230Sdonn rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng); 117840230Sdonn rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) ); 117940230Sdonn if( (rp->rpltag = rp->rplxp->tag) == TERROR) 118040230Sdonn err("disagreement of argument types in statement function call"); 118140230Sdonn else if(tnp->vtype!=ap->headblock.vtype) 118240230Sdonn warn("argument type mismatch in statement function"); 118340230Sdonn } 118440230Sdonn rp->rplnextp = tlist; 118540230Sdonn tlist = rp; 118640230Sdonn actuals = actuals->nextp; 118740230Sdonn formals = formals->nextp; 118840230Sdonn ++nargs; 118940230Sdonn } 119040230Sdonn 119140230Sdonn if(actuals!=NULL || formals!=NULL) 119240230Sdonn err("statement function definition and argument list differ"); 119340230Sdonn 119440230Sdonn /* 119540230Sdonn now push down names involved in formal argument list, then 119640230Sdonn evaluate rhs of statement function definition in this environment 119740230Sdonn */ 119840230Sdonn 119940230Sdonn if(tlist) /* put tlist in front of the rpllist */ 120040230Sdonn { 120140230Sdonn for(rp = tlist; rp->rplnextp; rp = rp->rplnextp) 120240230Sdonn ; 120340230Sdonn rp->rplnextp = rpllist; 120440230Sdonn rpllist = tlist; 120540230Sdonn } 120640230Sdonn 120740230Sdonn q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) ); 120840230Sdonn 120940230Sdonn /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */ 121040230Sdonn while(--nargs >= 0) 121140230Sdonn { 121240230Sdonn if(rpllist->rplxp) 121340230Sdonn q = mkexpr(OPCOMMA, rpllist->rplxp, q); 121440230Sdonn rp = rpllist->rplnextp; 121540230Sdonn frexpr(rpllist->rplvp); 121640230Sdonn free(rpllist); 121740230Sdonn rpllist = rp; 121840230Sdonn } 121940230Sdonn 122040230Sdonn ret: 122140230Sdonn frchain( &oactp ); 122240230Sdonn return(q); 122340230Sdonn } 122440230Sdonn 122540230Sdonn 122640230Sdonn 122740230Sdonn 122840230Sdonn Addrp mkplace(np) 122940230Sdonn register Namep np; 123040230Sdonn { 123140230Sdonn register Addrp s; 123240230Sdonn register struct Rplblock *rp; 123340230Sdonn int regn; 123440230Sdonn 123540230Sdonn /* is name on the replace list? */ 123640230Sdonn 123740230Sdonn for(rp = rpllist ; rp ; rp = rp->rplnextp) 123840230Sdonn { 123940230Sdonn if(np == rp->rplnp) 124040230Sdonn { 124140230Sdonn if(rp->rpltag == TNAME) 124240230Sdonn { 124340230Sdonn np = (Namep) (rp->rplvp); 124440230Sdonn break; 124540230Sdonn } 124640230Sdonn else return( (Addrp) cpexpr(rp->rplvp) ); 124740230Sdonn } 124840230Sdonn } 124940230Sdonn 125040230Sdonn /* is variable a DO index in a register ? */ 125140230Sdonn 125240230Sdonn if(np->vdovar && ( (regn = inregister(np)) >= 0) ) 125340230Sdonn if(np->vtype == TYERROR) 125440230Sdonn return( (Addrp) errnode() ); 125540230Sdonn else 125640230Sdonn { 125740230Sdonn s = ALLOC(Addrblock); 125840230Sdonn s->tag = TADDR; 125940230Sdonn s->vstg = STGREG; 126040230Sdonn s->vtype = TYIREG; 126140230Sdonn s->issaved = np->vsave; 126240230Sdonn s->memno = regn; 126340230Sdonn s->memoffset = ICON(0); 126440230Sdonn return(s); 126540230Sdonn } 126640230Sdonn 126740230Sdonn vardcl(np); 126840230Sdonn return(mkaddr(np)); 126940230Sdonn } 127040230Sdonn 127140230Sdonn 127240230Sdonn 127340230Sdonn 127440230Sdonn expptr mklhs(p) 127540230Sdonn register struct Primblock *p; 127640230Sdonn { 127740230Sdonn expptr suboffset(); 127840230Sdonn register Addrp s; 127940230Sdonn Namep np; 128040230Sdonn 128140230Sdonn if(p->tag != TPRIM) 128240230Sdonn return( (expptr) p ); 128340230Sdonn np = p->namep; 128440230Sdonn 128540230Sdonn s = mkplace(np); 128640230Sdonn if(s->tag!=TADDR || s->vstg==STGREG) 128740230Sdonn { 128840230Sdonn free( (charptr) p ); 128940230Sdonn return( (expptr) s ); 129040230Sdonn } 129140230Sdonn 129240230Sdonn /* compute the address modified by subscripts */ 129340230Sdonn 129440230Sdonn s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) ); 129540230Sdonn frexpr(p->argsp); 129640230Sdonn p->argsp = NULL; 129740230Sdonn 129840230Sdonn /* now do substring part */ 129940230Sdonn 130040230Sdonn if(p->fcharp || p->lcharp) 130140230Sdonn { 130240230Sdonn if(np->vtype != TYCHAR) 130340230Sdonn errstr("substring of noncharacter %s", varstr(VL,np->varname)); 130440230Sdonn else { 130540230Sdonn if(p->lcharp == NULL) 130640230Sdonn p->lcharp = (expptr) cpexpr(s->vleng); 130740230Sdonn frexpr(s->vleng); 130840230Sdonn if(p->fcharp) 130940230Sdonn { 131040230Sdonn if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM 131140230Sdonn && p->fcharp->primblock.namep == p->lcharp->primblock.namep) 131240230Sdonn /* A trivial optimization -- upper == lower */ 131340230Sdonn s->vleng = ICON(1); 131440230Sdonn else 131540230Sdonn s->vleng = mkexpr(OPMINUS, p->lcharp, 131640230Sdonn mkexpr(OPMINUS, p->fcharp, ICON(1) )); 131740230Sdonn } 131840230Sdonn else 131940230Sdonn s->vleng = p->lcharp; 132040230Sdonn } 132140230Sdonn } 132240230Sdonn 132340230Sdonn s->vleng = fixtype( s->vleng ); 132440230Sdonn s->memoffset = fixtype( s->memoffset ); 132540230Sdonn free( (charptr) p ); 132640230Sdonn return( (expptr) s ); 132740230Sdonn } 132840230Sdonn 132940230Sdonn 133040230Sdonn 133140230Sdonn 133240230Sdonn 133340230Sdonn deregister(np) 133440230Sdonn Namep np; 133540230Sdonn { 133640230Sdonn if(nregvar>0 && regnamep[nregvar-1]==np) 133740230Sdonn { 133840230Sdonn --nregvar; 133940230Sdonn #if FAMILY == DMR 134040230Sdonn putnreg(); 134140230Sdonn #endif 134240230Sdonn } 134340230Sdonn } 134440230Sdonn 134540230Sdonn 134640230Sdonn 134740230Sdonn 134840230Sdonn Addrp memversion(np) 134940230Sdonn register Namep np; 135040230Sdonn { 135140230Sdonn register Addrp s; 135240230Sdonn 135340230Sdonn if(np->vdovar==NO || (inregister(np)<0) ) 135440230Sdonn return(NULL); 135540230Sdonn np->vdovar = NO; 135640230Sdonn s = mkplace(np); 135740230Sdonn np->vdovar = YES; 135840230Sdonn return(s); 135940230Sdonn } 136040230Sdonn 136140230Sdonn 136240230Sdonn 136340230Sdonn inregister(np) 136440230Sdonn register Namep np; 136540230Sdonn { 136640230Sdonn register int i; 136740230Sdonn 136840230Sdonn for(i = 0 ; i < nregvar ; ++i) 136940230Sdonn if(regnamep[i] == np) 137040230Sdonn return( regnum[i] ); 137140230Sdonn return(-1); 137240230Sdonn } 137340230Sdonn 137440230Sdonn 137540230Sdonn 137640230Sdonn 137740230Sdonn enregister(np) 137840230Sdonn Namep np; 137940230Sdonn { 138040230Sdonn if( inregister(np) >= 0) 138140230Sdonn return(YES); 138240230Sdonn if(nregvar >= maxregvar) 138340230Sdonn return(NO); 138440230Sdonn vardcl(np); 138540230Sdonn if( ONEOF(np->vtype, MSKIREG) ) 138640230Sdonn { 138740230Sdonn regnamep[nregvar++] = np; 138840230Sdonn if(nregvar > highregvar) 138940230Sdonn highregvar = nregvar; 139040230Sdonn #if FAMILY == DMR 139140230Sdonn putnreg(); 139240230Sdonn #endif 139340230Sdonn return(YES); 139440230Sdonn } 139540230Sdonn else 139640230Sdonn return(NO); 139740230Sdonn } 139840230Sdonn 139940230Sdonn 140040230Sdonn 140140230Sdonn 140240230Sdonn expptr suboffset(p) 140340230Sdonn register struct Primblock *p; 140440230Sdonn { 140540230Sdonn int n; 140640230Sdonn expptr size; 140740230Sdonn expptr oftwo(); 140840230Sdonn chainp cp; 140940230Sdonn expptr offp, prod; 141040230Sdonn expptr subcheck(); 141140230Sdonn struct Dimblock *dimp; 141240230Sdonn expptr sub[MAXDIM+1]; 141340230Sdonn register Namep np; 141440230Sdonn 141540230Sdonn np = p->namep; 141640230Sdonn offp = ICON(0); 141740230Sdonn n = 0; 141840230Sdonn if(p->argsp) 141940230Sdonn for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp) 142040230Sdonn { 142140230Sdonn sub[n] = fixtype(cpexpr(cp->datap)); 142240230Sdonn if ( ! ISINT(sub[n]->headblock.vtype)) { 142340230Sdonn errstr("%s: non-integer subscript expression", 142440230Sdonn varstr(VL, np->varname) ); 142540230Sdonn /* Provide a substitute -- go on to find more errors */ 142640230Sdonn frexpr(sub[n]); 142740230Sdonn sub[n] = ICON(1); 142840230Sdonn } 142940230Sdonn if(n > maxdim) 143040230Sdonn { 143140230Sdonn char str[28+VL]; 143240230Sdonn sprintf(str, "%s: more than %d subscripts", 143340230Sdonn varstr(VL, np->varname), maxdim ); 143440230Sdonn err( str ); 143540230Sdonn break; 143640230Sdonn } 143740230Sdonn } 143840230Sdonn 143940230Sdonn dimp = np->vdim; 144040230Sdonn if(n>0 && dimp==NULL) 144140230Sdonn errstr("%s: subscripts on scalar variable", 144240230Sdonn varstr(VL, np->varname), maxdim ); 144340230Sdonn else if(dimp && dimp->ndim!=n) 144440230Sdonn errstr("wrong number of subscripts on %s", 144540230Sdonn varstr(VL, np->varname) ); 144640230Sdonn else if(n > 0) 144740230Sdonn { 144840230Sdonn prod = sub[--n]; 144940230Sdonn while( --n >= 0) 145040230Sdonn prod = mkexpr(OPPLUS, sub[n], 145140230Sdonn mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) ); 145240230Sdonn #if TARGET == VAX || TARGET == TAHOE 145340230Sdonn #ifdef SDB 145440230Sdonn if(checksubs || np->vstg!=STGARG || sdbflag) 145540230Sdonn #else 145640230Sdonn if(checksubs || np->vstg!=STGARG) 145740230Sdonn #endif 145840230Sdonn prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset)); 145940230Sdonn #else 146040230Sdonn prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset)); 146140230Sdonn #endif 146240230Sdonn if(checksubs) 146340230Sdonn prod = subcheck(np, prod); 146440230Sdonn size = np->vtype == TYCHAR ? 146540230Sdonn (expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]); 146640230Sdonn if (!oftwo(size)) 146740230Sdonn prod = mkexpr(OPSTAR, prod, size); 146840230Sdonn else 146940230Sdonn prod = mkexpr(OPLSHIFT,prod,oftwo(size)); 147040230Sdonn 147140230Sdonn offp = mkexpr(OPPLUS, offp, prod); 147240230Sdonn } 147340230Sdonn 147440230Sdonn if(p->fcharp && np->vtype==TYCHAR) 147540230Sdonn offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) )); 147640230Sdonn 147740230Sdonn return(offp); 147840230Sdonn } 147940230Sdonn 148040230Sdonn 148140230Sdonn 148240230Sdonn 148340230Sdonn expptr subcheck(np, p) 148440230Sdonn Namep np; 148540230Sdonn register expptr p; 148640230Sdonn { 148740230Sdonn struct Dimblock *dimp; 148840230Sdonn expptr t, checkvar, checkcond, badcall; 148940230Sdonn 149040230Sdonn dimp = np->vdim; 149140230Sdonn if(dimp->nelt == NULL) 149240230Sdonn return(p); /* don't check arrays with * bounds */ 149340230Sdonn checkvar = NULL; 149440230Sdonn checkcond = NULL; 149540230Sdonn if( ISICON(p) ) 149640230Sdonn { 149740230Sdonn if(p->constblock.const.ci < 0) 149840230Sdonn goto badsub; 149940230Sdonn if( ISICON(dimp->nelt) ) 150040230Sdonn if(p->constblock.const.ci < dimp->nelt->constblock.const.ci) 150140230Sdonn return(p); 150240230Sdonn else 150340230Sdonn goto badsub; 150440230Sdonn } 150540230Sdonn if(p->tag==TADDR && p->addrblock.vstg==STGREG) 150640230Sdonn { 150740230Sdonn checkvar = (expptr) cpexpr(p); 150840230Sdonn t = p; 150940230Sdonn } 151040230Sdonn else { 151140230Sdonn checkvar = (expptr) mktemp(p->headblock.vtype, ENULL); 151240230Sdonn t = mkexpr(OPASSIGN, cpexpr(checkvar), p); 151340230Sdonn } 151440230Sdonn checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) ); 151540230Sdonn if( ! ISICON(p) ) 151640230Sdonn checkcond = mkexpr(OPAND, checkcond, 151740230Sdonn mkexpr(OPLE, ICON(0), cpexpr(checkvar)) ); 151840230Sdonn 151940230Sdonn badcall = call4(p->headblock.vtype, "s_rnge", 152040230Sdonn mkstrcon(VL, np->varname), 152140230Sdonn mkconv(TYLONG, cpexpr(checkvar)), 152240230Sdonn mkstrcon(XL, procname), 152340230Sdonn ICON(lineno) ); 152440230Sdonn badcall->exprblock.opcode = OPCCALL; 152540230Sdonn p = mkexpr(OPQUEST, checkcond, 152640230Sdonn mkexpr(OPCOLON, checkvar, badcall)); 152740230Sdonn 152840230Sdonn return(p); 152940230Sdonn 153040230Sdonn badsub: 153140230Sdonn frexpr(p); 153240230Sdonn errstr("subscript on variable %s out of range", varstr(VL,np->varname)); 153340230Sdonn return ( ICON(0) ); 153440230Sdonn } 153540230Sdonn 153640230Sdonn 153740230Sdonn 153840230Sdonn 153940230Sdonn Addrp mkaddr(p) 154040230Sdonn register Namep p; 154140230Sdonn { 154240230Sdonn struct Extsym *extp; 154340230Sdonn register Addrp t; 154440230Sdonn Addrp intraddr(); 154540230Sdonn 154640230Sdonn switch( p->vstg) 154740230Sdonn { 154840230Sdonn case STGUNKNOWN: 154940230Sdonn if(p->vclass != CLPROC) 155040230Sdonn break; 155140230Sdonn extp = mkext( varunder(VL, p->varname) ); 155240230Sdonn extp->extstg = STGEXT; 155340230Sdonn p->vstg = STGEXT; 155440230Sdonn p->vardesc.varno = extp - extsymtab; 155540230Sdonn p->vprocclass = PEXTERNAL; 155640230Sdonn 155740230Sdonn case STGCOMMON: 155840230Sdonn case STGEXT: 155940230Sdonn case STGBSS: 156040230Sdonn case STGINIT: 156140230Sdonn case STGEQUIV: 156240230Sdonn case STGARG: 156340230Sdonn case STGLENG: 156440230Sdonn case STGAUTO: 156540230Sdonn t = ALLOC(Addrblock); 156640230Sdonn t->tag = TADDR; 156740230Sdonn if(p->vclass==CLPROC && p->vprocclass==PTHISPROC) 156840230Sdonn t->vclass = CLVAR; 156940230Sdonn else 157040230Sdonn t->vclass = p->vclass; 157140230Sdonn t->vtype = p->vtype; 157240230Sdonn t->vstg = p->vstg; 157340230Sdonn t->memno = p->vardesc.varno; 157440230Sdonn t->issaved = p->vsave; 157540230Sdonn if(p->vdim) t->isarray = YES; 157640230Sdonn t->memoffset = ICON(p->voffset); 157740230Sdonn if(p->vleng) 157840230Sdonn { 157940230Sdonn t->vleng = (expptr) cpexpr(p->vleng); 158040230Sdonn if( ISICON(t->vleng) ) 158140230Sdonn t->varleng = t->vleng->constblock.const.ci; 158240230Sdonn } 158340230Sdonn if (p->vstg == STGBSS) 158440230Sdonn t->varsize = p->varsize; 158540230Sdonn else if (p->vstg == STGEQUIV) 158640230Sdonn t->varsize = eqvclass[t->memno].eqvleng; 158740230Sdonn return(t); 158840230Sdonn 158940230Sdonn case STGINTR: 159040230Sdonn return( intraddr(p) ); 159140230Sdonn 159240230Sdonn } 159340230Sdonn /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass); 159440230Sdonn badstg("mkaddr", p->vstg); 159540230Sdonn /* NOTREACHED */ 159640230Sdonn } 159740230Sdonn 159840230Sdonn 159940230Sdonn 160040230Sdonn 160140230Sdonn Addrp mkarg(type, argno) 160240230Sdonn int type, argno; 160340230Sdonn { 160440230Sdonn register Addrp p; 160540230Sdonn 160640230Sdonn p = ALLOC(Addrblock); 160740230Sdonn p->tag = TADDR; 160840230Sdonn p->vtype = type; 160940230Sdonn p->vclass = CLVAR; 161040230Sdonn p->vstg = (type==TYLENG ? STGLENG : STGARG); 161140230Sdonn p->memno = argno; 161240230Sdonn return(p); 161340230Sdonn } 161440230Sdonn 161540230Sdonn 161640230Sdonn 161740230Sdonn 161840230Sdonn expptr mkprim(v, args, substr) 161940230Sdonn register union 162040230Sdonn { 162140230Sdonn struct Paramblock paramblock; 162240230Sdonn struct Nameblock nameblock; 162340230Sdonn struct Headblock headblock; 162440230Sdonn } *v; 162540230Sdonn struct Listblock *args; 162640230Sdonn chainp substr; 162740230Sdonn { 162840230Sdonn register struct Primblock *p; 162940230Sdonn 163040230Sdonn if(v->headblock.vclass == CLPARAM) 163140230Sdonn { 163240230Sdonn if(args || substr) 163340230Sdonn { 163440230Sdonn errstr("no qualifiers on parameter name %s", 163540230Sdonn varstr(VL,v->paramblock.varname)); 163640230Sdonn frexpr(args); 163740230Sdonn if(substr) 163840230Sdonn { 163940230Sdonn frexpr(substr->datap); 164040230Sdonn frexpr(substr->nextp->datap); 164140230Sdonn frchain(&substr); 164240230Sdonn } 164340230Sdonn frexpr(v); 164440230Sdonn return( errnode() ); 164540230Sdonn } 164640230Sdonn return( (expptr) cpexpr(v->paramblock.paramval) ); 164740230Sdonn } 164840230Sdonn 164940230Sdonn p = ALLOC(Primblock); 165040230Sdonn p->tag = TPRIM; 165140230Sdonn p->vtype = v->nameblock.vtype; 165240230Sdonn p->namep = (Namep) v; 165340230Sdonn p->argsp = args; 165440230Sdonn if(substr) 165540230Sdonn { 165640230Sdonn p->fcharp = (expptr) substr->datap; 1657*40231Sdonn if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype)) 165840230Sdonn p->fcharp = mkconv(TYINT, p->fcharp); 165940230Sdonn p->lcharp = (expptr) substr->nextp->datap; 1660*40231Sdonn if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype)) 166140230Sdonn p->lcharp = mkconv(TYINT, p->lcharp); 166240230Sdonn frchain(&substr); 166340230Sdonn } 166440230Sdonn return( (expptr) p); 166540230Sdonn } 166640230Sdonn 166740230Sdonn 166840230Sdonn 166940230Sdonn vardcl(v) 167040230Sdonn register Namep v; 167140230Sdonn { 167240230Sdonn int nelt; 167340230Sdonn struct Dimblock *t; 167440230Sdonn Addrp p; 167540230Sdonn expptr neltp; 167640230Sdonn int eltsize; 167740230Sdonn int varsize; 167840230Sdonn int tsize; 167940230Sdonn int align; 168040230Sdonn 168140230Sdonn if(v->vdcldone) 168240230Sdonn return; 168340230Sdonn if(v->vclass == CLNAMELIST) 168440230Sdonn return; 168540230Sdonn 168640230Sdonn if(v->vtype == TYUNKNOWN) 168740230Sdonn impldcl(v); 168840230Sdonn if(v->vclass == CLUNKNOWN) 168940230Sdonn v->vclass = CLVAR; 169040230Sdonn else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC) 169140230Sdonn { 169240230Sdonn dclerr("used both as variable and non-variable", v); 169340230Sdonn return; 169440230Sdonn } 169540230Sdonn if(v->vstg==STGUNKNOWN) 169640230Sdonn v->vstg = implstg[ letter(v->varname[0]) ]; 169740230Sdonn 169840230Sdonn switch(v->vstg) 169940230Sdonn { 170040230Sdonn case STGBSS: 170140230Sdonn v->vardesc.varno = ++lastvarno; 170240230Sdonn if (v->vclass != CLVAR) 170340230Sdonn break; 170440230Sdonn nelt = 1; 170540230Sdonn t = v->vdim; 170640230Sdonn if (t) 170740230Sdonn { 170840230Sdonn neltp = t->nelt; 170940230Sdonn if (neltp && ISICON(neltp)) 171040230Sdonn nelt = neltp->constblock.const.ci; 171140230Sdonn else 171240230Sdonn dclerr("improperly dimensioned array", v); 171340230Sdonn } 171440230Sdonn 171540230Sdonn if (v->vtype == TYCHAR) 171640230Sdonn { 171740230Sdonn v->vleng = fixtype(v->vleng); 171840230Sdonn if (v->vleng == NULL) 171940230Sdonn eltsize = typesize[TYCHAR]; 172040230Sdonn else if (ISICON(v->vleng)) 172140230Sdonn eltsize = typesize[TYCHAR] * 172240230Sdonn v->vleng->constblock.const.ci; 172340230Sdonn else if (v->vleng->tag != TERROR) 172440230Sdonn { 172540230Sdonn errstr("nonconstant string length on %s", 172640230Sdonn varstr(VL, v->varname)); 172740230Sdonn eltsize = 0; 172840230Sdonn } 172940230Sdonn } 173040230Sdonn else 173140230Sdonn eltsize = typesize[v->vtype]; 173240230Sdonn 173340230Sdonn v->varsize = nelt * eltsize; 173440230Sdonn break; 173540230Sdonn case STGAUTO: 173640230Sdonn if(v->vclass==CLPROC && v->vprocclass==PTHISPROC) 173740230Sdonn break; 173840230Sdonn nelt = 1; 173940230Sdonn if(t = v->vdim) 174040230Sdonn if( (neltp = t->nelt) && ISCONST(neltp) ) 174140230Sdonn nelt = neltp->constblock.const.ci; 174240230Sdonn else 174340230Sdonn dclerr("adjustable automatic array", v); 174440230Sdonn p = autovar(nelt, v->vtype, v->vleng); 174540230Sdonn v->vardesc.varno = p->memno; 174640230Sdonn v->voffset = p->memoffset->constblock.const.ci; 174740230Sdonn frexpr(p); 174840230Sdonn break; 174940230Sdonn 175040230Sdonn default: 175140230Sdonn break; 175240230Sdonn } 175340230Sdonn v->vdcldone = YES; 175440230Sdonn } 175540230Sdonn 175640230Sdonn 175740230Sdonn 175840230Sdonn 175940230Sdonn impldcl(p) 176040230Sdonn register Namep p; 176140230Sdonn { 176240230Sdonn register int k; 176340230Sdonn int type, leng; 176440230Sdonn 176540230Sdonn if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) ) 176640230Sdonn return; 176740230Sdonn if(p->vtype == TYUNKNOWN) 176840230Sdonn { 176940230Sdonn k = letter(p->varname[0]); 177040230Sdonn type = impltype[ k ]; 177140230Sdonn leng = implleng[ k ]; 177240230Sdonn if(type == TYUNKNOWN) 177340230Sdonn { 177440230Sdonn if(p->vclass == CLPROC) 177540230Sdonn dclerr("attempt to use function of undefined type", p); 177640230Sdonn else 177740230Sdonn dclerr("attempt to use undefined variable", p); 177840230Sdonn type = TYERROR; 177940230Sdonn leng = 1; 178040230Sdonn } 178140230Sdonn settype(p, type, leng); 178240230Sdonn } 178340230Sdonn } 178440230Sdonn 178540230Sdonn 178640230Sdonn 178740230Sdonn 178840230Sdonn LOCAL letter(c) 178940230Sdonn register int c; 179040230Sdonn { 179140230Sdonn if( isupper(c) ) 179240230Sdonn c = tolower(c); 179340230Sdonn return(c - 'a'); 179440230Sdonn } 179540230Sdonn 179640230Sdonn #define ICONEQ(z, c) (ISICON(z) && z->constblock.const.ci==c) 179740230Sdonn #define COMMUTE { e = lp; lp = rp; rp = e; } 179840230Sdonn 179940230Sdonn 180040230Sdonn expptr mkexpr(opcode, lp, rp) 180140230Sdonn int opcode; 180240230Sdonn register expptr lp, rp; 180340230Sdonn { 180440230Sdonn register expptr e, e1; 180540230Sdonn int etype; 180640230Sdonn int ltype, rtype; 180740230Sdonn int ltag, rtag; 180840230Sdonn expptr q, q1; 180940230Sdonn expptr fold(); 181040230Sdonn int k; 181140230Sdonn 181240230Sdonn ltype = lp->headblock.vtype; 181340230Sdonn ltag = lp->tag; 181440230Sdonn if(rp && opcode!=OPCALL && opcode!=OPCCALL) 181540230Sdonn { 181640230Sdonn rtype = rp->headblock.vtype; 181740230Sdonn rtag = rp->tag; 181840230Sdonn } 181940230Sdonn else { 182040230Sdonn rtype = 0; 182140230Sdonn rtag = 0; 182240230Sdonn } 182340230Sdonn 182440230Sdonn /* 182540230Sdonn * Yuck. Why can't we fold constants AFTER 182640230Sdonn * variables are implicitly declared??? 182740230Sdonn */ 182840230Sdonn if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL) 182940230Sdonn { 183040230Sdonn k = letter(lp->primblock.namep->varname[0]); 183140230Sdonn ltype = impltype[ k ]; 183240230Sdonn } 183340230Sdonn if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL) 183440230Sdonn { 183540230Sdonn k = letter(rp->primblock.namep->varname[0]); 183640230Sdonn rtype = impltype[ k ]; 183740230Sdonn } 183840230Sdonn 183940230Sdonn etype = cktype(opcode, ltype, rtype); 184040230Sdonn if(etype == TYERROR) 184140230Sdonn goto error; 184240230Sdonn 184340230Sdonn if(etype != TYUNKNOWN) 184440230Sdonn switch(opcode) 184540230Sdonn { 184640230Sdonn /* check for multiplication by 0 and 1 and addition to 0 */ 184740230Sdonn 184840230Sdonn case OPSTAR: 184940230Sdonn if( ISCONST(lp) ) 185040230Sdonn COMMUTE 185140230Sdonn 185240230Sdonn if( ISICON(rp) ) 185340230Sdonn { 185440230Sdonn if(rp->constblock.const.ci == 0) 185540230Sdonn { 185640230Sdonn if(etype == TYUNKNOWN) 185740230Sdonn break; 185840230Sdonn rp = mkconv(etype, rp); 185940230Sdonn goto retright; 186040230Sdonn } 186140230Sdonn if ((lp->tag == TEXPR) && 186240230Sdonn ((lp->exprblock.opcode == OPPLUS) || 186340230Sdonn (lp->exprblock.opcode == OPMINUS)) && 186440230Sdonn ISCONST(lp->exprblock.rightp) && 186540230Sdonn ISINT(lp->exprblock.rightp->constblock.vtype)) 186640230Sdonn { 186740230Sdonn q1 = mkexpr(OPSTAR, lp->exprblock.rightp, 186840230Sdonn cpexpr(rp)); 186940230Sdonn q = mkexpr(OPSTAR, lp->exprblock.leftp, rp); 187040230Sdonn q = mkexpr(lp->exprblock.opcode, q, q1); 187140230Sdonn free ((char *) lp); 187240230Sdonn return q; 187340230Sdonn } 187440230Sdonn else 187540230Sdonn goto mulop; 187640230Sdonn } 187740230Sdonn break; 187840230Sdonn 187940230Sdonn case OPSLASH: 188040230Sdonn case OPMOD: 188140230Sdonn if( ICONEQ(rp, 0) ) 188240230Sdonn { 188340230Sdonn err("attempted division by zero"); 188440230Sdonn rp = ICON(1); 188540230Sdonn break; 188640230Sdonn } 188740230Sdonn if(opcode == OPMOD) 188840230Sdonn break; 188940230Sdonn 189040230Sdonn 189140230Sdonn mulop: 189240230Sdonn if( ISICON(rp) ) 189340230Sdonn { 189440230Sdonn if(rp->constblock.const.ci == 1) 189540230Sdonn goto retleft; 189640230Sdonn 189740230Sdonn if(rp->constblock.const.ci == -1) 189840230Sdonn { 189940230Sdonn frexpr(rp); 190040230Sdonn return( mkexpr(OPNEG, lp, PNULL) ); 190140230Sdonn } 190240230Sdonn } 190340230Sdonn 190440230Sdonn if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) ) 190540230Sdonn { 190640230Sdonn if(opcode == OPSTAR) 190740230Sdonn e = mkexpr(OPSTAR, lp->exprblock.rightp, rp); 190840230Sdonn else if(ISICON(rp) && 190940230Sdonn (lp->exprblock.rightp->constblock.const.ci % 191040230Sdonn rp->constblock.const.ci) == 0) 191140230Sdonn e = mkexpr(OPSLASH, lp->exprblock.rightp, rp); 191240230Sdonn else break; 191340230Sdonn 191440230Sdonn e1 = lp->exprblock.leftp; 191540230Sdonn free( (charptr) lp ); 191640230Sdonn return( mkexpr(OPSTAR, e1, e) ); 191740230Sdonn } 191840230Sdonn break; 191940230Sdonn 192040230Sdonn 192140230Sdonn case OPPLUS: 192240230Sdonn if( ISCONST(lp) ) 192340230Sdonn COMMUTE 192440230Sdonn goto addop; 192540230Sdonn 192640230Sdonn case OPMINUS: 192740230Sdonn if( ICONEQ(lp, 0) ) 192840230Sdonn { 192940230Sdonn frexpr(lp); 193040230Sdonn return( mkexpr(OPNEG, rp, ENULL) ); 193140230Sdonn } 193240230Sdonn 193340230Sdonn if( ISCONST(rp) ) 193440230Sdonn { 193540230Sdonn opcode = OPPLUS; 193640230Sdonn consnegop(rp); 193740230Sdonn } 193840230Sdonn 193940230Sdonn addop: 194040230Sdonn if( ISICON(rp) ) 194140230Sdonn { 194240230Sdonn if(rp->constblock.const.ci == 0) 194340230Sdonn goto retleft; 194440230Sdonn if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) ) 194540230Sdonn { 194640230Sdonn e = mkexpr(OPPLUS, lp->exprblock.rightp, rp); 194740230Sdonn e1 = lp->exprblock.leftp; 194840230Sdonn free( (charptr) lp ); 194940230Sdonn return( mkexpr(OPPLUS, e1, e) ); 195040230Sdonn } 195140230Sdonn } 195240230Sdonn break; 195340230Sdonn 195440230Sdonn 195540230Sdonn case OPPOWER: 195640230Sdonn break; 195740230Sdonn 195840230Sdonn case OPNEG: 195940230Sdonn if(ltag==TEXPR && lp->exprblock.opcode==OPNEG) 196040230Sdonn { 196140230Sdonn e = lp->exprblock.leftp; 196240230Sdonn free( (charptr) lp ); 196340230Sdonn return(e); 196440230Sdonn } 196540230Sdonn break; 196640230Sdonn 196740230Sdonn case OPNOT: 196840230Sdonn if(ltag==TEXPR && lp->exprblock.opcode==OPNOT) 196940230Sdonn { 197040230Sdonn e = lp->exprblock.leftp; 197140230Sdonn free( (charptr) lp ); 197240230Sdonn return(e); 197340230Sdonn } 197440230Sdonn break; 197540230Sdonn 197640230Sdonn case OPCALL: 197740230Sdonn case OPCCALL: 197840230Sdonn etype = ltype; 197940230Sdonn if(rp!=NULL && rp->listblock.listp==NULL) 198040230Sdonn { 198140230Sdonn free( (charptr) rp ); 198240230Sdonn rp = NULL; 198340230Sdonn } 198440230Sdonn break; 198540230Sdonn 198640230Sdonn case OPAND: 198740230Sdonn case OPOR: 198840230Sdonn if( ISCONST(lp) ) 198940230Sdonn COMMUTE 199040230Sdonn 199140230Sdonn if( ISCONST(rp) ) 199240230Sdonn { 199340230Sdonn if(rp->constblock.const.ci == 0) 199440230Sdonn if(opcode == OPOR) 199540230Sdonn goto retleft; 199640230Sdonn else 199740230Sdonn goto retright; 199840230Sdonn else if(opcode == OPOR) 199940230Sdonn goto retright; 200040230Sdonn else 200140230Sdonn goto retleft; 200240230Sdonn } 200340230Sdonn case OPLSHIFT: 200440230Sdonn if (ISICON(rp)) 200540230Sdonn { 200640230Sdonn if (rp->constblock.const.ci == 0) 200740230Sdonn goto retleft; 200840230Sdonn if ((lp->tag == TEXPR) && 200940230Sdonn ((lp->exprblock.opcode == OPPLUS) || 201040230Sdonn (lp->exprblock.opcode == OPMINUS)) && 201140230Sdonn ISICON(lp->exprblock.rightp)) 201240230Sdonn { 201340230Sdonn q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp, 201440230Sdonn cpexpr(rp)); 201540230Sdonn q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp); 201640230Sdonn q = mkexpr(lp->exprblock.opcode, q, q1); 201740230Sdonn free((char *) lp); 201840230Sdonn return q; 201940230Sdonn } 202040230Sdonn } 202140230Sdonn 202240230Sdonn case OPEQV: 202340230Sdonn case OPNEQV: 202440230Sdonn 202540230Sdonn case OPBITAND: 202640230Sdonn case OPBITOR: 202740230Sdonn case OPBITXOR: 202840230Sdonn case OPBITNOT: 202940230Sdonn case OPRSHIFT: 203040230Sdonn 203140230Sdonn case OPLT: 203240230Sdonn case OPGT: 203340230Sdonn case OPLE: 203440230Sdonn case OPGE: 203540230Sdonn case OPEQ: 203640230Sdonn case OPNE: 203740230Sdonn 203840230Sdonn case OPCONCAT: 203940230Sdonn break; 204040230Sdonn case OPMIN: 204140230Sdonn case OPMAX: 204240230Sdonn 204340230Sdonn case OPASSIGN: 204440230Sdonn case OPPLUSEQ: 204540230Sdonn case OPSTAREQ: 204640230Sdonn 204740230Sdonn case OPCONV: 204840230Sdonn case OPADDR: 204940230Sdonn 205040230Sdonn case OPCOMMA: 205140230Sdonn case OPQUEST: 205240230Sdonn case OPCOLON: 205340230Sdonn 205440230Sdonn case OPPAREN: 205540230Sdonn break; 205640230Sdonn 205740230Sdonn default: 205840230Sdonn badop("mkexpr", opcode); 205940230Sdonn } 206040230Sdonn 206140230Sdonn e = (expptr) ALLOC(Exprblock); 206240230Sdonn e->exprblock.tag = TEXPR; 206340230Sdonn e->exprblock.opcode = opcode; 206440230Sdonn e->exprblock.vtype = etype; 206540230Sdonn e->exprblock.leftp = lp; 206640230Sdonn e->exprblock.rightp = rp; 206740230Sdonn if(ltag==TCONST && (rp==0 || rtag==TCONST) ) 206840230Sdonn e = fold(e); 206940230Sdonn return(e); 207040230Sdonn 207140230Sdonn retleft: 207240230Sdonn frexpr(rp); 207340230Sdonn return(lp); 207440230Sdonn 207540230Sdonn retright: 207640230Sdonn frexpr(lp); 207740230Sdonn return(rp); 207840230Sdonn 207940230Sdonn error: 208040230Sdonn frexpr(lp); 208140230Sdonn if(rp && opcode!=OPCALL && opcode!=OPCCALL) 208240230Sdonn frexpr(rp); 208340230Sdonn return( errnode() ); 208440230Sdonn } 208540230Sdonn 208640230Sdonn #define ERR(s) { errs = s; goto error; } 208740230Sdonn 208840230Sdonn cktype(op, lt, rt) 208940230Sdonn register int op, lt, rt; 209040230Sdonn { 209140230Sdonn char *errs; 209240230Sdonn 209340230Sdonn if(lt==TYERROR || rt==TYERROR) 209440230Sdonn goto error1; 209540230Sdonn 209640230Sdonn if(lt==TYUNKNOWN) 209740230Sdonn return(TYUNKNOWN); 209840230Sdonn if(rt==TYUNKNOWN) 209940230Sdonn if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL && 210040230Sdonn op!=OPCCALL && op!=OPADDR && op!=OPPAREN) 210140230Sdonn return(TYUNKNOWN); 210240230Sdonn 210340230Sdonn switch(op) 210440230Sdonn { 210540230Sdonn case OPPLUS: 210640230Sdonn case OPMINUS: 210740230Sdonn case OPSTAR: 210840230Sdonn case OPSLASH: 210940230Sdonn case OPPOWER: 211040230Sdonn case OPMOD: 211140230Sdonn if( ISNUMERIC(lt) && ISNUMERIC(rt) ) 211240230Sdonn return( maxtype(lt, rt) ); 211340230Sdonn ERR("nonarithmetic operand of arithmetic operator") 211440230Sdonn 211540230Sdonn case OPNEG: 211640230Sdonn if( ISNUMERIC(lt) ) 211740230Sdonn return(lt); 211840230Sdonn ERR("nonarithmetic operand of negation") 211940230Sdonn 212040230Sdonn case OPNOT: 212140230Sdonn if(lt == TYLOGICAL) 212240230Sdonn return(TYLOGICAL); 212340230Sdonn ERR("NOT of nonlogical") 212440230Sdonn 212540230Sdonn case OPAND: 212640230Sdonn case OPOR: 212740230Sdonn case OPEQV: 212840230Sdonn case OPNEQV: 212940230Sdonn if(lt==TYLOGICAL && rt==TYLOGICAL) 213040230Sdonn return(TYLOGICAL); 213140230Sdonn ERR("nonlogical operand of logical operator") 213240230Sdonn 213340230Sdonn case OPLT: 213440230Sdonn case OPGT: 213540230Sdonn case OPLE: 213640230Sdonn case OPGE: 213740230Sdonn case OPEQ: 213840230Sdonn case OPNE: 213940230Sdonn if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) 214040230Sdonn { 214140230Sdonn if(lt != rt) 214240230Sdonn ERR("illegal comparison") 214340230Sdonn } 214440230Sdonn 214540230Sdonn else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) ) 214640230Sdonn { 214740230Sdonn if(op!=OPEQ && op!=OPNE) 214840230Sdonn ERR("order comparison of complex data") 214940230Sdonn } 215040230Sdonn 215140230Sdonn else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) ) 215240230Sdonn ERR("comparison of nonarithmetic data") 215340230Sdonn return(TYLOGICAL); 215440230Sdonn 215540230Sdonn case OPCONCAT: 215640230Sdonn if(lt==TYCHAR && rt==TYCHAR) 215740230Sdonn return(TYCHAR); 215840230Sdonn ERR("concatenation of nonchar data") 215940230Sdonn 216040230Sdonn case OPCALL: 216140230Sdonn case OPCCALL: 216240230Sdonn return(lt); 216340230Sdonn 216440230Sdonn case OPADDR: 216540230Sdonn return(TYADDR); 216640230Sdonn 216740230Sdonn case OPCONV: 216840230Sdonn if(ISCOMPLEX(lt)) 216940230Sdonn { 217040230Sdonn if(ISNUMERIC(rt)) 217140230Sdonn return(lt); 217240230Sdonn ERR("impossible conversion") 217340230Sdonn } 217440230Sdonn if(rt == 0) 217540230Sdonn return(0); 217640230Sdonn if(lt==TYCHAR && ISINT(rt) ) 217740230Sdonn return(TYCHAR); 217840230Sdonn case OPASSIGN: 217940230Sdonn case OPPLUSEQ: 218040230Sdonn case OPSTAREQ: 218140230Sdonn if( ISINT(lt) && rt==TYCHAR) 218240230Sdonn return(lt); 218340230Sdonn if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) 218440230Sdonn if(op!=OPASSIGN || lt!=rt) 218540230Sdonn { 218640230Sdonn /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */ 218740230Sdonn /* debug fatal("impossible conversion. possible compiler bug"); */ 218840230Sdonn ERR("impossible conversion") 218940230Sdonn } 219040230Sdonn return(lt); 219140230Sdonn 219240230Sdonn case OPMIN: 219340230Sdonn case OPMAX: 219440230Sdonn case OPBITOR: 219540230Sdonn case OPBITAND: 219640230Sdonn case OPBITXOR: 219740230Sdonn case OPBITNOT: 219840230Sdonn case OPLSHIFT: 219940230Sdonn case OPRSHIFT: 220040230Sdonn case OPPAREN: 220140230Sdonn return(lt); 220240230Sdonn 220340230Sdonn case OPCOMMA: 220440230Sdonn case OPQUEST: 220540230Sdonn case OPCOLON: 220640230Sdonn return(rt); 220740230Sdonn 220840230Sdonn default: 220940230Sdonn badop("cktype", op); 221040230Sdonn } 221140230Sdonn error: err(errs); 221240230Sdonn error1: return(TYERROR); 221340230Sdonn } 221440230Sdonn 221540230Sdonn LOCAL expptr fold(e) 221640230Sdonn register expptr e; 221740230Sdonn { 221840230Sdonn Constp p; 221940230Sdonn register expptr lp, rp; 222040230Sdonn int etype, mtype, ltype, rtype, opcode; 222140230Sdonn int i, ll, lr; 222240230Sdonn char *q, *s; 222340230Sdonn union Constant lcon, rcon; 222440230Sdonn 222540230Sdonn opcode = e->exprblock.opcode; 222640230Sdonn etype = e->exprblock.vtype; 222740230Sdonn 222840230Sdonn lp = e->exprblock.leftp; 222940230Sdonn ltype = lp->headblock.vtype; 223040230Sdonn rp = e->exprblock.rightp; 223140230Sdonn 223240230Sdonn if(rp == 0) 223340230Sdonn switch(opcode) 223440230Sdonn { 223540230Sdonn case OPNOT: 223640230Sdonn lp->constblock.const.ci = ! lp->constblock.const.ci; 223740230Sdonn return(lp); 223840230Sdonn 223940230Sdonn case OPBITNOT: 224040230Sdonn lp->constblock.const.ci = ~ lp->constblock.const.ci; 224140230Sdonn return(lp); 224240230Sdonn 224340230Sdonn case OPNEG: 224440230Sdonn consnegop(lp); 224540230Sdonn return(lp); 224640230Sdonn 224740230Sdonn case OPCONV: 224840230Sdonn case OPADDR: 224940230Sdonn case OPPAREN: 225040230Sdonn return(e); 225140230Sdonn 225240230Sdonn default: 225340230Sdonn badop("fold", opcode); 225440230Sdonn } 225540230Sdonn 225640230Sdonn rtype = rp->headblock.vtype; 225740230Sdonn 225840230Sdonn p = ALLOC(Constblock); 225940230Sdonn p->tag = TCONST; 226040230Sdonn p->vtype = etype; 226140230Sdonn p->vleng = e->exprblock.vleng; 226240230Sdonn 226340230Sdonn switch(opcode) 226440230Sdonn { 226540230Sdonn case OPCOMMA: 226640230Sdonn case OPQUEST: 226740230Sdonn case OPCOLON: 226840230Sdonn return(e); 226940230Sdonn 227040230Sdonn case OPAND: 227140230Sdonn p->const.ci = lp->constblock.const.ci && 227240230Sdonn rp->constblock.const.ci; 227340230Sdonn break; 227440230Sdonn 227540230Sdonn case OPOR: 227640230Sdonn p->const.ci = lp->constblock.const.ci || 227740230Sdonn rp->constblock.const.ci; 227840230Sdonn break; 227940230Sdonn 228040230Sdonn case OPEQV: 228140230Sdonn p->const.ci = lp->constblock.const.ci == 228240230Sdonn rp->constblock.const.ci; 228340230Sdonn break; 228440230Sdonn 228540230Sdonn case OPNEQV: 228640230Sdonn p->const.ci = lp->constblock.const.ci != 228740230Sdonn rp->constblock.const.ci; 228840230Sdonn break; 228940230Sdonn 229040230Sdonn case OPBITAND: 229140230Sdonn p->const.ci = lp->constblock.const.ci & 229240230Sdonn rp->constblock.const.ci; 229340230Sdonn break; 229440230Sdonn 229540230Sdonn case OPBITOR: 229640230Sdonn p->const.ci = lp->constblock.const.ci | 229740230Sdonn rp->constblock.const.ci; 229840230Sdonn break; 229940230Sdonn 230040230Sdonn case OPBITXOR: 230140230Sdonn p->const.ci = lp->constblock.const.ci ^ 230240230Sdonn rp->constblock.const.ci; 230340230Sdonn break; 230440230Sdonn 230540230Sdonn case OPLSHIFT: 230640230Sdonn p->const.ci = lp->constblock.const.ci << 230740230Sdonn rp->constblock.const.ci; 230840230Sdonn break; 230940230Sdonn 231040230Sdonn case OPRSHIFT: 231140230Sdonn p->const.ci = lp->constblock.const.ci >> 231240230Sdonn rp->constblock.const.ci; 231340230Sdonn break; 231440230Sdonn 231540230Sdonn case OPCONCAT: 231640230Sdonn ll = lp->constblock.vleng->constblock.const.ci; 231740230Sdonn lr = rp->constblock.vleng->constblock.const.ci; 231840230Sdonn p->const.ccp = q = (char *) ckalloc(ll+lr); 231940230Sdonn p->vleng = ICON(ll+lr); 232040230Sdonn s = lp->constblock.const.ccp; 232140230Sdonn for(i = 0 ; i < ll ; ++i) 232240230Sdonn *q++ = *s++; 232340230Sdonn s = rp->constblock.const.ccp; 232440230Sdonn for(i = 0; i < lr; ++i) 232540230Sdonn *q++ = *s++; 232640230Sdonn break; 232740230Sdonn 232840230Sdonn 232940230Sdonn case OPPOWER: 233040230Sdonn if( ! ISINT(rtype) ) 233140230Sdonn return(e); 233240230Sdonn conspower(&(p->const), lp, rp->constblock.const.ci); 233340230Sdonn break; 233440230Sdonn 233540230Sdonn 233640230Sdonn default: 233740230Sdonn if(ltype == TYCHAR) 233840230Sdonn { 233940230Sdonn lcon.ci = cmpstr(lp->constblock.const.ccp, 234040230Sdonn rp->constblock.const.ccp, 234140230Sdonn lp->constblock.vleng->constblock.const.ci, 234240230Sdonn rp->constblock.vleng->constblock.const.ci); 234340230Sdonn rcon.ci = 0; 234440230Sdonn mtype = tyint; 234540230Sdonn } 234640230Sdonn else { 234740230Sdonn mtype = maxtype(ltype, rtype); 234840230Sdonn consconv(mtype, &lcon, ltype, &(lp->constblock.const) ); 234940230Sdonn consconv(mtype, &rcon, rtype, &(rp->constblock.const) ); 235040230Sdonn } 235140230Sdonn consbinop(opcode, mtype, &(p->const), &lcon, &rcon); 235240230Sdonn break; 235340230Sdonn } 235440230Sdonn 235540230Sdonn frexpr(e); 235640230Sdonn return( (expptr) p ); 235740230Sdonn } 235840230Sdonn 235940230Sdonn 236040230Sdonn 236140230Sdonn /* assign constant l = r , doing coercion */ 236240230Sdonn 236340230Sdonn consconv(lt, lv, rt, rv) 236440230Sdonn int lt, rt; 236540230Sdonn register union Constant *lv, *rv; 236640230Sdonn { 236740230Sdonn switch(lt) 236840230Sdonn { 236940230Sdonn case TYCHAR: 237040230Sdonn *(lv->ccp = (char *) ckalloc(1)) = rv->ci; 237140230Sdonn break; 237240230Sdonn 237340230Sdonn case TYSHORT: 237440230Sdonn case TYLONG: 237540230Sdonn if(rt == TYCHAR) 237640230Sdonn lv->ci = rv->ccp[0]; 237740230Sdonn else if( ISINT(rt) ) 237840230Sdonn lv->ci = rv->ci; 237940230Sdonn else lv->ci = rv->cd[0]; 238040230Sdonn break; 238140230Sdonn 238240230Sdonn case TYCOMPLEX: 238340230Sdonn case TYDCOMPLEX: 238440230Sdonn switch(rt) 238540230Sdonn { 238640230Sdonn case TYSHORT: 238740230Sdonn case TYLONG: 238840230Sdonn /* fall through and do real assignment of 238940230Sdonn first element 239040230Sdonn */ 239140230Sdonn case TYREAL: 239240230Sdonn case TYDREAL: 239340230Sdonn lv->cd[1] = 0; break; 239440230Sdonn case TYCOMPLEX: 239540230Sdonn case TYDCOMPLEX: 239640230Sdonn lv->cd[1] = rv->cd[1]; break; 239740230Sdonn } 239840230Sdonn 239940230Sdonn case TYREAL: 240040230Sdonn case TYDREAL: 240140230Sdonn if( ISINT(rt) ) 240240230Sdonn lv->cd[0] = rv->ci; 240340230Sdonn else lv->cd[0] = rv->cd[0]; 240440230Sdonn if( lt == TYREAL) 240540230Sdonn { 240640230Sdonn float f = lv->cd[0]; 240740230Sdonn lv->cd[0] = f; 240840230Sdonn } 240940230Sdonn break; 241040230Sdonn 241140230Sdonn case TYLOGICAL: 241240230Sdonn lv->ci = rv->ci; 241340230Sdonn break; 241440230Sdonn } 241540230Sdonn } 241640230Sdonn 241740230Sdonn 241840230Sdonn 241940230Sdonn consnegop(p) 242040230Sdonn register Constp p; 242140230Sdonn { 242240230Sdonn switch(p->vtype) 242340230Sdonn { 242440230Sdonn case TYSHORT: 242540230Sdonn case TYLONG: 242640230Sdonn p->const.ci = - p->const.ci; 242740230Sdonn break; 242840230Sdonn 242940230Sdonn case TYCOMPLEX: 243040230Sdonn case TYDCOMPLEX: 243140230Sdonn p->const.cd[1] = - p->const.cd[1]; 243240230Sdonn /* fall through and do the real parts */ 243340230Sdonn case TYREAL: 243440230Sdonn case TYDREAL: 243540230Sdonn p->const.cd[0] = - p->const.cd[0]; 243640230Sdonn break; 243740230Sdonn default: 243840230Sdonn badtype("consnegop", p->vtype); 243940230Sdonn } 244040230Sdonn } 244140230Sdonn 244240230Sdonn 244340230Sdonn 244440230Sdonn LOCAL conspower(powp, ap, n) 244540230Sdonn register union Constant *powp; 244640230Sdonn Constp ap; 244740230Sdonn ftnint n; 244840230Sdonn { 244940230Sdonn register int type; 245040230Sdonn union Constant x; 245140230Sdonn 245240230Sdonn switch(type = ap->vtype) /* pow = 1 */ 245340230Sdonn { 245440230Sdonn case TYSHORT: 245540230Sdonn case TYLONG: 245640230Sdonn powp->ci = 1; 245740230Sdonn break; 245840230Sdonn case TYCOMPLEX: 245940230Sdonn case TYDCOMPLEX: 246040230Sdonn powp->cd[1] = 0; 246140230Sdonn case TYREAL: 246240230Sdonn case TYDREAL: 246340230Sdonn powp->cd[0] = 1; 246440230Sdonn break; 246540230Sdonn default: 246640230Sdonn badtype("conspower", type); 246740230Sdonn } 246840230Sdonn 246940230Sdonn if(n == 0) 247040230Sdonn return; 247140230Sdonn if(n < 0) 247240230Sdonn { 247340230Sdonn if( ISINT(type) ) 247440230Sdonn { 247540230Sdonn if (ap->const.ci == 0) 247640230Sdonn err("zero raised to a negative power"); 247740230Sdonn else if (ap->const.ci == 1) 247840230Sdonn return; 247940230Sdonn else if (ap->const.ci == -1) 248040230Sdonn { 248140230Sdonn if (n < -2) 248240230Sdonn n = n + 2; 248340230Sdonn n = -n; 248440230Sdonn if (n % 2 == 1) 248540230Sdonn powp->ci = -1; 248640230Sdonn } 248740230Sdonn else 248840230Sdonn powp->ci = 0; 248940230Sdonn return; 249040230Sdonn } 249140230Sdonn n = - n; 249240230Sdonn consbinop(OPSLASH, type, &x, powp, &(ap->const)); 249340230Sdonn } 249440230Sdonn else 249540230Sdonn consbinop(OPSTAR, type, &x, powp, &(ap->const)); 249640230Sdonn 249740230Sdonn for( ; ; ) 249840230Sdonn { 249940230Sdonn if(n & 01) 250040230Sdonn consbinop(OPSTAR, type, powp, powp, &x); 250140230Sdonn if(n >>= 1) 250240230Sdonn consbinop(OPSTAR, type, &x, &x, &x); 250340230Sdonn else 250440230Sdonn break; 250540230Sdonn } 250640230Sdonn } 250740230Sdonn 250840230Sdonn 250940230Sdonn 251040230Sdonn /* do constant operation cp = a op b */ 251140230Sdonn 251240230Sdonn 251340230Sdonn LOCAL consbinop(opcode, type, cp, ap, bp) 251440230Sdonn int opcode, type; 251540230Sdonn register union Constant *ap, *bp, *cp; 251640230Sdonn { 251740230Sdonn int k; 251840230Sdonn double temp; 251940230Sdonn 252040230Sdonn switch(opcode) 252140230Sdonn { 252240230Sdonn case OPPLUS: 252340230Sdonn switch(type) 252440230Sdonn { 252540230Sdonn case TYSHORT: 252640230Sdonn case TYLONG: 252740230Sdonn cp->ci = ap->ci + bp->ci; 252840230Sdonn break; 252940230Sdonn case TYCOMPLEX: 253040230Sdonn case TYDCOMPLEX: 253140230Sdonn cp->cd[1] = ap->cd[1] + bp->cd[1]; 253240230Sdonn case TYREAL: 253340230Sdonn case TYDREAL: 253440230Sdonn cp->cd[0] = ap->cd[0] + bp->cd[0]; 253540230Sdonn break; 253640230Sdonn } 253740230Sdonn break; 253840230Sdonn 253940230Sdonn case OPMINUS: 254040230Sdonn switch(type) 254140230Sdonn { 254240230Sdonn case TYSHORT: 254340230Sdonn case TYLONG: 254440230Sdonn cp->ci = ap->ci - bp->ci; 254540230Sdonn break; 254640230Sdonn case TYCOMPLEX: 254740230Sdonn case TYDCOMPLEX: 254840230Sdonn cp->cd[1] = ap->cd[1] - bp->cd[1]; 254940230Sdonn case TYREAL: 255040230Sdonn case TYDREAL: 255140230Sdonn cp->cd[0] = ap->cd[0] - bp->cd[0]; 255240230Sdonn break; 255340230Sdonn } 255440230Sdonn break; 255540230Sdonn 255640230Sdonn case OPSTAR: 255740230Sdonn switch(type) 255840230Sdonn { 255940230Sdonn case TYSHORT: 256040230Sdonn case TYLONG: 256140230Sdonn cp->ci = ap->ci * bp->ci; 256240230Sdonn break; 256340230Sdonn case TYREAL: 256440230Sdonn case TYDREAL: 256540230Sdonn cp->cd[0] = ap->cd[0] * bp->cd[0]; 256640230Sdonn break; 256740230Sdonn case TYCOMPLEX: 256840230Sdonn case TYDCOMPLEX: 256940230Sdonn temp = ap->cd[0] * bp->cd[0] - 257040230Sdonn ap->cd[1] * bp->cd[1] ; 257140230Sdonn cp->cd[1] = ap->cd[0] * bp->cd[1] + 257240230Sdonn ap->cd[1] * bp->cd[0] ; 257340230Sdonn cp->cd[0] = temp; 257440230Sdonn break; 257540230Sdonn } 257640230Sdonn break; 257740230Sdonn case OPSLASH: 257840230Sdonn switch(type) 257940230Sdonn { 258040230Sdonn case TYSHORT: 258140230Sdonn case TYLONG: 258240230Sdonn cp->ci = ap->ci / bp->ci; 258340230Sdonn break; 258440230Sdonn case TYREAL: 258540230Sdonn case TYDREAL: 258640230Sdonn cp->cd[0] = ap->cd[0] / bp->cd[0]; 258740230Sdonn break; 258840230Sdonn case TYCOMPLEX: 258940230Sdonn case TYDCOMPLEX: 259040230Sdonn zdiv(cp,ap,bp); 259140230Sdonn break; 259240230Sdonn } 259340230Sdonn break; 259440230Sdonn 259540230Sdonn case OPMOD: 259640230Sdonn if( ISINT(type) ) 259740230Sdonn { 259840230Sdonn cp->ci = ap->ci % bp->ci; 259940230Sdonn break; 260040230Sdonn } 260140230Sdonn else 260240230Sdonn fatal("inline mod of noninteger"); 260340230Sdonn 260440230Sdonn default: /* relational ops */ 260540230Sdonn switch(type) 260640230Sdonn { 260740230Sdonn case TYSHORT: 260840230Sdonn case TYLONG: 260940230Sdonn if(ap->ci < bp->ci) 261040230Sdonn k = -1; 261140230Sdonn else if(ap->ci == bp->ci) 261240230Sdonn k = 0; 261340230Sdonn else k = 1; 261440230Sdonn break; 261540230Sdonn case TYREAL: 261640230Sdonn case TYDREAL: 261740230Sdonn if(ap->cd[0] < bp->cd[0]) 261840230Sdonn k = -1; 261940230Sdonn else if(ap->cd[0] == bp->cd[0]) 262040230Sdonn k = 0; 262140230Sdonn else k = 1; 262240230Sdonn break; 262340230Sdonn case TYCOMPLEX: 262440230Sdonn case TYDCOMPLEX: 262540230Sdonn if(ap->cd[0] == bp->cd[0] && 262640230Sdonn ap->cd[1] == bp->cd[1] ) 262740230Sdonn k = 0; 262840230Sdonn else k = 1; 262940230Sdonn break; 263040230Sdonn } 263140230Sdonn 263240230Sdonn switch(opcode) 263340230Sdonn { 263440230Sdonn case OPEQ: 263540230Sdonn cp->ci = (k == 0); 263640230Sdonn break; 263740230Sdonn case OPNE: 263840230Sdonn cp->ci = (k != 0); 263940230Sdonn break; 264040230Sdonn case OPGT: 264140230Sdonn cp->ci = (k == 1); 264240230Sdonn break; 264340230Sdonn case OPLT: 264440230Sdonn cp->ci = (k == -1); 264540230Sdonn break; 264640230Sdonn case OPGE: 264740230Sdonn cp->ci = (k >= 0); 264840230Sdonn break; 264940230Sdonn case OPLE: 265040230Sdonn cp->ci = (k <= 0); 265140230Sdonn break; 265240230Sdonn default: 265340230Sdonn badop ("consbinop", opcode); 265440230Sdonn } 265540230Sdonn break; 265640230Sdonn } 265740230Sdonn } 265840230Sdonn 265940230Sdonn 266040230Sdonn 266140230Sdonn 266240230Sdonn conssgn(p) 266340230Sdonn register expptr p; 266440230Sdonn { 266540230Sdonn if( ! ISCONST(p) ) 266640230Sdonn fatal( "sgn(nonconstant)" ); 266740230Sdonn 266840230Sdonn switch(p->headblock.vtype) 266940230Sdonn { 267040230Sdonn case TYSHORT: 267140230Sdonn case TYLONG: 267240230Sdonn if(p->constblock.const.ci > 0) return(1); 267340230Sdonn if(p->constblock.const.ci < 0) return(-1); 267440230Sdonn return(0); 267540230Sdonn 267640230Sdonn case TYREAL: 267740230Sdonn case TYDREAL: 267840230Sdonn if(p->constblock.const.cd[0] > 0) return(1); 267940230Sdonn if(p->constblock.const.cd[0] < 0) return(-1); 268040230Sdonn return(0); 268140230Sdonn 268240230Sdonn case TYCOMPLEX: 268340230Sdonn case TYDCOMPLEX: 268440230Sdonn return(p->constblock.const.cd[0]!=0 || p->constblock.const.cd[1]!=0); 268540230Sdonn 268640230Sdonn default: 268740230Sdonn badtype( "conssgn", p->constblock.vtype); 268840230Sdonn } 268940230Sdonn /* NOTREACHED */ 269040230Sdonn } 269140230Sdonn 269240230Sdonn char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" }; 269340230Sdonn 269440230Sdonn 269540230Sdonn LOCAL expptr mkpower(p) 269640230Sdonn register expptr p; 269740230Sdonn { 269840230Sdonn register expptr q, lp, rp; 269940230Sdonn int ltype, rtype, mtype; 270040230Sdonn 270140230Sdonn lp = p->exprblock.leftp; 270240230Sdonn rp = p->exprblock.rightp; 270340230Sdonn ltype = lp->headblock.vtype; 270440230Sdonn rtype = rp->headblock.vtype; 270540230Sdonn 270640230Sdonn if(ISICON(rp)) 270740230Sdonn { 270840230Sdonn if(rp->constblock.const.ci == 0) 270940230Sdonn { 271040230Sdonn frexpr(p); 271140230Sdonn if( ISINT(ltype) ) 271240230Sdonn return( ICON(1) ); 271340230Sdonn else 271440230Sdonn { 271540230Sdonn expptr pp; 271640230Sdonn pp = mkconv(ltype, ICON(1)); 271740230Sdonn return( pp ); 271840230Sdonn } 271940230Sdonn } 272040230Sdonn if(rp->constblock.const.ci < 0) 272140230Sdonn { 272240230Sdonn if( ISINT(ltype) ) 272340230Sdonn { 272440230Sdonn frexpr(p); 272540230Sdonn err("integer**negative"); 272640230Sdonn return( errnode() ); 272740230Sdonn } 272840230Sdonn rp->constblock.const.ci = - rp->constblock.const.ci; 272940230Sdonn p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp)); 273040230Sdonn } 273140230Sdonn if(rp->constblock.const.ci == 1) 273240230Sdonn { 273340230Sdonn frexpr(rp); 273440230Sdonn free( (charptr) p ); 273540230Sdonn return(lp); 273640230Sdonn } 273740230Sdonn 273840230Sdonn if( ONEOF(ltype, MSKINT|MSKREAL) ) 273940230Sdonn { 274040230Sdonn p->exprblock.vtype = ltype; 274140230Sdonn return(p); 274240230Sdonn } 274340230Sdonn } 274440230Sdonn if( ISINT(rtype) ) 274540230Sdonn { 274640230Sdonn if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) ) 274740230Sdonn q = call2(TYSHORT, "pow_hh", lp, rp); 274840230Sdonn else { 274940230Sdonn if(ltype == TYSHORT) 275040230Sdonn { 275140230Sdonn ltype = TYLONG; 275240230Sdonn lp = mkconv(TYLONG,lp); 275340230Sdonn } 275440230Sdonn q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp)); 275540230Sdonn } 275640230Sdonn } 275740230Sdonn else if( ISREAL( (mtype = maxtype(ltype,rtype)) )) 275840230Sdonn q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp)); 275940230Sdonn else { 276040230Sdonn q = call2(TYDCOMPLEX, "pow_zz", 276140230Sdonn mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp)); 276240230Sdonn if(mtype == TYCOMPLEX) 276340230Sdonn q = mkconv(TYCOMPLEX, q); 276440230Sdonn } 276540230Sdonn free( (charptr) p ); 276640230Sdonn return(q); 276740230Sdonn } 276840230Sdonn 276940230Sdonn 277040230Sdonn 277140230Sdonn /* Complex Division. Same code as in Runtime Library 277240230Sdonn */ 277340230Sdonn 277440230Sdonn struct dcomplex { double dreal, dimag; }; 277540230Sdonn 277640230Sdonn 277740230Sdonn LOCAL zdiv(c, a, b) 277840230Sdonn register struct dcomplex *a, *b, *c; 277940230Sdonn { 278040230Sdonn double ratio, den; 278140230Sdonn double abr, abi; 278240230Sdonn 278340230Sdonn if( (abr = b->dreal) < 0.) 278440230Sdonn abr = - abr; 278540230Sdonn if( (abi = b->dimag) < 0.) 278640230Sdonn abi = - abi; 278740230Sdonn if( abr <= abi ) 278840230Sdonn { 278940230Sdonn if(abi == 0) 279040230Sdonn fatal("complex division by zero"); 279140230Sdonn ratio = b->dreal / b->dimag ; 279240230Sdonn den = b->dimag * (1 + ratio*ratio); 279340230Sdonn c->dreal = (a->dreal*ratio + a->dimag) / den; 279440230Sdonn c->dimag = (a->dimag*ratio - a->dreal) / den; 279540230Sdonn } 279640230Sdonn 279740230Sdonn else 279840230Sdonn { 279940230Sdonn ratio = b->dimag / b->dreal ; 280040230Sdonn den = b->dreal * (1 + ratio*ratio); 280140230Sdonn c->dreal = (a->dreal + a->dimag*ratio) / den; 280240230Sdonn c->dimag = (a->dimag - a->dreal*ratio) / den; 280340230Sdonn } 280440230Sdonn 280540230Sdonn } 280640230Sdonn 280740230Sdonn expptr oftwo(e) 280840230Sdonn expptr e; 280940230Sdonn { 281040230Sdonn int val,res; 281140230Sdonn 281240230Sdonn if (! ISCONST (e)) 281340230Sdonn return (0); 281440230Sdonn 281540230Sdonn val = e->constblock.const.ci; 281640230Sdonn switch (val) 281740230Sdonn { 281840230Sdonn case 2: res = 1; break; 281940230Sdonn case 4: res = 2; break; 282040230Sdonn case 8: res = 3; break; 282140230Sdonn case 16: res = 4; break; 282240230Sdonn case 32: res = 5; break; 282340230Sdonn case 64: res = 6; break; 282440230Sdonn case 128: res = 7; break; 282540230Sdonn case 256: res = 8; break; 282640230Sdonn default: return (0); 282740230Sdonn } 282840230Sdonn return (ICON (res)); 282940230Sdonn } 2830