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