1*47951Sbostic /*-
2*47951Sbostic * Copyright (c) 1980 The Regents of the University of California.
3*47951Sbostic * All rights reserved.
4*47951Sbostic *
5*47951Sbostic * %sccs.include.proprietary.c%
640230Sdonn */
740230Sdonn
840230Sdonn #ifndef lint
9*47951Sbostic static char sccsid[] = "@(#)expr.c 1.4 (Berkeley) 04/12/91";
10*47951Sbostic #endif /* not lint */
1140230Sdonn
1240230Sdonn /*
1340230Sdonn * expr.c
1440230Sdonn *
1540230Sdonn * Routines for handling expressions, f77 compiler pass 1.
1640230Sdonn *
1740230Sdonn * University of Utah CS Dept modification history:
1840230Sdonn *
1940230Sdonn * $Log: expr.c,v $
2040230Sdonn * Revision 1.3 86/02/26 17:13:37 rcs
2140230Sdonn * Correct COFR 411.
2240230Sdonn * P. Wong
2340230Sdonn *
2440230Sdonn * Revision 3.16 85/06/21 16:38:09 donn
2540230Sdonn * The fix to mkprim() didn't handle null substring parameters (sigh).
2640230Sdonn *
2740230Sdonn * Revision 3.15 85/06/04 04:37:03 donn
2840230Sdonn * Changed mkprim() to force substring parameters to be integral types.
2940230Sdonn *
3040230Sdonn * Revision 3.14 85/06/04 03:41:52 donn
3140230Sdonn * Change impldcl() to handle functions of type 'undefined'.
3240230Sdonn *
3340230Sdonn * Revision 3.13 85/05/06 23:14:55 donn
3440230Sdonn * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get
3540230Sdonn * a temporary when converting character strings to integers; previously we
3640230Sdonn * were having problems because mkconv() was called after tempalloc().
3740230Sdonn *
3840230Sdonn * Revision 3.12 85/03/18 08:07:47 donn
3940230Sdonn * Fixes to help out with short integers -- if integers are by default short,
4040230Sdonn * then so are constants; and if addresses can't be stored in shorts, complain.
4140230Sdonn *
4240230Sdonn * Revision 3.11 85/03/16 22:31:27 donn
4340230Sdonn * Added hack to mkconv() to allow character values of length > 1 to be
4440230Sdonn * converted to numeric types, for Helge Skrivervik. Note that this does
4540230Sdonn * not affect use of the intrinsic ichar() conversion.
4640230Sdonn *
4740230Sdonn * Revision 3.10 85/01/15 21:06:47 donn
4840230Sdonn * Changed mkconv() to comment on implicit conversions; added intrconv() for
4940230Sdonn * use with explicit conversions by intrinsic functions.
5040230Sdonn *
5140230Sdonn * Revision 3.9 85/01/11 21:05:49 donn
5240230Sdonn * Added changes to implement SAVE statements.
5340230Sdonn *
5440230Sdonn * Revision 3.8 84/12/17 02:21:06 donn
5540230Sdonn * Added a test to prevent constant folding from being done on expressions
5640230Sdonn * whose type is not known at that point in mkexpr().
5740230Sdonn *
5840230Sdonn * Revision 3.7 84/12/11 21:14:17 donn
5940230Sdonn * Removed obnoxious 'excess precision' warning.
6040230Sdonn *
6140230Sdonn * Revision 3.6 84/11/23 01:00:36 donn
6240230Sdonn * Added code to trim excess precision from single-precision constants, and
6340230Sdonn * to warn the user when this occurs.
6440230Sdonn *
6540230Sdonn * Revision 3.5 84/11/23 00:10:39 donn
6640230Sdonn * Changed stfcall() to remark on argument type clashes in 'calls' to
6740230Sdonn * statement functions.
6840230Sdonn *
6940230Sdonn * Revision 3.4 84/11/22 21:21:17 donn
7040230Sdonn * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics.
7140230Sdonn *
7240230Sdonn * Revision 3.3 84/11/12 18:26:14 donn
7340230Sdonn * Shuffled some code around so that the compiler remembers to free some vleng
7440230Sdonn * structures which used to just sit around.
7540230Sdonn *
7640230Sdonn * Revision 3.2 84/10/16 19:24:15 donn
7740230Sdonn * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent
7840230Sdonn * core dumps by replacing bad subscripts with good ones.
7940230Sdonn *
8040230Sdonn * Revision 3.1 84/10/13 01:31:32 donn
8140230Sdonn * Merged Jerry Berkman's version into mine.
8240230Sdonn *
8340230Sdonn * Revision 2.7 84/09/27 15:42:52 donn
8440230Sdonn * The last fix for multiplying undeclared variables by 0 isn't sufficient,
8540230Sdonn * since the type of the 0 may not be the (implicit) type of the variable.
8640230Sdonn * I added a hack to check the implicit type of implicitly declared
8740230Sdonn * variables...
8840230Sdonn *
8940230Sdonn * Revision 2.6 84/09/14 19:34:03 donn
9040230Sdonn * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert
9140230Sdonn * 0 to type UNKNOWN, which is illegal. Fix is to use native type instead.
9240230Sdonn * Not sure how correct (or important) this is...
9340230Sdonn *
9440230Sdonn * Revision 2.5 84/08/05 23:05:27 donn
9540230Sdonn * Added fixes to prevent fixexpr() from slicing and dicing complex conversions
9640230Sdonn * with two operands.
9740230Sdonn *
9840230Sdonn * Revision 2.4 84/08/05 17:34:48 donn
9940230Sdonn * Added an optimization to mklhs() to detect substrings of the form ch(i:i)
10040230Sdonn * and assign constant length 1 to them.
10140230Sdonn *
10240230Sdonn * Revision 2.3 84/07/19 19:38:33 donn
10340230Sdonn * Added a typecast to the last fix. Somehow I missed it the first time...
10440230Sdonn *
10540230Sdonn * Revision 2.2 84/07/19 17:19:57 donn
10640230Sdonn * Caused OPPAREN expressions to inherit the length of their operands, so
10740230Sdonn * that parenthesized character expressions work correctly.
10840230Sdonn *
10940230Sdonn * Revision 2.1 84/07/19 12:03:02 donn
11040230Sdonn * Changed comment headers for UofU.
11140230Sdonn *
11240230Sdonn * Revision 1.2 84/04/06 20:12:17 donn
11340230Sdonn * Fixed bug which caused programs with mixed-type multiplications involving
11440230Sdonn * the constant 0 to choke the compiler.
11540230Sdonn *
11640230Sdonn */
11740230Sdonn
11840230Sdonn #include "defs.h"
11940230Sdonn
12040230Sdonn
12140230Sdonn /* little routines to create constant blocks */
12240230Sdonn
mkconst(t)12340230Sdonn Constp mkconst(t)
12440230Sdonn register int t;
12540230Sdonn {
12640230Sdonn register Constp p;
12740230Sdonn
12840230Sdonn p = ALLOC(Constblock);
12940230Sdonn p->tag = TCONST;
13040230Sdonn p->vtype = t;
13140230Sdonn return(p);
13240230Sdonn }
13340230Sdonn
13440230Sdonn
mklogcon(l)13540230Sdonn expptr mklogcon(l)
13640230Sdonn register int l;
13740230Sdonn {
13840230Sdonn register Constp p;
13940230Sdonn
14040230Sdonn p = mkconst(TYLOGICAL);
14146303Sbostic p->constant.ci = l;
14240230Sdonn return( (expptr) p );
14340230Sdonn }
14440230Sdonn
14540230Sdonn
14640230Sdonn
mkintcon(l)14740230Sdonn expptr mkintcon(l)
14840230Sdonn ftnint l;
14940230Sdonn {
15040230Sdonn register Constp p;
15140230Sdonn int usetype;
15240230Sdonn
15340230Sdonn if(tyint == TYSHORT)
15440230Sdonn {
15540230Sdonn short s = l;
15640230Sdonn if(l != s)
15740230Sdonn usetype = TYLONG;
15840230Sdonn else
15940230Sdonn usetype = TYSHORT;
16040230Sdonn }
16140230Sdonn else
16240230Sdonn usetype = tyint;
16340230Sdonn p = mkconst(usetype);
16446303Sbostic p->constant.ci = l;
16540230Sdonn return( (expptr) p );
16640230Sdonn }
16740230Sdonn
16840230Sdonn
16940230Sdonn
mkaddcon(l)17040230Sdonn expptr mkaddcon(l)
17140230Sdonn register int l;
17240230Sdonn {
17340230Sdonn register Constp p;
17440230Sdonn
17540230Sdonn p = mkconst(TYADDR);
17646303Sbostic p->constant.ci = l;
17740230Sdonn return( (expptr) p );
17840230Sdonn }
17940230Sdonn
18040230Sdonn
18140230Sdonn
mkrealcon(t,d)18240230Sdonn expptr mkrealcon(t, d)
18340230Sdonn register int t;
18440230Sdonn double d;
18540230Sdonn {
18640230Sdonn register Constp p;
18740230Sdonn
18840230Sdonn p = mkconst(t);
18946303Sbostic p->constant.cd[0] = d;
19040230Sdonn return( (expptr) p );
19140230Sdonn }
19240230Sdonn
mkbitcon(shift,leng,s)19340230Sdonn expptr mkbitcon(shift, leng, s)
19440230Sdonn int shift;
19540230Sdonn register int leng;
19640230Sdonn register char *s;
19740230Sdonn {
19840230Sdonn Constp p;
19940230Sdonn register int i, j, k;
20040230Sdonn register char *bp;
20140230Sdonn int size;
20240230Sdonn
20340230Sdonn size = (shift*leng + BYTESIZE -1)/BYTESIZE;
20440230Sdonn bp = (char *) ckalloc(size);
20540230Sdonn
20640230Sdonn i = 0;
20740230Sdonn
20840230Sdonn #if (HERE == PDP11 || HERE == VAX)
20940230Sdonn j = 0;
21040230Sdonn #else
21140230Sdonn j = size;
21240230Sdonn #endif
21340230Sdonn
21440230Sdonn k = 0;
21540230Sdonn
21640230Sdonn while (leng > 0)
21740230Sdonn {
21840230Sdonn k |= (hextoi(s[--leng]) << i);
21940230Sdonn i += shift;
22040230Sdonn if (i >= BYTESIZE)
22140230Sdonn {
22240230Sdonn #if (HERE == PDP11 || HERE == VAX)
22340230Sdonn bp[j++] = k & MAXBYTE;
22440230Sdonn #else
22540230Sdonn bp[--j] = k & MAXBYTE;
22640230Sdonn #endif
22740230Sdonn k = k >> BYTESIZE;
22840230Sdonn i -= BYTESIZE;
22940230Sdonn }
23040230Sdonn }
23140230Sdonn
23240230Sdonn if (k != 0)
23340230Sdonn #if (HERE == PDP11 || HERE == VAX)
23440230Sdonn bp[j++] = k;
23540230Sdonn #else
23640230Sdonn bp[--j] = k;
23740230Sdonn #endif
23840230Sdonn
23940230Sdonn p = mkconst(TYBITSTR);
24040230Sdonn p->vleng = ICON(size);
24146303Sbostic p->constant.ccp = bp;
24240230Sdonn
24340230Sdonn return ((expptr) p);
24440230Sdonn }
24540230Sdonn
24640230Sdonn
24740230Sdonn
mkstrcon(l,v)24840230Sdonn expptr mkstrcon(l,v)
24940230Sdonn int l;
25040230Sdonn register char *v;
25140230Sdonn {
25240230Sdonn register Constp p;
25340230Sdonn register char *s;
25440230Sdonn
25540230Sdonn p = mkconst(TYCHAR);
25640230Sdonn p->vleng = ICON(l);
25746303Sbostic p->constant.ccp = s = (char *) ckalloc(l);
25840230Sdonn while(--l >= 0)
25940230Sdonn *s++ = *v++;
26040230Sdonn return( (expptr) p );
26140230Sdonn }
26240230Sdonn
26340230Sdonn
mkcxcon(realp,imagp)26440230Sdonn expptr mkcxcon(realp,imagp)
26540230Sdonn register expptr realp, imagp;
26640230Sdonn {
26740230Sdonn int rtype, itype;
26840230Sdonn register Constp p;
26940230Sdonn
27040230Sdonn rtype = realp->headblock.vtype;
27140230Sdonn itype = imagp->headblock.vtype;
27240230Sdonn
27340230Sdonn if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
27440230Sdonn {
27540230Sdonn p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX);
27640230Sdonn if( ISINT(rtype) )
27746303Sbostic p->constant.cd[0] = realp->constblock.constant.ci;
27846303Sbostic else p->constant.cd[0] = realp->constblock.constant.cd[0];
27940230Sdonn if( ISINT(itype) )
28046303Sbostic p->constant.cd[1] = imagp->constblock.constant.ci;
28146303Sbostic else p->constant.cd[1] = imagp->constblock.constant.cd[0];
28240230Sdonn }
28340230Sdonn else
28440230Sdonn {
28540230Sdonn err("invalid complex constant");
28640230Sdonn p = (Constp) errnode();
28740230Sdonn }
28840230Sdonn
28940230Sdonn frexpr(realp);
29040230Sdonn frexpr(imagp);
29140230Sdonn return( (expptr) p );
29240230Sdonn }
29340230Sdonn
29440230Sdonn
errnode()29540230Sdonn expptr errnode()
29640230Sdonn {
29740230Sdonn struct Errorblock *p;
29840230Sdonn p = ALLOC(Errorblock);
29940230Sdonn p->tag = TERROR;
30040230Sdonn p->vtype = TYERROR;
30140230Sdonn return( (expptr) p );
30240230Sdonn }
30340230Sdonn
30440230Sdonn
30540230Sdonn
30640230Sdonn
30740230Sdonn
mkconv(t,p)30840230Sdonn expptr mkconv(t, p)
30940230Sdonn register int t;
31040230Sdonn register expptr p;
31140230Sdonn {
31240230Sdonn register expptr q;
31340230Sdonn Addrp r, s;
31440230Sdonn register int pt;
31540230Sdonn expptr opconv();
31640230Sdonn
31740230Sdonn if(t==TYUNKNOWN || t==TYERROR)
31840230Sdonn badtype("mkconv", t);
31940230Sdonn pt = p->headblock.vtype;
32040230Sdonn if(t == pt)
32140230Sdonn return(p);
32240230Sdonn
32340230Sdonn if( pt == TYCHAR && ISNUMERIC(t) )
32440230Sdonn {
32540230Sdonn warn("implicit conversion of character to numeric type");
32640230Sdonn
32740230Sdonn /*
32840230Sdonn * Ugly kluge to copy character values into numerics.
32940230Sdonn */
33040230Sdonn s = mkaltemp(t, ENULL);
33140230Sdonn r = (Addrp) cpexpr(s);
33240230Sdonn r->vtype = TYCHAR;
33340230Sdonn r->varleng = typesize[t];
33440230Sdonn r->vleng = mkintcon(r->varleng);
33540230Sdonn q = mkexpr(OPASSIGN, r, p);
33640230Sdonn q = mkexpr(OPCOMMA, q, s);
33740230Sdonn return(q);
33840230Sdonn }
33940230Sdonn
34040230Sdonn #if SZADDR > SZSHORT
34140230Sdonn if( pt == TYADDR && t == TYSHORT)
34240230Sdonn {
34340230Sdonn err("insufficient precision to hold address type");
34440230Sdonn return( errnode() );
34540230Sdonn }
34640230Sdonn #endif
34740230Sdonn if( pt == TYADDR && ISNUMERIC(t) )
34840230Sdonn warn("implicit conversion of address to numeric type");
34940230Sdonn
35040230Sdonn if( ISCONST(p) && pt!=TYADDR)
35140230Sdonn {
35240230Sdonn q = (expptr) mkconst(t);
35346303Sbostic consconv(t, &(q->constblock.constant),
35446303Sbostic p->constblock.vtype, &(p->constblock.constant) );
35540230Sdonn frexpr(p);
35640230Sdonn }
35740230Sdonn #if TARGET == PDP11
35840230Sdonn else if(ISINT(t) && pt==TYCHAR)
35940230Sdonn {
36040230Sdonn q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
36140230Sdonn if(t == TYLONG)
36240230Sdonn q = opconv(q, TYLONG);
36340230Sdonn }
36440230Sdonn #endif
36540230Sdonn else
36640230Sdonn q = opconv(p, t);
36740230Sdonn
36840230Sdonn if(t == TYCHAR)
36940230Sdonn q->constblock.vleng = ICON(1);
37040230Sdonn return(q);
37140230Sdonn }
37240230Sdonn
37340230Sdonn
37440230Sdonn
37540230Sdonn /* intrinsic conversions */
intrconv(t,p)37640230Sdonn expptr intrconv(t, p)
37740230Sdonn register int t;
37840230Sdonn register expptr p;
37940230Sdonn {
38040230Sdonn register expptr q;
38140230Sdonn register int pt;
38240230Sdonn expptr opconv();
38340230Sdonn
38440230Sdonn if(t==TYUNKNOWN || t==TYERROR)
38540230Sdonn badtype("intrconv", t);
38640230Sdonn pt = p->headblock.vtype;
38740230Sdonn if(t == pt)
38840230Sdonn return(p);
38940230Sdonn
39040230Sdonn else if( ISCONST(p) && pt!=TYADDR)
39140230Sdonn {
39240230Sdonn q = (expptr) mkconst(t);
39346303Sbostic consconv(t, &(q->constblock.constant),
39446303Sbostic p->constblock.vtype, &(p->constblock.constant) );
39540230Sdonn frexpr(p);
39640230Sdonn }
39740230Sdonn #if TARGET == PDP11
39840230Sdonn else if(ISINT(t) && pt==TYCHAR)
39940230Sdonn {
40040230Sdonn q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
40140230Sdonn if(t == TYLONG)
40240230Sdonn q = opconv(q, TYLONG);
40340230Sdonn }
40440230Sdonn #endif
40540230Sdonn else
40640230Sdonn q = opconv(p, t);
40740230Sdonn
40840230Sdonn if(t == TYCHAR)
40940230Sdonn q->constblock.vleng = ICON(1);
41040230Sdonn return(q);
41140230Sdonn }
41240230Sdonn
41340230Sdonn
41440230Sdonn
opconv(p,t)41540230Sdonn expptr opconv(p, t)
41640230Sdonn expptr p;
41740230Sdonn int t;
41840230Sdonn {
41940230Sdonn register expptr q;
42040230Sdonn
42140230Sdonn q = mkexpr(OPCONV, p, PNULL);
42240230Sdonn q->headblock.vtype = t;
42340230Sdonn return(q);
42440230Sdonn }
42540230Sdonn
42640230Sdonn
42740230Sdonn
addrof(p)42840230Sdonn expptr addrof(p)
42940230Sdonn expptr p;
43040230Sdonn {
43140230Sdonn return( mkexpr(OPADDR, p, PNULL) );
43240230Sdonn }
43340230Sdonn
43440230Sdonn
43540230Sdonn
cpexpr(p)43640230Sdonn tagptr cpexpr(p)
43740230Sdonn register tagptr p;
43840230Sdonn {
43940230Sdonn register tagptr e;
44040230Sdonn int tag;
44140230Sdonn register chainp ep, pp;
44240230Sdonn tagptr cpblock();
44340230Sdonn
44440230Sdonn static int blksize[ ] =
44540230Sdonn { 0,
44640230Sdonn sizeof(struct Nameblock),
44740230Sdonn sizeof(struct Constblock),
44840230Sdonn sizeof(struct Exprblock),
44940230Sdonn sizeof(struct Addrblock),
45040230Sdonn sizeof(struct Tempblock),
45140230Sdonn sizeof(struct Primblock),
45240230Sdonn sizeof(struct Listblock),
45340230Sdonn sizeof(struct Errorblock)
45440230Sdonn };
45540230Sdonn
45640230Sdonn if(p == NULL)
45740230Sdonn return(NULL);
45840230Sdonn
45940230Sdonn if( (tag = p->tag) == TNAME)
46040230Sdonn return(p);
46140230Sdonn
46240230Sdonn e = cpblock( blksize[p->tag] , p);
46340230Sdonn
46440230Sdonn switch(tag)
46540230Sdonn {
46640230Sdonn case TCONST:
46740230Sdonn if(e->constblock.vtype == TYCHAR)
46840230Sdonn {
46946303Sbostic e->constblock.constant.ccp =
47046303Sbostic copyn(1+strlen(e->constblock.constant.ccp),
47146303Sbostic e->constblock.constant.ccp);
47240230Sdonn e->constblock.vleng =
47340230Sdonn (expptr) cpexpr(e->constblock.vleng);
47440230Sdonn }
47540230Sdonn case TERROR:
47640230Sdonn break;
47740230Sdonn
47840230Sdonn case TEXPR:
47940230Sdonn e->exprblock.leftp = (expptr) cpexpr(p->exprblock.leftp);
48040230Sdonn e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
48140230Sdonn break;
48240230Sdonn
48340230Sdonn case TLIST:
48440230Sdonn if(pp = p->listblock.listp)
48540230Sdonn {
48640230Sdonn ep = e->listblock.listp =
48740230Sdonn mkchain( cpexpr(pp->datap), CHNULL);
48840230Sdonn for(pp = pp->nextp ; pp ; pp = pp->nextp)
48940230Sdonn ep = ep->nextp =
49040230Sdonn mkchain( cpexpr(pp->datap), CHNULL);
49140230Sdonn }
49240230Sdonn break;
49340230Sdonn
49440230Sdonn case TADDR:
49540230Sdonn e->addrblock.vleng = (expptr) cpexpr(e->addrblock.vleng);
49640230Sdonn e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset);
49740230Sdonn e->addrblock.istemp = NO;
49840230Sdonn break;
49940230Sdonn
50040230Sdonn case TTEMP:
50140230Sdonn e->tempblock.vleng = (expptr) cpexpr(e->tempblock.vleng);
50240230Sdonn e->tempblock.istemp = NO;
50340230Sdonn break;
50440230Sdonn
50540230Sdonn case TPRIM:
50640230Sdonn e->primblock.argsp = (struct Listblock *)
50740230Sdonn cpexpr(e->primblock.argsp);
50840230Sdonn e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp);
50940230Sdonn e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp);
51040230Sdonn break;
51140230Sdonn
51240230Sdonn default:
51340230Sdonn badtag("cpexpr", tag);
51440230Sdonn }
51540230Sdonn
51640230Sdonn return(e);
51740230Sdonn }
51840230Sdonn
frexpr(p)51940230Sdonn frexpr(p)
52040230Sdonn register tagptr p;
52140230Sdonn {
52240230Sdonn register chainp q;
52340230Sdonn
52440230Sdonn if(p == NULL)
52540230Sdonn return;
52640230Sdonn
52740230Sdonn switch(p->tag)
52840230Sdonn {
52940230Sdonn case TCONST:
53040230Sdonn switch (p->constblock.vtype)
53140230Sdonn {
53240230Sdonn case TYBITSTR:
53340230Sdonn case TYCHAR:
53440230Sdonn case TYHOLLERITH:
53546303Sbostic free( (charptr) (p->constblock.constant.ccp) );
53640230Sdonn frexpr(p->constblock.vleng);
53740230Sdonn }
53840230Sdonn break;
53940230Sdonn
54040230Sdonn case TADDR:
54140230Sdonn if (!optimflag && p->addrblock.istemp)
54240230Sdonn {
54340230Sdonn frtemp(p);
54440230Sdonn return;
54540230Sdonn }
54640230Sdonn frexpr(p->addrblock.vleng);
54740230Sdonn frexpr(p->addrblock.memoffset);
54840230Sdonn break;
54940230Sdonn
55040230Sdonn case TTEMP:
55140230Sdonn frexpr(p->tempblock.vleng);
55240230Sdonn break;
55340230Sdonn
55440230Sdonn case TERROR:
55540230Sdonn break;
55640230Sdonn
55740230Sdonn case TNAME:
55840230Sdonn return;
55940230Sdonn
56040230Sdonn case TPRIM:
56140230Sdonn frexpr(p->primblock.argsp);
56240230Sdonn frexpr(p->primblock.fcharp);
56340230Sdonn frexpr(p->primblock.lcharp);
56440230Sdonn break;
56540230Sdonn
56640230Sdonn case TEXPR:
56740230Sdonn frexpr(p->exprblock.leftp);
56840230Sdonn if(p->exprblock.rightp)
56940230Sdonn frexpr(p->exprblock.rightp);
57040230Sdonn break;
57140230Sdonn
57240230Sdonn case TLIST:
57340230Sdonn for(q = p->listblock.listp ; q ; q = q->nextp)
57440230Sdonn frexpr(q->datap);
57540230Sdonn frchain( &(p->listblock.listp) );
57640230Sdonn break;
57740230Sdonn
57840230Sdonn default:
57940230Sdonn badtag("frexpr", p->tag);
58040230Sdonn }
58140230Sdonn
58240230Sdonn free( (charptr) p );
58340230Sdonn }
58440230Sdonn
58540230Sdonn /* fix up types in expression; replace subtrees and convert
58640230Sdonn names to address blocks */
58740230Sdonn
fixtype(p)58840230Sdonn expptr fixtype(p)
58940230Sdonn register tagptr p;
59040230Sdonn {
59140230Sdonn
59240230Sdonn if(p == 0)
59340230Sdonn return(0);
59440230Sdonn
59540230Sdonn switch(p->tag)
59640230Sdonn {
59740230Sdonn case TCONST:
59840230Sdonn return( (expptr) p );
59940230Sdonn
60040230Sdonn case TADDR:
60140230Sdonn p->addrblock.memoffset = fixtype(p->addrblock.memoffset);
60240230Sdonn return( (expptr) p);
60340230Sdonn
60440230Sdonn case TTEMP:
60540230Sdonn return( (expptr) p);
60640230Sdonn
60740230Sdonn case TERROR:
60840230Sdonn return( (expptr) p);
60940230Sdonn
61040230Sdonn default:
61140230Sdonn badtag("fixtype", p->tag);
61240230Sdonn
61340230Sdonn case TEXPR:
61440230Sdonn return( fixexpr(p) );
61540230Sdonn
61640230Sdonn case TLIST:
61740230Sdonn return( (expptr) p );
61840230Sdonn
61940230Sdonn case TPRIM:
62040230Sdonn if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR)
62140230Sdonn {
62240230Sdonn if(p->primblock.namep->vtype == TYSUBR)
62340230Sdonn {
62440230Sdonn err("function invocation of subroutine");
62540230Sdonn return( errnode() );
62640230Sdonn }
62740230Sdonn else
62840230Sdonn return( mkfunct(p) );
62940230Sdonn }
63040230Sdonn else return( mklhs(p) );
63140230Sdonn }
63240230Sdonn }
63340230Sdonn
63440230Sdonn
63540230Sdonn
63640230Sdonn
63740230Sdonn
63840230Sdonn /* special case tree transformations and cleanups of expression trees */
63940230Sdonn
fixexpr(p)64040230Sdonn expptr fixexpr(p)
64140230Sdonn register Exprp p;
64240230Sdonn {
64340230Sdonn expptr lp;
64440230Sdonn register expptr rp;
64540230Sdonn register expptr q;
64640230Sdonn int opcode, ltype, rtype, ptype, mtype;
64740230Sdonn expptr lconst, rconst;
64840230Sdonn expptr mkpower();
64940230Sdonn
65040230Sdonn if( ISERROR(p) )
65140230Sdonn return( (expptr) p );
65240230Sdonn else if(p->tag != TEXPR)
65340230Sdonn badtag("fixexpr", p->tag);
65440230Sdonn opcode = p->opcode;
65540230Sdonn if (ISCONST(p->leftp))
65640230Sdonn lconst = (expptr) cpexpr(p->leftp);
65740230Sdonn else
65840230Sdonn lconst = NULL;
65940230Sdonn if (p->rightp && ISCONST(p->rightp))
66040230Sdonn rconst = (expptr) cpexpr(p->rightp);
66140230Sdonn else
66240230Sdonn rconst = NULL;
66340230Sdonn lp = p->leftp = fixtype(p->leftp);
66440230Sdonn ltype = lp->headblock.vtype;
66540230Sdonn if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP)
66640230Sdonn {
66740230Sdonn err("left side of assignment must be variable");
66840230Sdonn frexpr(p);
66940230Sdonn return( errnode() );
67040230Sdonn }
67140230Sdonn
67240230Sdonn if(p->rightp)
67340230Sdonn {
67440230Sdonn rp = p->rightp = fixtype(p->rightp);
67540230Sdonn rtype = rp->headblock.vtype;
67640230Sdonn }
67740230Sdonn else
67840230Sdonn {
67940230Sdonn rp = NULL;
68040230Sdonn rtype = 0;
68140230Sdonn }
68240230Sdonn
68340230Sdonn if(ltype==TYERROR || rtype==TYERROR)
68440230Sdonn {
68540230Sdonn frexpr(p);
68640230Sdonn frexpr(lconst);
68740230Sdonn frexpr(rconst);
68840230Sdonn return( errnode() );
68940230Sdonn }
69040230Sdonn
69140230Sdonn /* force folding if possible */
69240230Sdonn if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
69340230Sdonn {
69440230Sdonn q = mkexpr(opcode, lp, rp);
69540230Sdonn if( ISCONST(q) )
69640230Sdonn {
69740230Sdonn frexpr(lconst);
69840230Sdonn frexpr(rconst);
69940230Sdonn return(q);
70040230Sdonn }
70140230Sdonn free( (charptr) q ); /* constants did not fold */
70240230Sdonn }
70340230Sdonn
70440230Sdonn if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
70540230Sdonn {
70640230Sdonn frexpr(p);
70740230Sdonn frexpr(lconst);
70840230Sdonn frexpr(rconst);
70940230Sdonn return( errnode() );
71040230Sdonn }
71140230Sdonn
71240230Sdonn switch(opcode)
71340230Sdonn {
71440230Sdonn case OPCONCAT:
71540230Sdonn if(p->vleng == NULL)
71640230Sdonn p->vleng = mkexpr(OPPLUS,
71740230Sdonn cpexpr(lp->headblock.vleng),
71840230Sdonn cpexpr(rp->headblock.vleng) );
71940230Sdonn break;
72040230Sdonn
72140230Sdonn case OPASSIGN:
72240230Sdonn case OPPLUSEQ:
72340230Sdonn case OPSTAREQ:
72440230Sdonn if(ltype == rtype)
72540230Sdonn break;
72640230Sdonn #if TARGET == VAX
72740230Sdonn if( ! rconst && ISREAL(ltype) && ISREAL(rtype) )
72840230Sdonn break;
72940230Sdonn #endif
73040230Sdonn if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
73140230Sdonn break;
73240230Sdonn if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
73340230Sdonn #if FAMILY==PCC
73440230Sdonn && typesize[ltype]>=typesize[rtype] )
73540230Sdonn #else
73640230Sdonn && typesize[ltype]==typesize[rtype] )
73740230Sdonn #endif
73840230Sdonn break;
73940230Sdonn if (rconst)
74040230Sdonn {
74140230Sdonn p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) );
74240230Sdonn frexpr(rp);
74340230Sdonn }
74440230Sdonn else
74540230Sdonn p->rightp = fixtype(mkconv(ptype, rp));
74640230Sdonn break;
74740230Sdonn
74840230Sdonn case OPSLASH:
74940230Sdonn if( ISCOMPLEX(rtype) )
75040230Sdonn {
75140230Sdonn p = (Exprp) call2(ptype,
75240230Sdonn ptype==TYCOMPLEX? "c_div" : "z_div",
75340230Sdonn mkconv(ptype, lp), mkconv(ptype, rp) );
75440230Sdonn break;
75540230Sdonn }
75640230Sdonn case OPPLUS:
75740230Sdonn case OPMINUS:
75840230Sdonn case OPSTAR:
75940230Sdonn case OPMOD:
76040230Sdonn #if TARGET == VAX
76140230Sdonn if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) ||
76240230Sdonn (rtype==TYREAL && ! rconst ) ))
76340230Sdonn break;
76440230Sdonn #endif
76540230Sdonn if( ISCOMPLEX(ptype) )
76640230Sdonn break;
76740230Sdonn if(ltype != ptype)
76840230Sdonn if (lconst)
76940230Sdonn {
77040230Sdonn p->leftp = fixtype(mkconv(ptype,
77140230Sdonn cpexpr(lconst)));
77240230Sdonn frexpr(lp);
77340230Sdonn }
77440230Sdonn else
77540230Sdonn p->leftp = fixtype(mkconv(ptype,lp));
77640230Sdonn if(rtype != ptype)
77740230Sdonn if (rconst)
77840230Sdonn {
77940230Sdonn p->rightp = fixtype(mkconv(ptype,
78040230Sdonn cpexpr(rconst)));
78140230Sdonn frexpr(rp);
78240230Sdonn }
78340230Sdonn else
78440230Sdonn p->rightp = fixtype(mkconv(ptype,rp));
78540230Sdonn break;
78640230Sdonn
78740230Sdonn case OPPOWER:
78840230Sdonn return( mkpower(p) );
78940230Sdonn
79040230Sdonn case OPLT:
79140230Sdonn case OPLE:
79240230Sdonn case OPGT:
79340230Sdonn case OPGE:
79440230Sdonn case OPEQ:
79540230Sdonn case OPNE:
79640230Sdonn if(ltype == rtype)
79740230Sdonn break;
79840230Sdonn mtype = cktype(OPMINUS, ltype, rtype);
79940230Sdonn #if TARGET == VAX
80040230Sdonn if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) ||
80140230Sdonn (rtype==TYREAL && ! rconst) ))
80240230Sdonn break;
80340230Sdonn #endif
80440230Sdonn if( ISCOMPLEX(mtype) )
80540230Sdonn break;
80640230Sdonn if(ltype != mtype)
80740230Sdonn if (lconst)
80840230Sdonn {
80940230Sdonn p->leftp = fixtype(mkconv(mtype,
81040230Sdonn cpexpr(lconst)));
81140230Sdonn frexpr(lp);
81240230Sdonn }
81340230Sdonn else
81440230Sdonn p->leftp = fixtype(mkconv(mtype,lp));
81540230Sdonn if(rtype != mtype)
81640230Sdonn if (rconst)
81740230Sdonn {
81840230Sdonn p->rightp = fixtype(mkconv(mtype,
81940230Sdonn cpexpr(rconst)));
82040230Sdonn frexpr(rp);
82140230Sdonn }
82240230Sdonn else
82340230Sdonn p->rightp = fixtype(mkconv(mtype,rp));
82440230Sdonn break;
82540230Sdonn
82640230Sdonn
82740230Sdonn case OPCONV:
82840230Sdonn if(ISCOMPLEX(p->vtype))
82940230Sdonn {
83040230Sdonn ptype = cktype(OPCONV, p->vtype, ltype);
83140230Sdonn if(p->rightp)
83240230Sdonn ptype = cktype(OPCONV, ptype, rtype);
83340230Sdonn break;
83440230Sdonn }
83540230Sdonn ptype = cktype(OPCONV, p->vtype, ltype);
83640230Sdonn if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA)
83740230Sdonn {
83840230Sdonn lp->exprblock.rightp =
83940230Sdonn fixtype( mkconv(ptype, lp->exprblock.rightp) );
84040230Sdonn free( (charptr) p );
84140230Sdonn p = (Exprp) lp;
84240230Sdonn }
84340230Sdonn break;
84440230Sdonn
84540230Sdonn case OPADDR:
84640230Sdonn if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR)
84740230Sdonn fatal("addr of addr");
84840230Sdonn break;
84940230Sdonn
85040230Sdonn case OPCOMMA:
85140230Sdonn case OPQUEST:
85240230Sdonn case OPCOLON:
85340230Sdonn break;
85440230Sdonn
85540230Sdonn case OPPAREN:
85640230Sdonn p->vleng = (expptr) cpexpr( lp->headblock.vleng );
85740230Sdonn break;
85840230Sdonn
85940230Sdonn case OPMIN:
86040230Sdonn case OPMAX:
86140230Sdonn ptype = p->vtype;
86240230Sdonn break;
86340230Sdonn
86440230Sdonn default:
86540230Sdonn break;
86640230Sdonn }
86740230Sdonn
86840230Sdonn p->vtype = ptype;
86940230Sdonn frexpr(lconst);
87040230Sdonn frexpr(rconst);
87140230Sdonn return((expptr) p);
87240230Sdonn }
87340230Sdonn
87440230Sdonn #if SZINT < SZLONG
87540230Sdonn /*
87640230Sdonn for efficient subscripting, replace long ints by shorts
87740230Sdonn in easy places
87840230Sdonn */
87940230Sdonn
shorten(p)88040230Sdonn expptr shorten(p)
88140230Sdonn register expptr p;
88240230Sdonn {
88340230Sdonn register expptr q;
88440230Sdonn
88540230Sdonn if(p->headblock.vtype != TYLONG)
88640230Sdonn return(p);
88740230Sdonn
88840230Sdonn switch(p->tag)
88940230Sdonn {
89040230Sdonn case TERROR:
89140230Sdonn case TLIST:
89240230Sdonn return(p);
89340230Sdonn
89440230Sdonn case TCONST:
89540230Sdonn case TADDR:
89640230Sdonn return( mkconv(TYINT,p) );
89740230Sdonn
89840230Sdonn case TEXPR:
89940230Sdonn break;
90040230Sdonn
90140230Sdonn default:
90240230Sdonn badtag("shorten", p->tag);
90340230Sdonn }
90440230Sdonn
90540230Sdonn switch(p->exprblock.opcode)
90640230Sdonn {
90740230Sdonn case OPPLUS:
90840230Sdonn case OPMINUS:
90940230Sdonn case OPSTAR:
91040230Sdonn q = shorten( cpexpr(p->exprblock.rightp) );
91140230Sdonn if(q->headblock.vtype == TYINT)
91240230Sdonn {
91340230Sdonn p->exprblock.leftp = shorten(p->exprblock.leftp);
91440230Sdonn if(p->exprblock.leftp->headblock.vtype == TYLONG)
91540230Sdonn frexpr(q);
91640230Sdonn else
91740230Sdonn {
91840230Sdonn frexpr(p->exprblock.rightp);
91940230Sdonn p->exprblock.rightp = q;
92040230Sdonn p->exprblock.vtype = TYINT;
92140230Sdonn }
92240230Sdonn }
92340230Sdonn break;
92440230Sdonn
92540230Sdonn case OPNEG:
92640230Sdonn case OPPAREN:
92740230Sdonn p->exprblock.leftp = shorten(p->exprblock.leftp);
92840230Sdonn if(p->exprblock.leftp->headblock.vtype == TYINT)
92940230Sdonn p->exprblock.vtype = TYINT;
93040230Sdonn break;
93140230Sdonn
93240230Sdonn case OPCALL:
93340230Sdonn case OPCCALL:
93440230Sdonn p = mkconv(TYINT,p);
93540230Sdonn break;
93640230Sdonn default:
93740230Sdonn break;
93840230Sdonn }
93940230Sdonn
94040230Sdonn return(p);
94140230Sdonn }
94240230Sdonn #endif
94340230Sdonn /* fix an argument list, taking due care for special first level cases */
94440230Sdonn
fixargs(doput,p0)94540230Sdonn fixargs(doput, p0)
94640230Sdonn int doput; /* doput is true if the function is not intrinsic;
94740230Sdonn was used to decide whether to do a putconst,
94840230Sdonn but this is no longer done here (Feb82)*/
94940230Sdonn struct Listblock *p0;
95040230Sdonn {
95140230Sdonn register chainp p;
95240230Sdonn register tagptr q, t;
95340230Sdonn register int qtag;
95440230Sdonn int nargs;
95540230Sdonn Addrp mkscalar();
95640230Sdonn
95740230Sdonn nargs = 0;
95840230Sdonn if(p0)
95940230Sdonn for(p = p0->listp ; p ; p = p->nextp)
96040230Sdonn {
96140230Sdonn ++nargs;
96240230Sdonn q = p->datap;
96340230Sdonn qtag = q->tag;
96440230Sdonn if(qtag == TCONST)
96540230Sdonn {
96640230Sdonn
96740230Sdonn /*
96840230Sdonn if(q->constblock.vtype == TYSHORT)
96940230Sdonn q = (tagptr) mkconv(tyint, q);
97040230Sdonn */
97140230Sdonn p->datap = q ;
97240230Sdonn }
97340230Sdonn else if(qtag==TPRIM && q->primblock.argsp==0 &&
97440230Sdonn q->primblock.namep->vclass==CLPROC)
97540230Sdonn p->datap = (tagptr) mkaddr(q->primblock.namep);
97640230Sdonn else if(qtag==TPRIM && q->primblock.argsp==0 &&
97740230Sdonn q->primblock.namep->vdim!=NULL)
97840230Sdonn p->datap = (tagptr) mkscalar(q->primblock.namep);
97940230Sdonn else if(qtag==TPRIM && q->primblock.argsp==0 &&
98040230Sdonn q->primblock.namep->vdovar &&
98140230Sdonn (t = (tagptr) memversion(q->primblock.namep)) )
98240230Sdonn p->datap = (tagptr) fixtype(t);
98340230Sdonn else
98440230Sdonn p->datap = (tagptr) fixtype(q);
98540230Sdonn }
98640230Sdonn return(nargs);
98740230Sdonn }
98840230Sdonn
98940230Sdonn
mkscalar(np)99040230Sdonn Addrp mkscalar(np)
99140230Sdonn register Namep np;
99240230Sdonn {
99340230Sdonn register Addrp ap;
99440230Sdonn
99540230Sdonn vardcl(np);
99640230Sdonn ap = mkaddr(np);
99740230Sdonn
99840230Sdonn #if TARGET == VAX || TARGET == TAHOE
99940230Sdonn /* on the VAX, prolog causes array arguments
100040230Sdonn to point at the (0,...,0) element, except when
100140230Sdonn subscript checking is on
100240230Sdonn */
100340230Sdonn #ifdef SDB
100440230Sdonn if( !checksubs && !sdbflag && np->vstg==STGARG)
100540230Sdonn #else
100640230Sdonn if( !checksubs && np->vstg==STGARG)
100740230Sdonn #endif
100840230Sdonn {
100940230Sdonn register struct Dimblock *dp;
101040230Sdonn dp = np->vdim;
101140230Sdonn frexpr(ap->memoffset);
101240230Sdonn ap->memoffset = mkexpr(OPSTAR,
101340230Sdonn (np->vtype==TYCHAR ?
101440230Sdonn cpexpr(np->vleng) :
101540230Sdonn (tagptr)ICON(typesize[np->vtype]) ),
101640230Sdonn cpexpr(dp->baseoffset) );
101740230Sdonn }
101840230Sdonn #endif
101940230Sdonn return(ap);
102040230Sdonn }
102140230Sdonn
102240230Sdonn
102340230Sdonn
102440230Sdonn
102540230Sdonn
mkfunct(p)102640230Sdonn expptr mkfunct(p)
102740230Sdonn register struct Primblock *p;
102840230Sdonn {
102940230Sdonn struct Entrypoint *ep;
103040230Sdonn Addrp ap;
103140230Sdonn struct Extsym *extp;
103240230Sdonn register Namep np;
103340230Sdonn register expptr q;
103440230Sdonn expptr intrcall(), stfcall();
103540230Sdonn int k, nargs;
103640230Sdonn int class;
103740230Sdonn
103840230Sdonn if(p->tag != TPRIM)
103940230Sdonn return( errnode() );
104040230Sdonn
104140230Sdonn np = p->namep;
104240230Sdonn class = np->vclass;
104340230Sdonn
104440230Sdonn if(class == CLUNKNOWN)
104540230Sdonn {
104640230Sdonn np->vclass = class = CLPROC;
104740230Sdonn if(np->vstg == STGUNKNOWN)
104840230Sdonn {
104940230Sdonn if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) )
105040230Sdonn {
105140230Sdonn np->vstg = STGINTR;
105240230Sdonn np->vardesc.varno = k;
105340230Sdonn np->vprocclass = PINTRINSIC;
105440230Sdonn }
105540230Sdonn else
105640230Sdonn {
105740230Sdonn extp = mkext( varunder(VL,np->varname) );
105840230Sdonn if(extp->extstg == STGCOMMON)
105940230Sdonn warn("conflicting declarations", np->varname);
106040230Sdonn extp->extstg = STGEXT;
106140230Sdonn np->vstg = STGEXT;
106240230Sdonn np->vardesc.varno = extp - extsymtab;
106340230Sdonn np->vprocclass = PEXTERNAL;
106440230Sdonn }
106540230Sdonn }
106640230Sdonn else if(np->vstg==STGARG)
106740230Sdonn {
106840230Sdonn if(np->vtype!=TYCHAR && !ftn66flag)
106940230Sdonn warn("Dummy procedure not declared EXTERNAL. Code may be wrong.");
107040230Sdonn np->vprocclass = PEXTERNAL;
107140230Sdonn }
107240230Sdonn }
107340230Sdonn
107440230Sdonn if(class != CLPROC)
107540230Sdonn fatali("invalid class code %d for function", class);
107640230Sdonn if(p->fcharp || p->lcharp)
107740230Sdonn {
107840230Sdonn err("no substring of function call");
107940230Sdonn goto error;
108040230Sdonn }
108140230Sdonn impldcl(np);
108240230Sdonn nargs = fixargs( np->vprocclass!=PINTRINSIC, p->argsp);
108340230Sdonn
108440230Sdonn switch(np->vprocclass)
108540230Sdonn {
108640230Sdonn case PEXTERNAL:
108740230Sdonn ap = mkaddr(np);
108840230Sdonn call:
108940230Sdonn q = mkexpr(OPCALL, ap, p->argsp);
109040230Sdonn if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN)
109140230Sdonn {
109240230Sdonn err("attempt to use untyped function");
109340230Sdonn goto error;
109440230Sdonn }
109540230Sdonn if(np->vleng)
109640230Sdonn q->exprblock.vleng = (expptr) cpexpr(np->vleng);
109740230Sdonn break;
109840230Sdonn
109940230Sdonn case PINTRINSIC:
110040230Sdonn q = intrcall(np, p->argsp, nargs);
110140230Sdonn break;
110240230Sdonn
110340230Sdonn case PSTFUNCT:
110440230Sdonn q = stfcall(np, p->argsp);
110540230Sdonn break;
110640230Sdonn
110740230Sdonn case PTHISPROC:
110840230Sdonn warn("recursive call");
110940230Sdonn for(ep = entries ; ep ; ep = ep->entnextp)
111040230Sdonn if(ep->enamep == np)
111140230Sdonn break;
111240230Sdonn if(ep == NULL)
111340230Sdonn fatal("mkfunct: impossible recursion");
111440230Sdonn ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) );
111540230Sdonn goto call;
111640230Sdonn
111740230Sdonn default:
111840230Sdonn fatali("mkfunct: impossible vprocclass %d",
111940230Sdonn (int) (np->vprocclass) );
112040230Sdonn }
112140230Sdonn free( (charptr) p );
112240230Sdonn return(q);
112340230Sdonn
112440230Sdonn error:
112540230Sdonn frexpr(p);
112640230Sdonn return( errnode() );
112740230Sdonn }
112840230Sdonn
112940230Sdonn
113040230Sdonn
stfcall(np,actlist)113140230Sdonn LOCAL expptr stfcall(np, actlist)
113240230Sdonn Namep np;
113340230Sdonn struct Listblock *actlist;
113440230Sdonn {
113540230Sdonn register chainp actuals;
113640230Sdonn int nargs;
113740230Sdonn chainp oactp, formals;
113840230Sdonn int type;
113940230Sdonn expptr q, rhs, ap;
114040230Sdonn Namep tnp;
114140230Sdonn register struct Rplblock *rp;
114240230Sdonn struct Rplblock *tlist;
114340230Sdonn
114440230Sdonn if(actlist)
114540230Sdonn {
114640230Sdonn actuals = actlist->listp;
114740230Sdonn free( (charptr) actlist);
114840230Sdonn }
114940230Sdonn else
115040230Sdonn actuals = NULL;
115140230Sdonn oactp = actuals;
115240230Sdonn
115340230Sdonn nargs = 0;
115440230Sdonn tlist = NULL;
115540230Sdonn if( (type = np->vtype) == TYUNKNOWN)
115640230Sdonn {
115740230Sdonn err("attempt to use untyped statement function");
115840230Sdonn q = errnode();
115940230Sdonn goto ret;
116040230Sdonn }
116140230Sdonn formals = (chainp) (np->varxptr.vstfdesc->datap);
116240230Sdonn rhs = (expptr) (np->varxptr.vstfdesc->nextp);
116340230Sdonn
116440230Sdonn /* copy actual arguments into temporaries */
116540230Sdonn while(actuals!=NULL && formals!=NULL)
116640230Sdonn {
116740230Sdonn rp = ALLOC(Rplblock);
116840230Sdonn rp->rplnp = tnp = (Namep) (formals->datap);
116940230Sdonn ap = fixtype(actuals->datap);
117040230Sdonn if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR
117140230Sdonn && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) )
117240230Sdonn {
117340230Sdonn rp->rplvp = (expptr) ap;
117440230Sdonn rp->rplxp = NULL;
117540230Sdonn rp->rpltag = ap->tag;
117640230Sdonn }
117740230Sdonn else {
117840230Sdonn rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng);
117940230Sdonn rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) );
118040230Sdonn if( (rp->rpltag = rp->rplxp->tag) == TERROR)
118140230Sdonn err("disagreement of argument types in statement function call");
118240230Sdonn else if(tnp->vtype!=ap->headblock.vtype)
118340230Sdonn warn("argument type mismatch in statement function");
118440230Sdonn }
118540230Sdonn rp->rplnextp = tlist;
118640230Sdonn tlist = rp;
118740230Sdonn actuals = actuals->nextp;
118840230Sdonn formals = formals->nextp;
118940230Sdonn ++nargs;
119040230Sdonn }
119140230Sdonn
119240230Sdonn if(actuals!=NULL || formals!=NULL)
119340230Sdonn err("statement function definition and argument list differ");
119440230Sdonn
119540230Sdonn /*
119640230Sdonn now push down names involved in formal argument list, then
119740230Sdonn evaluate rhs of statement function definition in this environment
119840230Sdonn */
119940230Sdonn
120040230Sdonn if(tlist) /* put tlist in front of the rpllist */
120140230Sdonn {
120240230Sdonn for(rp = tlist; rp->rplnextp; rp = rp->rplnextp)
120340230Sdonn ;
120440230Sdonn rp->rplnextp = rpllist;
120540230Sdonn rpllist = tlist;
120640230Sdonn }
120740230Sdonn
120840230Sdonn q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) );
120940230Sdonn
121040230Sdonn /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
121140230Sdonn while(--nargs >= 0)
121240230Sdonn {
121340230Sdonn if(rpllist->rplxp)
121440230Sdonn q = mkexpr(OPCOMMA, rpllist->rplxp, q);
121540230Sdonn rp = rpllist->rplnextp;
121640230Sdonn frexpr(rpllist->rplvp);
121740230Sdonn free(rpllist);
121840230Sdonn rpllist = rp;
121940230Sdonn }
122040230Sdonn
122140230Sdonn ret:
122240230Sdonn frchain( &oactp );
122340230Sdonn return(q);
122440230Sdonn }
122540230Sdonn
122640230Sdonn
122740230Sdonn
122840230Sdonn
mkplace(np)122940230Sdonn Addrp mkplace(np)
123040230Sdonn register Namep np;
123140230Sdonn {
123240230Sdonn register Addrp s;
123340230Sdonn register struct Rplblock *rp;
123440230Sdonn int regn;
123540230Sdonn
123640230Sdonn /* is name on the replace list? */
123740230Sdonn
123840230Sdonn for(rp = rpllist ; rp ; rp = rp->rplnextp)
123940230Sdonn {
124040230Sdonn if(np == rp->rplnp)
124140230Sdonn {
124240230Sdonn if(rp->rpltag == TNAME)
124340230Sdonn {
124440230Sdonn np = (Namep) (rp->rplvp);
124540230Sdonn break;
124640230Sdonn }
124740230Sdonn else return( (Addrp) cpexpr(rp->rplvp) );
124840230Sdonn }
124940230Sdonn }
125040230Sdonn
125140230Sdonn /* is variable a DO index in a register ? */
125240230Sdonn
125340230Sdonn if(np->vdovar && ( (regn = inregister(np)) >= 0) )
125440230Sdonn if(np->vtype == TYERROR)
125540230Sdonn return( (Addrp) errnode() );
125640230Sdonn else
125740230Sdonn {
125840230Sdonn s = ALLOC(Addrblock);
125940230Sdonn s->tag = TADDR;
126040230Sdonn s->vstg = STGREG;
126140230Sdonn s->vtype = TYIREG;
126240230Sdonn s->issaved = np->vsave;
126340230Sdonn s->memno = regn;
126440230Sdonn s->memoffset = ICON(0);
126540230Sdonn return(s);
126640230Sdonn }
126740230Sdonn
126840230Sdonn vardcl(np);
126940230Sdonn return(mkaddr(np));
127040230Sdonn }
127140230Sdonn
127240230Sdonn
127340230Sdonn
127440230Sdonn
mklhs(p)127540230Sdonn expptr mklhs(p)
127640230Sdonn register struct Primblock *p;
127740230Sdonn {
127840230Sdonn expptr suboffset();
127940230Sdonn register Addrp s;
128040230Sdonn Namep np;
128140230Sdonn
128240230Sdonn if(p->tag != TPRIM)
128340230Sdonn return( (expptr) p );
128440230Sdonn np = p->namep;
128540230Sdonn
128640230Sdonn s = mkplace(np);
128740230Sdonn if(s->tag!=TADDR || s->vstg==STGREG)
128840230Sdonn {
128940230Sdonn free( (charptr) p );
129040230Sdonn return( (expptr) s );
129140230Sdonn }
129240230Sdonn
129340230Sdonn /* compute the address modified by subscripts */
129440230Sdonn
129540230Sdonn s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) );
129640230Sdonn frexpr(p->argsp);
129740230Sdonn p->argsp = NULL;
129840230Sdonn
129940230Sdonn /* now do substring part */
130040230Sdonn
130140230Sdonn if(p->fcharp || p->lcharp)
130240230Sdonn {
130340230Sdonn if(np->vtype != TYCHAR)
130440230Sdonn errstr("substring of noncharacter %s", varstr(VL,np->varname));
130540230Sdonn else {
130640230Sdonn if(p->lcharp == NULL)
130740230Sdonn p->lcharp = (expptr) cpexpr(s->vleng);
130840230Sdonn frexpr(s->vleng);
130940230Sdonn if(p->fcharp)
131040230Sdonn {
131140230Sdonn if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM
131240230Sdonn && p->fcharp->primblock.namep == p->lcharp->primblock.namep)
131340230Sdonn /* A trivial optimization -- upper == lower */
131440230Sdonn s->vleng = ICON(1);
131540230Sdonn else
131640230Sdonn s->vleng = mkexpr(OPMINUS, p->lcharp,
131740230Sdonn mkexpr(OPMINUS, p->fcharp, ICON(1) ));
131840230Sdonn }
131940230Sdonn else
132040230Sdonn s->vleng = p->lcharp;
132140230Sdonn }
132240230Sdonn }
132340230Sdonn
132440230Sdonn s->vleng = fixtype( s->vleng );
132540230Sdonn s->memoffset = fixtype( s->memoffset );
132640230Sdonn free( (charptr) p );
132740230Sdonn return( (expptr) s );
132840230Sdonn }
132940230Sdonn
133040230Sdonn
133140230Sdonn
133240230Sdonn
133340230Sdonn
deregister(np)133440230Sdonn deregister(np)
133540230Sdonn Namep np;
133640230Sdonn {
133740230Sdonn if(nregvar>0 && regnamep[nregvar-1]==np)
133840230Sdonn {
133940230Sdonn --nregvar;
134040230Sdonn #if FAMILY == DMR
134140230Sdonn putnreg();
134240230Sdonn #endif
134340230Sdonn }
134440230Sdonn }
134540230Sdonn
134640230Sdonn
134740230Sdonn
134840230Sdonn
memversion(np)134940230Sdonn Addrp memversion(np)
135040230Sdonn register Namep np;
135140230Sdonn {
135240230Sdonn register Addrp s;
135340230Sdonn
135440230Sdonn if(np->vdovar==NO || (inregister(np)<0) )
135540230Sdonn return(NULL);
135640230Sdonn np->vdovar = NO;
135740230Sdonn s = mkplace(np);
135840230Sdonn np->vdovar = YES;
135940230Sdonn return(s);
136040230Sdonn }
136140230Sdonn
136240230Sdonn
136340230Sdonn
inregister(np)136440230Sdonn inregister(np)
136540230Sdonn register Namep np;
136640230Sdonn {
136740230Sdonn register int i;
136840230Sdonn
136940230Sdonn for(i = 0 ; i < nregvar ; ++i)
137040230Sdonn if(regnamep[i] == np)
137140230Sdonn return( regnum[i] );
137240230Sdonn return(-1);
137340230Sdonn }
137440230Sdonn
137540230Sdonn
137640230Sdonn
137740230Sdonn
enregister(np)137840230Sdonn enregister(np)
137940230Sdonn Namep np;
138040230Sdonn {
138140230Sdonn if( inregister(np) >= 0)
138240230Sdonn return(YES);
138340230Sdonn if(nregvar >= maxregvar)
138440230Sdonn return(NO);
138540230Sdonn vardcl(np);
138640230Sdonn if( ONEOF(np->vtype, MSKIREG) )
138740230Sdonn {
138840230Sdonn regnamep[nregvar++] = np;
138940230Sdonn if(nregvar > highregvar)
139040230Sdonn highregvar = nregvar;
139140230Sdonn #if FAMILY == DMR
139240230Sdonn putnreg();
139340230Sdonn #endif
139440230Sdonn return(YES);
139540230Sdonn }
139640230Sdonn else
139740230Sdonn return(NO);
139840230Sdonn }
139940230Sdonn
140040230Sdonn
140140230Sdonn
140240230Sdonn
suboffset(p)140340230Sdonn expptr suboffset(p)
140440230Sdonn register struct Primblock *p;
140540230Sdonn {
140640230Sdonn int n;
140740230Sdonn expptr size;
140840230Sdonn expptr oftwo();
140940230Sdonn chainp cp;
141040230Sdonn expptr offp, prod;
141140230Sdonn expptr subcheck();
141240230Sdonn struct Dimblock *dimp;
141340230Sdonn expptr sub[MAXDIM+1];
141440230Sdonn register Namep np;
141540230Sdonn
141640230Sdonn np = p->namep;
141740230Sdonn offp = ICON(0);
141840230Sdonn n = 0;
141940230Sdonn if(p->argsp)
142040230Sdonn for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp)
142140230Sdonn {
142240230Sdonn sub[n] = fixtype(cpexpr(cp->datap));
142340230Sdonn if ( ! ISINT(sub[n]->headblock.vtype)) {
142440230Sdonn errstr("%s: non-integer subscript expression",
142540230Sdonn varstr(VL, np->varname) );
142640230Sdonn /* Provide a substitute -- go on to find more errors */
142740230Sdonn frexpr(sub[n]);
142840230Sdonn sub[n] = ICON(1);
142940230Sdonn }
143040230Sdonn if(n > maxdim)
143140230Sdonn {
143240230Sdonn char str[28+VL];
143340230Sdonn sprintf(str, "%s: more than %d subscripts",
143440230Sdonn varstr(VL, np->varname), maxdim );
143540230Sdonn err( str );
143640230Sdonn break;
143740230Sdonn }
143840230Sdonn }
143940230Sdonn
144040230Sdonn dimp = np->vdim;
144140230Sdonn if(n>0 && dimp==NULL)
144240230Sdonn errstr("%s: subscripts on scalar variable",
144340230Sdonn varstr(VL, np->varname), maxdim );
144440230Sdonn else if(dimp && dimp->ndim!=n)
144540230Sdonn errstr("wrong number of subscripts on %s",
144640230Sdonn varstr(VL, np->varname) );
144740230Sdonn else if(n > 0)
144840230Sdonn {
144940230Sdonn prod = sub[--n];
145040230Sdonn while( --n >= 0)
145140230Sdonn prod = mkexpr(OPPLUS, sub[n],
145240230Sdonn mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
145340230Sdonn #if TARGET == VAX || TARGET == TAHOE
145440230Sdonn #ifdef SDB
145540230Sdonn if(checksubs || np->vstg!=STGARG || sdbflag)
145640230Sdonn #else
145740230Sdonn if(checksubs || np->vstg!=STGARG)
145840230Sdonn #endif
145940230Sdonn prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
146040230Sdonn #else
146140230Sdonn prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
146240230Sdonn #endif
146340230Sdonn if(checksubs)
146440230Sdonn prod = subcheck(np, prod);
146540230Sdonn size = np->vtype == TYCHAR ?
146640230Sdonn (expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]);
146740230Sdonn if (!oftwo(size))
146840230Sdonn prod = mkexpr(OPSTAR, prod, size);
146940230Sdonn else
147040230Sdonn prod = mkexpr(OPLSHIFT,prod,oftwo(size));
147140230Sdonn
147240230Sdonn offp = mkexpr(OPPLUS, offp, prod);
147340230Sdonn }
147440230Sdonn
147540230Sdonn if(p->fcharp && np->vtype==TYCHAR)
147640230Sdonn offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
147740230Sdonn
147840230Sdonn return(offp);
147940230Sdonn }
148040230Sdonn
148140230Sdonn
148240230Sdonn
148340230Sdonn
subcheck(np,p)148440230Sdonn expptr subcheck(np, p)
148540230Sdonn Namep np;
148640230Sdonn register expptr p;
148740230Sdonn {
148840230Sdonn struct Dimblock *dimp;
148940230Sdonn expptr t, checkvar, checkcond, badcall;
149040230Sdonn
149140230Sdonn dimp = np->vdim;
149240230Sdonn if(dimp->nelt == NULL)
149340230Sdonn return(p); /* don't check arrays with * bounds */
149440230Sdonn checkvar = NULL;
149540230Sdonn checkcond = NULL;
149640230Sdonn if( ISICON(p) )
149740230Sdonn {
149846303Sbostic if(p->constblock.constant.ci < 0)
149940230Sdonn goto badsub;
150040230Sdonn if( ISICON(dimp->nelt) )
150146303Sbostic if(p->constblock.constant.ci <
150246303Sbostic dimp->nelt->constblock.constant.ci)
150340230Sdonn return(p);
150440230Sdonn else
150540230Sdonn goto badsub;
150640230Sdonn }
150740230Sdonn if(p->tag==TADDR && p->addrblock.vstg==STGREG)
150840230Sdonn {
150940230Sdonn checkvar = (expptr) cpexpr(p);
151040230Sdonn t = p;
151140230Sdonn }
151240230Sdonn else {
151340230Sdonn checkvar = (expptr) mktemp(p->headblock.vtype, ENULL);
151440230Sdonn t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
151540230Sdonn }
151640230Sdonn checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
151740230Sdonn if( ! ISICON(p) )
151840230Sdonn checkcond = mkexpr(OPAND, checkcond,
151940230Sdonn mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
152040230Sdonn
152140230Sdonn badcall = call4(p->headblock.vtype, "s_rnge",
152240230Sdonn mkstrcon(VL, np->varname),
152340230Sdonn mkconv(TYLONG, cpexpr(checkvar)),
152440230Sdonn mkstrcon(XL, procname),
152540230Sdonn ICON(lineno) );
152640230Sdonn badcall->exprblock.opcode = OPCCALL;
152740230Sdonn p = mkexpr(OPQUEST, checkcond,
152840230Sdonn mkexpr(OPCOLON, checkvar, badcall));
152940230Sdonn
153040230Sdonn return(p);
153140230Sdonn
153240230Sdonn badsub:
153340230Sdonn frexpr(p);
153440230Sdonn errstr("subscript on variable %s out of range", varstr(VL,np->varname));
153540230Sdonn return ( ICON(0) );
153640230Sdonn }
153740230Sdonn
153840230Sdonn
153940230Sdonn
154040230Sdonn
mkaddr(p)154140230Sdonn Addrp mkaddr(p)
154240230Sdonn register Namep p;
154340230Sdonn {
154440230Sdonn struct Extsym *extp;
154540230Sdonn register Addrp t;
154640230Sdonn Addrp intraddr();
154740230Sdonn
154840230Sdonn switch( p->vstg)
154940230Sdonn {
155040230Sdonn case STGUNKNOWN:
155140230Sdonn if(p->vclass != CLPROC)
155240230Sdonn break;
155340230Sdonn extp = mkext( varunder(VL, p->varname) );
155440230Sdonn extp->extstg = STGEXT;
155540230Sdonn p->vstg = STGEXT;
155640230Sdonn p->vardesc.varno = extp - extsymtab;
155740230Sdonn p->vprocclass = PEXTERNAL;
155840230Sdonn
155940230Sdonn case STGCOMMON:
156040230Sdonn case STGEXT:
156140230Sdonn case STGBSS:
156240230Sdonn case STGINIT:
156340230Sdonn case STGEQUIV:
156440230Sdonn case STGARG:
156540230Sdonn case STGLENG:
156640230Sdonn case STGAUTO:
156740230Sdonn t = ALLOC(Addrblock);
156840230Sdonn t->tag = TADDR;
156940230Sdonn if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)
157040230Sdonn t->vclass = CLVAR;
157140230Sdonn else
157240230Sdonn t->vclass = p->vclass;
157340230Sdonn t->vtype = p->vtype;
157440230Sdonn t->vstg = p->vstg;
157540230Sdonn t->memno = p->vardesc.varno;
157640230Sdonn t->issaved = p->vsave;
157740230Sdonn if(p->vdim) t->isarray = YES;
157840230Sdonn t->memoffset = ICON(p->voffset);
157940230Sdonn if(p->vleng)
158040230Sdonn {
158140230Sdonn t->vleng = (expptr) cpexpr(p->vleng);
158240230Sdonn if( ISICON(t->vleng) )
158346303Sbostic t->varleng = t->vleng->constblock.constant.ci;
158440230Sdonn }
158540230Sdonn if (p->vstg == STGBSS)
158640230Sdonn t->varsize = p->varsize;
158740230Sdonn else if (p->vstg == STGEQUIV)
158840230Sdonn t->varsize = eqvclass[t->memno].eqvleng;
158940230Sdonn return(t);
159040230Sdonn
159140230Sdonn case STGINTR:
159240230Sdonn return( intraddr(p) );
159340230Sdonn
159440230Sdonn }
159540230Sdonn /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
159640230Sdonn badstg("mkaddr", p->vstg);
159740230Sdonn /* NOTREACHED */
159840230Sdonn }
159940230Sdonn
160040230Sdonn
160140230Sdonn
160240230Sdonn
mkarg(type,argno)160340230Sdonn Addrp mkarg(type, argno)
160440230Sdonn int type, argno;
160540230Sdonn {
160640230Sdonn register Addrp p;
160740230Sdonn
160840230Sdonn p = ALLOC(Addrblock);
160940230Sdonn p->tag = TADDR;
161040230Sdonn p->vtype = type;
161140230Sdonn p->vclass = CLVAR;
161240230Sdonn p->vstg = (type==TYLENG ? STGLENG : STGARG);
161340230Sdonn p->memno = argno;
161440230Sdonn return(p);
161540230Sdonn }
161640230Sdonn
161740230Sdonn
161840230Sdonn
161940230Sdonn
162040230Sdonn expptr mkprim(v, args, substr)
162140230Sdonn register union
162240230Sdonn {
162340230Sdonn struct Paramblock paramblock;
162440230Sdonn struct Nameblock nameblock;
162540230Sdonn struct Headblock headblock;
162640230Sdonn } *v;
162740230Sdonn struct Listblock *args;
162840230Sdonn chainp substr;
162940230Sdonn {
163040230Sdonn register struct Primblock *p;
163140230Sdonn
163240230Sdonn if(v->headblock.vclass == CLPARAM)
163340230Sdonn {
163440230Sdonn if(args || substr)
163540230Sdonn {
163640230Sdonn errstr("no qualifiers on parameter name %s",
163740230Sdonn varstr(VL,v->paramblock.varname));
163840230Sdonn frexpr(args);
163940230Sdonn if(substr)
164040230Sdonn {
164140230Sdonn frexpr(substr->datap);
164240230Sdonn frexpr(substr->nextp->datap);
164340230Sdonn frchain(&substr);
164440230Sdonn }
164540230Sdonn frexpr(v);
164640230Sdonn return( errnode() );
164740230Sdonn }
164840230Sdonn return( (expptr) cpexpr(v->paramblock.paramval) );
164940230Sdonn }
165040230Sdonn
165140230Sdonn p = ALLOC(Primblock);
165240230Sdonn p->tag = TPRIM;
165340230Sdonn p->vtype = v->nameblock.vtype;
165440230Sdonn p->namep = (Namep) v;
165540230Sdonn p->argsp = args;
165640230Sdonn if(substr)
165740230Sdonn {
165840230Sdonn p->fcharp = (expptr) substr->datap;
165940231Sdonn if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype))
166040230Sdonn p->fcharp = mkconv(TYINT, p->fcharp);
166140230Sdonn p->lcharp = (expptr) substr->nextp->datap;
166240231Sdonn if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype))
166340230Sdonn p->lcharp = mkconv(TYINT, p->lcharp);
166440230Sdonn frchain(&substr);
166540230Sdonn }
166640230Sdonn return( (expptr) p);
166740230Sdonn }
166840230Sdonn
166940230Sdonn
167040230Sdonn
vardcl(v)167140230Sdonn vardcl(v)
167240230Sdonn register Namep v;
167340230Sdonn {
167440230Sdonn int nelt;
167540230Sdonn struct Dimblock *t;
167640230Sdonn Addrp p;
167740230Sdonn expptr neltp;
167840230Sdonn int eltsize;
167940230Sdonn int varsize;
168040230Sdonn int tsize;
168140230Sdonn int align;
168240230Sdonn
168340230Sdonn if(v->vdcldone)
168440230Sdonn return;
168540230Sdonn if(v->vclass == CLNAMELIST)
168640230Sdonn return;
168740230Sdonn
168840230Sdonn if(v->vtype == TYUNKNOWN)
168940230Sdonn impldcl(v);
169040230Sdonn if(v->vclass == CLUNKNOWN)
169140230Sdonn v->vclass = CLVAR;
169240230Sdonn else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
169340230Sdonn {
169440230Sdonn dclerr("used both as variable and non-variable", v);
169540230Sdonn return;
169640230Sdonn }
169740230Sdonn if(v->vstg==STGUNKNOWN)
169840230Sdonn v->vstg = implstg[ letter(v->varname[0]) ];
169940230Sdonn
170040230Sdonn switch(v->vstg)
170140230Sdonn {
170240230Sdonn case STGBSS:
170340230Sdonn v->vardesc.varno = ++lastvarno;
170440230Sdonn if (v->vclass != CLVAR)
170540230Sdonn break;
170640230Sdonn nelt = 1;
170740230Sdonn t = v->vdim;
170840230Sdonn if (t)
170940230Sdonn {
171040230Sdonn neltp = t->nelt;
171140230Sdonn if (neltp && ISICON(neltp))
171246303Sbostic nelt = neltp->constblock.constant.ci;
171340230Sdonn else
171440230Sdonn dclerr("improperly dimensioned array", v);
171540230Sdonn }
171640230Sdonn
171740230Sdonn if (v->vtype == TYCHAR)
171840230Sdonn {
171940230Sdonn v->vleng = fixtype(v->vleng);
172040230Sdonn if (v->vleng == NULL)
172140230Sdonn eltsize = typesize[TYCHAR];
172240230Sdonn else if (ISICON(v->vleng))
172340230Sdonn eltsize = typesize[TYCHAR] *
172446303Sbostic v->vleng->constblock.constant.ci;
172540230Sdonn else if (v->vleng->tag != TERROR)
172640230Sdonn {
172740230Sdonn errstr("nonconstant string length on %s",
172840230Sdonn varstr(VL, v->varname));
172940230Sdonn eltsize = 0;
173040230Sdonn }
173140230Sdonn }
173240230Sdonn else
173340230Sdonn eltsize = typesize[v->vtype];
173440230Sdonn
173540230Sdonn v->varsize = nelt * eltsize;
173640230Sdonn break;
173740230Sdonn case STGAUTO:
173840230Sdonn if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
173940230Sdonn break;
174040230Sdonn nelt = 1;
174140230Sdonn if(t = v->vdim)
174240230Sdonn if( (neltp = t->nelt) && ISCONST(neltp) )
174346303Sbostic nelt = neltp->constblock.constant.ci;
174440230Sdonn else
174540230Sdonn dclerr("adjustable automatic array", v);
174640230Sdonn p = autovar(nelt, v->vtype, v->vleng);
174740230Sdonn v->vardesc.varno = p->memno;
174846303Sbostic v->voffset = p->memoffset->constblock.constant.ci;
174940230Sdonn frexpr(p);
175040230Sdonn break;
175140230Sdonn
175240230Sdonn default:
175340230Sdonn break;
175440230Sdonn }
175540230Sdonn v->vdcldone = YES;
175640230Sdonn }
175740230Sdonn
175840230Sdonn
175940230Sdonn
176040230Sdonn
impldcl(p)176140230Sdonn impldcl(p)
176240230Sdonn register Namep p;
176340230Sdonn {
176440230Sdonn register int k;
176540230Sdonn int type, leng;
176640230Sdonn
176740230Sdonn if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
176840230Sdonn return;
176940230Sdonn if(p->vtype == TYUNKNOWN)
177040230Sdonn {
177140230Sdonn k = letter(p->varname[0]);
177240230Sdonn type = impltype[ k ];
177340230Sdonn leng = implleng[ k ];
177440230Sdonn if(type == TYUNKNOWN)
177540230Sdonn {
177640230Sdonn if(p->vclass == CLPROC)
177740230Sdonn dclerr("attempt to use function of undefined type", p);
177840230Sdonn else
177940230Sdonn dclerr("attempt to use undefined variable", p);
178040230Sdonn type = TYERROR;
178140230Sdonn leng = 1;
178240230Sdonn }
178340230Sdonn settype(p, type, leng);
178440230Sdonn }
178540230Sdonn }
178640230Sdonn
178740230Sdonn
178840230Sdonn
178940230Sdonn
letter(c)179040230Sdonn LOCAL letter(c)
179140230Sdonn register int c;
179240230Sdonn {
179340230Sdonn if( isupper(c) )
179440230Sdonn c = tolower(c);
179540230Sdonn return(c - 'a');
179640230Sdonn }
179740230Sdonn
179846303Sbostic #define ICONEQ(z, c) (ISICON(z) && z->constblock.constant.ci==c)
179940230Sdonn #define COMMUTE { e = lp; lp = rp; rp = e; }
180040230Sdonn
180140230Sdonn
mkexpr(opcode,lp,rp)180240230Sdonn expptr mkexpr(opcode, lp, rp)
180340230Sdonn int opcode;
180440230Sdonn register expptr lp, rp;
180540230Sdonn {
180640230Sdonn register expptr e, e1;
180740230Sdonn int etype;
180840230Sdonn int ltype, rtype;
180940230Sdonn int ltag, rtag;
181040230Sdonn expptr q, q1;
181140230Sdonn expptr fold();
181240230Sdonn int k;
181340230Sdonn
181440230Sdonn ltype = lp->headblock.vtype;
181540230Sdonn ltag = lp->tag;
181640230Sdonn if(rp && opcode!=OPCALL && opcode!=OPCCALL)
181740230Sdonn {
181840230Sdonn rtype = rp->headblock.vtype;
181940230Sdonn rtag = rp->tag;
182040230Sdonn }
182140230Sdonn else {
182240230Sdonn rtype = 0;
182340230Sdonn rtag = 0;
182440230Sdonn }
182540230Sdonn
182640230Sdonn /*
182740230Sdonn * Yuck. Why can't we fold constants AFTER
182840230Sdonn * variables are implicitly declared???
182940230Sdonn */
183040230Sdonn if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL)
183140230Sdonn {
183240230Sdonn k = letter(lp->primblock.namep->varname[0]);
183340230Sdonn ltype = impltype[ k ];
183440230Sdonn }
183540230Sdonn if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL)
183640230Sdonn {
183740230Sdonn k = letter(rp->primblock.namep->varname[0]);
183840230Sdonn rtype = impltype[ k ];
183940230Sdonn }
184040230Sdonn
184140230Sdonn etype = cktype(opcode, ltype, rtype);
184240230Sdonn if(etype == TYERROR)
184340230Sdonn goto error;
184440230Sdonn
184540230Sdonn if(etype != TYUNKNOWN)
184640230Sdonn switch(opcode)
184740230Sdonn {
184840230Sdonn /* check for multiplication by 0 and 1 and addition to 0 */
184940230Sdonn
185040230Sdonn case OPSTAR:
185140230Sdonn if( ISCONST(lp) )
185240230Sdonn COMMUTE
185340230Sdonn
185440230Sdonn if( ISICON(rp) )
185540230Sdonn {
185646303Sbostic if(rp->constblock.constant.ci == 0)
185740230Sdonn {
185840230Sdonn if(etype == TYUNKNOWN)
185940230Sdonn break;
186040230Sdonn rp = mkconv(etype, rp);
186140230Sdonn goto retright;
186240230Sdonn }
186340230Sdonn if ((lp->tag == TEXPR) &&
186440230Sdonn ((lp->exprblock.opcode == OPPLUS) ||
186540230Sdonn (lp->exprblock.opcode == OPMINUS)) &&
186640230Sdonn ISCONST(lp->exprblock.rightp) &&
186740230Sdonn ISINT(lp->exprblock.rightp->constblock.vtype))
186840230Sdonn {
186940230Sdonn q1 = mkexpr(OPSTAR, lp->exprblock.rightp,
187040230Sdonn cpexpr(rp));
187140230Sdonn q = mkexpr(OPSTAR, lp->exprblock.leftp, rp);
187240230Sdonn q = mkexpr(lp->exprblock.opcode, q, q1);
187340230Sdonn free ((char *) lp);
187440230Sdonn return q;
187540230Sdonn }
187640230Sdonn else
187740230Sdonn goto mulop;
187840230Sdonn }
187940230Sdonn break;
188040230Sdonn
188140230Sdonn case OPSLASH:
188240230Sdonn case OPMOD:
188340230Sdonn if( ICONEQ(rp, 0) )
188440230Sdonn {
188540230Sdonn err("attempted division by zero");
188640230Sdonn rp = ICON(1);
188740230Sdonn break;
188840230Sdonn }
188940230Sdonn if(opcode == OPMOD)
189040230Sdonn break;
189140230Sdonn
189240230Sdonn
189340230Sdonn mulop:
189440230Sdonn if( ISICON(rp) )
189540230Sdonn {
189646303Sbostic if(rp->constblock.constant.ci == 1)
189740230Sdonn goto retleft;
189840230Sdonn
189946303Sbostic if(rp->constblock.constant.ci == -1)
190040230Sdonn {
190140230Sdonn frexpr(rp);
190240230Sdonn return( mkexpr(OPNEG, lp, PNULL) );
190340230Sdonn }
190440230Sdonn }
190540230Sdonn
190640230Sdonn if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) )
190740230Sdonn {
190840230Sdonn if(opcode == OPSTAR)
190940230Sdonn e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
191040230Sdonn else if(ISICON(rp) &&
191146303Sbostic (lp->exprblock.rightp->constblock.constant.ci %
191246303Sbostic rp->constblock.constant.ci) == 0)
191340230Sdonn e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
191440230Sdonn else break;
191540230Sdonn
191640230Sdonn e1 = lp->exprblock.leftp;
191740230Sdonn free( (charptr) lp );
191840230Sdonn return( mkexpr(OPSTAR, e1, e) );
191940230Sdonn }
192040230Sdonn break;
192140230Sdonn
192240230Sdonn
192340230Sdonn case OPPLUS:
192440230Sdonn if( ISCONST(lp) )
192540230Sdonn COMMUTE
192640230Sdonn goto addop;
192740230Sdonn
192840230Sdonn case OPMINUS:
192940230Sdonn if( ICONEQ(lp, 0) )
193040230Sdonn {
193140230Sdonn frexpr(lp);
193240230Sdonn return( mkexpr(OPNEG, rp, ENULL) );
193340230Sdonn }
193440230Sdonn
193540230Sdonn if( ISCONST(rp) )
193640230Sdonn {
193740230Sdonn opcode = OPPLUS;
193840230Sdonn consnegop(rp);
193940230Sdonn }
194040230Sdonn
194140230Sdonn addop:
194240230Sdonn if( ISICON(rp) )
194340230Sdonn {
194446303Sbostic if(rp->constblock.constant.ci == 0)
194540230Sdonn goto retleft;
194640230Sdonn if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
194740230Sdonn {
194840230Sdonn e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
194940230Sdonn e1 = lp->exprblock.leftp;
195040230Sdonn free( (charptr) lp );
195140230Sdonn return( mkexpr(OPPLUS, e1, e) );
195240230Sdonn }
195340230Sdonn }
195440230Sdonn break;
195540230Sdonn
195640230Sdonn
195740230Sdonn case OPPOWER:
195840230Sdonn break;
195940230Sdonn
196040230Sdonn case OPNEG:
196140230Sdonn if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
196240230Sdonn {
196340230Sdonn e = lp->exprblock.leftp;
196440230Sdonn free( (charptr) lp );
196540230Sdonn return(e);
196640230Sdonn }
196740230Sdonn break;
196840230Sdonn
196940230Sdonn case OPNOT:
197040230Sdonn if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
197140230Sdonn {
197240230Sdonn e = lp->exprblock.leftp;
197340230Sdonn free( (charptr) lp );
197440230Sdonn return(e);
197540230Sdonn }
197640230Sdonn break;
197740230Sdonn
197840230Sdonn case OPCALL:
197940230Sdonn case OPCCALL:
198040230Sdonn etype = ltype;
198140230Sdonn if(rp!=NULL && rp->listblock.listp==NULL)
198240230Sdonn {
198340230Sdonn free( (charptr) rp );
198440230Sdonn rp = NULL;
198540230Sdonn }
198640230Sdonn break;
198740230Sdonn
198840230Sdonn case OPAND:
198940230Sdonn case OPOR:
199040230Sdonn if( ISCONST(lp) )
199140230Sdonn COMMUTE
199240230Sdonn
199340230Sdonn if( ISCONST(rp) )
199440230Sdonn {
199546303Sbostic if(rp->constblock.constant.ci == 0)
199640230Sdonn if(opcode == OPOR)
199740230Sdonn goto retleft;
199840230Sdonn else
199940230Sdonn goto retright;
200040230Sdonn else if(opcode == OPOR)
200140230Sdonn goto retright;
200240230Sdonn else
200340230Sdonn goto retleft;
200440230Sdonn }
200540230Sdonn case OPLSHIFT:
200640230Sdonn if (ISICON(rp))
200740230Sdonn {
200846303Sbostic if (rp->constblock.constant.ci == 0)
200940230Sdonn goto retleft;
201040230Sdonn if ((lp->tag == TEXPR) &&
201140230Sdonn ((lp->exprblock.opcode == OPPLUS) ||
201240230Sdonn (lp->exprblock.opcode == OPMINUS)) &&
201340230Sdonn ISICON(lp->exprblock.rightp))
201440230Sdonn {
201540230Sdonn q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp,
201640230Sdonn cpexpr(rp));
201740230Sdonn q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp);
201840230Sdonn q = mkexpr(lp->exprblock.opcode, q, q1);
201940230Sdonn free((char *) lp);
202040230Sdonn return q;
202140230Sdonn }
202240230Sdonn }
202340230Sdonn
202440230Sdonn case OPEQV:
202540230Sdonn case OPNEQV:
202640230Sdonn
202740230Sdonn case OPBITAND:
202840230Sdonn case OPBITOR:
202940230Sdonn case OPBITXOR:
203040230Sdonn case OPBITNOT:
203140230Sdonn case OPRSHIFT:
203240230Sdonn
203340230Sdonn case OPLT:
203440230Sdonn case OPGT:
203540230Sdonn case OPLE:
203640230Sdonn case OPGE:
203740230Sdonn case OPEQ:
203840230Sdonn case OPNE:
203940230Sdonn
204040230Sdonn case OPCONCAT:
204140230Sdonn break;
204240230Sdonn case OPMIN:
204340230Sdonn case OPMAX:
204440230Sdonn
204540230Sdonn case OPASSIGN:
204640230Sdonn case OPPLUSEQ:
204740230Sdonn case OPSTAREQ:
204840230Sdonn
204940230Sdonn case OPCONV:
205040230Sdonn case OPADDR:
205140230Sdonn
205240230Sdonn case OPCOMMA:
205340230Sdonn case OPQUEST:
205440230Sdonn case OPCOLON:
205540230Sdonn
205640230Sdonn case OPPAREN:
205740230Sdonn break;
205840230Sdonn
205940230Sdonn default:
206040230Sdonn badop("mkexpr", opcode);
206140230Sdonn }
206240230Sdonn
206340230Sdonn e = (expptr) ALLOC(Exprblock);
206440230Sdonn e->exprblock.tag = TEXPR;
206540230Sdonn e->exprblock.opcode = opcode;
206640230Sdonn e->exprblock.vtype = etype;
206740230Sdonn e->exprblock.leftp = lp;
206840230Sdonn e->exprblock.rightp = rp;
206940230Sdonn if(ltag==TCONST && (rp==0 || rtag==TCONST) )
207040230Sdonn e = fold(e);
207140230Sdonn return(e);
207240230Sdonn
207340230Sdonn retleft:
207440230Sdonn frexpr(rp);
207540230Sdonn return(lp);
207640230Sdonn
207740230Sdonn retright:
207840230Sdonn frexpr(lp);
207940230Sdonn return(rp);
208040230Sdonn
208140230Sdonn error:
208240230Sdonn frexpr(lp);
208340230Sdonn if(rp && opcode!=OPCALL && opcode!=OPCCALL)
208440230Sdonn frexpr(rp);
208540230Sdonn return( errnode() );
208640230Sdonn }
208740230Sdonn
208840230Sdonn #define ERR(s) { errs = s; goto error; }
208940230Sdonn
cktype(op,lt,rt)209040230Sdonn cktype(op, lt, rt)
209140230Sdonn register int op, lt, rt;
209240230Sdonn {
209340230Sdonn char *errs;
209440230Sdonn
209540230Sdonn if(lt==TYERROR || rt==TYERROR)
209640230Sdonn goto error1;
209740230Sdonn
209840230Sdonn if(lt==TYUNKNOWN)
209940230Sdonn return(TYUNKNOWN);
210040230Sdonn if(rt==TYUNKNOWN)
210140230Sdonn if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL &&
210240230Sdonn op!=OPCCALL && op!=OPADDR && op!=OPPAREN)
210340230Sdonn return(TYUNKNOWN);
210440230Sdonn
210540230Sdonn switch(op)
210640230Sdonn {
210740230Sdonn case OPPLUS:
210840230Sdonn case OPMINUS:
210940230Sdonn case OPSTAR:
211040230Sdonn case OPSLASH:
211140230Sdonn case OPPOWER:
211240230Sdonn case OPMOD:
211340230Sdonn if( ISNUMERIC(lt) && ISNUMERIC(rt) )
211440230Sdonn return( maxtype(lt, rt) );
211540230Sdonn ERR("nonarithmetic operand of arithmetic operator")
211640230Sdonn
211740230Sdonn case OPNEG:
211840230Sdonn if( ISNUMERIC(lt) )
211940230Sdonn return(lt);
212040230Sdonn ERR("nonarithmetic operand of negation")
212140230Sdonn
212240230Sdonn case OPNOT:
212340230Sdonn if(lt == TYLOGICAL)
212440230Sdonn return(TYLOGICAL);
212540230Sdonn ERR("NOT of nonlogical")
212640230Sdonn
212740230Sdonn case OPAND:
212840230Sdonn case OPOR:
212940230Sdonn case OPEQV:
213040230Sdonn case OPNEQV:
213140230Sdonn if(lt==TYLOGICAL && rt==TYLOGICAL)
213240230Sdonn return(TYLOGICAL);
213340230Sdonn ERR("nonlogical operand of logical operator")
213440230Sdonn
213540230Sdonn case OPLT:
213640230Sdonn case OPGT:
213740230Sdonn case OPLE:
213840230Sdonn case OPGE:
213940230Sdonn case OPEQ:
214040230Sdonn case OPNE:
214140230Sdonn if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
214240230Sdonn {
214340230Sdonn if(lt != rt)
214440230Sdonn ERR("illegal comparison")
214540230Sdonn }
214640230Sdonn
214740230Sdonn else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
214840230Sdonn {
214940230Sdonn if(op!=OPEQ && op!=OPNE)
215040230Sdonn ERR("order comparison of complex data")
215140230Sdonn }
215240230Sdonn
215340230Sdonn else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
215440230Sdonn ERR("comparison of nonarithmetic data")
215540230Sdonn return(TYLOGICAL);
215640230Sdonn
215740230Sdonn case OPCONCAT:
215840230Sdonn if(lt==TYCHAR && rt==TYCHAR)
215940230Sdonn return(TYCHAR);
216040230Sdonn ERR("concatenation of nonchar data")
216140230Sdonn
216240230Sdonn case OPCALL:
216340230Sdonn case OPCCALL:
216440230Sdonn return(lt);
216540230Sdonn
216640230Sdonn case OPADDR:
216740230Sdonn return(TYADDR);
216840230Sdonn
216940230Sdonn case OPCONV:
217040230Sdonn if(ISCOMPLEX(lt))
217140230Sdonn {
217240230Sdonn if(ISNUMERIC(rt))
217340230Sdonn return(lt);
217440230Sdonn ERR("impossible conversion")
217540230Sdonn }
217640230Sdonn if(rt == 0)
217740230Sdonn return(0);
217840230Sdonn if(lt==TYCHAR && ISINT(rt) )
217940230Sdonn return(TYCHAR);
218040230Sdonn case OPASSIGN:
218140230Sdonn case OPPLUSEQ:
218240230Sdonn case OPSTAREQ:
218340230Sdonn if( ISINT(lt) && rt==TYCHAR)
218440230Sdonn return(lt);
218540230Sdonn if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
218640230Sdonn if(op!=OPASSIGN || lt!=rt)
218740230Sdonn {
218840230Sdonn /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
218940230Sdonn /* debug fatal("impossible conversion. possible compiler bug"); */
219040230Sdonn ERR("impossible conversion")
219140230Sdonn }
219240230Sdonn return(lt);
219340230Sdonn
219440230Sdonn case OPMIN:
219540230Sdonn case OPMAX:
219640230Sdonn case OPBITOR:
219740230Sdonn case OPBITAND:
219840230Sdonn case OPBITXOR:
219940230Sdonn case OPBITNOT:
220040230Sdonn case OPLSHIFT:
220140230Sdonn case OPRSHIFT:
220240230Sdonn case OPPAREN:
220340230Sdonn return(lt);
220440230Sdonn
220540230Sdonn case OPCOMMA:
220640230Sdonn case OPQUEST:
220740230Sdonn case OPCOLON:
220840230Sdonn return(rt);
220940230Sdonn
221040230Sdonn default:
221140230Sdonn badop("cktype", op);
221240230Sdonn }
221340230Sdonn error: err(errs);
221440230Sdonn error1: return(TYERROR);
221540230Sdonn }
221640230Sdonn
fold(e)221740230Sdonn LOCAL expptr fold(e)
221840230Sdonn register expptr e;
221940230Sdonn {
222040230Sdonn Constp p;
222140230Sdonn register expptr lp, rp;
222240230Sdonn int etype, mtype, ltype, rtype, opcode;
222340230Sdonn int i, ll, lr;
222440230Sdonn char *q, *s;
222540230Sdonn union Constant lcon, rcon;
222640230Sdonn
222740230Sdonn opcode = e->exprblock.opcode;
222840230Sdonn etype = e->exprblock.vtype;
222940230Sdonn
223040230Sdonn lp = e->exprblock.leftp;
223140230Sdonn ltype = lp->headblock.vtype;
223240230Sdonn rp = e->exprblock.rightp;
223340230Sdonn
223440230Sdonn if(rp == 0)
223540230Sdonn switch(opcode)
223640230Sdonn {
223740230Sdonn case OPNOT:
223846303Sbostic lp->constblock.constant.ci =
223946303Sbostic ! lp->constblock.constant.ci;
224040230Sdonn return(lp);
224140230Sdonn
224240230Sdonn case OPBITNOT:
224346303Sbostic lp->constblock.constant.ci =
224446303Sbostic ~ lp->constblock.constant.ci;
224540230Sdonn return(lp);
224640230Sdonn
224740230Sdonn case OPNEG:
224840230Sdonn consnegop(lp);
224940230Sdonn return(lp);
225040230Sdonn
225140230Sdonn case OPCONV:
225240230Sdonn case OPADDR:
225340230Sdonn case OPPAREN:
225440230Sdonn return(e);
225540230Sdonn
225640230Sdonn default:
225740230Sdonn badop("fold", opcode);
225840230Sdonn }
225940230Sdonn
226040230Sdonn rtype = rp->headblock.vtype;
226140230Sdonn
226240230Sdonn p = ALLOC(Constblock);
226340230Sdonn p->tag = TCONST;
226440230Sdonn p->vtype = etype;
226540230Sdonn p->vleng = e->exprblock.vleng;
226640230Sdonn
226740230Sdonn switch(opcode)
226840230Sdonn {
226940230Sdonn case OPCOMMA:
227040230Sdonn case OPQUEST:
227140230Sdonn case OPCOLON:
227240230Sdonn return(e);
227340230Sdonn
227440230Sdonn case OPAND:
227546303Sbostic p->constant.ci = lp->constblock.constant.ci &&
227646303Sbostic rp->constblock.constant.ci;
227740230Sdonn break;
227840230Sdonn
227940230Sdonn case OPOR:
228046303Sbostic p->constant.ci = lp->constblock.constant.ci ||
228146303Sbostic rp->constblock.constant.ci;
228240230Sdonn break;
228340230Sdonn
228440230Sdonn case OPEQV:
228546303Sbostic p->constant.ci = lp->constblock.constant.ci ==
228646303Sbostic rp->constblock.constant.ci;
228740230Sdonn break;
228840230Sdonn
228940230Sdonn case OPNEQV:
229046303Sbostic p->constant.ci = lp->constblock.constant.ci !=
229146303Sbostic rp->constblock.constant.ci;
229240230Sdonn break;
229340230Sdonn
229440230Sdonn case OPBITAND:
229546303Sbostic p->constant.ci = lp->constblock.constant.ci &
229646303Sbostic rp->constblock.constant.ci;
229740230Sdonn break;
229840230Sdonn
229940230Sdonn case OPBITOR:
230046303Sbostic p->constant.ci = lp->constblock.constant.ci |
230146303Sbostic rp->constblock.constant.ci;
230240230Sdonn break;
230340230Sdonn
230440230Sdonn case OPBITXOR:
230546303Sbostic p->constant.ci = lp->constblock.constant.ci ^
230646303Sbostic rp->constblock.constant.ci;
230740230Sdonn break;
230840230Sdonn
230940230Sdonn case OPLSHIFT:
231046303Sbostic p->constant.ci = lp->constblock.constant.ci <<
231146303Sbostic rp->constblock.constant.ci;
231240230Sdonn break;
231340230Sdonn
231440230Sdonn case OPRSHIFT:
231546303Sbostic p->constant.ci = lp->constblock.constant.ci >>
231646303Sbostic rp->constblock.constant.ci;
231740230Sdonn break;
231840230Sdonn
231940230Sdonn case OPCONCAT:
232046303Sbostic ll = lp->constblock.vleng->constblock.constant.ci;
232146303Sbostic lr = rp->constblock.vleng->constblock.constant.ci;
232246303Sbostic p->constant.ccp = q = (char *) ckalloc(ll+lr);
232340230Sdonn p->vleng = ICON(ll+lr);
232446303Sbostic s = lp->constblock.constant.ccp;
232540230Sdonn for(i = 0 ; i < ll ; ++i)
232640230Sdonn *q++ = *s++;
232746303Sbostic s = rp->constblock.constant.ccp;
232840230Sdonn for(i = 0; i < lr; ++i)
232940230Sdonn *q++ = *s++;
233040230Sdonn break;
233140230Sdonn
233240230Sdonn
233340230Sdonn case OPPOWER:
233440230Sdonn if( ! ISINT(rtype) )
233540230Sdonn return(e);
233646303Sbostic conspower(&(p->constant), lp, rp->constblock.constant.ci);
233740230Sdonn break;
233840230Sdonn
233940230Sdonn
234040230Sdonn default:
234140230Sdonn if(ltype == TYCHAR)
234240230Sdonn {
234346303Sbostic lcon.ci = cmpstr(lp->constblock.constant.ccp,
234446303Sbostic rp->constblock.constant.ccp,
234546303Sbostic lp->constblock.vleng->constblock.constant.ci,
234646303Sbostic rp->constblock.vleng->constblock.constant.ci);
234740230Sdonn rcon.ci = 0;
234840230Sdonn mtype = tyint;
234940230Sdonn }
235040230Sdonn else {
235140230Sdonn mtype = maxtype(ltype, rtype);
235246303Sbostic consconv(mtype, &lcon, ltype,
235346303Sbostic &(lp->constblock.constant) );
235446303Sbostic consconv(mtype, &rcon, rtype,
235546303Sbostic &(rp->constblock.constant) );
235640230Sdonn }
235746303Sbostic consbinop(opcode, mtype, &(p->constant), &lcon, &rcon);
235840230Sdonn break;
235940230Sdonn }
236040230Sdonn
236140230Sdonn frexpr(e);
236240230Sdonn return( (expptr) p );
236340230Sdonn }
236440230Sdonn
236540230Sdonn
236640230Sdonn
236740230Sdonn /* assign constant l = r , doing coercion */
236840230Sdonn
consconv(lt,lv,rt,rv)236940230Sdonn consconv(lt, lv, rt, rv)
237040230Sdonn int lt, rt;
237140230Sdonn register union Constant *lv, *rv;
237240230Sdonn {
237340230Sdonn switch(lt)
237440230Sdonn {
237540230Sdonn case TYCHAR:
237640230Sdonn *(lv->ccp = (char *) ckalloc(1)) = rv->ci;
237740230Sdonn break;
237840230Sdonn
237940230Sdonn case TYSHORT:
238040230Sdonn case TYLONG:
238140230Sdonn if(rt == TYCHAR)
238240230Sdonn lv->ci = rv->ccp[0];
238340230Sdonn else if( ISINT(rt) )
238440230Sdonn lv->ci = rv->ci;
238540230Sdonn else lv->ci = rv->cd[0];
238640230Sdonn break;
238740230Sdonn
238840230Sdonn case TYCOMPLEX:
238940230Sdonn case TYDCOMPLEX:
239040230Sdonn switch(rt)
239140230Sdonn {
239240230Sdonn case TYSHORT:
239340230Sdonn case TYLONG:
239440230Sdonn /* fall through and do real assignment of
239540230Sdonn first element
239640230Sdonn */
239740230Sdonn case TYREAL:
239840230Sdonn case TYDREAL:
239940230Sdonn lv->cd[1] = 0; break;
240040230Sdonn case TYCOMPLEX:
240140230Sdonn case TYDCOMPLEX:
240240230Sdonn lv->cd[1] = rv->cd[1]; break;
240340230Sdonn }
240440230Sdonn
240540230Sdonn case TYREAL:
240640230Sdonn case TYDREAL:
240740230Sdonn if( ISINT(rt) )
240840230Sdonn lv->cd[0] = rv->ci;
240940230Sdonn else lv->cd[0] = rv->cd[0];
241040230Sdonn if( lt == TYREAL)
241140230Sdonn {
241240230Sdonn float f = lv->cd[0];
241340230Sdonn lv->cd[0] = f;
241440230Sdonn }
241540230Sdonn break;
241640230Sdonn
241740230Sdonn case TYLOGICAL:
241840230Sdonn lv->ci = rv->ci;
241940230Sdonn break;
242040230Sdonn }
242140230Sdonn }
242240230Sdonn
242340230Sdonn
242440230Sdonn
consnegop(p)242540230Sdonn consnegop(p)
242640230Sdonn register Constp p;
242740230Sdonn {
242840230Sdonn switch(p->vtype)
242940230Sdonn {
243040230Sdonn case TYSHORT:
243140230Sdonn case TYLONG:
243246303Sbostic p->constant.ci = - p->constant.ci;
243340230Sdonn break;
243440230Sdonn
243540230Sdonn case TYCOMPLEX:
243640230Sdonn case TYDCOMPLEX:
243746303Sbostic p->constant.cd[1] = - p->constant.cd[1];
243840230Sdonn /* fall through and do the real parts */
243940230Sdonn case TYREAL:
244040230Sdonn case TYDREAL:
244146303Sbostic p->constant.cd[0] = - p->constant.cd[0];
244240230Sdonn break;
244340230Sdonn default:
244440230Sdonn badtype("consnegop", p->vtype);
244540230Sdonn }
244640230Sdonn }
244740230Sdonn
244840230Sdonn
244940230Sdonn
conspower(powp,ap,n)245040230Sdonn LOCAL conspower(powp, ap, n)
245140230Sdonn register union Constant *powp;
245240230Sdonn Constp ap;
245340230Sdonn ftnint n;
245440230Sdonn {
245540230Sdonn register int type;
245640230Sdonn union Constant x;
245740230Sdonn
245840230Sdonn switch(type = ap->vtype) /* pow = 1 */
245940230Sdonn {
246040230Sdonn case TYSHORT:
246140230Sdonn case TYLONG:
246240230Sdonn powp->ci = 1;
246340230Sdonn break;
246440230Sdonn case TYCOMPLEX:
246540230Sdonn case TYDCOMPLEX:
246640230Sdonn powp->cd[1] = 0;
246740230Sdonn case TYREAL:
246840230Sdonn case TYDREAL:
246940230Sdonn powp->cd[0] = 1;
247040230Sdonn break;
247140230Sdonn default:
247240230Sdonn badtype("conspower", type);
247340230Sdonn }
247440230Sdonn
247540230Sdonn if(n == 0)
247640230Sdonn return;
247740230Sdonn if(n < 0)
247840230Sdonn {
247940230Sdonn if( ISINT(type) )
248040230Sdonn {
248146303Sbostic if (ap->constant.ci == 0)
248240230Sdonn err("zero raised to a negative power");
248346303Sbostic else if (ap->constant.ci == 1)
248440230Sdonn return;
248546303Sbostic else if (ap->constant.ci == -1)
248640230Sdonn {
248740230Sdonn if (n < -2)
248840230Sdonn n = n + 2;
248940230Sdonn n = -n;
249040230Sdonn if (n % 2 == 1)
249140230Sdonn powp->ci = -1;
249240230Sdonn }
249340230Sdonn else
249440230Sdonn powp->ci = 0;
249540230Sdonn return;
249640230Sdonn }
249740230Sdonn n = - n;
249846303Sbostic consbinop(OPSLASH, type, &x, powp, &(ap->constant));
249940230Sdonn }
250040230Sdonn else
250146303Sbostic consbinop(OPSTAR, type, &x, powp, &(ap->constant));
250240230Sdonn
250340230Sdonn for( ; ; )
250440230Sdonn {
250540230Sdonn if(n & 01)
250640230Sdonn consbinop(OPSTAR, type, powp, powp, &x);
250740230Sdonn if(n >>= 1)
250840230Sdonn consbinop(OPSTAR, type, &x, &x, &x);
250940230Sdonn else
251040230Sdonn break;
251140230Sdonn }
251240230Sdonn }
251340230Sdonn
251440230Sdonn
251540230Sdonn
251640230Sdonn /* do constant operation cp = a op b */
251740230Sdonn
251840230Sdonn
consbinop(opcode,type,cp,ap,bp)251940230Sdonn LOCAL consbinop(opcode, type, cp, ap, bp)
252040230Sdonn int opcode, type;
252140230Sdonn register union Constant *ap, *bp, *cp;
252240230Sdonn {
252340230Sdonn int k;
252440230Sdonn double temp;
252540230Sdonn
252640230Sdonn switch(opcode)
252740230Sdonn {
252840230Sdonn case OPPLUS:
252940230Sdonn switch(type)
253040230Sdonn {
253140230Sdonn case TYSHORT:
253240230Sdonn case TYLONG:
253340230Sdonn cp->ci = ap->ci + bp->ci;
253440230Sdonn break;
253540230Sdonn case TYCOMPLEX:
253640230Sdonn case TYDCOMPLEX:
253740230Sdonn cp->cd[1] = ap->cd[1] + bp->cd[1];
253840230Sdonn case TYREAL:
253940230Sdonn case TYDREAL:
254040230Sdonn cp->cd[0] = ap->cd[0] + bp->cd[0];
254140230Sdonn break;
254240230Sdonn }
254340230Sdonn break;
254440230Sdonn
254540230Sdonn case OPMINUS:
254640230Sdonn switch(type)
254740230Sdonn {
254840230Sdonn case TYSHORT:
254940230Sdonn case TYLONG:
255040230Sdonn cp->ci = ap->ci - bp->ci;
255140230Sdonn break;
255240230Sdonn case TYCOMPLEX:
255340230Sdonn case TYDCOMPLEX:
255440230Sdonn cp->cd[1] = ap->cd[1] - bp->cd[1];
255540230Sdonn case TYREAL:
255640230Sdonn case TYDREAL:
255740230Sdonn cp->cd[0] = ap->cd[0] - bp->cd[0];
255840230Sdonn break;
255940230Sdonn }
256040230Sdonn break;
256140230Sdonn
256240230Sdonn case OPSTAR:
256340230Sdonn switch(type)
256440230Sdonn {
256540230Sdonn case TYSHORT:
256640230Sdonn case TYLONG:
256740230Sdonn cp->ci = ap->ci * bp->ci;
256840230Sdonn break;
256940230Sdonn case TYREAL:
257040230Sdonn case TYDREAL:
257140230Sdonn cp->cd[0] = ap->cd[0] * bp->cd[0];
257240230Sdonn break;
257340230Sdonn case TYCOMPLEX:
257440230Sdonn case TYDCOMPLEX:
257540230Sdonn temp = ap->cd[0] * bp->cd[0] -
257640230Sdonn ap->cd[1] * bp->cd[1] ;
257740230Sdonn cp->cd[1] = ap->cd[0] * bp->cd[1] +
257840230Sdonn ap->cd[1] * bp->cd[0] ;
257940230Sdonn cp->cd[0] = temp;
258040230Sdonn break;
258140230Sdonn }
258240230Sdonn break;
258340230Sdonn case OPSLASH:
258440230Sdonn switch(type)
258540230Sdonn {
258640230Sdonn case TYSHORT:
258740230Sdonn case TYLONG:
258840230Sdonn cp->ci = ap->ci / bp->ci;
258940230Sdonn break;
259040230Sdonn case TYREAL:
259140230Sdonn case TYDREAL:
259240230Sdonn cp->cd[0] = ap->cd[0] / bp->cd[0];
259340230Sdonn break;
259440230Sdonn case TYCOMPLEX:
259540230Sdonn case TYDCOMPLEX:
259640230Sdonn zdiv(cp,ap,bp);
259740230Sdonn break;
259840230Sdonn }
259940230Sdonn break;
260040230Sdonn
260140230Sdonn case OPMOD:
260240230Sdonn if( ISINT(type) )
260340230Sdonn {
260440230Sdonn cp->ci = ap->ci % bp->ci;
260540230Sdonn break;
260640230Sdonn }
260740230Sdonn else
260840230Sdonn fatal("inline mod of noninteger");
260940230Sdonn
261040230Sdonn default: /* relational ops */
261140230Sdonn switch(type)
261240230Sdonn {
261340230Sdonn case TYSHORT:
261440230Sdonn case TYLONG:
261540230Sdonn if(ap->ci < bp->ci)
261640230Sdonn k = -1;
261740230Sdonn else if(ap->ci == bp->ci)
261840230Sdonn k = 0;
261940230Sdonn else k = 1;
262040230Sdonn break;
262140230Sdonn case TYREAL:
262240230Sdonn case TYDREAL:
262340230Sdonn if(ap->cd[0] < bp->cd[0])
262440230Sdonn k = -1;
262540230Sdonn else if(ap->cd[0] == bp->cd[0])
262640230Sdonn k = 0;
262740230Sdonn else k = 1;
262840230Sdonn break;
262940230Sdonn case TYCOMPLEX:
263040230Sdonn case TYDCOMPLEX:
263140230Sdonn if(ap->cd[0] == bp->cd[0] &&
263240230Sdonn ap->cd[1] == bp->cd[1] )
263340230Sdonn k = 0;
263440230Sdonn else k = 1;
263540230Sdonn break;
263640230Sdonn }
263740230Sdonn
263840230Sdonn switch(opcode)
263940230Sdonn {
264040230Sdonn case OPEQ:
264140230Sdonn cp->ci = (k == 0);
264240230Sdonn break;
264340230Sdonn case OPNE:
264440230Sdonn cp->ci = (k != 0);
264540230Sdonn break;
264640230Sdonn case OPGT:
264740230Sdonn cp->ci = (k == 1);
264840230Sdonn break;
264940230Sdonn case OPLT:
265040230Sdonn cp->ci = (k == -1);
265140230Sdonn break;
265240230Sdonn case OPGE:
265340230Sdonn cp->ci = (k >= 0);
265440230Sdonn break;
265540230Sdonn case OPLE:
265640230Sdonn cp->ci = (k <= 0);
265740230Sdonn break;
265840230Sdonn default:
265940230Sdonn badop ("consbinop", opcode);
266040230Sdonn }
266140230Sdonn break;
266240230Sdonn }
266340230Sdonn }
266440230Sdonn
266540230Sdonn
266640230Sdonn
266740230Sdonn
conssgn(p)266840230Sdonn conssgn(p)
266940230Sdonn register expptr p;
267040230Sdonn {
267140230Sdonn if( ! ISCONST(p) )
267240230Sdonn fatal( "sgn(nonconstant)" );
267340230Sdonn
267440230Sdonn switch(p->headblock.vtype)
267540230Sdonn {
267640230Sdonn case TYSHORT:
267740230Sdonn case TYLONG:
267846303Sbostic if(p->constblock.constant.ci > 0) return(1);
267946303Sbostic if(p->constblock.constant.ci < 0) return(-1);
268040230Sdonn return(0);
268140230Sdonn
268240230Sdonn case TYREAL:
268340230Sdonn case TYDREAL:
268446303Sbostic if(p->constblock.constant.cd[0] > 0) return(1);
268546303Sbostic if(p->constblock.constant.cd[0] < 0) return(-1);
268640230Sdonn return(0);
268740230Sdonn
268840230Sdonn case TYCOMPLEX:
268940230Sdonn case TYDCOMPLEX:
269046303Sbostic return(p->constblock.constant.cd[0]!=0 ||
269146303Sbostic p->constblock.constant.cd[1]!=0);
269240230Sdonn
269340230Sdonn default:
269440230Sdonn badtype( "conssgn", p->constblock.vtype);
269540230Sdonn }
269640230Sdonn /* NOTREACHED */
269740230Sdonn }
269840230Sdonn
269940230Sdonn char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
270040230Sdonn
270140230Sdonn
mkpower(p)270240230Sdonn LOCAL expptr mkpower(p)
270340230Sdonn register expptr p;
270440230Sdonn {
270540230Sdonn register expptr q, lp, rp;
270640230Sdonn int ltype, rtype, mtype;
270740230Sdonn
270840230Sdonn lp = p->exprblock.leftp;
270940230Sdonn rp = p->exprblock.rightp;
271040230Sdonn ltype = lp->headblock.vtype;
271140230Sdonn rtype = rp->headblock.vtype;
271240230Sdonn
271340230Sdonn if(ISICON(rp))
271440230Sdonn {
271546303Sbostic if(rp->constblock.constant.ci == 0)
271640230Sdonn {
271740230Sdonn frexpr(p);
271840230Sdonn if( ISINT(ltype) )
271940230Sdonn return( ICON(1) );
272040230Sdonn else
272140230Sdonn {
272240230Sdonn expptr pp;
272340230Sdonn pp = mkconv(ltype, ICON(1));
272440230Sdonn return( pp );
272540230Sdonn }
272640230Sdonn }
272746303Sbostic if(rp->constblock.constant.ci < 0)
272840230Sdonn {
272940230Sdonn if( ISINT(ltype) )
273040230Sdonn {
273140230Sdonn frexpr(p);
273240230Sdonn err("integer**negative");
273340230Sdonn return( errnode() );
273440230Sdonn }
273546303Sbostic rp->constblock.constant.ci = - rp->constblock.constant.ci;
273640230Sdonn p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));
273740230Sdonn }
273846303Sbostic if(rp->constblock.constant.ci == 1)
273940230Sdonn {
274040230Sdonn frexpr(rp);
274140230Sdonn free( (charptr) p );
274240230Sdonn return(lp);
274340230Sdonn }
274440230Sdonn
274540230Sdonn if( ONEOF(ltype, MSKINT|MSKREAL) )
274640230Sdonn {
274740230Sdonn p->exprblock.vtype = ltype;
274840230Sdonn return(p);
274940230Sdonn }
275040230Sdonn }
275140230Sdonn if( ISINT(rtype) )
275240230Sdonn {
275340230Sdonn if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
275440230Sdonn q = call2(TYSHORT, "pow_hh", lp, rp);
275540230Sdonn else {
275640230Sdonn if(ltype == TYSHORT)
275740230Sdonn {
275840230Sdonn ltype = TYLONG;
275940230Sdonn lp = mkconv(TYLONG,lp);
276040230Sdonn }
276140230Sdonn q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
276240230Sdonn }
276340230Sdonn }
276440230Sdonn else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
276540230Sdonn q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp));
276640230Sdonn else {
276740230Sdonn q = call2(TYDCOMPLEX, "pow_zz",
276840230Sdonn mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
276940230Sdonn if(mtype == TYCOMPLEX)
277040230Sdonn q = mkconv(TYCOMPLEX, q);
277140230Sdonn }
277240230Sdonn free( (charptr) p );
277340230Sdonn return(q);
277440230Sdonn }
277540230Sdonn
277640230Sdonn
277740230Sdonn
277840230Sdonn /* Complex Division. Same code as in Runtime Library
277940230Sdonn */
278040230Sdonn
278140230Sdonn struct dcomplex { double dreal, dimag; };
278240230Sdonn
278340230Sdonn
zdiv(c,a,b)278440230Sdonn LOCAL zdiv(c, a, b)
278540230Sdonn register struct dcomplex *a, *b, *c;
278640230Sdonn {
278740230Sdonn double ratio, den;
278840230Sdonn double abr, abi;
278940230Sdonn
279040230Sdonn if( (abr = b->dreal) < 0.)
279140230Sdonn abr = - abr;
279240230Sdonn if( (abi = b->dimag) < 0.)
279340230Sdonn abi = - abi;
279440230Sdonn if( abr <= abi )
279540230Sdonn {
279640230Sdonn if(abi == 0)
279740230Sdonn fatal("complex division by zero");
279840230Sdonn ratio = b->dreal / b->dimag ;
279940230Sdonn den = b->dimag * (1 + ratio*ratio);
280040230Sdonn c->dreal = (a->dreal*ratio + a->dimag) / den;
280140230Sdonn c->dimag = (a->dimag*ratio - a->dreal) / den;
280240230Sdonn }
280340230Sdonn
280440230Sdonn else
280540230Sdonn {
280640230Sdonn ratio = b->dimag / b->dreal ;
280740230Sdonn den = b->dreal * (1 + ratio*ratio);
280840230Sdonn c->dreal = (a->dreal + a->dimag*ratio) / den;
280940230Sdonn c->dimag = (a->dimag - a->dreal*ratio) / den;
281040230Sdonn }
281140230Sdonn
281240230Sdonn }
281340230Sdonn
oftwo(e)281440230Sdonn expptr oftwo(e)
281540230Sdonn expptr e;
281640230Sdonn {
281740230Sdonn int val,res;
281840230Sdonn
281940230Sdonn if (! ISCONST (e))
282040230Sdonn return (0);
282140230Sdonn
282246303Sbostic val = e->constblock.constant.ci;
282340230Sdonn switch (val)
282440230Sdonn {
282540230Sdonn case 2: res = 1; break;
282640230Sdonn case 4: res = 2; break;
282740230Sdonn case 8: res = 3; break;
282840230Sdonn case 16: res = 4; break;
282940230Sdonn case 32: res = 5; break;
283040230Sdonn case 64: res = 6; break;
283140230Sdonn case 128: res = 7; break;
283240230Sdonn case 256: res = 8; break;
283340230Sdonn default: return (0);
283440230Sdonn }
283540230Sdonn return (ICON (res));
283640230Sdonn }
2837