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