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