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