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