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