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