122812Smckusick /* 222812Smckusick * Copyright (c) 1980 Regents of the University of California. 322812Smckusick * All rights reserved. The Berkeley software License Agreement 422812Smckusick * specifies the terms and conditions for redistribution. 522812Smckusick */ 622812Smckusick 722812Smckusick #ifndef lint 8*24477Sdonn static char *sccsid[] = "@(#)expr.c 5.4 (Berkeley) 08/29/85"; 922812Smckusick #endif not lint 1022812Smckusick 1122812Smckusick /* 1222812Smckusick * expr.c 1322812Smckusick * 1422812Smckusick * Routines for handling expressions, f77 compiler pass 1. 1522812Smckusick * 1622812Smckusick * University of Utah CS Dept modification history: 1722812Smckusick * 1823476Smckusick * $Log: expr.c,v $ 19*24477Sdonn * Revision 5.3 85/08/10 05:48:16 donn 20*24477Sdonn * Fixed another of my goofs in the substring parameter conversion code. 21*24477Sdonn * 22*24477Sdonn * Revision 5.2 85/08/10 04:13:51 donn 23*24477Sdonn * Jerry Berkman's change to call pow() directly rather than indirectly 24*24477Sdonn * through pow_dd, in mkpower(). 25*24477Sdonn * 26*24477Sdonn * Revision 5.1 85/08/10 03:44:19 donn 27*24477Sdonn * 4.3 alpha 28*24477Sdonn * 2923680Smckusick * Revision 3.16 85/06/21 16:38:09 donn 3023680Smckusick * The fix to mkprim() didn't handle null substring parameters (sigh). 3123680Smckusick * 3223476Smckusick * Revision 3.15 85/06/04 04:37:03 donn 3323476Smckusick * Changed mkprim() to force substring parameters to be integral types. 3422812Smckusick * 3523476Smckusick * Revision 3.14 85/06/04 03:41:52 donn 3623476Smckusick * Change impldcl() to handle functions of type 'undefined'. 3723476Smckusick * 3823476Smckusick * Revision 3.13 85/05/06 23:14:55 donn 3923476Smckusick * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get 4023476Smckusick * a temporary when converting character strings to integers; previously we 4123476Smckusick * were having problems because mkconv() was called after tempalloc(). 4223476Smckusick * 4322812Smckusick * Revision 3.12 85/03/18 08:07:47 donn 4422812Smckusick * Fixes to help out with short integers -- if integers are by default short, 4522812Smckusick * then so are constants; and if addresses can't be stored in shorts, complain. 4622812Smckusick * 4722812Smckusick * Revision 3.11 85/03/16 22:31:27 donn 4822812Smckusick * Added hack to mkconv() to allow character values of length > 1 to be 4922812Smckusick * converted to numeric types, for Helge Skrivervik. Note that this does 5022812Smckusick * not affect use of the intrinsic ichar() conversion. 5122812Smckusick * 5222812Smckusick * Revision 3.10 85/01/15 21:06:47 donn 5322812Smckusick * Changed mkconv() to comment on implicit conversions; added intrconv() for 5422812Smckusick * use with explicit conversions by intrinsic functions. 5522812Smckusick * 5622812Smckusick * Revision 3.9 85/01/11 21:05:49 donn 5722812Smckusick * Added changes to implement SAVE statements. 5822812Smckusick * 5922812Smckusick * Revision 3.8 84/12/17 02:21:06 donn 6022812Smckusick * Added a test to prevent constant folding from being done on expressions 6122812Smckusick * whose type is not known at that point in mkexpr(). 6222812Smckusick * 6322812Smckusick * Revision 3.7 84/12/11 21:14:17 donn 6422812Smckusick * Removed obnoxious 'excess precision' warning. 6522812Smckusick * 6622812Smckusick * Revision 3.6 84/11/23 01:00:36 donn 6722812Smckusick * Added code to trim excess precision from single-precision constants, and 6822812Smckusick * to warn the user when this occurs. 6922812Smckusick * 7022812Smckusick * Revision 3.5 84/11/23 00:10:39 donn 7122812Smckusick * Changed stfcall() to remark on argument type clashes in 'calls' to 7222812Smckusick * statement functions. 7322812Smckusick * 7422812Smckusick * Revision 3.4 84/11/22 21:21:17 donn 7522812Smckusick * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics. 7622812Smckusick * 7722812Smckusick * Revision 3.3 84/11/12 18:26:14 donn 7822812Smckusick * Shuffled some code around so that the compiler remembers to free some vleng 7922812Smckusick * structures which used to just sit around. 8022812Smckusick * 8122812Smckusick * Revision 3.2 84/10/16 19:24:15 donn 8222812Smckusick * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent 8322812Smckusick * core dumps by replacing bad subscripts with good ones. 8422812Smckusick * 8522812Smckusick * Revision 3.1 84/10/13 01:31:32 donn 8622812Smckusick * Merged Jerry Berkman's version into mine. 8722812Smckusick * 8822812Smckusick * Revision 2.7 84/09/27 15:42:52 donn 8922812Smckusick * The last fix for multiplying undeclared variables by 0 isn't sufficient, 9022812Smckusick * since the type of the 0 may not be the (implicit) type of the variable. 9122812Smckusick * I added a hack to check the implicit type of implicitly declared 9222812Smckusick * variables... 9322812Smckusick * 9422812Smckusick * Revision 2.6 84/09/14 19:34:03 donn 9522812Smckusick * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert 9622812Smckusick * 0 to type UNKNOWN, which is illegal. Fix is to use native type instead. 9722812Smckusick * Not sure how correct (or important) this is... 9822812Smckusick * 9922812Smckusick * Revision 2.5 84/08/05 23:05:27 donn 10022812Smckusick * Added fixes to prevent fixexpr() from slicing and dicing complex conversions 10122812Smckusick * with two operands. 10222812Smckusick * 10322812Smckusick * Revision 2.4 84/08/05 17:34:48 donn 10422812Smckusick * Added an optimization to mklhs() to detect substrings of the form ch(i:i) 10522812Smckusick * and assign constant length 1 to them. 10622812Smckusick * 10722812Smckusick * Revision 2.3 84/07/19 19:38:33 donn 10822812Smckusick * Added a typecast to the last fix. Somehow I missed it the first time... 10922812Smckusick * 11022812Smckusick * Revision 2.2 84/07/19 17:19:57 donn 11122812Smckusick * Caused OPPAREN expressions to inherit the length of their operands, so 11222812Smckusick * that parenthesized character expressions work correctly. 11322812Smckusick * 11422812Smckusick * Revision 2.1 84/07/19 12:03:02 donn 11522812Smckusick * Changed comment headers for UofU. 11622812Smckusick * 11722812Smckusick * Revision 1.2 84/04/06 20:12:17 donn 11822812Smckusick * Fixed bug which caused programs with mixed-type multiplications involving 11922812Smckusick * the constant 0 to choke the compiler. 12022812Smckusick * 12122812Smckusick */ 12222812Smckusick 12322812Smckusick #include "defs.h" 12422812Smckusick 12522812Smckusick 12622812Smckusick /* little routines to create constant blocks */ 12722812Smckusick 12822812Smckusick Constp mkconst(t) 12922812Smckusick register int t; 13022812Smckusick { 13122812Smckusick register Constp p; 13222812Smckusick 13322812Smckusick p = ALLOC(Constblock); 13422812Smckusick p->tag = TCONST; 13522812Smckusick p->vtype = t; 13622812Smckusick return(p); 13722812Smckusick } 13822812Smckusick 13922812Smckusick 14022812Smckusick expptr mklogcon(l) 14122812Smckusick register int l; 14222812Smckusick { 14322812Smckusick register Constp p; 14422812Smckusick 14522812Smckusick p = mkconst(TYLOGICAL); 14622812Smckusick p->const.ci = l; 14722812Smckusick return( (expptr) p ); 14822812Smckusick } 14922812Smckusick 15022812Smckusick 15122812Smckusick 15222812Smckusick expptr mkintcon(l) 15322812Smckusick ftnint l; 15422812Smckusick { 15522812Smckusick register Constp p; 15622812Smckusick int usetype; 15722812Smckusick 15822812Smckusick if(tyint == TYSHORT) 15922812Smckusick { 16022812Smckusick short s = l; 16122812Smckusick if(l != s) 16222812Smckusick usetype = TYLONG; 16322812Smckusick else 16422812Smckusick usetype = TYSHORT; 16522812Smckusick } 16622812Smckusick else 16722812Smckusick usetype = tyint; 16822812Smckusick p = mkconst(usetype); 16922812Smckusick p->const.ci = l; 17022812Smckusick return( (expptr) p ); 17122812Smckusick } 17222812Smckusick 17322812Smckusick 17422812Smckusick 17522812Smckusick expptr mkaddcon(l) 17622812Smckusick register int l; 17722812Smckusick { 17822812Smckusick register Constp p; 17922812Smckusick 18022812Smckusick p = mkconst(TYADDR); 18122812Smckusick p->const.ci = l; 18222812Smckusick return( (expptr) p ); 18322812Smckusick } 18422812Smckusick 18522812Smckusick 18622812Smckusick 18722812Smckusick expptr mkrealcon(t, d) 18822812Smckusick register int t; 18922812Smckusick double d; 19022812Smckusick { 19122812Smckusick register Constp p; 19222812Smckusick 19322812Smckusick if(t == TYREAL) 19422812Smckusick { 19522812Smckusick float f = d; 19622812Smckusick if(f != d) 19722812Smckusick { 19822812Smckusick #ifdef notdef 19922812Smckusick warn("excess precision in real constant lost"); 20022812Smckusick #endif notdef 20122812Smckusick d = f; 20222812Smckusick } 20322812Smckusick } 20422812Smckusick p = mkconst(t); 20522812Smckusick p->const.cd[0] = d; 20622812Smckusick return( (expptr) p ); 20722812Smckusick } 20822812Smckusick 20922812Smckusick 21022812Smckusick expptr mkbitcon(shift, leng, s) 21122812Smckusick int shift; 21222812Smckusick register int leng; 21322812Smckusick register char *s; 21422812Smckusick { 21522812Smckusick Constp p; 21622812Smckusick register int i, j, k; 21722812Smckusick register char *bp; 21822812Smckusick int size; 21922812Smckusick 22022812Smckusick size = (shift*leng + BYTESIZE -1)/BYTESIZE; 22122812Smckusick bp = (char *) ckalloc(size); 22222812Smckusick 22322812Smckusick i = 0; 22422812Smckusick 22522812Smckusick #if (TARGET == PDP11 || TARGET == VAX) 22622812Smckusick j = 0; 22722812Smckusick #else 22822812Smckusick j = size; 22922812Smckusick #endif 23022812Smckusick 23122812Smckusick k = 0; 23222812Smckusick 23322812Smckusick while (leng > 0) 23422812Smckusick { 23522812Smckusick k |= (hextoi(s[--leng]) << i); 23622812Smckusick i += shift; 23722812Smckusick if (i >= BYTESIZE) 23822812Smckusick { 23922812Smckusick #if (TARGET == PDP11 || TARGET == VAX) 24022812Smckusick bp[j++] = k & MAXBYTE; 24122812Smckusick #else 24222812Smckusick bp[--j] = k & MAXBYTE; 24322812Smckusick #endif 24422812Smckusick k = k >> BYTESIZE; 24522812Smckusick i -= BYTESIZE; 24622812Smckusick } 24722812Smckusick } 24822812Smckusick 24922812Smckusick if (k != 0) 25022812Smckusick #if (TARGET == PDP11 || TARGET == VAX) 25122812Smckusick bp[j++] = k; 25222812Smckusick #else 25322812Smckusick bp[--j] = k; 25422812Smckusick #endif 25522812Smckusick 25622812Smckusick p = mkconst(TYBITSTR); 25722812Smckusick p->vleng = ICON(size); 25822812Smckusick p->const.ccp = bp; 25922812Smckusick 26022812Smckusick return ((expptr) p); 26122812Smckusick } 26222812Smckusick 26322812Smckusick 26422812Smckusick 26522812Smckusick expptr mkstrcon(l,v) 26622812Smckusick int l; 26722812Smckusick register char *v; 26822812Smckusick { 26922812Smckusick register Constp p; 27022812Smckusick register char *s; 27122812Smckusick 27222812Smckusick p = mkconst(TYCHAR); 27322812Smckusick p->vleng = ICON(l); 27422812Smckusick p->const.ccp = s = (char *) ckalloc(l); 27522812Smckusick while(--l >= 0) 27622812Smckusick *s++ = *v++; 27722812Smckusick return( (expptr) p ); 27822812Smckusick } 27922812Smckusick 28022812Smckusick 28122812Smckusick expptr mkcxcon(realp,imagp) 28222812Smckusick register expptr realp, imagp; 28322812Smckusick { 28422812Smckusick int rtype, itype; 28522812Smckusick register Constp p; 28622812Smckusick 28722812Smckusick rtype = realp->headblock.vtype; 28822812Smckusick itype = imagp->headblock.vtype; 28922812Smckusick 29022812Smckusick if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) ) 29122812Smckusick { 29222812Smckusick p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX); 29322812Smckusick if( ISINT(rtype) ) 29422812Smckusick p->const.cd[0] = realp->constblock.const.ci; 29522812Smckusick else p->const.cd[0] = realp->constblock.const.cd[0]; 29622812Smckusick if( ISINT(itype) ) 29722812Smckusick p->const.cd[1] = imagp->constblock.const.ci; 29822812Smckusick else p->const.cd[1] = imagp->constblock.const.cd[0]; 29922812Smckusick } 30022812Smckusick else 30122812Smckusick { 30222812Smckusick err("invalid complex constant"); 30322812Smckusick p = (Constp) errnode(); 30422812Smckusick } 30522812Smckusick 30622812Smckusick frexpr(realp); 30722812Smckusick frexpr(imagp); 30822812Smckusick return( (expptr) p ); 30922812Smckusick } 31022812Smckusick 31122812Smckusick 31222812Smckusick expptr errnode() 31322812Smckusick { 31422812Smckusick struct Errorblock *p; 31522812Smckusick p = ALLOC(Errorblock); 31622812Smckusick p->tag = TERROR; 31722812Smckusick p->vtype = TYERROR; 31822812Smckusick return( (expptr) p ); 31922812Smckusick } 32022812Smckusick 32122812Smckusick 32222812Smckusick 32322812Smckusick 32422812Smckusick 32522812Smckusick expptr mkconv(t, p) 32622812Smckusick register int t; 32722812Smckusick register expptr p; 32822812Smckusick { 32922812Smckusick register expptr q; 33022812Smckusick Addrp r, s; 33122812Smckusick register int pt; 33222812Smckusick expptr opconv(); 33322812Smckusick 33422812Smckusick if(t==TYUNKNOWN || t==TYERROR) 33522812Smckusick badtype("mkconv", t); 33622812Smckusick pt = p->headblock.vtype; 33722812Smckusick if(t == pt) 33822812Smckusick return(p); 33922812Smckusick 34022812Smckusick if( pt == TYCHAR && ISNUMERIC(t) ) 34122812Smckusick { 34222812Smckusick warn("implicit conversion of character to numeric type"); 34322812Smckusick 34422812Smckusick /* 34522812Smckusick * Ugly kluge to copy character values into numerics. 34622812Smckusick */ 34722812Smckusick s = mkaltemp(t, ENULL); 34822812Smckusick r = (Addrp) cpexpr(s); 34922812Smckusick r->vtype = TYCHAR; 35022812Smckusick r->varleng = typesize[t]; 35122812Smckusick r->vleng = mkintcon(r->varleng); 35222812Smckusick q = mkexpr(OPASSIGN, r, p); 35322812Smckusick q = mkexpr(OPCOMMA, q, s); 35422812Smckusick return(q); 35522812Smckusick } 35622812Smckusick 35722812Smckusick #if SZADDR > SZSHORT 35822812Smckusick if( pt == TYADDR && t == TYSHORT) 35922812Smckusick { 36022812Smckusick err("insufficient precision to hold address type"); 36122812Smckusick return( errnode() ); 36222812Smckusick } 36322812Smckusick #endif 36422812Smckusick if( pt == TYADDR && ISNUMERIC(t) ) 36522812Smckusick warn("implicit conversion of address to numeric type"); 36622812Smckusick 36722812Smckusick if( ISCONST(p) && pt!=TYADDR) 36822812Smckusick { 36922812Smckusick q = (expptr) mkconst(t); 37022812Smckusick consconv(t, &(q->constblock.const), 37122812Smckusick p->constblock.vtype, &(p->constblock.const) ); 37222812Smckusick frexpr(p); 37322812Smckusick } 37422812Smckusick #if TARGET == PDP11 37522812Smckusick else if(ISINT(t) && pt==TYCHAR) 37622812Smckusick { 37722812Smckusick q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255)); 37822812Smckusick if(t == TYLONG) 37922812Smckusick q = opconv(q, TYLONG); 38022812Smckusick } 38122812Smckusick #endif 38222812Smckusick else 38322812Smckusick q = opconv(p, t); 38422812Smckusick 38522812Smckusick if(t == TYCHAR) 38622812Smckusick q->constblock.vleng = ICON(1); 38722812Smckusick return(q); 38822812Smckusick } 38922812Smckusick 39022812Smckusick 39122812Smckusick 39222812Smckusick /* intrinsic conversions */ 39322812Smckusick expptr intrconv(t, p) 39422812Smckusick register int t; 39522812Smckusick register expptr p; 39622812Smckusick { 39722812Smckusick register expptr q; 39822812Smckusick register int pt; 39922812Smckusick expptr opconv(); 40022812Smckusick 40122812Smckusick if(t==TYUNKNOWN || t==TYERROR) 40222812Smckusick badtype("intrconv", t); 40322812Smckusick pt = p->headblock.vtype; 40422812Smckusick if(t == pt) 40522812Smckusick return(p); 40622812Smckusick 40722812Smckusick else if( ISCONST(p) && pt!=TYADDR) 40822812Smckusick { 40922812Smckusick q = (expptr) mkconst(t); 41022812Smckusick consconv(t, &(q->constblock.const), 41122812Smckusick p->constblock.vtype, &(p->constblock.const) ); 41222812Smckusick frexpr(p); 41322812Smckusick } 41422812Smckusick #if TARGET == PDP11 41522812Smckusick else if(ISINT(t) && pt==TYCHAR) 41622812Smckusick { 41722812Smckusick q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255)); 41822812Smckusick if(t == TYLONG) 41922812Smckusick q = opconv(q, TYLONG); 42022812Smckusick } 42122812Smckusick #endif 42222812Smckusick else 42322812Smckusick q = opconv(p, t); 42422812Smckusick 42522812Smckusick if(t == TYCHAR) 42622812Smckusick q->constblock.vleng = ICON(1); 42722812Smckusick return(q); 42822812Smckusick } 42922812Smckusick 43022812Smckusick 43122812Smckusick 43222812Smckusick expptr opconv(p, t) 43322812Smckusick expptr p; 43422812Smckusick int t; 43522812Smckusick { 43622812Smckusick register expptr q; 43722812Smckusick 43822812Smckusick q = mkexpr(OPCONV, p, PNULL); 43922812Smckusick q->headblock.vtype = t; 44022812Smckusick return(q); 44122812Smckusick } 44222812Smckusick 44322812Smckusick 44422812Smckusick 44522812Smckusick expptr addrof(p) 44622812Smckusick expptr p; 44722812Smckusick { 44822812Smckusick return( mkexpr(OPADDR, p, PNULL) ); 44922812Smckusick } 45022812Smckusick 45122812Smckusick 45222812Smckusick 45322812Smckusick tagptr cpexpr(p) 45422812Smckusick register tagptr p; 45522812Smckusick { 45622812Smckusick register tagptr e; 45722812Smckusick int tag; 45822812Smckusick register chainp ep, pp; 45922812Smckusick tagptr cpblock(); 46022812Smckusick 46122812Smckusick static int blksize[ ] = 46222812Smckusick { 0, 46322812Smckusick sizeof(struct Nameblock), 46422812Smckusick sizeof(struct Constblock), 46522812Smckusick sizeof(struct Exprblock), 46622812Smckusick sizeof(struct Addrblock), 46722812Smckusick sizeof(struct Tempblock), 46822812Smckusick sizeof(struct Primblock), 46922812Smckusick sizeof(struct Listblock), 47022812Smckusick sizeof(struct Errorblock) 47122812Smckusick }; 47222812Smckusick 47322812Smckusick if(p == NULL) 47422812Smckusick return(NULL); 47522812Smckusick 47622812Smckusick if( (tag = p->tag) == TNAME) 47722812Smckusick return(p); 47822812Smckusick 47922812Smckusick e = cpblock( blksize[p->tag] , p); 48022812Smckusick 48122812Smckusick switch(tag) 48222812Smckusick { 48322812Smckusick case TCONST: 48422812Smckusick if(e->constblock.vtype == TYCHAR) 48522812Smckusick { 48622812Smckusick e->constblock.const.ccp = 48722812Smckusick copyn(1+strlen(e->constblock.const.ccp), 48822812Smckusick e->constblock.const.ccp); 48922812Smckusick e->constblock.vleng = 49022812Smckusick (expptr) cpexpr(e->constblock.vleng); 49122812Smckusick } 49222812Smckusick case TERROR: 49322812Smckusick break; 49422812Smckusick 49522812Smckusick case TEXPR: 49622812Smckusick e->exprblock.leftp = (expptr) cpexpr(p->exprblock.leftp); 49722812Smckusick e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp); 49822812Smckusick break; 49922812Smckusick 50022812Smckusick case TLIST: 50122812Smckusick if(pp = p->listblock.listp) 50222812Smckusick { 50322812Smckusick ep = e->listblock.listp = 50422812Smckusick mkchain( cpexpr(pp->datap), CHNULL); 50522812Smckusick for(pp = pp->nextp ; pp ; pp = pp->nextp) 50622812Smckusick ep = ep->nextp = 50722812Smckusick mkchain( cpexpr(pp->datap), CHNULL); 50822812Smckusick } 50922812Smckusick break; 51022812Smckusick 51122812Smckusick case TADDR: 51222812Smckusick e->addrblock.vleng = (expptr) cpexpr(e->addrblock.vleng); 51322812Smckusick e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset); 51422812Smckusick e->addrblock.istemp = NO; 51522812Smckusick break; 51622812Smckusick 51722812Smckusick case TTEMP: 51822812Smckusick e->tempblock.vleng = (expptr) cpexpr(e->tempblock.vleng); 51922812Smckusick e->tempblock.istemp = NO; 52022812Smckusick break; 52122812Smckusick 52222812Smckusick case TPRIM: 52322812Smckusick e->primblock.argsp = (struct Listblock *) 52422812Smckusick cpexpr(e->primblock.argsp); 52522812Smckusick e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp); 52622812Smckusick e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp); 52722812Smckusick break; 52822812Smckusick 52922812Smckusick default: 53022812Smckusick badtag("cpexpr", tag); 53122812Smckusick } 53222812Smckusick 53322812Smckusick return(e); 53422812Smckusick } 53522812Smckusick 53622812Smckusick frexpr(p) 53722812Smckusick register tagptr p; 53822812Smckusick { 53922812Smckusick register chainp q; 54022812Smckusick 54122812Smckusick if(p == NULL) 54222812Smckusick return; 54322812Smckusick 54422812Smckusick switch(p->tag) 54522812Smckusick { 54622812Smckusick case TCONST: 54722812Smckusick switch (p->constblock.vtype) 54822812Smckusick { 54922812Smckusick case TYBITSTR: 55022812Smckusick case TYCHAR: 55122812Smckusick case TYHOLLERITH: 55222812Smckusick free( (charptr) (p->constblock.const.ccp) ); 55322812Smckusick frexpr(p->constblock.vleng); 55422812Smckusick } 55522812Smckusick break; 55622812Smckusick 55722812Smckusick case TADDR: 55822812Smckusick if (!optimflag && p->addrblock.istemp) 55922812Smckusick { 56022812Smckusick frtemp(p); 56122812Smckusick return; 56222812Smckusick } 56322812Smckusick frexpr(p->addrblock.vleng); 56422812Smckusick frexpr(p->addrblock.memoffset); 56522812Smckusick break; 56622812Smckusick 56722812Smckusick case TTEMP: 56822812Smckusick frexpr(p->tempblock.vleng); 56922812Smckusick break; 57022812Smckusick 57122812Smckusick case TERROR: 57222812Smckusick break; 57322812Smckusick 57422812Smckusick case TNAME: 57522812Smckusick return; 57622812Smckusick 57722812Smckusick case TPRIM: 57822812Smckusick frexpr(p->primblock.argsp); 57922812Smckusick frexpr(p->primblock.fcharp); 58022812Smckusick frexpr(p->primblock.lcharp); 58122812Smckusick break; 58222812Smckusick 58322812Smckusick case TEXPR: 58422812Smckusick frexpr(p->exprblock.leftp); 58522812Smckusick if(p->exprblock.rightp) 58622812Smckusick frexpr(p->exprblock.rightp); 58722812Smckusick break; 58822812Smckusick 58922812Smckusick case TLIST: 59022812Smckusick for(q = p->listblock.listp ; q ; q = q->nextp) 59122812Smckusick frexpr(q->datap); 59222812Smckusick frchain( &(p->listblock.listp) ); 59322812Smckusick break; 59422812Smckusick 59522812Smckusick default: 59622812Smckusick badtag("frexpr", p->tag); 59722812Smckusick } 59822812Smckusick 59922812Smckusick free( (charptr) p ); 60022812Smckusick } 60122812Smckusick 60222812Smckusick /* fix up types in expression; replace subtrees and convert 60322812Smckusick names to address blocks */ 60422812Smckusick 60522812Smckusick expptr fixtype(p) 60622812Smckusick register tagptr p; 60722812Smckusick { 60822812Smckusick 60922812Smckusick if(p == 0) 61022812Smckusick return(0); 61122812Smckusick 61222812Smckusick switch(p->tag) 61322812Smckusick { 61422812Smckusick case TCONST: 61522812Smckusick return( (expptr) p ); 61622812Smckusick 61722812Smckusick case TADDR: 61822812Smckusick p->addrblock.memoffset = fixtype(p->addrblock.memoffset); 61922812Smckusick return( (expptr) p); 62022812Smckusick 62122812Smckusick case TTEMP: 62222812Smckusick return( (expptr) p); 62322812Smckusick 62422812Smckusick case TERROR: 62522812Smckusick return( (expptr) p); 62622812Smckusick 62722812Smckusick default: 62822812Smckusick badtag("fixtype", p->tag); 62922812Smckusick 63022812Smckusick case TEXPR: 63122812Smckusick return( fixexpr(p) ); 63222812Smckusick 63322812Smckusick case TLIST: 63422812Smckusick return( (expptr) p ); 63522812Smckusick 63622812Smckusick case TPRIM: 63722812Smckusick if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR) 63822812Smckusick { 63922812Smckusick if(p->primblock.namep->vtype == TYSUBR) 64022812Smckusick { 64122812Smckusick err("function invocation of subroutine"); 64222812Smckusick return( errnode() ); 64322812Smckusick } 64422812Smckusick else 64522812Smckusick return( mkfunct(p) ); 64622812Smckusick } 64722812Smckusick else return( mklhs(p) ); 64822812Smckusick } 64922812Smckusick } 65022812Smckusick 65122812Smckusick 65222812Smckusick 65322812Smckusick 65422812Smckusick 65522812Smckusick /* special case tree transformations and cleanups of expression trees */ 65622812Smckusick 65722812Smckusick expptr fixexpr(p) 65822812Smckusick register Exprp p; 65922812Smckusick { 66022812Smckusick expptr lp; 66122812Smckusick register expptr rp; 66222812Smckusick register expptr q; 66322812Smckusick int opcode, ltype, rtype, ptype, mtype; 66422812Smckusick expptr lconst, rconst; 66522812Smckusick expptr mkpower(); 66622812Smckusick 66722812Smckusick if( ISERROR(p) ) 66822812Smckusick return( (expptr) p ); 66922812Smckusick else if(p->tag != TEXPR) 67022812Smckusick badtag("fixexpr", p->tag); 67122812Smckusick opcode = p->opcode; 67222812Smckusick if (ISCONST(p->leftp)) 67322812Smckusick lconst = (expptr) cpexpr(p->leftp); 67422812Smckusick else 67522812Smckusick lconst = NULL; 67622812Smckusick if (p->rightp && ISCONST(p->rightp)) 67722812Smckusick rconst = (expptr) cpexpr(p->rightp); 67822812Smckusick else 67922812Smckusick rconst = NULL; 68022812Smckusick lp = p->leftp = fixtype(p->leftp); 68122812Smckusick ltype = lp->headblock.vtype; 68222812Smckusick if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP) 68322812Smckusick { 68422812Smckusick err("left side of assignment must be variable"); 68522812Smckusick frexpr(p); 68622812Smckusick return( errnode() ); 68722812Smckusick } 68822812Smckusick 68922812Smckusick if(p->rightp) 69022812Smckusick { 69122812Smckusick rp = p->rightp = fixtype(p->rightp); 69222812Smckusick rtype = rp->headblock.vtype; 69322812Smckusick } 69422812Smckusick else 69522812Smckusick { 69622812Smckusick rp = NULL; 69722812Smckusick rtype = 0; 69822812Smckusick } 69922812Smckusick 70022812Smckusick if(ltype==TYERROR || rtype==TYERROR) 70122812Smckusick { 70222812Smckusick frexpr(p); 70322812Smckusick frexpr(lconst); 70422812Smckusick frexpr(rconst); 70522812Smckusick return( errnode() ); 70622812Smckusick } 70722812Smckusick 70822812Smckusick /* force folding if possible */ 70922812Smckusick if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) ) 71022812Smckusick { 71122812Smckusick q = mkexpr(opcode, lp, rp); 71222812Smckusick if( ISCONST(q) ) 71322812Smckusick { 71422812Smckusick frexpr(lconst); 71522812Smckusick frexpr(rconst); 71622812Smckusick return(q); 71722812Smckusick } 71822812Smckusick free( (charptr) q ); /* constants did not fold */ 71922812Smckusick } 72022812Smckusick 72122812Smckusick if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR) 72222812Smckusick { 72322812Smckusick frexpr(p); 72422812Smckusick frexpr(lconst); 72522812Smckusick frexpr(rconst); 72622812Smckusick return( errnode() ); 72722812Smckusick } 72822812Smckusick 72922812Smckusick switch(opcode) 73022812Smckusick { 73122812Smckusick case OPCONCAT: 73222812Smckusick if(p->vleng == NULL) 73322812Smckusick p->vleng = mkexpr(OPPLUS, 73422812Smckusick cpexpr(lp->headblock.vleng), 73522812Smckusick cpexpr(rp->headblock.vleng) ); 73622812Smckusick break; 73722812Smckusick 73822812Smckusick case OPASSIGN: 73922812Smckusick case OPPLUSEQ: 74022812Smckusick case OPSTAREQ: 74122812Smckusick if(ltype == rtype) 74222812Smckusick break; 74322812Smckusick if( ! rconst && ISREAL(ltype) && ISREAL(rtype) ) 74422812Smckusick break; 74522812Smckusick if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) ) 74622812Smckusick break; 74722812Smckusick if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT) 74822812Smckusick #if FAMILY==PCC 74922812Smckusick && typesize[ltype]>=typesize[rtype] ) 75022812Smckusick #else 75122812Smckusick && typesize[ltype]==typesize[rtype] ) 75222812Smckusick #endif 75322812Smckusick break; 75422812Smckusick if (rconst) 75522812Smckusick { 75622812Smckusick p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) ); 75722812Smckusick frexpr(rp); 75822812Smckusick } 75922812Smckusick else 76022812Smckusick p->rightp = fixtype(mkconv(ptype, rp)); 76122812Smckusick break; 76222812Smckusick 76322812Smckusick case OPSLASH: 76422812Smckusick if( ISCOMPLEX(rtype) ) 76522812Smckusick { 76622812Smckusick p = (Exprp) call2(ptype, 76722812Smckusick ptype==TYCOMPLEX? "c_div" : "z_div", 76822812Smckusick mkconv(ptype, lp), mkconv(ptype, rp) ); 76922812Smckusick break; 77022812Smckusick } 77122812Smckusick case OPPLUS: 77222812Smckusick case OPMINUS: 77322812Smckusick case OPSTAR: 77422812Smckusick case OPMOD: 77522812Smckusick if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) || 77622812Smckusick (rtype==TYREAL && ! rconst ) )) 77722812Smckusick break; 77822812Smckusick if( ISCOMPLEX(ptype) ) 77922812Smckusick break; 78022812Smckusick if(ltype != ptype) 78122812Smckusick if (lconst) 78222812Smckusick { 78322812Smckusick p->leftp = fixtype(mkconv(ptype, 78422812Smckusick cpexpr(lconst))); 78522812Smckusick frexpr(lp); 78622812Smckusick } 78722812Smckusick else 78822812Smckusick p->leftp = fixtype(mkconv(ptype,lp)); 78922812Smckusick if(rtype != ptype) 79022812Smckusick if (rconst) 79122812Smckusick { 79222812Smckusick p->rightp = fixtype(mkconv(ptype, 79322812Smckusick cpexpr(rconst))); 79422812Smckusick frexpr(rp); 79522812Smckusick } 79622812Smckusick else 79722812Smckusick p->rightp = fixtype(mkconv(ptype,rp)); 79822812Smckusick break; 79922812Smckusick 80022812Smckusick case OPPOWER: 80122812Smckusick return( mkpower(p) ); 80222812Smckusick 80322812Smckusick case OPLT: 80422812Smckusick case OPLE: 80522812Smckusick case OPGT: 80622812Smckusick case OPGE: 80722812Smckusick case OPEQ: 80822812Smckusick case OPNE: 80922812Smckusick if(ltype == rtype) 81022812Smckusick break; 81122812Smckusick mtype = cktype(OPMINUS, ltype, rtype); 81222812Smckusick if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) || 81322812Smckusick (rtype==TYREAL && ! rconst) )) 81422812Smckusick break; 81522812Smckusick if( ISCOMPLEX(mtype) ) 81622812Smckusick break; 81722812Smckusick if(ltype != mtype) 81822812Smckusick if (lconst) 81922812Smckusick { 82022812Smckusick p->leftp = fixtype(mkconv(mtype, 82122812Smckusick cpexpr(lconst))); 82222812Smckusick frexpr(lp); 82322812Smckusick } 82422812Smckusick else 82522812Smckusick p->leftp = fixtype(mkconv(mtype,lp)); 82622812Smckusick if(rtype != mtype) 82722812Smckusick if (rconst) 82822812Smckusick { 82922812Smckusick p->rightp = fixtype(mkconv(mtype, 83022812Smckusick cpexpr(rconst))); 83122812Smckusick frexpr(rp); 83222812Smckusick } 83322812Smckusick else 83422812Smckusick p->rightp = fixtype(mkconv(mtype,rp)); 83522812Smckusick break; 83622812Smckusick 83722812Smckusick 83822812Smckusick case OPCONV: 83922812Smckusick if(ISCOMPLEX(p->vtype)) 84022812Smckusick { 84122812Smckusick ptype = cktype(OPCONV, p->vtype, ltype); 84222812Smckusick if(p->rightp) 84322812Smckusick ptype = cktype(OPCONV, ptype, rtype); 84422812Smckusick break; 84522812Smckusick } 84622812Smckusick ptype = cktype(OPCONV, p->vtype, ltype); 84722812Smckusick if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA) 84822812Smckusick { 84922812Smckusick lp->exprblock.rightp = 85022812Smckusick fixtype( mkconv(ptype, lp->exprblock.rightp) ); 85122812Smckusick free( (charptr) p ); 85222812Smckusick p = (Exprp) lp; 85322812Smckusick } 85422812Smckusick break; 85522812Smckusick 85622812Smckusick case OPADDR: 85722812Smckusick if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR) 85822812Smckusick fatal("addr of addr"); 85922812Smckusick break; 86022812Smckusick 86122812Smckusick case OPCOMMA: 86222812Smckusick case OPQUEST: 86322812Smckusick case OPCOLON: 86422812Smckusick break; 86522812Smckusick 86622812Smckusick case OPPAREN: 86722812Smckusick p->vleng = (expptr) cpexpr( lp->headblock.vleng ); 86822812Smckusick break; 86922812Smckusick 87022812Smckusick case OPMIN: 87122812Smckusick case OPMAX: 87222812Smckusick ptype = p->vtype; 87322812Smckusick break; 87422812Smckusick 87522812Smckusick default: 87622812Smckusick break; 87722812Smckusick } 87822812Smckusick 87922812Smckusick p->vtype = ptype; 88022812Smckusick frexpr(lconst); 88122812Smckusick frexpr(rconst); 88222812Smckusick return((expptr) p); 88322812Smckusick } 88422812Smckusick 88522812Smckusick #if SZINT < SZLONG 88622812Smckusick /* 88722812Smckusick for efficient subscripting, replace long ints by shorts 88822812Smckusick in easy places 88922812Smckusick */ 89022812Smckusick 89122812Smckusick expptr shorten(p) 89222812Smckusick register expptr p; 89322812Smckusick { 89422812Smckusick register expptr q; 89522812Smckusick 89622812Smckusick if(p->headblock.vtype != TYLONG) 89722812Smckusick return(p); 89822812Smckusick 89922812Smckusick switch(p->tag) 90022812Smckusick { 90122812Smckusick case TERROR: 90222812Smckusick case TLIST: 90322812Smckusick return(p); 90422812Smckusick 90522812Smckusick case TCONST: 90622812Smckusick case TADDR: 90722812Smckusick return( mkconv(TYINT,p) ); 90822812Smckusick 90922812Smckusick case TEXPR: 91022812Smckusick break; 91122812Smckusick 91222812Smckusick default: 91322812Smckusick badtag("shorten", p->tag); 91422812Smckusick } 91522812Smckusick 91622812Smckusick switch(p->exprblock.opcode) 91722812Smckusick { 91822812Smckusick case OPPLUS: 91922812Smckusick case OPMINUS: 92022812Smckusick case OPSTAR: 92122812Smckusick q = shorten( cpexpr(p->exprblock.rightp) ); 92222812Smckusick if(q->headblock.vtype == TYINT) 92322812Smckusick { 92422812Smckusick p->exprblock.leftp = shorten(p->exprblock.leftp); 92522812Smckusick if(p->exprblock.leftp->headblock.vtype == TYLONG) 92622812Smckusick frexpr(q); 92722812Smckusick else 92822812Smckusick { 92922812Smckusick frexpr(p->exprblock.rightp); 93022812Smckusick p->exprblock.rightp = q; 93122812Smckusick p->exprblock.vtype = TYINT; 93222812Smckusick } 93322812Smckusick } 93422812Smckusick break; 93522812Smckusick 93622812Smckusick case OPNEG: 93722812Smckusick case OPPAREN: 93822812Smckusick p->exprblock.leftp = shorten(p->exprblock.leftp); 93922812Smckusick if(p->exprblock.leftp->headblock.vtype == TYINT) 94022812Smckusick p->exprblock.vtype = TYINT; 94122812Smckusick break; 94222812Smckusick 94322812Smckusick case OPCALL: 94422812Smckusick case OPCCALL: 94522812Smckusick p = mkconv(TYINT,p); 94622812Smckusick break; 94722812Smckusick default: 94822812Smckusick break; 94922812Smckusick } 95022812Smckusick 95122812Smckusick return(p); 95222812Smckusick } 95322812Smckusick #endif 95422812Smckusick 95522812Smckusick /* fix an argument list, taking due care for special first level cases */ 95622812Smckusick 95722812Smckusick fixargs(doput, p0) 95822812Smckusick int doput; /* doput is true if the function is not intrinsic; 95922812Smckusick was used to decide whether to do a putconst, 96022812Smckusick but this is no longer done here (Feb82)*/ 96122812Smckusick struct Listblock *p0; 96222812Smckusick { 96322812Smckusick register chainp p; 96422812Smckusick register tagptr q, t; 96522812Smckusick register int qtag; 96622812Smckusick int nargs; 96722812Smckusick Addrp mkscalar(); 96822812Smckusick 96922812Smckusick nargs = 0; 97022812Smckusick if(p0) 97122812Smckusick for(p = p0->listp ; p ; p = p->nextp) 97222812Smckusick { 97322812Smckusick ++nargs; 97422812Smckusick q = p->datap; 97522812Smckusick qtag = q->tag; 97622812Smckusick if(qtag == TCONST) 97722812Smckusick { 97822812Smckusick if(q->constblock.vtype == TYSHORT) 97922812Smckusick q = (tagptr) mkconv(tyint, q); 98022812Smckusick p->datap = q ; 98122812Smckusick } 98222812Smckusick else if(qtag==TPRIM && q->primblock.argsp==0 && 98322812Smckusick q->primblock.namep->vclass==CLPROC) 98422812Smckusick p->datap = (tagptr) mkaddr(q->primblock.namep); 98522812Smckusick else if(qtag==TPRIM && q->primblock.argsp==0 && 98622812Smckusick q->primblock.namep->vdim!=NULL) 98722812Smckusick p->datap = (tagptr) mkscalar(q->primblock.namep); 98822812Smckusick else if(qtag==TPRIM && q->primblock.argsp==0 && 98922812Smckusick q->primblock.namep->vdovar && 99022812Smckusick (t = (tagptr) memversion(q->primblock.namep)) ) 99122812Smckusick p->datap = (tagptr) fixtype(t); 99222812Smckusick else 99322812Smckusick p->datap = (tagptr) fixtype(q); 99422812Smckusick } 99522812Smckusick return(nargs); 99622812Smckusick } 99722812Smckusick 99822812Smckusick 99922812Smckusick Addrp mkscalar(np) 100022812Smckusick register Namep np; 100122812Smckusick { 100222812Smckusick register Addrp ap; 100322812Smckusick 100422812Smckusick vardcl(np); 100522812Smckusick ap = mkaddr(np); 100622812Smckusick 100722812Smckusick #if TARGET == VAX 100822812Smckusick /* on the VAX, prolog causes array arguments 100922812Smckusick to point at the (0,...,0) element, except when 101022812Smckusick subscript checking is on 101122812Smckusick */ 101222812Smckusick #ifdef SDB 101322812Smckusick if( !checksubs && !sdbflag && np->vstg==STGARG) 101422812Smckusick #else 101522812Smckusick if( !checksubs && np->vstg==STGARG) 101622812Smckusick #endif 101722812Smckusick { 101822812Smckusick register struct Dimblock *dp; 101922812Smckusick dp = np->vdim; 102022812Smckusick frexpr(ap->memoffset); 102122812Smckusick ap->memoffset = mkexpr(OPSTAR, 102222812Smckusick (np->vtype==TYCHAR ? 102322812Smckusick cpexpr(np->vleng) : 102422812Smckusick (tagptr)ICON(typesize[np->vtype]) ), 102522812Smckusick cpexpr(dp->baseoffset) ); 102622812Smckusick } 102722812Smckusick #endif 102822812Smckusick return(ap); 102922812Smckusick } 103022812Smckusick 103122812Smckusick 103222812Smckusick 103322812Smckusick 103422812Smckusick 103522812Smckusick expptr mkfunct(p) 103622812Smckusick register struct Primblock *p; 103722812Smckusick { 103822812Smckusick struct Entrypoint *ep; 103922812Smckusick Addrp ap; 104022812Smckusick struct Extsym *extp; 104122812Smckusick register Namep np; 104222812Smckusick register expptr q; 104322812Smckusick expptr intrcall(), stfcall(); 104422812Smckusick int k, nargs; 104522812Smckusick int class; 104622812Smckusick 104722812Smckusick if(p->tag != TPRIM) 104822812Smckusick return( errnode() ); 104922812Smckusick 105022812Smckusick np = p->namep; 105122812Smckusick class = np->vclass; 105222812Smckusick 105322812Smckusick if(class == CLUNKNOWN) 105422812Smckusick { 105522812Smckusick np->vclass = class = CLPROC; 105622812Smckusick if(np->vstg == STGUNKNOWN) 105722812Smckusick { 105822812Smckusick if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) ) 105922812Smckusick { 106022812Smckusick np->vstg = STGINTR; 106122812Smckusick np->vardesc.varno = k; 106222812Smckusick np->vprocclass = PINTRINSIC; 106322812Smckusick } 106422812Smckusick else 106522812Smckusick { 106622812Smckusick extp = mkext( varunder(VL,np->varname) ); 106722812Smckusick extp->extstg = STGEXT; 106822812Smckusick np->vstg = STGEXT; 106922812Smckusick np->vardesc.varno = extp - extsymtab; 107022812Smckusick np->vprocclass = PEXTERNAL; 107122812Smckusick } 107222812Smckusick } 107322812Smckusick else if(np->vstg==STGARG) 107422812Smckusick { 107522812Smckusick if(np->vtype!=TYCHAR && !ftn66flag) 107622812Smckusick warn("Dummy procedure not declared EXTERNAL. Code may be wrong."); 107722812Smckusick np->vprocclass = PEXTERNAL; 107822812Smckusick } 107922812Smckusick } 108022812Smckusick 108122812Smckusick if(class != CLPROC) 108222812Smckusick fatali("invalid class code %d for function", class); 108322812Smckusick if(p->fcharp || p->lcharp) 108422812Smckusick { 108522812Smckusick err("no substring of function call"); 108622812Smckusick goto error; 108722812Smckusick } 108822812Smckusick impldcl(np); 108922812Smckusick nargs = fixargs( np->vprocclass!=PINTRINSIC, p->argsp); 109022812Smckusick 109122812Smckusick switch(np->vprocclass) 109222812Smckusick { 109322812Smckusick case PEXTERNAL: 109422812Smckusick ap = mkaddr(np); 109522812Smckusick call: 109622812Smckusick q = mkexpr(OPCALL, ap, p->argsp); 109722812Smckusick if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN) 109822812Smckusick { 109922812Smckusick err("attempt to use untyped function"); 110022812Smckusick goto error; 110122812Smckusick } 110222812Smckusick if(np->vleng) 110322812Smckusick q->exprblock.vleng = (expptr) cpexpr(np->vleng); 110422812Smckusick break; 110522812Smckusick 110622812Smckusick case PINTRINSIC: 110722812Smckusick q = intrcall(np, p->argsp, nargs); 110822812Smckusick break; 110922812Smckusick 111022812Smckusick case PSTFUNCT: 111122812Smckusick q = stfcall(np, p->argsp); 111222812Smckusick break; 111322812Smckusick 111422812Smckusick case PTHISPROC: 111522812Smckusick warn("recursive call"); 111622812Smckusick for(ep = entries ; ep ; ep = ep->entnextp) 111722812Smckusick if(ep->enamep == np) 111822812Smckusick break; 111922812Smckusick if(ep == NULL) 112022812Smckusick fatal("mkfunct: impossible recursion"); 112122812Smckusick ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) ); 112222812Smckusick goto call; 112322812Smckusick 112422812Smckusick default: 112522812Smckusick fatali("mkfunct: impossible vprocclass %d", 112622812Smckusick (int) (np->vprocclass) ); 112722812Smckusick } 112822812Smckusick free( (charptr) p ); 112922812Smckusick return(q); 113022812Smckusick 113122812Smckusick error: 113222812Smckusick frexpr(p); 113322812Smckusick return( errnode() ); 113422812Smckusick } 113522812Smckusick 113622812Smckusick 113722812Smckusick 113822812Smckusick LOCAL expptr stfcall(np, actlist) 113922812Smckusick Namep np; 114022812Smckusick struct Listblock *actlist; 114122812Smckusick { 114222812Smckusick register chainp actuals; 114322812Smckusick int nargs; 114422812Smckusick chainp oactp, formals; 114522812Smckusick int type; 114622812Smckusick expptr q, rhs, ap; 114722812Smckusick Namep tnp; 114822812Smckusick register struct Rplblock *rp; 114922812Smckusick struct Rplblock *tlist; 115022812Smckusick 115122812Smckusick if(actlist) 115222812Smckusick { 115322812Smckusick actuals = actlist->listp; 115422812Smckusick free( (charptr) actlist); 115522812Smckusick } 115622812Smckusick else 115722812Smckusick actuals = NULL; 115822812Smckusick oactp = actuals; 115922812Smckusick 116022812Smckusick nargs = 0; 116122812Smckusick tlist = NULL; 116222812Smckusick if( (type = np->vtype) == TYUNKNOWN) 116322812Smckusick { 116422812Smckusick err("attempt to use untyped statement function"); 116522812Smckusick q = errnode(); 116622812Smckusick goto ret; 116722812Smckusick } 116822812Smckusick formals = (chainp) (np->varxptr.vstfdesc->datap); 116922812Smckusick rhs = (expptr) (np->varxptr.vstfdesc->nextp); 117022812Smckusick 117122812Smckusick /* copy actual arguments into temporaries */ 117222812Smckusick while(actuals!=NULL && formals!=NULL) 117322812Smckusick { 117422812Smckusick rp = ALLOC(Rplblock); 117522812Smckusick rp->rplnp = tnp = (Namep) (formals->datap); 117622812Smckusick ap = fixtype(actuals->datap); 117722812Smckusick if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR 117822812Smckusick && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) ) 117922812Smckusick { 118022812Smckusick rp->rplvp = (expptr) ap; 118122812Smckusick rp->rplxp = NULL; 118222812Smckusick rp->rpltag = ap->tag; 118322812Smckusick } 118422812Smckusick else { 118522812Smckusick rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng); 118622812Smckusick rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) ); 118722812Smckusick if( (rp->rpltag = rp->rplxp->tag) == TERROR) 118822812Smckusick err("disagreement of argument types in statement function call"); 118922812Smckusick else if(tnp->vtype!=ap->headblock.vtype) 119022812Smckusick warn("argument type mismatch in statement function"); 119122812Smckusick } 119222812Smckusick rp->rplnextp = tlist; 119322812Smckusick tlist = rp; 119422812Smckusick actuals = actuals->nextp; 119522812Smckusick formals = formals->nextp; 119622812Smckusick ++nargs; 119722812Smckusick } 119822812Smckusick 119922812Smckusick if(actuals!=NULL || formals!=NULL) 120022812Smckusick err("statement function definition and argument list differ"); 120122812Smckusick 120222812Smckusick /* 120322812Smckusick now push down names involved in formal argument list, then 120422812Smckusick evaluate rhs of statement function definition in this environment 120522812Smckusick */ 120622812Smckusick 120722812Smckusick if(tlist) /* put tlist in front of the rpllist */ 120822812Smckusick { 120922812Smckusick for(rp = tlist; rp->rplnextp; rp = rp->rplnextp) 121022812Smckusick ; 121122812Smckusick rp->rplnextp = rpllist; 121222812Smckusick rpllist = tlist; 121322812Smckusick } 121422812Smckusick 121522812Smckusick q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) ); 121622812Smckusick 121722812Smckusick /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */ 121822812Smckusick while(--nargs >= 0) 121922812Smckusick { 122022812Smckusick if(rpllist->rplxp) 122122812Smckusick q = mkexpr(OPCOMMA, rpllist->rplxp, q); 122222812Smckusick rp = rpllist->rplnextp; 122322812Smckusick frexpr(rpllist->rplvp); 122422812Smckusick free(rpllist); 122522812Smckusick rpllist = rp; 122622812Smckusick } 122722812Smckusick 122822812Smckusick ret: 122922812Smckusick frchain( &oactp ); 123022812Smckusick return(q); 123122812Smckusick } 123222812Smckusick 123322812Smckusick 123422812Smckusick 123522812Smckusick 123622812Smckusick Addrp mkplace(np) 123722812Smckusick register Namep np; 123822812Smckusick { 123922812Smckusick register Addrp s; 124022812Smckusick register struct Rplblock *rp; 124122812Smckusick int regn; 124222812Smckusick 124322812Smckusick /* is name on the replace list? */ 124422812Smckusick 124522812Smckusick for(rp = rpllist ; rp ; rp = rp->rplnextp) 124622812Smckusick { 124722812Smckusick if(np == rp->rplnp) 124822812Smckusick { 124922812Smckusick if(rp->rpltag == TNAME) 125022812Smckusick { 125122812Smckusick np = (Namep) (rp->rplvp); 125222812Smckusick break; 125322812Smckusick } 125422812Smckusick else return( (Addrp) cpexpr(rp->rplvp) ); 125522812Smckusick } 125622812Smckusick } 125722812Smckusick 125822812Smckusick /* is variable a DO index in a register ? */ 125922812Smckusick 126022812Smckusick if(np->vdovar && ( (regn = inregister(np)) >= 0) ) 126122812Smckusick if(np->vtype == TYERROR) 126222812Smckusick return( (Addrp) errnode() ); 126322812Smckusick else 126422812Smckusick { 126522812Smckusick s = ALLOC(Addrblock); 126622812Smckusick s->tag = TADDR; 126722812Smckusick s->vstg = STGREG; 126822812Smckusick s->vtype = TYIREG; 126922812Smckusick s->issaved = np->vsave; 127022812Smckusick s->memno = regn; 127122812Smckusick s->memoffset = ICON(0); 127222812Smckusick return(s); 127322812Smckusick } 127422812Smckusick 127522812Smckusick vardcl(np); 127622812Smckusick return(mkaddr(np)); 127722812Smckusick } 127822812Smckusick 127922812Smckusick 128022812Smckusick 128122812Smckusick 128222812Smckusick expptr mklhs(p) 128322812Smckusick register struct Primblock *p; 128422812Smckusick { 128522812Smckusick expptr suboffset(); 128622812Smckusick register Addrp s; 128722812Smckusick Namep np; 128822812Smckusick 128922812Smckusick if(p->tag != TPRIM) 129022812Smckusick return( (expptr) p ); 129122812Smckusick np = p->namep; 129222812Smckusick 129322812Smckusick s = mkplace(np); 129422812Smckusick if(s->tag!=TADDR || s->vstg==STGREG) 129522812Smckusick { 129622812Smckusick free( (charptr) p ); 129722812Smckusick return( (expptr) s ); 129822812Smckusick } 129922812Smckusick 130022812Smckusick /* compute the address modified by subscripts */ 130122812Smckusick 130222812Smckusick s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) ); 130322812Smckusick frexpr(p->argsp); 130422812Smckusick p->argsp = NULL; 130522812Smckusick 130622812Smckusick /* now do substring part */ 130722812Smckusick 130822812Smckusick if(p->fcharp || p->lcharp) 130922812Smckusick { 131022812Smckusick if(np->vtype != TYCHAR) 131122812Smckusick errstr("substring of noncharacter %s", varstr(VL,np->varname)); 131222812Smckusick else { 131322812Smckusick if(p->lcharp == NULL) 131422812Smckusick p->lcharp = (expptr) cpexpr(s->vleng); 131522812Smckusick frexpr(s->vleng); 131622812Smckusick if(p->fcharp) 131722812Smckusick { 131822812Smckusick if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM 131922812Smckusick && p->fcharp->primblock.namep == p->lcharp->primblock.namep) 132022812Smckusick /* A trivial optimization -- upper == lower */ 132122812Smckusick s->vleng = ICON(1); 132222812Smckusick else 132322812Smckusick s->vleng = mkexpr(OPMINUS, p->lcharp, 132422812Smckusick mkexpr(OPMINUS, p->fcharp, ICON(1) )); 132522812Smckusick } 132622812Smckusick else 132722812Smckusick s->vleng = p->lcharp; 132822812Smckusick } 132922812Smckusick } 133022812Smckusick 133122812Smckusick s->vleng = fixtype( s->vleng ); 133222812Smckusick s->memoffset = fixtype( s->memoffset ); 133322812Smckusick free( (charptr) p ); 133422812Smckusick return( (expptr) s ); 133522812Smckusick } 133622812Smckusick 133722812Smckusick 133822812Smckusick 133922812Smckusick 134022812Smckusick 134122812Smckusick deregister(np) 134222812Smckusick Namep np; 134322812Smckusick { 134422812Smckusick if(nregvar>0 && regnamep[nregvar-1]==np) 134522812Smckusick { 134622812Smckusick --nregvar; 134722812Smckusick #if FAMILY == DMR 134822812Smckusick putnreg(); 134922812Smckusick #endif 135022812Smckusick } 135122812Smckusick } 135222812Smckusick 135322812Smckusick 135422812Smckusick 135522812Smckusick 135622812Smckusick Addrp memversion(np) 135722812Smckusick register Namep np; 135822812Smckusick { 135922812Smckusick register Addrp s; 136022812Smckusick 136122812Smckusick if(np->vdovar==NO || (inregister(np)<0) ) 136222812Smckusick return(NULL); 136322812Smckusick np->vdovar = NO; 136422812Smckusick s = mkplace(np); 136522812Smckusick np->vdovar = YES; 136622812Smckusick return(s); 136722812Smckusick } 136822812Smckusick 136922812Smckusick 137022812Smckusick 137122812Smckusick inregister(np) 137222812Smckusick register Namep np; 137322812Smckusick { 137422812Smckusick register int i; 137522812Smckusick 137622812Smckusick for(i = 0 ; i < nregvar ; ++i) 137722812Smckusick if(regnamep[i] == np) 137822812Smckusick return( regnum[i] ); 137922812Smckusick return(-1); 138022812Smckusick } 138122812Smckusick 138222812Smckusick 138322812Smckusick 138422812Smckusick 138522812Smckusick enregister(np) 138622812Smckusick Namep np; 138722812Smckusick { 138822812Smckusick if( inregister(np) >= 0) 138922812Smckusick return(YES); 139022812Smckusick if(nregvar >= maxregvar) 139122812Smckusick return(NO); 139222812Smckusick vardcl(np); 139322812Smckusick if( ONEOF(np->vtype, MSKIREG) ) 139422812Smckusick { 139522812Smckusick regnamep[nregvar++] = np; 139622812Smckusick if(nregvar > highregvar) 139722812Smckusick highregvar = nregvar; 139822812Smckusick #if FAMILY == DMR 139922812Smckusick putnreg(); 140022812Smckusick #endif 140122812Smckusick return(YES); 140222812Smckusick } 140322812Smckusick else 140422812Smckusick return(NO); 140522812Smckusick } 140622812Smckusick 140722812Smckusick 140822812Smckusick 140922812Smckusick 141022812Smckusick expptr suboffset(p) 141122812Smckusick register struct Primblock *p; 141222812Smckusick { 141322812Smckusick int n; 141422812Smckusick expptr size; 141522812Smckusick expptr oftwo(); 141622812Smckusick chainp cp; 141722812Smckusick expptr offp, prod; 141822812Smckusick expptr subcheck(); 141922812Smckusick struct Dimblock *dimp; 142022812Smckusick expptr sub[MAXDIM+1]; 142122812Smckusick register Namep np; 142222812Smckusick 142322812Smckusick np = p->namep; 142422812Smckusick offp = ICON(0); 142522812Smckusick n = 0; 142622812Smckusick if(p->argsp) 142722812Smckusick for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp) 142822812Smckusick { 142922812Smckusick sub[n] = fixtype(cpexpr(cp->datap)); 143022812Smckusick if ( ! ISINT(sub[n]->headblock.vtype)) { 143122812Smckusick errstr("%s: non-integer subscript expression", 143222812Smckusick varstr(VL, np->varname) ); 143322812Smckusick /* Provide a substitute -- go on to find more errors */ 143422812Smckusick frexpr(sub[n]); 143522812Smckusick sub[n] = ICON(1); 143622812Smckusick } 143722812Smckusick if(n > maxdim) 143822812Smckusick { 143922812Smckusick char str[28+VL]; 144022812Smckusick sprintf(str, "%s: more than %d subscripts", 144122812Smckusick varstr(VL, np->varname), maxdim ); 144222812Smckusick err( str ); 144322812Smckusick break; 144422812Smckusick } 144522812Smckusick } 144622812Smckusick 144722812Smckusick dimp = np->vdim; 144822812Smckusick if(n>0 && dimp==NULL) 144922812Smckusick errstr("%s: subscripts on scalar variable", 145022812Smckusick varstr(VL, np->varname), maxdim ); 145122812Smckusick else if(dimp && dimp->ndim!=n) 145222812Smckusick errstr("wrong number of subscripts on %s", 145322812Smckusick varstr(VL, np->varname) ); 145422812Smckusick else if(n > 0) 145522812Smckusick { 145622812Smckusick prod = sub[--n]; 145722812Smckusick while( --n >= 0) 145822812Smckusick prod = mkexpr(OPPLUS, sub[n], 145922812Smckusick mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) ); 146022812Smckusick #if TARGET == VAX 146122812Smckusick #ifdef SDB 146222812Smckusick if(checksubs || np->vstg!=STGARG || sdbflag) 146322812Smckusick #else 146422812Smckusick if(checksubs || np->vstg!=STGARG) 146522812Smckusick #endif 146622812Smckusick prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset)); 146722812Smckusick #else 146822812Smckusick prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset)); 146922812Smckusick #endif 147022812Smckusick if(checksubs) 147122812Smckusick prod = subcheck(np, prod); 147222812Smckusick size = np->vtype == TYCHAR ? 147322812Smckusick (expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]); 147422812Smckusick if (!oftwo(size)) 147522812Smckusick prod = mkexpr(OPSTAR, prod, size); 147622812Smckusick else 147722812Smckusick prod = mkexpr(OPLSHIFT,prod,oftwo(size)); 147822812Smckusick 147922812Smckusick offp = mkexpr(OPPLUS, offp, prod); 148022812Smckusick } 148122812Smckusick 148222812Smckusick if(p->fcharp && np->vtype==TYCHAR) 148322812Smckusick offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) )); 148422812Smckusick 148522812Smckusick return(offp); 148622812Smckusick } 148722812Smckusick 148822812Smckusick 148922812Smckusick 149022812Smckusick 149122812Smckusick expptr subcheck(np, p) 149222812Smckusick Namep np; 149322812Smckusick register expptr p; 149422812Smckusick { 149522812Smckusick struct Dimblock *dimp; 149622812Smckusick expptr t, checkvar, checkcond, badcall; 149722812Smckusick 149822812Smckusick dimp = np->vdim; 149922812Smckusick if(dimp->nelt == NULL) 150022812Smckusick return(p); /* don't check arrays with * bounds */ 150122812Smckusick checkvar = NULL; 150222812Smckusick checkcond = NULL; 150322812Smckusick if( ISICON(p) ) 150422812Smckusick { 150522812Smckusick if(p->constblock.const.ci < 0) 150622812Smckusick goto badsub; 150722812Smckusick if( ISICON(dimp->nelt) ) 150822812Smckusick if(p->constblock.const.ci < dimp->nelt->constblock.const.ci) 150922812Smckusick return(p); 151022812Smckusick else 151122812Smckusick goto badsub; 151222812Smckusick } 151322812Smckusick if(p->tag==TADDR && p->addrblock.vstg==STGREG) 151422812Smckusick { 151522812Smckusick checkvar = (expptr) cpexpr(p); 151622812Smckusick t = p; 151722812Smckusick } 151822812Smckusick else { 151922812Smckusick checkvar = (expptr) mktemp(p->headblock.vtype, ENULL); 152022812Smckusick t = mkexpr(OPASSIGN, cpexpr(checkvar), p); 152122812Smckusick } 152222812Smckusick checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) ); 152322812Smckusick if( ! ISICON(p) ) 152422812Smckusick checkcond = mkexpr(OPAND, checkcond, 152522812Smckusick mkexpr(OPLE, ICON(0), cpexpr(checkvar)) ); 152622812Smckusick 152722812Smckusick badcall = call4(p->headblock.vtype, "s_rnge", 152822812Smckusick mkstrcon(VL, np->varname), 152922812Smckusick mkconv(TYLONG, cpexpr(checkvar)), 153022812Smckusick mkstrcon(XL, procname), 153122812Smckusick ICON(lineno) ); 153222812Smckusick badcall->exprblock.opcode = OPCCALL; 153322812Smckusick p = mkexpr(OPQUEST, checkcond, 153422812Smckusick mkexpr(OPCOLON, checkvar, badcall)); 153522812Smckusick 153622812Smckusick return(p); 153722812Smckusick 153822812Smckusick badsub: 153922812Smckusick frexpr(p); 154022812Smckusick errstr("subscript on variable %s out of range", varstr(VL,np->varname)); 154122812Smckusick return ( ICON(0) ); 154222812Smckusick } 154322812Smckusick 154422812Smckusick 154522812Smckusick 154622812Smckusick 154722812Smckusick Addrp mkaddr(p) 154822812Smckusick register Namep p; 154922812Smckusick { 155022812Smckusick struct Extsym *extp; 155122812Smckusick register Addrp t; 155222812Smckusick Addrp intraddr(); 155322812Smckusick 155422812Smckusick switch( p->vstg) 155522812Smckusick { 155622812Smckusick case STGUNKNOWN: 155722812Smckusick if(p->vclass != CLPROC) 155822812Smckusick break; 155922812Smckusick extp = mkext( varunder(VL, p->varname) ); 156022812Smckusick extp->extstg = STGEXT; 156122812Smckusick p->vstg = STGEXT; 156222812Smckusick p->vardesc.varno = extp - extsymtab; 156322812Smckusick p->vprocclass = PEXTERNAL; 156422812Smckusick 156522812Smckusick case STGCOMMON: 156622812Smckusick case STGEXT: 156722812Smckusick case STGBSS: 156822812Smckusick case STGINIT: 156922812Smckusick case STGEQUIV: 157022812Smckusick case STGARG: 157122812Smckusick case STGLENG: 157222812Smckusick case STGAUTO: 157322812Smckusick t = ALLOC(Addrblock); 157422812Smckusick t->tag = TADDR; 157522812Smckusick if(p->vclass==CLPROC && p->vprocclass==PTHISPROC) 157622812Smckusick t->vclass = CLVAR; 157722812Smckusick else 157822812Smckusick t->vclass = p->vclass; 157922812Smckusick t->vtype = p->vtype; 158022812Smckusick t->vstg = p->vstg; 158122812Smckusick t->memno = p->vardesc.varno; 158222812Smckusick t->issaved = p->vsave; 158322812Smckusick if(p->vdim) t->isarray = YES; 158422812Smckusick t->memoffset = ICON(p->voffset); 158522812Smckusick if(p->vleng) 158622812Smckusick { 158722812Smckusick t->vleng = (expptr) cpexpr(p->vleng); 158822812Smckusick if( ISICON(t->vleng) ) 158922812Smckusick t->varleng = t->vleng->constblock.const.ci; 159022812Smckusick } 159122812Smckusick if (p->vstg == STGBSS) 159222812Smckusick t->varsize = p->varsize; 159322812Smckusick else if (p->vstg == STGEQUIV) 159422812Smckusick t->varsize = eqvclass[t->memno].eqvleng; 159522812Smckusick return(t); 159622812Smckusick 159722812Smckusick case STGINTR: 159822812Smckusick return( intraddr(p) ); 159922812Smckusick 160022812Smckusick } 160122812Smckusick /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass); 160222812Smckusick badstg("mkaddr", p->vstg); 160322812Smckusick /* NOTREACHED */ 160422812Smckusick } 160522812Smckusick 160622812Smckusick 160722812Smckusick 160822812Smckusick 160922812Smckusick Addrp mkarg(type, argno) 161022812Smckusick int type, argno; 161122812Smckusick { 161222812Smckusick register Addrp p; 161322812Smckusick 161422812Smckusick p = ALLOC(Addrblock); 161522812Smckusick p->tag = TADDR; 161622812Smckusick p->vtype = type; 161722812Smckusick p->vclass = CLVAR; 161822812Smckusick p->vstg = (type==TYLENG ? STGLENG : STGARG); 161922812Smckusick p->memno = argno; 162022812Smckusick return(p); 162122812Smckusick } 162222812Smckusick 162322812Smckusick 162422812Smckusick 162522812Smckusick 162622812Smckusick expptr mkprim(v, args, substr) 162722812Smckusick register union 162822812Smckusick { 162922812Smckusick struct Paramblock paramblock; 163022812Smckusick struct Nameblock nameblock; 163122812Smckusick struct Headblock headblock; 163222812Smckusick } *v; 163322812Smckusick struct Listblock *args; 163422812Smckusick chainp substr; 163522812Smckusick { 163622812Smckusick register struct Primblock *p; 163722812Smckusick 163822812Smckusick if(v->headblock.vclass == CLPARAM) 163922812Smckusick { 164022812Smckusick if(args || substr) 164122812Smckusick { 164222812Smckusick errstr("no qualifiers on parameter name %s", 164322812Smckusick varstr(VL,v->paramblock.varname)); 164422812Smckusick frexpr(args); 164522812Smckusick if(substr) 164622812Smckusick { 164722812Smckusick frexpr(substr->datap); 164822812Smckusick frexpr(substr->nextp->datap); 164922812Smckusick frchain(&substr); 165022812Smckusick } 165122812Smckusick frexpr(v); 165222812Smckusick return( errnode() ); 165322812Smckusick } 165422812Smckusick return( (expptr) cpexpr(v->paramblock.paramval) ); 165522812Smckusick } 165622812Smckusick 165722812Smckusick p = ALLOC(Primblock); 165822812Smckusick p->tag = TPRIM; 165922812Smckusick p->vtype = v->nameblock.vtype; 166022812Smckusick p->namep = (Namep) v; 166122812Smckusick p->argsp = args; 166222812Smckusick if(substr) 166322812Smckusick { 166423680Smckusick p->fcharp = (expptr) substr->datap; 1665*24477Sdonn if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype)) 166623680Smckusick p->fcharp = mkconv(TYINT, p->fcharp); 166723680Smckusick p->lcharp = (expptr) substr->nextp->datap; 1668*24477Sdonn if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype)) 166923680Smckusick p->lcharp = mkconv(TYINT, p->lcharp); 167022812Smckusick frchain(&substr); 167122812Smckusick } 167222812Smckusick return( (expptr) p); 167322812Smckusick } 167422812Smckusick 167522812Smckusick 167622812Smckusick 167722812Smckusick vardcl(v) 167822812Smckusick register Namep v; 167922812Smckusick { 168022812Smckusick int nelt; 168122812Smckusick struct Dimblock *t; 168222812Smckusick Addrp p; 168322812Smckusick expptr neltp; 168422812Smckusick int eltsize; 168522812Smckusick int varsize; 168622812Smckusick int tsize; 168722812Smckusick int align; 168822812Smckusick 168922812Smckusick if(v->vdcldone) 169022812Smckusick return; 169122812Smckusick if(v->vclass == CLNAMELIST) 169222812Smckusick return; 169322812Smckusick 169422812Smckusick if(v->vtype == TYUNKNOWN) 169522812Smckusick impldcl(v); 169622812Smckusick if(v->vclass == CLUNKNOWN) 169722812Smckusick v->vclass = CLVAR; 169822812Smckusick else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC) 169922812Smckusick { 170022812Smckusick dclerr("used both as variable and non-variable", v); 170122812Smckusick return; 170222812Smckusick } 170322812Smckusick if(v->vstg==STGUNKNOWN) 170422812Smckusick v->vstg = implstg[ letter(v->varname[0]) ]; 170522812Smckusick 170622812Smckusick switch(v->vstg) 170722812Smckusick { 170822812Smckusick case STGBSS: 170922812Smckusick v->vardesc.varno = ++lastvarno; 171022812Smckusick if (v->vclass != CLVAR) 171122812Smckusick break; 171222812Smckusick nelt = 1; 171322812Smckusick t = v->vdim; 171422812Smckusick if (t) 171522812Smckusick { 171622812Smckusick neltp = t->nelt; 171722812Smckusick if (neltp && ISICON(neltp)) 171822812Smckusick nelt = neltp->constblock.const.ci; 171922812Smckusick else 172022812Smckusick dclerr("improperly dimensioned array", v); 172122812Smckusick } 172222812Smckusick 172322812Smckusick if (v->vtype == TYCHAR) 172422812Smckusick { 172522812Smckusick v->vleng = fixtype(v->vleng); 172622812Smckusick if (v->vleng == NULL) 172722812Smckusick eltsize = typesize[TYCHAR]; 172822812Smckusick else if (ISICON(v->vleng)) 172922812Smckusick eltsize = typesize[TYCHAR] * 173022812Smckusick v->vleng->constblock.const.ci; 173122812Smckusick else if (v->vleng->tag != TERROR) 173222812Smckusick { 173322812Smckusick errstr("nonconstant string length on %s", 173422812Smckusick varstr(VL, v->varname)); 173522812Smckusick eltsize = 0; 173622812Smckusick } 173722812Smckusick } 173822812Smckusick else 173922812Smckusick eltsize = typesize[v->vtype]; 174022812Smckusick 174122812Smckusick v->varsize = nelt * eltsize; 174222812Smckusick break; 174322812Smckusick case STGAUTO: 174422812Smckusick if(v->vclass==CLPROC && v->vprocclass==PTHISPROC) 174522812Smckusick break; 174622812Smckusick nelt = 1; 174722812Smckusick if(t = v->vdim) 174822812Smckusick if( (neltp = t->nelt) && ISCONST(neltp) ) 174922812Smckusick nelt = neltp->constblock.const.ci; 175022812Smckusick else 175122812Smckusick dclerr("adjustable automatic array", v); 175222812Smckusick p = autovar(nelt, v->vtype, v->vleng); 175322812Smckusick v->vardesc.varno = p->memno; 175422812Smckusick v->voffset = p->memoffset->constblock.const.ci; 175522812Smckusick frexpr(p); 175622812Smckusick break; 175722812Smckusick 175822812Smckusick default: 175922812Smckusick break; 176022812Smckusick } 176122812Smckusick v->vdcldone = YES; 176222812Smckusick } 176322812Smckusick 176422812Smckusick 176522812Smckusick 176622812Smckusick 176722812Smckusick impldcl(p) 176822812Smckusick register Namep p; 176922812Smckusick { 177022812Smckusick register int k; 177122812Smckusick int type, leng; 177222812Smckusick 177322812Smckusick if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) ) 177422812Smckusick return; 177522812Smckusick if(p->vtype == TYUNKNOWN) 177622812Smckusick { 177722812Smckusick k = letter(p->varname[0]); 177822812Smckusick type = impltype[ k ]; 177922812Smckusick leng = implleng[ k ]; 178022812Smckusick if(type == TYUNKNOWN) 178122812Smckusick { 178222812Smckusick if(p->vclass == CLPROC) 178323476Smckusick dclerr("attempt to use function of undefined type", p); 178423476Smckusick else 178523476Smckusick dclerr("attempt to use undefined variable", p); 178622812Smckusick type = TYERROR; 178722812Smckusick leng = 1; 178822812Smckusick } 178922812Smckusick settype(p, type, leng); 179022812Smckusick } 179122812Smckusick } 179222812Smckusick 179322812Smckusick 179422812Smckusick 179522812Smckusick 179622812Smckusick LOCAL letter(c) 179722812Smckusick register int c; 179822812Smckusick { 179922812Smckusick if( isupper(c) ) 180022812Smckusick c = tolower(c); 180122812Smckusick return(c - 'a'); 180222812Smckusick } 180322812Smckusick 180422812Smckusick #define ICONEQ(z, c) (ISICON(z) && z->constblock.const.ci==c) 180522812Smckusick #define COMMUTE { e = lp; lp = rp; rp = e; } 180622812Smckusick 180722812Smckusick 180822812Smckusick expptr mkexpr(opcode, lp, rp) 180922812Smckusick int opcode; 181022812Smckusick register expptr lp, rp; 181122812Smckusick { 181222812Smckusick register expptr e, e1; 181322812Smckusick int etype; 181422812Smckusick int ltype, rtype; 181522812Smckusick int ltag, rtag; 181622812Smckusick expptr q, q1; 181722812Smckusick expptr fold(); 181822812Smckusick int k; 181922812Smckusick 182022812Smckusick ltype = lp->headblock.vtype; 182122812Smckusick ltag = lp->tag; 182222812Smckusick if(rp && opcode!=OPCALL && opcode!=OPCCALL) 182322812Smckusick { 182422812Smckusick rtype = rp->headblock.vtype; 182522812Smckusick rtag = rp->tag; 182622812Smckusick } 182722812Smckusick else { 182822812Smckusick rtype = 0; 182922812Smckusick rtag = 0; 183022812Smckusick } 183122812Smckusick 183222812Smckusick /* 183322812Smckusick * Yuck. Why can't we fold constants AFTER 183422812Smckusick * variables are implicitly declared??? 183522812Smckusick */ 183622812Smckusick if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL) 183722812Smckusick { 183822812Smckusick k = letter(lp->primblock.namep->varname[0]); 183922812Smckusick ltype = impltype[ k ]; 184022812Smckusick } 184122812Smckusick if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL) 184222812Smckusick { 184322812Smckusick k = letter(rp->primblock.namep->varname[0]); 184422812Smckusick rtype = impltype[ k ]; 184522812Smckusick } 184622812Smckusick 184722812Smckusick etype = cktype(opcode, ltype, rtype); 184822812Smckusick if(etype == TYERROR) 184922812Smckusick goto error; 185022812Smckusick 185122812Smckusick if(etype != TYUNKNOWN) 185222812Smckusick switch(opcode) 185322812Smckusick { 185422812Smckusick /* check for multiplication by 0 and 1 and addition to 0 */ 185522812Smckusick 185622812Smckusick case OPSTAR: 185722812Smckusick if( ISCONST(lp) ) 185822812Smckusick COMMUTE 185922812Smckusick 186022812Smckusick if( ISICON(rp) ) 186122812Smckusick { 186222812Smckusick if(rp->constblock.const.ci == 0) 186322812Smckusick { 186422812Smckusick if(etype == TYUNKNOWN) 186522812Smckusick break; 186622812Smckusick rp = mkconv(etype, rp); 186722812Smckusick goto retright; 186822812Smckusick } 186922812Smckusick if ((lp->tag == TEXPR) && 187022812Smckusick ((lp->exprblock.opcode == OPPLUS) || 187122812Smckusick (lp->exprblock.opcode == OPMINUS)) && 187222812Smckusick ISCONST(lp->exprblock.rightp) && 187322812Smckusick ISINT(lp->exprblock.rightp->constblock.vtype)) 187422812Smckusick { 187522812Smckusick q1 = mkexpr(OPSTAR, lp->exprblock.rightp, 187622812Smckusick cpexpr(rp)); 187722812Smckusick q = mkexpr(OPSTAR, lp->exprblock.leftp, rp); 187822812Smckusick q = mkexpr(lp->exprblock.opcode, q, q1); 187922812Smckusick free ((char *) lp); 188022812Smckusick return q; 188122812Smckusick } 188222812Smckusick else 188322812Smckusick goto mulop; 188422812Smckusick } 188522812Smckusick break; 188622812Smckusick 188722812Smckusick case OPSLASH: 188822812Smckusick case OPMOD: 188922812Smckusick if( ICONEQ(rp, 0) ) 189022812Smckusick { 189122812Smckusick err("attempted division by zero"); 189222812Smckusick rp = ICON(1); 189322812Smckusick break; 189422812Smckusick } 189522812Smckusick if(opcode == OPMOD) 189622812Smckusick break; 189722812Smckusick 189822812Smckusick 189922812Smckusick mulop: 190022812Smckusick if( ISICON(rp) ) 190122812Smckusick { 190222812Smckusick if(rp->constblock.const.ci == 1) 190322812Smckusick goto retleft; 190422812Smckusick 190522812Smckusick if(rp->constblock.const.ci == -1) 190622812Smckusick { 190722812Smckusick frexpr(rp); 190822812Smckusick return( mkexpr(OPNEG, lp, PNULL) ); 190922812Smckusick } 191022812Smckusick } 191122812Smckusick 191222812Smckusick if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) ) 191322812Smckusick { 191422812Smckusick if(opcode == OPSTAR) 191522812Smckusick e = mkexpr(OPSTAR, lp->exprblock.rightp, rp); 191622812Smckusick else if(ISICON(rp) && 191722812Smckusick (lp->exprblock.rightp->constblock.const.ci % 191822812Smckusick rp->constblock.const.ci) == 0) 191922812Smckusick e = mkexpr(OPSLASH, lp->exprblock.rightp, rp); 192022812Smckusick else break; 192122812Smckusick 192222812Smckusick e1 = lp->exprblock.leftp; 192322812Smckusick free( (charptr) lp ); 192422812Smckusick return( mkexpr(OPSTAR, e1, e) ); 192522812Smckusick } 192622812Smckusick break; 192722812Smckusick 192822812Smckusick 192922812Smckusick case OPPLUS: 193022812Smckusick if( ISCONST(lp) ) 193122812Smckusick COMMUTE 193222812Smckusick goto addop; 193322812Smckusick 193422812Smckusick case OPMINUS: 193522812Smckusick if( ICONEQ(lp, 0) ) 193622812Smckusick { 193722812Smckusick frexpr(lp); 193822812Smckusick return( mkexpr(OPNEG, rp, ENULL) ); 193922812Smckusick } 194022812Smckusick 194122812Smckusick if( ISCONST(rp) ) 194222812Smckusick { 194322812Smckusick opcode = OPPLUS; 194422812Smckusick consnegop(rp); 194522812Smckusick } 194622812Smckusick 194722812Smckusick addop: 194822812Smckusick if( ISICON(rp) ) 194922812Smckusick { 195022812Smckusick if(rp->constblock.const.ci == 0) 195122812Smckusick goto retleft; 195222812Smckusick if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) ) 195322812Smckusick { 195422812Smckusick e = mkexpr(OPPLUS, lp->exprblock.rightp, rp); 195522812Smckusick e1 = lp->exprblock.leftp; 195622812Smckusick free( (charptr) lp ); 195722812Smckusick return( mkexpr(OPPLUS, e1, e) ); 195822812Smckusick } 195922812Smckusick } 196022812Smckusick break; 196122812Smckusick 196222812Smckusick 196322812Smckusick case OPPOWER: 196422812Smckusick break; 196522812Smckusick 196622812Smckusick case OPNEG: 196722812Smckusick if(ltag==TEXPR && lp->exprblock.opcode==OPNEG) 196822812Smckusick { 196922812Smckusick e = lp->exprblock.leftp; 197022812Smckusick free( (charptr) lp ); 197122812Smckusick return(e); 197222812Smckusick } 197322812Smckusick break; 197422812Smckusick 197522812Smckusick case OPNOT: 197622812Smckusick if(ltag==TEXPR && lp->exprblock.opcode==OPNOT) 197722812Smckusick { 197822812Smckusick e = lp->exprblock.leftp; 197922812Smckusick free( (charptr) lp ); 198022812Smckusick return(e); 198122812Smckusick } 198222812Smckusick break; 198322812Smckusick 198422812Smckusick case OPCALL: 198522812Smckusick case OPCCALL: 198622812Smckusick etype = ltype; 198722812Smckusick if(rp!=NULL && rp->listblock.listp==NULL) 198822812Smckusick { 198922812Smckusick free( (charptr) rp ); 199022812Smckusick rp = NULL; 199122812Smckusick } 199222812Smckusick break; 199322812Smckusick 199422812Smckusick case OPAND: 199522812Smckusick case OPOR: 199622812Smckusick if( ISCONST(lp) ) 199722812Smckusick COMMUTE 199822812Smckusick 199922812Smckusick if( ISCONST(rp) ) 200022812Smckusick { 200122812Smckusick if(rp->constblock.const.ci == 0) 200222812Smckusick if(opcode == OPOR) 200322812Smckusick goto retleft; 200422812Smckusick else 200522812Smckusick goto retright; 200622812Smckusick else if(opcode == OPOR) 200722812Smckusick goto retright; 200822812Smckusick else 200922812Smckusick goto retleft; 201022812Smckusick } 201122812Smckusick case OPLSHIFT: 201222812Smckusick if (ISICON(rp)) 201322812Smckusick { 201422812Smckusick if (rp->constblock.const.ci == 0) 201522812Smckusick goto retleft; 201622812Smckusick if ((lp->tag == TEXPR) && 201722812Smckusick ((lp->exprblock.opcode == OPPLUS) || 201822812Smckusick (lp->exprblock.opcode == OPMINUS)) && 201922812Smckusick ISICON(lp->exprblock.rightp)) 202022812Smckusick { 202122812Smckusick q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp, 202222812Smckusick cpexpr(rp)); 202322812Smckusick q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp); 202422812Smckusick q = mkexpr(lp->exprblock.opcode, q, q1); 202522812Smckusick free((char *) lp); 202622812Smckusick return q; 202722812Smckusick } 202822812Smckusick } 202922812Smckusick 203022812Smckusick case OPEQV: 203122812Smckusick case OPNEQV: 203222812Smckusick 203322812Smckusick case OPBITAND: 203422812Smckusick case OPBITOR: 203522812Smckusick case OPBITXOR: 203622812Smckusick case OPBITNOT: 203722812Smckusick case OPRSHIFT: 203822812Smckusick 203922812Smckusick case OPLT: 204022812Smckusick case OPGT: 204122812Smckusick case OPLE: 204222812Smckusick case OPGE: 204322812Smckusick case OPEQ: 204422812Smckusick case OPNE: 204522812Smckusick 204622812Smckusick case OPCONCAT: 204722812Smckusick break; 204822812Smckusick case OPMIN: 204922812Smckusick case OPMAX: 205022812Smckusick 205122812Smckusick case OPASSIGN: 205222812Smckusick case OPPLUSEQ: 205322812Smckusick case OPSTAREQ: 205422812Smckusick 205522812Smckusick case OPCONV: 205622812Smckusick case OPADDR: 205722812Smckusick 205822812Smckusick case OPCOMMA: 205922812Smckusick case OPQUEST: 206022812Smckusick case OPCOLON: 206122812Smckusick 206222812Smckusick case OPPAREN: 206322812Smckusick break; 206422812Smckusick 206522812Smckusick default: 206622812Smckusick badop("mkexpr", opcode); 206722812Smckusick } 206822812Smckusick 206922812Smckusick e = (expptr) ALLOC(Exprblock); 207022812Smckusick e->exprblock.tag = TEXPR; 207122812Smckusick e->exprblock.opcode = opcode; 207222812Smckusick e->exprblock.vtype = etype; 207322812Smckusick e->exprblock.leftp = lp; 207422812Smckusick e->exprblock.rightp = rp; 207522812Smckusick if(ltag==TCONST && (rp==0 || rtag==TCONST) ) 207622812Smckusick e = fold(e); 207722812Smckusick return(e); 207822812Smckusick 207922812Smckusick retleft: 208022812Smckusick frexpr(rp); 208122812Smckusick return(lp); 208222812Smckusick 208322812Smckusick retright: 208422812Smckusick frexpr(lp); 208522812Smckusick return(rp); 208622812Smckusick 208722812Smckusick error: 208822812Smckusick frexpr(lp); 208922812Smckusick if(rp && opcode!=OPCALL && opcode!=OPCCALL) 209022812Smckusick frexpr(rp); 209122812Smckusick return( errnode() ); 209222812Smckusick } 209322812Smckusick 209422812Smckusick #define ERR(s) { errs = s; goto error; } 209522812Smckusick 209622812Smckusick cktype(op, lt, rt) 209722812Smckusick register int op, lt, rt; 209822812Smckusick { 209922812Smckusick char *errs; 210022812Smckusick 210122812Smckusick if(lt==TYERROR || rt==TYERROR) 210222812Smckusick goto error1; 210322812Smckusick 210422812Smckusick if(lt==TYUNKNOWN) 210522812Smckusick return(TYUNKNOWN); 210622812Smckusick if(rt==TYUNKNOWN) 210722812Smckusick if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL && 210822812Smckusick op!=OPCCALL && op!=OPADDR && op!=OPPAREN) 210922812Smckusick return(TYUNKNOWN); 211022812Smckusick 211122812Smckusick switch(op) 211222812Smckusick { 211322812Smckusick case OPPLUS: 211422812Smckusick case OPMINUS: 211522812Smckusick case OPSTAR: 211622812Smckusick case OPSLASH: 211722812Smckusick case OPPOWER: 211822812Smckusick case OPMOD: 211922812Smckusick if( ISNUMERIC(lt) && ISNUMERIC(rt) ) 212022812Smckusick return( maxtype(lt, rt) ); 212122812Smckusick ERR("nonarithmetic operand of arithmetic operator") 212222812Smckusick 212322812Smckusick case OPNEG: 212422812Smckusick if( ISNUMERIC(lt) ) 212522812Smckusick return(lt); 212622812Smckusick ERR("nonarithmetic operand of negation") 212722812Smckusick 212822812Smckusick case OPNOT: 212922812Smckusick if(lt == TYLOGICAL) 213022812Smckusick return(TYLOGICAL); 213122812Smckusick ERR("NOT of nonlogical") 213222812Smckusick 213322812Smckusick case OPAND: 213422812Smckusick case OPOR: 213522812Smckusick case OPEQV: 213622812Smckusick case OPNEQV: 213722812Smckusick if(lt==TYLOGICAL && rt==TYLOGICAL) 213822812Smckusick return(TYLOGICAL); 213922812Smckusick ERR("nonlogical operand of logical operator") 214022812Smckusick 214122812Smckusick case OPLT: 214222812Smckusick case OPGT: 214322812Smckusick case OPLE: 214422812Smckusick case OPGE: 214522812Smckusick case OPEQ: 214622812Smckusick case OPNE: 214722812Smckusick if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) 214822812Smckusick { 214922812Smckusick if(lt != rt) 215022812Smckusick ERR("illegal comparison") 215122812Smckusick } 215222812Smckusick 215322812Smckusick else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) ) 215422812Smckusick { 215522812Smckusick if(op!=OPEQ && op!=OPNE) 215622812Smckusick ERR("order comparison of complex data") 215722812Smckusick } 215822812Smckusick 215922812Smckusick else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) ) 216022812Smckusick ERR("comparison of nonarithmetic data") 216122812Smckusick return(TYLOGICAL); 216222812Smckusick 216322812Smckusick case OPCONCAT: 216422812Smckusick if(lt==TYCHAR && rt==TYCHAR) 216522812Smckusick return(TYCHAR); 216622812Smckusick ERR("concatenation of nonchar data") 216722812Smckusick 216822812Smckusick case OPCALL: 216922812Smckusick case OPCCALL: 217022812Smckusick return(lt); 217122812Smckusick 217222812Smckusick case OPADDR: 217322812Smckusick return(TYADDR); 217422812Smckusick 217522812Smckusick case OPCONV: 217622812Smckusick if(ISCOMPLEX(lt)) 217722812Smckusick { 217822812Smckusick if(ISNUMERIC(rt)) 217922812Smckusick return(lt); 218022812Smckusick ERR("impossible conversion") 218122812Smckusick } 218222812Smckusick if(rt == 0) 218322812Smckusick return(0); 218422812Smckusick if(lt==TYCHAR && ISINT(rt) ) 218522812Smckusick return(TYCHAR); 218622812Smckusick case OPASSIGN: 218722812Smckusick case OPPLUSEQ: 218822812Smckusick case OPSTAREQ: 218922812Smckusick if( ISINT(lt) && rt==TYCHAR) 219022812Smckusick return(lt); 219122812Smckusick if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL) 219222812Smckusick if(op!=OPASSIGN || lt!=rt) 219322812Smckusick { 219422812Smckusick /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */ 219522812Smckusick /* debug fatal("impossible conversion. possible compiler bug"); */ 219622812Smckusick ERR("impossible conversion") 219722812Smckusick } 219822812Smckusick return(lt); 219922812Smckusick 220022812Smckusick case OPMIN: 220122812Smckusick case OPMAX: 220222812Smckusick case OPBITOR: 220322812Smckusick case OPBITAND: 220422812Smckusick case OPBITXOR: 220522812Smckusick case OPBITNOT: 220622812Smckusick case OPLSHIFT: 220722812Smckusick case OPRSHIFT: 220822812Smckusick case OPPAREN: 220922812Smckusick return(lt); 221022812Smckusick 221122812Smckusick case OPCOMMA: 221222812Smckusick case OPQUEST: 221322812Smckusick case OPCOLON: 221422812Smckusick return(rt); 221522812Smckusick 221622812Smckusick default: 221722812Smckusick badop("cktype", op); 221822812Smckusick } 221922812Smckusick error: err(errs); 222022812Smckusick error1: return(TYERROR); 222122812Smckusick } 222222812Smckusick 222322812Smckusick LOCAL expptr fold(e) 222422812Smckusick register expptr e; 222522812Smckusick { 222622812Smckusick Constp p; 222722812Smckusick register expptr lp, rp; 222822812Smckusick int etype, mtype, ltype, rtype, opcode; 222922812Smckusick int i, ll, lr; 223022812Smckusick char *q, *s; 223122812Smckusick union Constant lcon, rcon; 223222812Smckusick 223322812Smckusick opcode = e->exprblock.opcode; 223422812Smckusick etype = e->exprblock.vtype; 223522812Smckusick 223622812Smckusick lp = e->exprblock.leftp; 223722812Smckusick ltype = lp->headblock.vtype; 223822812Smckusick rp = e->exprblock.rightp; 223922812Smckusick 224022812Smckusick if(rp == 0) 224122812Smckusick switch(opcode) 224222812Smckusick { 224322812Smckusick case OPNOT: 224422812Smckusick lp->constblock.const.ci = ! lp->constblock.const.ci; 224522812Smckusick return(lp); 224622812Smckusick 224722812Smckusick case OPBITNOT: 224822812Smckusick lp->constblock.const.ci = ~ lp->constblock.const.ci; 224922812Smckusick return(lp); 225022812Smckusick 225122812Smckusick case OPNEG: 225222812Smckusick consnegop(lp); 225322812Smckusick return(lp); 225422812Smckusick 225522812Smckusick case OPCONV: 225622812Smckusick case OPADDR: 225722812Smckusick case OPPAREN: 225822812Smckusick return(e); 225922812Smckusick 226022812Smckusick default: 226122812Smckusick badop("fold", opcode); 226222812Smckusick } 226322812Smckusick 226422812Smckusick rtype = rp->headblock.vtype; 226522812Smckusick 226622812Smckusick p = ALLOC(Constblock); 226722812Smckusick p->tag = TCONST; 226822812Smckusick p->vtype = etype; 226922812Smckusick p->vleng = e->exprblock.vleng; 227022812Smckusick 227122812Smckusick switch(opcode) 227222812Smckusick { 227322812Smckusick case OPCOMMA: 227422812Smckusick case OPQUEST: 227522812Smckusick case OPCOLON: 227622812Smckusick return(e); 227722812Smckusick 227822812Smckusick case OPAND: 227922812Smckusick p->const.ci = lp->constblock.const.ci && 228022812Smckusick rp->constblock.const.ci; 228122812Smckusick break; 228222812Smckusick 228322812Smckusick case OPOR: 228422812Smckusick p->const.ci = lp->constblock.const.ci || 228522812Smckusick rp->constblock.const.ci; 228622812Smckusick break; 228722812Smckusick 228822812Smckusick case OPEQV: 228922812Smckusick p->const.ci = lp->constblock.const.ci == 229022812Smckusick rp->constblock.const.ci; 229122812Smckusick break; 229222812Smckusick 229322812Smckusick case OPNEQV: 229422812Smckusick p->const.ci = lp->constblock.const.ci != 229522812Smckusick rp->constblock.const.ci; 229622812Smckusick break; 229722812Smckusick 229822812Smckusick case OPBITAND: 229922812Smckusick p->const.ci = lp->constblock.const.ci & 230022812Smckusick rp->constblock.const.ci; 230122812Smckusick break; 230222812Smckusick 230322812Smckusick case OPBITOR: 230422812Smckusick p->const.ci = lp->constblock.const.ci | 230522812Smckusick rp->constblock.const.ci; 230622812Smckusick break; 230722812Smckusick 230822812Smckusick case OPBITXOR: 230922812Smckusick p->const.ci = lp->constblock.const.ci ^ 231022812Smckusick rp->constblock.const.ci; 231122812Smckusick break; 231222812Smckusick 231322812Smckusick case OPLSHIFT: 231422812Smckusick p->const.ci = lp->constblock.const.ci << 231522812Smckusick rp->constblock.const.ci; 231622812Smckusick break; 231722812Smckusick 231822812Smckusick case OPRSHIFT: 231922812Smckusick p->const.ci = lp->constblock.const.ci >> 232022812Smckusick rp->constblock.const.ci; 232122812Smckusick break; 232222812Smckusick 232322812Smckusick case OPCONCAT: 232422812Smckusick ll = lp->constblock.vleng->constblock.const.ci; 232522812Smckusick lr = rp->constblock.vleng->constblock.const.ci; 232622812Smckusick p->const.ccp = q = (char *) ckalloc(ll+lr); 232722812Smckusick p->vleng = ICON(ll+lr); 232822812Smckusick s = lp->constblock.const.ccp; 232922812Smckusick for(i = 0 ; i < ll ; ++i) 233022812Smckusick *q++ = *s++; 233122812Smckusick s = rp->constblock.const.ccp; 233222812Smckusick for(i = 0; i < lr; ++i) 233322812Smckusick *q++ = *s++; 233422812Smckusick break; 233522812Smckusick 233622812Smckusick 233722812Smckusick case OPPOWER: 233822812Smckusick if( ! ISINT(rtype) ) 233922812Smckusick return(e); 234022812Smckusick conspower(&(p->const), lp, rp->constblock.const.ci); 234122812Smckusick break; 234222812Smckusick 234322812Smckusick 234422812Smckusick default: 234522812Smckusick if(ltype == TYCHAR) 234622812Smckusick { 234722812Smckusick lcon.ci = cmpstr(lp->constblock.const.ccp, 234822812Smckusick rp->constblock.const.ccp, 234922812Smckusick lp->constblock.vleng->constblock.const.ci, 235022812Smckusick rp->constblock.vleng->constblock.const.ci); 235122812Smckusick rcon.ci = 0; 235222812Smckusick mtype = tyint; 235322812Smckusick } 235422812Smckusick else { 235522812Smckusick mtype = maxtype(ltype, rtype); 235622812Smckusick consconv(mtype, &lcon, ltype, &(lp->constblock.const) ); 235722812Smckusick consconv(mtype, &rcon, rtype, &(rp->constblock.const) ); 235822812Smckusick } 235922812Smckusick consbinop(opcode, mtype, &(p->const), &lcon, &rcon); 236022812Smckusick break; 236122812Smckusick } 236222812Smckusick 236322812Smckusick frexpr(e); 236422812Smckusick return( (expptr) p ); 236522812Smckusick } 236622812Smckusick 236722812Smckusick 236822812Smckusick 236922812Smckusick /* assign constant l = r , doing coercion */ 237022812Smckusick 237122812Smckusick consconv(lt, lv, rt, rv) 237222812Smckusick int lt, rt; 237322812Smckusick register union Constant *lv, *rv; 237422812Smckusick { 237522812Smckusick switch(lt) 237622812Smckusick { 237722812Smckusick case TYCHAR: 237822812Smckusick *(lv->ccp = (char *) ckalloc(1)) = rv->ci; 237922812Smckusick break; 238022812Smckusick 238122812Smckusick case TYSHORT: 238222812Smckusick case TYLONG: 238322812Smckusick if(rt == TYCHAR) 238422812Smckusick lv->ci = rv->ccp[0]; 238522812Smckusick else if( ISINT(rt) ) 238622812Smckusick lv->ci = rv->ci; 238722812Smckusick else lv->ci = rv->cd[0]; 238822812Smckusick break; 238922812Smckusick 239022812Smckusick case TYCOMPLEX: 239122812Smckusick case TYDCOMPLEX: 239222812Smckusick switch(rt) 239322812Smckusick { 239422812Smckusick case TYSHORT: 239522812Smckusick case TYLONG: 239622812Smckusick /* fall through and do real assignment of 239722812Smckusick first element 239822812Smckusick */ 239922812Smckusick case TYREAL: 240022812Smckusick case TYDREAL: 240122812Smckusick lv->cd[1] = 0; break; 240222812Smckusick case TYCOMPLEX: 240322812Smckusick case TYDCOMPLEX: 240422812Smckusick lv->cd[1] = rv->cd[1]; break; 240522812Smckusick } 240622812Smckusick 240722812Smckusick case TYREAL: 240822812Smckusick case TYDREAL: 240922812Smckusick if( ISINT(rt) ) 241022812Smckusick lv->cd[0] = rv->ci; 241122812Smckusick else lv->cd[0] = rv->cd[0]; 241222812Smckusick if( lt == TYREAL) 241322812Smckusick { 241422812Smckusick float f = lv->cd[0]; 241522812Smckusick lv->cd[0] = f; 241622812Smckusick } 241722812Smckusick break; 241822812Smckusick 241922812Smckusick case TYLOGICAL: 242022812Smckusick lv->ci = rv->ci; 242122812Smckusick break; 242222812Smckusick } 242322812Smckusick } 242422812Smckusick 242522812Smckusick 242622812Smckusick 242722812Smckusick consnegop(p) 242822812Smckusick register Constp p; 242922812Smckusick { 243022812Smckusick switch(p->vtype) 243122812Smckusick { 243222812Smckusick case TYSHORT: 243322812Smckusick case TYLONG: 243422812Smckusick p->const.ci = - p->const.ci; 243522812Smckusick break; 243622812Smckusick 243722812Smckusick case TYCOMPLEX: 243822812Smckusick case TYDCOMPLEX: 243922812Smckusick p->const.cd[1] = - p->const.cd[1]; 244022812Smckusick /* fall through and do the real parts */ 244122812Smckusick case TYREAL: 244222812Smckusick case TYDREAL: 244322812Smckusick p->const.cd[0] = - p->const.cd[0]; 244422812Smckusick break; 244522812Smckusick default: 244622812Smckusick badtype("consnegop", p->vtype); 244722812Smckusick } 244822812Smckusick } 244922812Smckusick 245022812Smckusick 245122812Smckusick 245222812Smckusick LOCAL conspower(powp, ap, n) 245322812Smckusick register union Constant *powp; 245422812Smckusick Constp ap; 245522812Smckusick ftnint n; 245622812Smckusick { 245722812Smckusick register int type; 245822812Smckusick union Constant x; 245922812Smckusick 246022812Smckusick switch(type = ap->vtype) /* pow = 1 */ 246122812Smckusick { 246222812Smckusick case TYSHORT: 246322812Smckusick case TYLONG: 246422812Smckusick powp->ci = 1; 246522812Smckusick break; 246622812Smckusick case TYCOMPLEX: 246722812Smckusick case TYDCOMPLEX: 246822812Smckusick powp->cd[1] = 0; 246922812Smckusick case TYREAL: 247022812Smckusick case TYDREAL: 247122812Smckusick powp->cd[0] = 1; 247222812Smckusick break; 247322812Smckusick default: 247422812Smckusick badtype("conspower", type); 247522812Smckusick } 247622812Smckusick 247722812Smckusick if(n == 0) 247822812Smckusick return; 247922812Smckusick if(n < 0) 248022812Smckusick { 248122812Smckusick if( ISINT(type) ) 248222812Smckusick { 248322812Smckusick if (ap->const.ci == 0) 248422812Smckusick err("zero raised to a negative power"); 248522812Smckusick else if (ap->const.ci == 1) 248622812Smckusick return; 248722812Smckusick else if (ap->const.ci == -1) 248822812Smckusick { 248922812Smckusick if (n < -2) 249022812Smckusick n = n + 2; 249122812Smckusick n = -n; 249222812Smckusick if (n % 2 == 1) 249322812Smckusick powp->ci = -1; 249422812Smckusick } 249522812Smckusick else 249622812Smckusick powp->ci = 0; 249722812Smckusick return; 249822812Smckusick } 249922812Smckusick n = - n; 250022812Smckusick consbinop(OPSLASH, type, &x, powp, &(ap->const)); 250122812Smckusick } 250222812Smckusick else 250322812Smckusick consbinop(OPSTAR, type, &x, powp, &(ap->const)); 250422812Smckusick 250522812Smckusick for( ; ; ) 250622812Smckusick { 250722812Smckusick if(n & 01) 250822812Smckusick consbinop(OPSTAR, type, powp, powp, &x); 250922812Smckusick if(n >>= 1) 251022812Smckusick consbinop(OPSTAR, type, &x, &x, &x); 251122812Smckusick else 251222812Smckusick break; 251322812Smckusick } 251422812Smckusick } 251522812Smckusick 251622812Smckusick 251722812Smckusick 251822812Smckusick /* do constant operation cp = a op b */ 251922812Smckusick 252022812Smckusick 252122812Smckusick LOCAL consbinop(opcode, type, cp, ap, bp) 252222812Smckusick int opcode, type; 252322812Smckusick register union Constant *ap, *bp, *cp; 252422812Smckusick { 252522812Smckusick int k; 252622812Smckusick double temp; 252722812Smckusick 252822812Smckusick switch(opcode) 252922812Smckusick { 253022812Smckusick case OPPLUS: 253122812Smckusick switch(type) 253222812Smckusick { 253322812Smckusick case TYSHORT: 253422812Smckusick case TYLONG: 253522812Smckusick cp->ci = ap->ci + bp->ci; 253622812Smckusick break; 253722812Smckusick case TYCOMPLEX: 253822812Smckusick case TYDCOMPLEX: 253922812Smckusick cp->cd[1] = ap->cd[1] + bp->cd[1]; 254022812Smckusick case TYREAL: 254122812Smckusick case TYDREAL: 254222812Smckusick cp->cd[0] = ap->cd[0] + bp->cd[0]; 254322812Smckusick break; 254422812Smckusick } 254522812Smckusick break; 254622812Smckusick 254722812Smckusick case OPMINUS: 254822812Smckusick switch(type) 254922812Smckusick { 255022812Smckusick case TYSHORT: 255122812Smckusick case TYLONG: 255222812Smckusick cp->ci = ap->ci - bp->ci; 255322812Smckusick break; 255422812Smckusick case TYCOMPLEX: 255522812Smckusick case TYDCOMPLEX: 255622812Smckusick cp->cd[1] = ap->cd[1] - bp->cd[1]; 255722812Smckusick case TYREAL: 255822812Smckusick case TYDREAL: 255922812Smckusick cp->cd[0] = ap->cd[0] - bp->cd[0]; 256022812Smckusick break; 256122812Smckusick } 256222812Smckusick break; 256322812Smckusick 256422812Smckusick case OPSTAR: 256522812Smckusick switch(type) 256622812Smckusick { 256722812Smckusick case TYSHORT: 256822812Smckusick case TYLONG: 256922812Smckusick cp->ci = ap->ci * bp->ci; 257022812Smckusick break; 257122812Smckusick case TYREAL: 257222812Smckusick case TYDREAL: 257322812Smckusick cp->cd[0] = ap->cd[0] * bp->cd[0]; 257422812Smckusick break; 257522812Smckusick case TYCOMPLEX: 257622812Smckusick case TYDCOMPLEX: 257722812Smckusick temp = ap->cd[0] * bp->cd[0] - 257822812Smckusick ap->cd[1] * bp->cd[1] ; 257922812Smckusick cp->cd[1] = ap->cd[0] * bp->cd[1] + 258022812Smckusick ap->cd[1] * bp->cd[0] ; 258122812Smckusick cp->cd[0] = temp; 258222812Smckusick break; 258322812Smckusick } 258422812Smckusick break; 258522812Smckusick case OPSLASH: 258622812Smckusick switch(type) 258722812Smckusick { 258822812Smckusick case TYSHORT: 258922812Smckusick case TYLONG: 259022812Smckusick cp->ci = ap->ci / bp->ci; 259122812Smckusick break; 259222812Smckusick case TYREAL: 259322812Smckusick case TYDREAL: 259422812Smckusick cp->cd[0] = ap->cd[0] / bp->cd[0]; 259522812Smckusick break; 259622812Smckusick case TYCOMPLEX: 259722812Smckusick case TYDCOMPLEX: 259822812Smckusick zdiv(cp,ap,bp); 259922812Smckusick break; 260022812Smckusick } 260122812Smckusick break; 260222812Smckusick 260322812Smckusick case OPMOD: 260422812Smckusick if( ISINT(type) ) 260522812Smckusick { 260622812Smckusick cp->ci = ap->ci % bp->ci; 260722812Smckusick break; 260822812Smckusick } 260922812Smckusick else 261022812Smckusick fatal("inline mod of noninteger"); 261122812Smckusick 261222812Smckusick default: /* relational ops */ 261322812Smckusick switch(type) 261422812Smckusick { 261522812Smckusick case TYSHORT: 261622812Smckusick case TYLONG: 261722812Smckusick if(ap->ci < bp->ci) 261822812Smckusick k = -1; 261922812Smckusick else if(ap->ci == bp->ci) 262022812Smckusick k = 0; 262122812Smckusick else k = 1; 262222812Smckusick break; 262322812Smckusick case TYREAL: 262422812Smckusick case TYDREAL: 262522812Smckusick if(ap->cd[0] < bp->cd[0]) 262622812Smckusick k = -1; 262722812Smckusick else if(ap->cd[0] == bp->cd[0]) 262822812Smckusick k = 0; 262922812Smckusick else k = 1; 263022812Smckusick break; 263122812Smckusick case TYCOMPLEX: 263222812Smckusick case TYDCOMPLEX: 263322812Smckusick if(ap->cd[0] == bp->cd[0] && 263422812Smckusick ap->cd[1] == bp->cd[1] ) 263522812Smckusick k = 0; 263622812Smckusick else k = 1; 263722812Smckusick break; 263822812Smckusick } 263922812Smckusick 264022812Smckusick switch(opcode) 264122812Smckusick { 264222812Smckusick case OPEQ: 264322812Smckusick cp->ci = (k == 0); 264422812Smckusick break; 264522812Smckusick case OPNE: 264622812Smckusick cp->ci = (k != 0); 264722812Smckusick break; 264822812Smckusick case OPGT: 264922812Smckusick cp->ci = (k == 1); 265022812Smckusick break; 265122812Smckusick case OPLT: 265222812Smckusick cp->ci = (k == -1); 265322812Smckusick break; 265422812Smckusick case OPGE: 265522812Smckusick cp->ci = (k >= 0); 265622812Smckusick break; 265722812Smckusick case OPLE: 265822812Smckusick cp->ci = (k <= 0); 265922812Smckusick break; 266022812Smckusick default: 266122812Smckusick badop ("consbinop", opcode); 266222812Smckusick } 266322812Smckusick break; 266422812Smckusick } 266522812Smckusick } 266622812Smckusick 266722812Smckusick 266822812Smckusick 266922812Smckusick 267022812Smckusick conssgn(p) 267122812Smckusick register expptr p; 267222812Smckusick { 267322812Smckusick if( ! ISCONST(p) ) 267422812Smckusick fatal( "sgn(nonconstant)" ); 267522812Smckusick 267622812Smckusick switch(p->headblock.vtype) 267722812Smckusick { 267822812Smckusick case TYSHORT: 267922812Smckusick case TYLONG: 268022812Smckusick if(p->constblock.const.ci > 0) return(1); 268122812Smckusick if(p->constblock.const.ci < 0) return(-1); 268222812Smckusick return(0); 268322812Smckusick 268422812Smckusick case TYREAL: 268522812Smckusick case TYDREAL: 268622812Smckusick if(p->constblock.const.cd[0] > 0) return(1); 268722812Smckusick if(p->constblock.const.cd[0] < 0) return(-1); 268822812Smckusick return(0); 268922812Smckusick 269022812Smckusick case TYCOMPLEX: 269122812Smckusick case TYDCOMPLEX: 269222812Smckusick return(p->constblock.const.cd[0]!=0 || p->constblock.const.cd[1]!=0); 269322812Smckusick 269422812Smckusick default: 269522812Smckusick badtype( "conssgn", p->constblock.vtype); 269622812Smckusick } 269722812Smckusick /* NOTREACHED */ 269822812Smckusick } 269922812Smckusick 270022812Smckusick char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" }; 270122812Smckusick 270222812Smckusick 270322812Smckusick LOCAL expptr mkpower(p) 270422812Smckusick register expptr p; 270522812Smckusick { 270622812Smckusick register expptr q, lp, rp; 270722812Smckusick int ltype, rtype, mtype; 2708*24477Sdonn struct Listblock *args, *mklist(); 2709*24477Sdonn Addrp ap; 271022812Smckusick 271122812Smckusick lp = p->exprblock.leftp; 271222812Smckusick rp = p->exprblock.rightp; 271322812Smckusick ltype = lp->headblock.vtype; 271422812Smckusick rtype = rp->headblock.vtype; 271522812Smckusick 271622812Smckusick if(ISICON(rp)) 271722812Smckusick { 271822812Smckusick if(rp->constblock.const.ci == 0) 271922812Smckusick { 272022812Smckusick frexpr(p); 272122812Smckusick if( ISINT(ltype) ) 272222812Smckusick return( ICON(1) ); 272322812Smckusick else 272422812Smckusick { 272522812Smckusick expptr pp; 272622812Smckusick pp = mkconv(ltype, ICON(1)); 272722812Smckusick return( pp ); 272822812Smckusick } 272922812Smckusick } 273022812Smckusick if(rp->constblock.const.ci < 0) 273122812Smckusick { 273222812Smckusick if( ISINT(ltype) ) 273322812Smckusick { 273422812Smckusick frexpr(p); 273522812Smckusick err("integer**negative"); 273622812Smckusick return( errnode() ); 273722812Smckusick } 273822812Smckusick rp->constblock.const.ci = - rp->constblock.const.ci; 273922812Smckusick p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp)); 274022812Smckusick } 274122812Smckusick if(rp->constblock.const.ci == 1) 274222812Smckusick { 274322812Smckusick frexpr(rp); 274422812Smckusick free( (charptr) p ); 274522812Smckusick return(lp); 274622812Smckusick } 274722812Smckusick 274822812Smckusick if( ONEOF(ltype, MSKINT|MSKREAL) ) 274922812Smckusick { 275022812Smckusick p->exprblock.vtype = ltype; 275122812Smckusick return(p); 275222812Smckusick } 275322812Smckusick } 275422812Smckusick if( ISINT(rtype) ) 275522812Smckusick { 275622812Smckusick if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) ) 275722812Smckusick q = call2(TYSHORT, "pow_hh", lp, rp); 275822812Smckusick else { 275922812Smckusick if(ltype == TYSHORT) 276022812Smckusick { 276122812Smckusick ltype = TYLONG; 276222812Smckusick lp = mkconv(TYLONG,lp); 276322812Smckusick } 276422812Smckusick q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp)); 276522812Smckusick } 276622812Smckusick } 276722812Smckusick else if( ISREAL( (mtype = maxtype(ltype,rtype)) )) 2768*24477Sdonn { 2769*24477Sdonn args = mklist( mkchain( mkconv(TYDREAL,lp), mkchain( mkconv(TYDREAL,rp), CHNULL ) ) ); 2770*24477Sdonn fixargs(YES, args ); 2771*24477Sdonn ap = builtin( TYDREAL, "pow" ); 2772*24477Sdonn ap->vstg = STGINTR; 2773*24477Sdonn q = fixexpr( mkexpr(OPCCALL, ap, args )); 2774*24477Sdonn q->exprblock.vtype = mtype; 2775*24477Sdonn } 277622812Smckusick else { 277722812Smckusick q = call2(TYDCOMPLEX, "pow_zz", 277822812Smckusick mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp)); 277922812Smckusick if(mtype == TYCOMPLEX) 278022812Smckusick q = mkconv(TYCOMPLEX, q); 278122812Smckusick } 278222812Smckusick free( (charptr) p ); 278322812Smckusick return(q); 278422812Smckusick } 278522812Smckusick 278622812Smckusick 278722812Smckusick 278822812Smckusick /* Complex Division. Same code as in Runtime Library 278922812Smckusick */ 279022812Smckusick 279122812Smckusick struct dcomplex { double dreal, dimag; }; 279222812Smckusick 279322812Smckusick 279422812Smckusick LOCAL zdiv(c, a, b) 279522812Smckusick register struct dcomplex *a, *b, *c; 279622812Smckusick { 279722812Smckusick double ratio, den; 279822812Smckusick double abr, abi; 279922812Smckusick 280022812Smckusick if( (abr = b->dreal) < 0.) 280122812Smckusick abr = - abr; 280222812Smckusick if( (abi = b->dimag) < 0.) 280322812Smckusick abi = - abi; 280422812Smckusick if( abr <= abi ) 280522812Smckusick { 280622812Smckusick if(abi == 0) 280722812Smckusick fatal("complex division by zero"); 280822812Smckusick ratio = b->dreal / b->dimag ; 280922812Smckusick den = b->dimag * (1 + ratio*ratio); 281022812Smckusick c->dreal = (a->dreal*ratio + a->dimag) / den; 281122812Smckusick c->dimag = (a->dimag*ratio - a->dreal) / den; 281222812Smckusick } 281322812Smckusick 281422812Smckusick else 281522812Smckusick { 281622812Smckusick ratio = b->dimag / b->dreal ; 281722812Smckusick den = b->dreal * (1 + ratio*ratio); 281822812Smckusick c->dreal = (a->dreal + a->dimag*ratio) / den; 281922812Smckusick c->dimag = (a->dimag - a->dreal*ratio) / den; 282022812Smckusick } 282122812Smckusick 282222812Smckusick } 282322812Smckusick 282422812Smckusick expptr oftwo(e) 282522812Smckusick expptr e; 282622812Smckusick { 282722812Smckusick int val,res; 282822812Smckusick 282922812Smckusick if (! ISCONST (e)) 283022812Smckusick return (0); 283122812Smckusick 283222812Smckusick val = e->constblock.const.ci; 283322812Smckusick switch (val) 283422812Smckusick { 283522812Smckusick case 2: res = 1; break; 283622812Smckusick case 4: res = 2; break; 283722812Smckusick case 8: res = 3; break; 283822812Smckusick case 16: res = 4; break; 283922812Smckusick case 32: res = 5; break; 284022812Smckusick case 64: res = 6; break; 284122812Smckusick case 128: res = 7; break; 284222812Smckusick case 256: res = 8; break; 284322812Smckusick default: return (0); 284422812Smckusick } 284522812Smckusick return (ICON (res)); 284622812Smckusick } 2847