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); 140*46303Sbostic p->constant.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); 163*46303Sbostic p->constant.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); 175*46303Sbostic p->constant.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); 188*46303Sbostic p->constant.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); 240*46303Sbostic p->constant.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); 256*46303Sbostic p->constant.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) ) 276*46303Sbostic p->constant.cd[0] = realp->constblock.constant.ci; 277*46303Sbostic else p->constant.cd[0] = realp->constblock.constant.cd[0]; 27840230Sdonn if( ISINT(itype) ) 279*46303Sbostic p->constant.cd[1] = imagp->constblock.constant.ci; 280*46303Sbostic else p->constant.cd[1] = imagp->constblock.constant.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); 352*46303Sbostic consconv(t, &(q->constblock.constant), 353*46303Sbostic p->constblock.vtype, &(p->constblock.constant) ); 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); 392*46303Sbostic consconv(t, &(q->constblock.constant), 393*46303Sbostic p->constblock.vtype, &(p->constblock.constant) ); 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 { 468*46303Sbostic e->constblock.constant.ccp = 469*46303Sbostic copyn(1+strlen(e->constblock.constant.ccp), 470*46303Sbostic e->constblock.constant.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: 534*46303Sbostic free( (charptr) (p->constblock.constant.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 { 1497*46303Sbostic if(p->constblock.constant.ci < 0) 149840230Sdonn goto badsub; 149940230Sdonn if( ISICON(dimp->nelt) ) 1500*46303Sbostic if(p->constblock.constant.ci < 1501*46303Sbostic dimp->nelt->constblock.constant.ci) 150240230Sdonn return(p); 150340230Sdonn else 150440230Sdonn goto badsub; 150540230Sdonn } 150640230Sdonn if(p->tag==TADDR && p->addrblock.vstg==STGREG) 150740230Sdonn { 150840230Sdonn checkvar = (expptr) cpexpr(p); 150940230Sdonn t = p; 151040230Sdonn } 151140230Sdonn else { 151240230Sdonn checkvar = (expptr) mktemp(p->headblock.vtype, ENULL); 151340230Sdonn t = mkexpr(OPASSIGN, cpexpr(checkvar), p); 151440230Sdonn } 151540230Sdonn checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) ); 151640230Sdonn if( ! ISICON(p) ) 151740230Sdonn checkcond = mkexpr(OPAND, checkcond, 151840230Sdonn mkexpr(OPLE, ICON(0), cpexpr(checkvar)) ); 151940230Sdonn 152040230Sdonn badcall = call4(p->headblock.vtype, "s_rnge", 152140230Sdonn mkstrcon(VL, np->varname), 152240230Sdonn mkconv(TYLONG, cpexpr(checkvar)), 152340230Sdonn mkstrcon(XL, procname), 152440230Sdonn ICON(lineno) ); 152540230Sdonn badcall->exprblock.opcode = OPCCALL; 152640230Sdonn p = mkexpr(OPQUEST, checkcond, 152740230Sdonn mkexpr(OPCOLON, checkvar, badcall)); 152840230Sdonn 152940230Sdonn return(p); 153040230Sdonn 153140230Sdonn badsub: 153240230Sdonn frexpr(p); 153340230Sdonn errstr("subscript on variable %s out of range", varstr(VL,np->varname)); 153440230Sdonn return ( ICON(0) ); 153540230Sdonn } 153640230Sdonn 153740230Sdonn 153840230Sdonn 153940230Sdonn 154040230Sdonn Addrp mkaddr(p) 154140230Sdonn register Namep p; 154240230Sdonn { 154340230Sdonn struct Extsym *extp; 154440230Sdonn register Addrp t; 154540230Sdonn Addrp intraddr(); 154640230Sdonn 154740230Sdonn switch( p->vstg) 154840230Sdonn { 154940230Sdonn case STGUNKNOWN: 155040230Sdonn if(p->vclass != CLPROC) 155140230Sdonn break; 155240230Sdonn extp = mkext( varunder(VL, p->varname) ); 155340230Sdonn extp->extstg = STGEXT; 155440230Sdonn p->vstg = STGEXT; 155540230Sdonn p->vardesc.varno = extp - extsymtab; 155640230Sdonn p->vprocclass = PEXTERNAL; 155740230Sdonn 155840230Sdonn case STGCOMMON: 155940230Sdonn case STGEXT: 156040230Sdonn case STGBSS: 156140230Sdonn case STGINIT: 156240230Sdonn case STGEQUIV: 156340230Sdonn case STGARG: 156440230Sdonn case STGLENG: 156540230Sdonn case STGAUTO: 156640230Sdonn t = ALLOC(Addrblock); 156740230Sdonn t->tag = TADDR; 156840230Sdonn if(p->vclass==CLPROC && p->vprocclass==PTHISPROC) 156940230Sdonn t->vclass = CLVAR; 157040230Sdonn else 157140230Sdonn t->vclass = p->vclass; 157240230Sdonn t->vtype = p->vtype; 157340230Sdonn t->vstg = p->vstg; 157440230Sdonn t->memno = p->vardesc.varno; 157540230Sdonn t->issaved = p->vsave; 157640230Sdonn if(p->vdim) t->isarray = YES; 157740230Sdonn t->memoffset = ICON(p->voffset); 157840230Sdonn if(p->vleng) 157940230Sdonn { 158040230Sdonn t->vleng = (expptr) cpexpr(p->vleng); 158140230Sdonn if( ISICON(t->vleng) ) 1582*46303Sbostic t->varleng = t->vleng->constblock.constant.ci; 158340230Sdonn } 158440230Sdonn if (p->vstg == STGBSS) 158540230Sdonn t->varsize = p->varsize; 158640230Sdonn else if (p->vstg == STGEQUIV) 158740230Sdonn t->varsize = eqvclass[t->memno].eqvleng; 158840230Sdonn return(t); 158940230Sdonn 159040230Sdonn case STGINTR: 159140230Sdonn return( intraddr(p) ); 159240230Sdonn 159340230Sdonn } 159440230Sdonn /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass); 159540230Sdonn badstg("mkaddr", p->vstg); 159640230Sdonn /* NOTREACHED */ 159740230Sdonn } 159840230Sdonn 159940230Sdonn 160040230Sdonn 160140230Sdonn 160240230Sdonn Addrp mkarg(type, argno) 160340230Sdonn int type, argno; 160440230Sdonn { 160540230Sdonn register Addrp p; 160640230Sdonn 160740230Sdonn p = ALLOC(Addrblock); 160840230Sdonn p->tag = TADDR; 160940230Sdonn p->vtype = type; 161040230Sdonn p->vclass = CLVAR; 161140230Sdonn p->vstg = (type==TYLENG ? STGLENG : STGARG); 161240230Sdonn p->memno = argno; 161340230Sdonn return(p); 161440230Sdonn } 161540230Sdonn 161640230Sdonn 161740230Sdonn 161840230Sdonn 161940230Sdonn expptr mkprim(v, args, substr) 162040230Sdonn register union 162140230Sdonn { 162240230Sdonn struct Paramblock paramblock; 162340230Sdonn struct Nameblock nameblock; 162440230Sdonn struct Headblock headblock; 162540230Sdonn } *v; 162640230Sdonn struct Listblock *args; 162740230Sdonn chainp substr; 162840230Sdonn { 162940230Sdonn register struct Primblock *p; 163040230Sdonn 163140230Sdonn if(v->headblock.vclass == CLPARAM) 163240230Sdonn { 163340230Sdonn if(args || substr) 163440230Sdonn { 163540230Sdonn errstr("no qualifiers on parameter name %s", 163640230Sdonn varstr(VL,v->paramblock.varname)); 163740230Sdonn frexpr(args); 163840230Sdonn if(substr) 163940230Sdonn { 164040230Sdonn frexpr(substr->datap); 164140230Sdonn frexpr(substr->nextp->datap); 164240230Sdonn frchain(&substr); 164340230Sdonn } 164440230Sdonn frexpr(v); 164540230Sdonn return( errnode() ); 164640230Sdonn } 164740230Sdonn return( (expptr) cpexpr(v->paramblock.paramval) ); 164840230Sdonn } 164940230Sdonn 165040230Sdonn p = ALLOC(Primblock); 165140230Sdonn p->tag = TPRIM; 165240230Sdonn p->vtype = v->nameblock.vtype; 165340230Sdonn p->namep = (Namep) v; 165440230Sdonn p->argsp = args; 165540230Sdonn if(substr) 165640230Sdonn { 165740230Sdonn p->fcharp = (expptr) substr->datap; 165840231Sdonn if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype)) 165940230Sdonn p->fcharp = mkconv(TYINT, p->fcharp); 166040230Sdonn p->lcharp = (expptr) substr->nextp->datap; 166140231Sdonn if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype)) 166240230Sdonn p->lcharp = mkconv(TYINT, p->lcharp); 166340230Sdonn frchain(&substr); 166440230Sdonn } 166540230Sdonn return( (expptr) p); 166640230Sdonn } 166740230Sdonn 166840230Sdonn 166940230Sdonn 167040230Sdonn vardcl(v) 167140230Sdonn register Namep v; 167240230Sdonn { 167340230Sdonn int nelt; 167440230Sdonn struct Dimblock *t; 167540230Sdonn Addrp p; 167640230Sdonn expptr neltp; 167740230Sdonn int eltsize; 167840230Sdonn int varsize; 167940230Sdonn int tsize; 168040230Sdonn int align; 168140230Sdonn 168240230Sdonn if(v->vdcldone) 168340230Sdonn return; 168440230Sdonn if(v->vclass == CLNAMELIST) 168540230Sdonn return; 168640230Sdonn 168740230Sdonn if(v->vtype == TYUNKNOWN) 168840230Sdonn impldcl(v); 168940230Sdonn if(v->vclass == CLUNKNOWN) 169040230Sdonn v->vclass = CLVAR; 169140230Sdonn else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC) 169240230Sdonn { 169340230Sdonn dclerr("used both as variable and non-variable", v); 169440230Sdonn return; 169540230Sdonn } 169640230Sdonn if(v->vstg==STGUNKNOWN) 169740230Sdonn v->vstg = implstg[ letter(v->varname[0]) ]; 169840230Sdonn 169940230Sdonn switch(v->vstg) 170040230Sdonn { 170140230Sdonn case STGBSS: 170240230Sdonn v->vardesc.varno = ++lastvarno; 170340230Sdonn if (v->vclass != CLVAR) 170440230Sdonn break; 170540230Sdonn nelt = 1; 170640230Sdonn t = v->vdim; 170740230Sdonn if (t) 170840230Sdonn { 170940230Sdonn neltp = t->nelt; 171040230Sdonn if (neltp && ISICON(neltp)) 1711*46303Sbostic nelt = neltp->constblock.constant.ci; 171240230Sdonn else 171340230Sdonn dclerr("improperly dimensioned array", v); 171440230Sdonn } 171540230Sdonn 171640230Sdonn if (v->vtype == TYCHAR) 171740230Sdonn { 171840230Sdonn v->vleng = fixtype(v->vleng); 171940230Sdonn if (v->vleng == NULL) 172040230Sdonn eltsize = typesize[TYCHAR]; 172140230Sdonn else if (ISICON(v->vleng)) 172240230Sdonn eltsize = typesize[TYCHAR] * 1723*46303Sbostic v->vleng->constblock.constant.ci; 172440230Sdonn else if (v->vleng->tag != TERROR) 172540230Sdonn { 172640230Sdonn errstr("nonconstant string length on %s", 172740230Sdonn varstr(VL, v->varname)); 172840230Sdonn eltsize = 0; 172940230Sdonn } 173040230Sdonn } 173140230Sdonn else 173240230Sdonn eltsize = typesize[v->vtype]; 173340230Sdonn 173440230Sdonn v->varsize = nelt * eltsize; 173540230Sdonn break; 173640230Sdonn case STGAUTO: 173740230Sdonn if(v->vclass==CLPROC && v->vprocclass==PTHISPROC) 173840230Sdonn break; 173940230Sdonn nelt = 1; 174040230Sdonn if(t = v->vdim) 174140230Sdonn if( (neltp = t->nelt) && ISCONST(neltp) ) 1742*46303Sbostic nelt = neltp->constblock.constant.ci; 174340230Sdonn else 174440230Sdonn dclerr("adjustable automatic array", v); 174540230Sdonn p = autovar(nelt, v->vtype, v->vleng); 174640230Sdonn v->vardesc.varno = p->memno; 1747*46303Sbostic v->voffset = p->memoffset->constblock.constant.ci; 174840230Sdonn frexpr(p); 174940230Sdonn break; 175040230Sdonn 175140230Sdonn default: 175240230Sdonn break; 175340230Sdonn } 175440230Sdonn v->vdcldone = YES; 175540230Sdonn } 175640230Sdonn 175740230Sdonn 175840230Sdonn 175940230Sdonn 176040230Sdonn impldcl(p) 176140230Sdonn register Namep p; 176240230Sdonn { 176340230Sdonn register int k; 176440230Sdonn int type, leng; 176540230Sdonn 176640230Sdonn if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) ) 176740230Sdonn return; 176840230Sdonn if(p->vtype == TYUNKNOWN) 176940230Sdonn { 177040230Sdonn k = letter(p->varname[0]); 177140230Sdonn type = impltype[ k ]; 177240230Sdonn leng = implleng[ k ]; 177340230Sdonn if(type == TYUNKNOWN) 177440230Sdonn { 177540230Sdonn if(p->vclass == CLPROC) 177640230Sdonn dclerr("attempt to use function of undefined type", p); 177740230Sdonn else 177840230Sdonn dclerr("attempt to use undefined variable", p); 177940230Sdonn type = TYERROR; 178040230Sdonn leng = 1; 178140230Sdonn } 178240230Sdonn settype(p, type, leng); 178340230Sdonn } 178440230Sdonn } 178540230Sdonn 178640230Sdonn 178740230Sdonn 178840230Sdonn 178940230Sdonn LOCAL letter(c) 179040230Sdonn register int c; 179140230Sdonn { 179240230Sdonn if( isupper(c) ) 179340230Sdonn c = tolower(c); 179440230Sdonn return(c - 'a'); 179540230Sdonn } 179640230Sdonn 1797*46303Sbostic #define ICONEQ(z, c) (ISICON(z) && z->constblock.constant.ci==c) 179840230Sdonn #define COMMUTE { e = lp; lp = rp; rp = e; } 179940230Sdonn 180040230Sdonn 180140230Sdonn expptr mkexpr(opcode, lp, rp) 180240230Sdonn int opcode; 180340230Sdonn register expptr lp, rp; 180440230Sdonn { 180540230Sdonn register expptr e, e1; 180640230Sdonn int etype; 180740230Sdonn int ltype, rtype; 180840230Sdonn int ltag, rtag; 180940230Sdonn expptr q, q1; 181040230Sdonn expptr fold(); 181140230Sdonn int k; 181240230Sdonn 181340230Sdonn ltype = lp->headblock.vtype; 181440230Sdonn ltag = lp->tag; 181540230Sdonn if(rp && opcode!=OPCALL && opcode!=OPCCALL) 181640230Sdonn { 181740230Sdonn rtype = rp->headblock.vtype; 181840230Sdonn rtag = rp->tag; 181940230Sdonn } 182040230Sdonn else { 182140230Sdonn rtype = 0; 182240230Sdonn rtag = 0; 182340230Sdonn } 182440230Sdonn 182540230Sdonn /* 182640230Sdonn * Yuck. Why can't we fold constants AFTER 182740230Sdonn * variables are implicitly declared??? 182840230Sdonn */ 182940230Sdonn if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL) 183040230Sdonn { 183140230Sdonn k = letter(lp->primblock.namep->varname[0]); 183240230Sdonn ltype = impltype[ k ]; 183340230Sdonn } 183440230Sdonn if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL) 183540230Sdonn { 183640230Sdonn k = letter(rp->primblock.namep->varname[0]); 183740230Sdonn rtype = impltype[ k ]; 183840230Sdonn } 183940230Sdonn 184040230Sdonn etype = cktype(opcode, ltype, rtype); 184140230Sdonn if(etype == TYERROR) 184240230Sdonn goto error; 184340230Sdonn 184440230Sdonn if(etype != TYUNKNOWN) 184540230Sdonn switch(opcode) 184640230Sdonn { 184740230Sdonn /* check for multiplication by 0 and 1 and addition to 0 */ 184840230Sdonn 184940230Sdonn case OPSTAR: 185040230Sdonn if( ISCONST(lp) ) 185140230Sdonn COMMUTE 185240230Sdonn 185340230Sdonn if( ISICON(rp) ) 185440230Sdonn { 1855*46303Sbostic if(rp->constblock.constant.ci == 0) 185640230Sdonn { 185740230Sdonn if(etype == TYUNKNOWN) 185840230Sdonn break; 185940230Sdonn rp = mkconv(etype, rp); 186040230Sdonn goto retright; 186140230Sdonn } 186240230Sdonn if ((lp->tag == TEXPR) && 186340230Sdonn ((lp->exprblock.opcode == OPPLUS) || 186440230Sdonn (lp->exprblock.opcode == OPMINUS)) && 186540230Sdonn ISCONST(lp->exprblock.rightp) && 186640230Sdonn ISINT(lp->exprblock.rightp->constblock.vtype)) 186740230Sdonn { 186840230Sdonn q1 = mkexpr(OPSTAR, lp->exprblock.rightp, 186940230Sdonn cpexpr(rp)); 187040230Sdonn q = mkexpr(OPSTAR, lp->exprblock.leftp, rp); 187140230Sdonn q = mkexpr(lp->exprblock.opcode, q, q1); 187240230Sdonn free ((char *) lp); 187340230Sdonn return q; 187440230Sdonn } 187540230Sdonn else 187640230Sdonn goto mulop; 187740230Sdonn } 187840230Sdonn break; 187940230Sdonn 188040230Sdonn case OPSLASH: 188140230Sdonn case OPMOD: 188240230Sdonn if( ICONEQ(rp, 0) ) 188340230Sdonn { 188440230Sdonn err("attempted division by zero"); 188540230Sdonn rp = ICON(1); 188640230Sdonn break; 188740230Sdonn } 188840230Sdonn if(opcode == OPMOD) 188940230Sdonn break; 189040230Sdonn 189140230Sdonn 189240230Sdonn mulop: 189340230Sdonn if( ISICON(rp) ) 189440230Sdonn { 1895*46303Sbostic if(rp->constblock.constant.ci == 1) 189640230Sdonn goto retleft; 189740230Sdonn 1898*46303Sbostic if(rp->constblock.constant.ci == -1) 189940230Sdonn { 190040230Sdonn frexpr(rp); 190140230Sdonn return( mkexpr(OPNEG, lp, PNULL) ); 190240230Sdonn } 190340230Sdonn } 190440230Sdonn 190540230Sdonn if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) ) 190640230Sdonn { 190740230Sdonn if(opcode == OPSTAR) 190840230Sdonn e = mkexpr(OPSTAR, lp->exprblock.rightp, rp); 190940230Sdonn else if(ISICON(rp) && 1910*46303Sbostic (lp->exprblock.rightp->constblock.constant.ci % 1911*46303Sbostic rp->constblock.constant.ci) == 0) 191240230Sdonn e = mkexpr(OPSLASH, lp->exprblock.rightp, rp); 191340230Sdonn else break; 191440230Sdonn 191540230Sdonn e1 = lp->exprblock.leftp; 191640230Sdonn free( (charptr) lp ); 191740230Sdonn return( mkexpr(OPSTAR, e1, e) ); 191840230Sdonn } 191940230Sdonn break; 192040230Sdonn 192140230Sdonn 192240230Sdonn case OPPLUS: 192340230Sdonn if( ISCONST(lp) ) 192440230Sdonn COMMUTE 192540230Sdonn goto addop; 192640230Sdonn 192740230Sdonn case OPMINUS: 192840230Sdonn if( ICONEQ(lp, 0) ) 192940230Sdonn { 193040230Sdonn frexpr(lp); 193140230Sdonn return( mkexpr(OPNEG, rp, ENULL) ); 193240230Sdonn } 193340230Sdonn 193440230Sdonn if( ISCONST(rp) ) 193540230Sdonn { 193640230Sdonn opcode = OPPLUS; 193740230Sdonn consnegop(rp); 193840230Sdonn } 193940230Sdonn 194040230Sdonn addop: 194140230Sdonn if( ISICON(rp) ) 194240230Sdonn { 1943*46303Sbostic if(rp->constblock.constant.ci == 0) 194440230Sdonn goto retleft; 194540230Sdonn if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) ) 194640230Sdonn { 194740230Sdonn e = mkexpr(OPPLUS, lp->exprblock.rightp, rp); 194840230Sdonn e1 = lp->exprblock.leftp; 194940230Sdonn free( (charptr) lp ); 195040230Sdonn return( mkexpr(OPPLUS, e1, e) ); 195140230Sdonn } 195240230Sdonn } 195340230Sdonn break; 195440230Sdonn 195540230Sdonn 195640230Sdonn case OPPOWER: 195740230Sdonn break; 195840230Sdonn 195940230Sdonn case OPNEG: 196040230Sdonn if(ltag==TEXPR && lp->exprblock.opcode==OPNEG) 196140230Sdonn { 196240230Sdonn e = lp->exprblock.leftp; 196340230Sdonn free( (charptr) lp ); 196440230Sdonn return(e); 196540230Sdonn } 196640230Sdonn break; 196740230Sdonn 196840230Sdonn case OPNOT: 196940230Sdonn if(ltag==TEXPR && lp->exprblock.opcode==OPNOT) 197040230Sdonn { 197140230Sdonn e = lp->exprblock.leftp; 197240230Sdonn free( (charptr) lp ); 197340230Sdonn return(e); 197440230Sdonn } 197540230Sdonn break; 197640230Sdonn 197740230Sdonn case OPCALL: 197840230Sdonn case OPCCALL: 197940230Sdonn etype = ltype; 198040230Sdonn if(rp!=NULL && rp->listblock.listp==NULL) 198140230Sdonn { 198240230Sdonn free( (charptr) rp ); 198340230Sdonn rp = NULL; 198440230Sdonn } 198540230Sdonn break; 198640230Sdonn 198740230Sdonn case OPAND: 198840230Sdonn case OPOR: 198940230Sdonn if( ISCONST(lp) ) 199040230Sdonn COMMUTE 199140230Sdonn 199240230Sdonn if( ISCONST(rp) ) 199340230Sdonn { 1994*46303Sbostic if(rp->constblock.constant.ci == 0) 199540230Sdonn if(opcode == OPOR) 199640230Sdonn goto retleft; 199740230Sdonn else 199840230Sdonn goto retright; 199940230Sdonn else if(opcode == OPOR) 200040230Sdonn goto retright; 200140230Sdonn else 200240230Sdonn goto retleft; 200340230Sdonn } 200440230Sdonn case OPLSHIFT: 200540230Sdonn if (ISICON(rp)) 200640230Sdonn { 2007*46303Sbostic if (rp->constblock.constant.ci == 0) 200840230Sdonn goto retleft; 200940230Sdonn if ((lp->tag == TEXPR) && 201040230Sdonn ((lp->exprblock.opcode == OPPLUS) || 201140230Sdonn (lp->exprblock.opcode == OPMINUS)) && 201240230Sdonn ISICON(lp->exprblock.rightp)) 201340230Sdonn { 201440230Sdonn q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp, 201540230Sdonn cpexpr(rp)); 201640230Sdonn q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp); 201740230Sdonn q = mkexpr(lp->exprblock.opcode, q, q1); 201840230Sdonn free((char *) lp); 201940230Sdonn return q; 202040230Sdonn } 202140230Sdonn } 202240230Sdonn 202340230Sdonn case OPEQV: 202440230Sdonn case OPNEQV: 202540230Sdonn 202640230Sdonn case OPBITAND: 202740230Sdonn case OPBITOR: 202840230Sdonn case OPBITXOR: 202940230Sdonn case OPBITNOT: 203040230Sdonn case OPRSHIFT: 203140230Sdonn 203240230Sdonn case OPLT: 203340230Sdonn case OPGT: 203440230Sdonn case OPLE: 203540230Sdonn case OPGE: 203640230Sdonn case OPEQ: 203740230Sdonn case OPNE: 203840230Sdonn 203940230Sdonn case OPCONCAT: 204040230Sdonn break; 204140230Sdonn case OPMIN: 204240230Sdonn case OPMAX: 204340230Sdonn 204440230Sdonn case OPASSIGN: 204540230Sdonn case OPPLUSEQ: 204640230Sdonn case OPSTAREQ: 204740230Sdonn 204840230Sdonn case OPCONV: 204940230Sdonn case OPADDR: 205040230Sdonn 205140230Sdonn case OPCOMMA: 205240230Sdonn case OPQUEST: 205340230Sdonn case OPCOLON: 205440230Sdonn 205540230Sdonn case OPPAREN: 205640230Sdonn break; 205740230Sdonn 205840230Sdonn default: 205940230Sdonn badop("mkexpr", opcode); 206040230Sdonn } 206140230Sdonn 206240230Sdonn e = (expptr) ALLOC(Exprblock); 206340230Sdonn e->exprblock.tag = TEXPR; 206440230Sdonn e->exprblock.opcode = opcode; 206540230Sdonn e->exprblock.vtype = etype; 206640230Sdonn e->exprblock.leftp = lp; 206740230Sdonn e->exprblock.rightp = rp; 206840230Sdonn if(ltag==TCONST && (rp==0 || rtag==TCONST) ) 206940230Sdonn e = fold(e); 207040230Sdonn return(e); 207140230Sdonn 207240230Sdonn retleft: 207340230Sdonn frexpr(rp); 207440230Sdonn return(lp); 207540230Sdonn 207640230Sdonn retright: 207740230Sdonn frexpr(lp); 207840230Sdonn return(rp); 207940230Sdonn 208040230Sdonn error: 208140230Sdonn frexpr(lp); 208240230Sdonn if(rp && opcode!=OPCALL && opcode!=OPCCALL) 208340230Sdonn frexpr(rp); 208440230Sdonn return( errnode() ); 208540230Sdonn } 208640230Sdonn 208740230Sdonn #define ERR(s) { errs = s; goto error; } 208840230Sdonn 208940230Sdonn cktype(op, lt, rt) 209040230Sdonn register int op, lt, rt; 209140230Sdonn { 209240230Sdonn char *errs; 209340230Sdonn 209440230Sdonn if(lt==TYERROR || rt==TYERROR) 209540230Sdonn goto error1; 209640230Sdonn 209740230Sdonn if(lt==TYUNKNOWN) 209840230Sdonn return(TYUNKNOWN); 209940230Sdonn if(rt==TYUNKNOWN) 210040230Sdonn if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL && 210140230Sdonn op!=OPCCALL && op!=OPADDR && op!=OPPAREN) 210240230Sdonn return(TYUNKNOWN); 210340230Sdonn 210440230Sdonn switch(op) 210540230Sdonn { 210640230Sdonn case OPPLUS: 210740230Sdonn case OPMINUS: 210840230Sdonn case OPSTAR: 210940230Sdonn case OPSLASH: 211040230Sdonn case OPPOWER: 211140230Sdonn case OPMOD: 211240230Sdonn if( ISNUMERIC(lt) && ISNUMERIC(rt) ) 211340230Sdonn return( maxtype(lt, rt) ); 211440230Sdonn ERR("nonarithmetic operand of arithmetic operator") 211540230Sdonn 211640230Sdonn case OPNEG: 211740230Sdonn if( ISNUMERIC(lt) ) 211840230Sdonn return(lt); 211940230Sdonn ERR("nonarithmetic operand of negation") 212040230Sdonn 212140230Sdonn case OPNOT: 212240230Sdonn if(lt == TYLOGICAL) 212340230Sdonn return(TYLOGICAL); 212440230Sdonn ERR("NOT of nonlogical") 212540230Sdonn 212640230Sdonn case OPAND: 212740230Sdonn case OPOR: 212840230Sdonn case OPEQV: 212940230Sdonn case OPNEQV: 213040230Sdonn if(lt==TYLOGICAL && rt==TYLOGICAL) 213140230Sdonn return(TYLOGICAL); 213240230Sdonn ERR("nonlogical operand of logical operator") 213340230Sdonn 213440230Sdonn case OPLT: 213540230Sdonn case OPGT: 213640230Sdonn case OPLE: 213740230Sdonn case OPGE: 213840230Sdonn case OPEQ: 213940230Sdonn case OPNE: 214040230Sdonn if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) 214140230Sdonn { 214240230Sdonn if(lt != rt) 214340230Sdonn ERR("illegal comparison") 214440230Sdonn } 214540230Sdonn 214640230Sdonn else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) ) 214740230Sdonn { 214840230Sdonn if(op!=OPEQ && op!=OPNE) 214940230Sdonn ERR("order comparison of complex data") 215040230Sdonn } 215140230Sdonn 215240230Sdonn else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) ) 215340230Sdonn ERR("comparison of nonarithmetic data") 215440230Sdonn return(TYLOGICAL); 215540230Sdonn 215640230Sdonn case OPCONCAT: 215740230Sdonn if(lt==TYCHAR && rt==TYCHAR) 215840230Sdonn return(TYCHAR); 215940230Sdonn ERR("concatenation of nonchar data") 216040230Sdonn 216140230Sdonn case OPCALL: 216240230Sdonn case OPCCALL: 216340230Sdonn return(lt); 216440230Sdonn 216540230Sdonn case OPADDR: 216640230Sdonn return(TYADDR); 216740230Sdonn 216840230Sdonn case OPCONV: 216940230Sdonn if(ISCOMPLEX(lt)) 217040230Sdonn { 217140230Sdonn if(ISNUMERIC(rt)) 217240230Sdonn return(lt); 217340230Sdonn ERR("impossible conversion") 217440230Sdonn } 217540230Sdonn if(rt == 0) 217640230Sdonn return(0); 217740230Sdonn if(lt==TYCHAR && ISINT(rt) ) 217840230Sdonn return(TYCHAR); 217940230Sdonn case OPASSIGN: 218040230Sdonn case OPPLUSEQ: 218140230Sdonn case OPSTAREQ: 218240230Sdonn if( ISINT(lt) && rt==TYCHAR) 218340230Sdonn return(lt); 218440230Sdonn if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) 218540230Sdonn if(op!=OPASSIGN || lt!=rt) 218640230Sdonn { 218740230Sdonn /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */ 218840230Sdonn /* debug fatal("impossible conversion. possible compiler bug"); */ 218940230Sdonn ERR("impossible conversion") 219040230Sdonn } 219140230Sdonn return(lt); 219240230Sdonn 219340230Sdonn case OPMIN: 219440230Sdonn case OPMAX: 219540230Sdonn case OPBITOR: 219640230Sdonn case OPBITAND: 219740230Sdonn case OPBITXOR: 219840230Sdonn case OPBITNOT: 219940230Sdonn case OPLSHIFT: 220040230Sdonn case OPRSHIFT: 220140230Sdonn case OPPAREN: 220240230Sdonn return(lt); 220340230Sdonn 220440230Sdonn case OPCOMMA: 220540230Sdonn case OPQUEST: 220640230Sdonn case OPCOLON: 220740230Sdonn return(rt); 220840230Sdonn 220940230Sdonn default: 221040230Sdonn badop("cktype", op); 221140230Sdonn } 221240230Sdonn error: err(errs); 221340230Sdonn error1: return(TYERROR); 221440230Sdonn } 221540230Sdonn 221640230Sdonn LOCAL expptr fold(e) 221740230Sdonn register expptr e; 221840230Sdonn { 221940230Sdonn Constp p; 222040230Sdonn register expptr lp, rp; 222140230Sdonn int etype, mtype, ltype, rtype, opcode; 222240230Sdonn int i, ll, lr; 222340230Sdonn char *q, *s; 222440230Sdonn union Constant lcon, rcon; 222540230Sdonn 222640230Sdonn opcode = e->exprblock.opcode; 222740230Sdonn etype = e->exprblock.vtype; 222840230Sdonn 222940230Sdonn lp = e->exprblock.leftp; 223040230Sdonn ltype = lp->headblock.vtype; 223140230Sdonn rp = e->exprblock.rightp; 223240230Sdonn 223340230Sdonn if(rp == 0) 223440230Sdonn switch(opcode) 223540230Sdonn { 223640230Sdonn case OPNOT: 2237*46303Sbostic lp->constblock.constant.ci = 2238*46303Sbostic ! lp->constblock.constant.ci; 223940230Sdonn return(lp); 224040230Sdonn 224140230Sdonn case OPBITNOT: 2242*46303Sbostic lp->constblock.constant.ci = 2243*46303Sbostic ~ lp->constblock.constant.ci; 224440230Sdonn return(lp); 224540230Sdonn 224640230Sdonn case OPNEG: 224740230Sdonn consnegop(lp); 224840230Sdonn return(lp); 224940230Sdonn 225040230Sdonn case OPCONV: 225140230Sdonn case OPADDR: 225240230Sdonn case OPPAREN: 225340230Sdonn return(e); 225440230Sdonn 225540230Sdonn default: 225640230Sdonn badop("fold", opcode); 225740230Sdonn } 225840230Sdonn 225940230Sdonn rtype = rp->headblock.vtype; 226040230Sdonn 226140230Sdonn p = ALLOC(Constblock); 226240230Sdonn p->tag = TCONST; 226340230Sdonn p->vtype = etype; 226440230Sdonn p->vleng = e->exprblock.vleng; 226540230Sdonn 226640230Sdonn switch(opcode) 226740230Sdonn { 226840230Sdonn case OPCOMMA: 226940230Sdonn case OPQUEST: 227040230Sdonn case OPCOLON: 227140230Sdonn return(e); 227240230Sdonn 227340230Sdonn case OPAND: 2274*46303Sbostic p->constant.ci = lp->constblock.constant.ci && 2275*46303Sbostic rp->constblock.constant.ci; 227640230Sdonn break; 227740230Sdonn 227840230Sdonn case OPOR: 2279*46303Sbostic p->constant.ci = lp->constblock.constant.ci || 2280*46303Sbostic rp->constblock.constant.ci; 228140230Sdonn break; 228240230Sdonn 228340230Sdonn case OPEQV: 2284*46303Sbostic p->constant.ci = lp->constblock.constant.ci == 2285*46303Sbostic rp->constblock.constant.ci; 228640230Sdonn break; 228740230Sdonn 228840230Sdonn case OPNEQV: 2289*46303Sbostic p->constant.ci = lp->constblock.constant.ci != 2290*46303Sbostic rp->constblock.constant.ci; 229140230Sdonn break; 229240230Sdonn 229340230Sdonn case OPBITAND: 2294*46303Sbostic p->constant.ci = lp->constblock.constant.ci & 2295*46303Sbostic rp->constblock.constant.ci; 229640230Sdonn break; 229740230Sdonn 229840230Sdonn case OPBITOR: 2299*46303Sbostic p->constant.ci = lp->constblock.constant.ci | 2300*46303Sbostic rp->constblock.constant.ci; 230140230Sdonn break; 230240230Sdonn 230340230Sdonn case OPBITXOR: 2304*46303Sbostic p->constant.ci = lp->constblock.constant.ci ^ 2305*46303Sbostic rp->constblock.constant.ci; 230640230Sdonn break; 230740230Sdonn 230840230Sdonn case OPLSHIFT: 2309*46303Sbostic p->constant.ci = lp->constblock.constant.ci << 2310*46303Sbostic rp->constblock.constant.ci; 231140230Sdonn break; 231240230Sdonn 231340230Sdonn case OPRSHIFT: 2314*46303Sbostic p->constant.ci = lp->constblock.constant.ci >> 2315*46303Sbostic rp->constblock.constant.ci; 231640230Sdonn break; 231740230Sdonn 231840230Sdonn case OPCONCAT: 2319*46303Sbostic ll = lp->constblock.vleng->constblock.constant.ci; 2320*46303Sbostic lr = rp->constblock.vleng->constblock.constant.ci; 2321*46303Sbostic p->constant.ccp = q = (char *) ckalloc(ll+lr); 232240230Sdonn p->vleng = ICON(ll+lr); 2323*46303Sbostic s = lp->constblock.constant.ccp; 232440230Sdonn for(i = 0 ; i < ll ; ++i) 232540230Sdonn *q++ = *s++; 2326*46303Sbostic s = rp->constblock.constant.ccp; 232740230Sdonn for(i = 0; i < lr; ++i) 232840230Sdonn *q++ = *s++; 232940230Sdonn break; 233040230Sdonn 233140230Sdonn 233240230Sdonn case OPPOWER: 233340230Sdonn if( ! ISINT(rtype) ) 233440230Sdonn return(e); 2335*46303Sbostic conspower(&(p->constant), lp, rp->constblock.constant.ci); 233640230Sdonn break; 233740230Sdonn 233840230Sdonn 233940230Sdonn default: 234040230Sdonn if(ltype == TYCHAR) 234140230Sdonn { 2342*46303Sbostic lcon.ci = cmpstr(lp->constblock.constant.ccp, 2343*46303Sbostic rp->constblock.constant.ccp, 2344*46303Sbostic lp->constblock.vleng->constblock.constant.ci, 2345*46303Sbostic rp->constblock.vleng->constblock.constant.ci); 234640230Sdonn rcon.ci = 0; 234740230Sdonn mtype = tyint; 234840230Sdonn } 234940230Sdonn else { 235040230Sdonn mtype = maxtype(ltype, rtype); 2351*46303Sbostic consconv(mtype, &lcon, ltype, 2352*46303Sbostic &(lp->constblock.constant) ); 2353*46303Sbostic consconv(mtype, &rcon, rtype, 2354*46303Sbostic &(rp->constblock.constant) ); 235540230Sdonn } 2356*46303Sbostic consbinop(opcode, mtype, &(p->constant), &lcon, &rcon); 235740230Sdonn break; 235840230Sdonn } 235940230Sdonn 236040230Sdonn frexpr(e); 236140230Sdonn return( (expptr) p ); 236240230Sdonn } 236340230Sdonn 236440230Sdonn 236540230Sdonn 236640230Sdonn /* assign constant l = r , doing coercion */ 236740230Sdonn 236840230Sdonn consconv(lt, lv, rt, rv) 236940230Sdonn int lt, rt; 237040230Sdonn register union Constant *lv, *rv; 237140230Sdonn { 237240230Sdonn switch(lt) 237340230Sdonn { 237440230Sdonn case TYCHAR: 237540230Sdonn *(lv->ccp = (char *) ckalloc(1)) = rv->ci; 237640230Sdonn break; 237740230Sdonn 237840230Sdonn case TYSHORT: 237940230Sdonn case TYLONG: 238040230Sdonn if(rt == TYCHAR) 238140230Sdonn lv->ci = rv->ccp[0]; 238240230Sdonn else if( ISINT(rt) ) 238340230Sdonn lv->ci = rv->ci; 238440230Sdonn else lv->ci = rv->cd[0]; 238540230Sdonn break; 238640230Sdonn 238740230Sdonn case TYCOMPLEX: 238840230Sdonn case TYDCOMPLEX: 238940230Sdonn switch(rt) 239040230Sdonn { 239140230Sdonn case TYSHORT: 239240230Sdonn case TYLONG: 239340230Sdonn /* fall through and do real assignment of 239440230Sdonn first element 239540230Sdonn */ 239640230Sdonn case TYREAL: 239740230Sdonn case TYDREAL: 239840230Sdonn lv->cd[1] = 0; break; 239940230Sdonn case TYCOMPLEX: 240040230Sdonn case TYDCOMPLEX: 240140230Sdonn lv->cd[1] = rv->cd[1]; break; 240240230Sdonn } 240340230Sdonn 240440230Sdonn case TYREAL: 240540230Sdonn case TYDREAL: 240640230Sdonn if( ISINT(rt) ) 240740230Sdonn lv->cd[0] = rv->ci; 240840230Sdonn else lv->cd[0] = rv->cd[0]; 240940230Sdonn if( lt == TYREAL) 241040230Sdonn { 241140230Sdonn float f = lv->cd[0]; 241240230Sdonn lv->cd[0] = f; 241340230Sdonn } 241440230Sdonn break; 241540230Sdonn 241640230Sdonn case TYLOGICAL: 241740230Sdonn lv->ci = rv->ci; 241840230Sdonn break; 241940230Sdonn } 242040230Sdonn } 242140230Sdonn 242240230Sdonn 242340230Sdonn 242440230Sdonn consnegop(p) 242540230Sdonn register Constp p; 242640230Sdonn { 242740230Sdonn switch(p->vtype) 242840230Sdonn { 242940230Sdonn case TYSHORT: 243040230Sdonn case TYLONG: 2431*46303Sbostic p->constant.ci = - p->constant.ci; 243240230Sdonn break; 243340230Sdonn 243440230Sdonn case TYCOMPLEX: 243540230Sdonn case TYDCOMPLEX: 2436*46303Sbostic p->constant.cd[1] = - p->constant.cd[1]; 243740230Sdonn /* fall through and do the real parts */ 243840230Sdonn case TYREAL: 243940230Sdonn case TYDREAL: 2440*46303Sbostic p->constant.cd[0] = - p->constant.cd[0]; 244140230Sdonn break; 244240230Sdonn default: 244340230Sdonn badtype("consnegop", p->vtype); 244440230Sdonn } 244540230Sdonn } 244640230Sdonn 244740230Sdonn 244840230Sdonn 244940230Sdonn LOCAL conspower(powp, ap, n) 245040230Sdonn register union Constant *powp; 245140230Sdonn Constp ap; 245240230Sdonn ftnint n; 245340230Sdonn { 245440230Sdonn register int type; 245540230Sdonn union Constant x; 245640230Sdonn 245740230Sdonn switch(type = ap->vtype) /* pow = 1 */ 245840230Sdonn { 245940230Sdonn case TYSHORT: 246040230Sdonn case TYLONG: 246140230Sdonn powp->ci = 1; 246240230Sdonn break; 246340230Sdonn case TYCOMPLEX: 246440230Sdonn case TYDCOMPLEX: 246540230Sdonn powp->cd[1] = 0; 246640230Sdonn case TYREAL: 246740230Sdonn case TYDREAL: 246840230Sdonn powp->cd[0] = 1; 246940230Sdonn break; 247040230Sdonn default: 247140230Sdonn badtype("conspower", type); 247240230Sdonn } 247340230Sdonn 247440230Sdonn if(n == 0) 247540230Sdonn return; 247640230Sdonn if(n < 0) 247740230Sdonn { 247840230Sdonn if( ISINT(type) ) 247940230Sdonn { 2480*46303Sbostic if (ap->constant.ci == 0) 248140230Sdonn err("zero raised to a negative power"); 2482*46303Sbostic else if (ap->constant.ci == 1) 248340230Sdonn return; 2484*46303Sbostic else if (ap->constant.ci == -1) 248540230Sdonn { 248640230Sdonn if (n < -2) 248740230Sdonn n = n + 2; 248840230Sdonn n = -n; 248940230Sdonn if (n % 2 == 1) 249040230Sdonn powp->ci = -1; 249140230Sdonn } 249240230Sdonn else 249340230Sdonn powp->ci = 0; 249440230Sdonn return; 249540230Sdonn } 249640230Sdonn n = - n; 2497*46303Sbostic consbinop(OPSLASH, type, &x, powp, &(ap->constant)); 249840230Sdonn } 249940230Sdonn else 2500*46303Sbostic consbinop(OPSTAR, type, &x, powp, &(ap->constant)); 250140230Sdonn 250240230Sdonn for( ; ; ) 250340230Sdonn { 250440230Sdonn if(n & 01) 250540230Sdonn consbinop(OPSTAR, type, powp, powp, &x); 250640230Sdonn if(n >>= 1) 250740230Sdonn consbinop(OPSTAR, type, &x, &x, &x); 250840230Sdonn else 250940230Sdonn break; 251040230Sdonn } 251140230Sdonn } 251240230Sdonn 251340230Sdonn 251440230Sdonn 251540230Sdonn /* do constant operation cp = a op b */ 251640230Sdonn 251740230Sdonn 251840230Sdonn LOCAL consbinop(opcode, type, cp, ap, bp) 251940230Sdonn int opcode, type; 252040230Sdonn register union Constant *ap, *bp, *cp; 252140230Sdonn { 252240230Sdonn int k; 252340230Sdonn double temp; 252440230Sdonn 252540230Sdonn switch(opcode) 252640230Sdonn { 252740230Sdonn case OPPLUS: 252840230Sdonn switch(type) 252940230Sdonn { 253040230Sdonn case TYSHORT: 253140230Sdonn case TYLONG: 253240230Sdonn cp->ci = ap->ci + bp->ci; 253340230Sdonn break; 253440230Sdonn case TYCOMPLEX: 253540230Sdonn case TYDCOMPLEX: 253640230Sdonn cp->cd[1] = ap->cd[1] + bp->cd[1]; 253740230Sdonn case TYREAL: 253840230Sdonn case TYDREAL: 253940230Sdonn cp->cd[0] = ap->cd[0] + bp->cd[0]; 254040230Sdonn break; 254140230Sdonn } 254240230Sdonn break; 254340230Sdonn 254440230Sdonn case OPMINUS: 254540230Sdonn switch(type) 254640230Sdonn { 254740230Sdonn case TYSHORT: 254840230Sdonn case TYLONG: 254940230Sdonn cp->ci = ap->ci - bp->ci; 255040230Sdonn break; 255140230Sdonn case TYCOMPLEX: 255240230Sdonn case TYDCOMPLEX: 255340230Sdonn cp->cd[1] = ap->cd[1] - bp->cd[1]; 255440230Sdonn case TYREAL: 255540230Sdonn case TYDREAL: 255640230Sdonn cp->cd[0] = ap->cd[0] - bp->cd[0]; 255740230Sdonn break; 255840230Sdonn } 255940230Sdonn break; 256040230Sdonn 256140230Sdonn case OPSTAR: 256240230Sdonn switch(type) 256340230Sdonn { 256440230Sdonn case TYSHORT: 256540230Sdonn case TYLONG: 256640230Sdonn cp->ci = ap->ci * bp->ci; 256740230Sdonn break; 256840230Sdonn case TYREAL: 256940230Sdonn case TYDREAL: 257040230Sdonn cp->cd[0] = ap->cd[0] * bp->cd[0]; 257140230Sdonn break; 257240230Sdonn case TYCOMPLEX: 257340230Sdonn case TYDCOMPLEX: 257440230Sdonn temp = ap->cd[0] * bp->cd[0] - 257540230Sdonn ap->cd[1] * bp->cd[1] ; 257640230Sdonn cp->cd[1] = ap->cd[0] * bp->cd[1] + 257740230Sdonn ap->cd[1] * bp->cd[0] ; 257840230Sdonn cp->cd[0] = temp; 257940230Sdonn break; 258040230Sdonn } 258140230Sdonn break; 258240230Sdonn case OPSLASH: 258340230Sdonn switch(type) 258440230Sdonn { 258540230Sdonn case TYSHORT: 258640230Sdonn case TYLONG: 258740230Sdonn cp->ci = ap->ci / bp->ci; 258840230Sdonn break; 258940230Sdonn case TYREAL: 259040230Sdonn case TYDREAL: 259140230Sdonn cp->cd[0] = ap->cd[0] / bp->cd[0]; 259240230Sdonn break; 259340230Sdonn case TYCOMPLEX: 259440230Sdonn case TYDCOMPLEX: 259540230Sdonn zdiv(cp,ap,bp); 259640230Sdonn break; 259740230Sdonn } 259840230Sdonn break; 259940230Sdonn 260040230Sdonn case OPMOD: 260140230Sdonn if( ISINT(type) ) 260240230Sdonn { 260340230Sdonn cp->ci = ap->ci % bp->ci; 260440230Sdonn break; 260540230Sdonn } 260640230Sdonn else 260740230Sdonn fatal("inline mod of noninteger"); 260840230Sdonn 260940230Sdonn default: /* relational ops */ 261040230Sdonn switch(type) 261140230Sdonn { 261240230Sdonn case TYSHORT: 261340230Sdonn case TYLONG: 261440230Sdonn if(ap->ci < bp->ci) 261540230Sdonn k = -1; 261640230Sdonn else if(ap->ci == bp->ci) 261740230Sdonn k = 0; 261840230Sdonn else k = 1; 261940230Sdonn break; 262040230Sdonn case TYREAL: 262140230Sdonn case TYDREAL: 262240230Sdonn if(ap->cd[0] < bp->cd[0]) 262340230Sdonn k = -1; 262440230Sdonn else if(ap->cd[0] == bp->cd[0]) 262540230Sdonn k = 0; 262640230Sdonn else k = 1; 262740230Sdonn break; 262840230Sdonn case TYCOMPLEX: 262940230Sdonn case TYDCOMPLEX: 263040230Sdonn if(ap->cd[0] == bp->cd[0] && 263140230Sdonn ap->cd[1] == bp->cd[1] ) 263240230Sdonn k = 0; 263340230Sdonn else k = 1; 263440230Sdonn break; 263540230Sdonn } 263640230Sdonn 263740230Sdonn switch(opcode) 263840230Sdonn { 263940230Sdonn case OPEQ: 264040230Sdonn cp->ci = (k == 0); 264140230Sdonn break; 264240230Sdonn case OPNE: 264340230Sdonn cp->ci = (k != 0); 264440230Sdonn break; 264540230Sdonn case OPGT: 264640230Sdonn cp->ci = (k == 1); 264740230Sdonn break; 264840230Sdonn case OPLT: 264940230Sdonn cp->ci = (k == -1); 265040230Sdonn break; 265140230Sdonn case OPGE: 265240230Sdonn cp->ci = (k >= 0); 265340230Sdonn break; 265440230Sdonn case OPLE: 265540230Sdonn cp->ci = (k <= 0); 265640230Sdonn break; 265740230Sdonn default: 265840230Sdonn badop ("consbinop", opcode); 265940230Sdonn } 266040230Sdonn break; 266140230Sdonn } 266240230Sdonn } 266340230Sdonn 266440230Sdonn 266540230Sdonn 266640230Sdonn 266740230Sdonn conssgn(p) 266840230Sdonn register expptr p; 266940230Sdonn { 267040230Sdonn if( ! ISCONST(p) ) 267140230Sdonn fatal( "sgn(nonconstant)" ); 267240230Sdonn 267340230Sdonn switch(p->headblock.vtype) 267440230Sdonn { 267540230Sdonn case TYSHORT: 267640230Sdonn case TYLONG: 2677*46303Sbostic if(p->constblock.constant.ci > 0) return(1); 2678*46303Sbostic if(p->constblock.constant.ci < 0) return(-1); 267940230Sdonn return(0); 268040230Sdonn 268140230Sdonn case TYREAL: 268240230Sdonn case TYDREAL: 2683*46303Sbostic if(p->constblock.constant.cd[0] > 0) return(1); 2684*46303Sbostic if(p->constblock.constant.cd[0] < 0) return(-1); 268540230Sdonn return(0); 268640230Sdonn 268740230Sdonn case TYCOMPLEX: 268840230Sdonn case TYDCOMPLEX: 2689*46303Sbostic return(p->constblock.constant.cd[0]!=0 || 2690*46303Sbostic p->constblock.constant.cd[1]!=0); 269140230Sdonn 269240230Sdonn default: 269340230Sdonn badtype( "conssgn", p->constblock.vtype); 269440230Sdonn } 269540230Sdonn /* NOTREACHED */ 269640230Sdonn } 269740230Sdonn 269840230Sdonn char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" }; 269940230Sdonn 270040230Sdonn 270140230Sdonn LOCAL expptr mkpower(p) 270240230Sdonn register expptr p; 270340230Sdonn { 270440230Sdonn register expptr q, lp, rp; 270540230Sdonn int ltype, rtype, mtype; 270640230Sdonn 270740230Sdonn lp = p->exprblock.leftp; 270840230Sdonn rp = p->exprblock.rightp; 270940230Sdonn ltype = lp->headblock.vtype; 271040230Sdonn rtype = rp->headblock.vtype; 271140230Sdonn 271240230Sdonn if(ISICON(rp)) 271340230Sdonn { 2714*46303Sbostic if(rp->constblock.constant.ci == 0) 271540230Sdonn { 271640230Sdonn frexpr(p); 271740230Sdonn if( ISINT(ltype) ) 271840230Sdonn return( ICON(1) ); 271940230Sdonn else 272040230Sdonn { 272140230Sdonn expptr pp; 272240230Sdonn pp = mkconv(ltype, ICON(1)); 272340230Sdonn return( pp ); 272440230Sdonn } 272540230Sdonn } 2726*46303Sbostic if(rp->constblock.constant.ci < 0) 272740230Sdonn { 272840230Sdonn if( ISINT(ltype) ) 272940230Sdonn { 273040230Sdonn frexpr(p); 273140230Sdonn err("integer**negative"); 273240230Sdonn return( errnode() ); 273340230Sdonn } 2734*46303Sbostic rp->constblock.constant.ci = - rp->constblock.constant.ci; 273540230Sdonn p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp)); 273640230Sdonn } 2737*46303Sbostic if(rp->constblock.constant.ci == 1) 273840230Sdonn { 273940230Sdonn frexpr(rp); 274040230Sdonn free( (charptr) p ); 274140230Sdonn return(lp); 274240230Sdonn } 274340230Sdonn 274440230Sdonn if( ONEOF(ltype, MSKINT|MSKREAL) ) 274540230Sdonn { 274640230Sdonn p->exprblock.vtype = ltype; 274740230Sdonn return(p); 274840230Sdonn } 274940230Sdonn } 275040230Sdonn if( ISINT(rtype) ) 275140230Sdonn { 275240230Sdonn if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) ) 275340230Sdonn q = call2(TYSHORT, "pow_hh", lp, rp); 275440230Sdonn else { 275540230Sdonn if(ltype == TYSHORT) 275640230Sdonn { 275740230Sdonn ltype = TYLONG; 275840230Sdonn lp = mkconv(TYLONG,lp); 275940230Sdonn } 276040230Sdonn q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp)); 276140230Sdonn } 276240230Sdonn } 276340230Sdonn else if( ISREAL( (mtype = maxtype(ltype,rtype)) )) 276440230Sdonn q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp)); 276540230Sdonn else { 276640230Sdonn q = call2(TYDCOMPLEX, "pow_zz", 276740230Sdonn mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp)); 276840230Sdonn if(mtype == TYCOMPLEX) 276940230Sdonn q = mkconv(TYCOMPLEX, q); 277040230Sdonn } 277140230Sdonn free( (charptr) p ); 277240230Sdonn return(q); 277340230Sdonn } 277440230Sdonn 277540230Sdonn 277640230Sdonn 277740230Sdonn /* Complex Division. Same code as in Runtime Library 277840230Sdonn */ 277940230Sdonn 278040230Sdonn struct dcomplex { double dreal, dimag; }; 278140230Sdonn 278240230Sdonn 278340230Sdonn LOCAL zdiv(c, a, b) 278440230Sdonn register struct dcomplex *a, *b, *c; 278540230Sdonn { 278640230Sdonn double ratio, den; 278740230Sdonn double abr, abi; 278840230Sdonn 278940230Sdonn if( (abr = b->dreal) < 0.) 279040230Sdonn abr = - abr; 279140230Sdonn if( (abi = b->dimag) < 0.) 279240230Sdonn abi = - abi; 279340230Sdonn if( abr <= abi ) 279440230Sdonn { 279540230Sdonn if(abi == 0) 279640230Sdonn fatal("complex division by zero"); 279740230Sdonn ratio = b->dreal / b->dimag ; 279840230Sdonn den = b->dimag * (1 + ratio*ratio); 279940230Sdonn c->dreal = (a->dreal*ratio + a->dimag) / den; 280040230Sdonn c->dimag = (a->dimag*ratio - a->dreal) / den; 280140230Sdonn } 280240230Sdonn 280340230Sdonn else 280440230Sdonn { 280540230Sdonn ratio = b->dimag / b->dreal ; 280640230Sdonn den = b->dreal * (1 + ratio*ratio); 280740230Sdonn c->dreal = (a->dreal + a->dimag*ratio) / den; 280840230Sdonn c->dimag = (a->dimag - a->dreal*ratio) / den; 280940230Sdonn } 281040230Sdonn 281140230Sdonn } 281240230Sdonn 281340230Sdonn expptr oftwo(e) 281440230Sdonn expptr e; 281540230Sdonn { 281640230Sdonn int val,res; 281740230Sdonn 281840230Sdonn if (! ISCONST (e)) 281940230Sdonn return (0); 282040230Sdonn 2821*46303Sbostic val = e->constblock.constant.ci; 282240230Sdonn switch (val) 282340230Sdonn { 282440230Sdonn case 2: res = 1; break; 282540230Sdonn case 4: res = 2; break; 282640230Sdonn case 8: res = 3; break; 282740230Sdonn case 16: res = 4; break; 282840230Sdonn case 32: res = 5; break; 282940230Sdonn case 64: res = 6; break; 283040230Sdonn case 128: res = 7; break; 283140230Sdonn case 256: res = 8; break; 283240230Sdonn default: return (0); 283340230Sdonn } 283440230Sdonn return (ICON (res)); 283540230Sdonn } 2836