|
|
1.1 root 1: /*
2: * Copyright (c) 1980 Regents of the University of California.
3: * All rights reserved. The Berkeley software License Agreement
4: * specifies the terms and conditions for redistribution.
5: */
6:
7: #ifndef lint
8: static char *sccsid[] = "@(#)expr.c 5.8 (Berkeley) 5/9/86";
9: #endif not lint
10:
11: /*
12: * expr.c
13: *
14: * Routines for handling expressions, f77 compiler pass 1.
15: *
16: * University of Utah CS Dept modification history:
17: *
18: * $Log: expr.c,v $
19: * Revision 5.13 86/05/07 18:54:23 donn
20: * Adjusted the warning for OPEQ with logical operands -- this is now printed
21: * in mkexpr since cktype can be called several times on the same operands
22: * (argh -- how slow can this compiler get?!).
23: *
24: * Revision 5.12 86/05/07 17:40:54 donn
25: * Make the lengths of expr nodes be copied by cpexpr and freed by frexpr.
26: *
27: * Revision 5.11 86/05/07 16:57:17 donn
28: * Logical data is supposed to be compared using .eqv. and .neqv., but we
29: * will support .eq. and .ne. with a warning. Other relational operators
30: * now provoke errors when used with logical operands.
31: *
32: * Revision 5.10 86/04/26 13:24:30 donn
33: * Someone forgot about comparisons of logical constants in consbinop() --
34: * the results of such tests were garbage.
35: *
36: * Revision 5.9 86/02/20 23:38:31 donn
37: * Fix memory management problem with reordering of array dimension and
38: * substring code in mklhs().
39: *
40: * Revision 5.8 85/12/20 21:37:58 donn
41: * Fix bug in mklhs() that caused the 'first character' substring parameter
42: * to be evaluated twice.
43: *
44: * Revision 5.7 85/12/20 19:42:05 donn
45: * Be more specfic -- name the offending subroutine when it's used as a
46: * function.
47: *
48: * Revision 5.6 85/12/19 20:08:12 donn
49: * Don't optimize first/last char values when they contain function calls
50: * or array references.
51: *
52: * Revision 5.5 85/12/19 00:35:22 donn
53: * Lots of changes for handling hardware errors which can crop up when
54: * evaluating constant expressions.
55: *
56: * Revision 5.4 85/11/25 00:23:53 donn
57: * 4.3 beta
58: *
59: * Revision 5.3 85/08/10 05:48:16 donn
60: * Fixed another of my goofs in the substring parameter conversion code.
61: *
62: * Revision 5.2 85/08/10 04:13:51 donn
63: * Jerry Berkman's change to call pow() directly rather than indirectly
64: * through pow_dd, in mkpower().
65: *
66: * Revision 5.1 85/08/10 03:44:19 donn
67: * 4.3 alpha
68: *
69: * Revision 3.16 85/06/21 16:38:09 donn
70: * The fix to mkprim() didn't handle null substring parameters (sigh).
71: *
72: * Revision 3.15 85/06/04 04:37:03 donn
73: * Changed mkprim() to force substring parameters to be integral types.
74: *
75: * Revision 3.14 85/06/04 03:41:52 donn
76: * Change impldcl() to handle functions of type 'undefined'.
77: *
78: * Revision 3.13 85/05/06 23:14:55 donn
79: * Changed mkconv() so that it calls mkaltemp() instead of mktemp() to get
80: * a temporary when converting character strings to integers; previously we
81: * were having problems because mkconv() was called after tempalloc().
82: *
83: * Revision 3.12 85/03/18 08:07:47 donn
84: * Fixes to help out with short integers -- if integers are by default short,
85: * then so are constants; and if addresses can't be stored in shorts, complain.
86: *
87: * Revision 3.11 85/03/16 22:31:27 donn
88: * Added hack to mkconv() to allow character values of length > 1 to be
89: * converted to numeric types, for Helge Skrivervik. Note that this does
90: * not affect use of the intrinsic ichar() conversion.
91: *
92: * Revision 3.10 85/01/15 21:06:47 donn
93: * Changed mkconv() to comment on implicit conversions; added intrconv() for
94: * use with explicit conversions by intrinsic functions.
95: *
96: * Revision 3.9 85/01/11 21:05:49 donn
97: * Added changes to implement SAVE statements.
98: *
99: * Revision 3.8 84/12/17 02:21:06 donn
100: * Added a test to prevent constant folding from being done on expressions
101: * whose type is not known at that point in mkexpr().
102: *
103: * Revision 3.7 84/12/11 21:14:17 donn
104: * Removed obnoxious 'excess precision' warning.
105: *
106: * Revision 3.6 84/11/23 01:00:36 donn
107: * Added code to trim excess precision from single-precision constants, and
108: * to warn the user when this occurs.
109: *
110: * Revision 3.5 84/11/23 00:10:39 donn
111: * Changed stfcall() to remark on argument type clashes in 'calls' to
112: * statement functions.
113: *
114: * Revision 3.4 84/11/22 21:21:17 donn
115: * Fixed bug in fix to mkexpr() that caused IMPLICIT to affect intrinsics.
116: *
117: * Revision 3.3 84/11/12 18:26:14 donn
118: * Shuffled some code around so that the compiler remembers to free some vleng
119: * structures which used to just sit around.
120: *
121: * Revision 3.2 84/10/16 19:24:15 donn
122: * Fix for Peter Montgomery's bug with -C and invalid subscripts -- prevent
123: * core dumps by replacing bad subscripts with good ones.
124: *
125: * Revision 3.1 84/10/13 01:31:32 donn
126: * Merged Jerry Berkman's version into mine.
127: *
128: * Revision 2.7 84/09/27 15:42:52 donn
129: * The last fix for multiplying undeclared variables by 0 isn't sufficient,
130: * since the type of the 0 may not be the (implicit) type of the variable.
131: * I added a hack to check the implicit type of implicitly declared
132: * variables...
133: *
134: * Revision 2.6 84/09/14 19:34:03 donn
135: * Problem noted by Mike Vevea -- mkexpr will sometimes attempt to convert
136: * 0 to type UNKNOWN, which is illegal. Fix is to use native type instead.
137: * Not sure how correct (or important) this is...
138: *
139: * Revision 2.5 84/08/05 23:05:27 donn
140: * Added fixes to prevent fixexpr() from slicing and dicing complex conversions
141: * with two operands.
142: *
143: * Revision 2.4 84/08/05 17:34:48 donn
144: * Added an optimization to mklhs() to detect substrings of the form ch(i:i)
145: * and assign constant length 1 to them.
146: *
147: * Revision 2.3 84/07/19 19:38:33 donn
148: * Added a typecast to the last fix. Somehow I missed it the first time...
149: *
150: * Revision 2.2 84/07/19 17:19:57 donn
151: * Caused OPPAREN expressions to inherit the length of their operands, so
152: * that parenthesized character expressions work correctly.
153: *
154: * Revision 2.1 84/07/19 12:03:02 donn
155: * Changed comment headers for UofU.
156: *
157: * Revision 1.2 84/04/06 20:12:17 donn
158: * Fixed bug which caused programs with mixed-type multiplications involving
159: * the constant 0 to choke the compiler.
160: *
161: */
162:
163: #include "defs.h"
164:
165:
166: /* little routines to create constant blocks */
167:
168: Constp mkconst(t)
169: register int t;
170: {
171: register Constp p;
172:
173: p = ALLOC(Constblock);
174: p->tag = TCONST;
175: p->vtype = t;
176: return(p);
177: }
178:
179:
180: expptr mklogcon(l)
181: register int l;
182: {
183: register Constp p;
184:
185: p = mkconst(TYLOGICAL);
186: p->const.ci = l;
187: return( (expptr) p );
188: }
189:
190:
191:
192: expptr mkintcon(l)
193: ftnint l;
194: {
195: register Constp p;
196: int usetype;
197:
198: if(tyint == TYSHORT)
199: {
200: short s = l;
201: if(l != s)
202: usetype = TYLONG;
203: else
204: usetype = TYSHORT;
205: }
206: else
207: usetype = tyint;
208: p = mkconst(usetype);
209: p->const.ci = l;
210: return( (expptr) p );
211: }
212:
213:
214:
215: expptr mkaddcon(l)
216: register int l;
217: {
218: register Constp p;
219:
220: p = mkconst(TYADDR);
221: p->const.ci = l;
222: return( (expptr) p );
223: }
224:
225:
226:
227: expptr mkrealcon(t, d)
228: register int t;
229: double d;
230: {
231: register Constp p;
232:
233: if(t == TYREAL)
234: {
235: float f = d;
236: if(f != d)
237: {
238: #ifdef notdef
239: warn("excess precision in real constant lost");
240: #endif notdef
241: d = f;
242: }
243: }
244: p = mkconst(t);
245: p->const.cd[0] = d;
246: return( (expptr) p );
247: }
248:
249:
250: expptr mkbitcon(shift, leng, s)
251: int shift;
252: register int leng;
253: register char *s;
254: {
255: Constp p;
256: register int i, j, k;
257: register char *bp;
258: int size;
259:
260: size = (shift*leng + BYTESIZE -1)/BYTESIZE;
261: bp = (char *) ckalloc(size);
262:
263: i = 0;
264:
265: #if (TARGET == PDP11 || TARGET == VAX)
266: j = 0;
267: #else
268: j = size;
269: #endif
270:
271: k = 0;
272:
273: while (leng > 0)
274: {
275: k |= (hextoi(s[--leng]) << i);
276: i += shift;
277: if (i >= BYTESIZE)
278: {
279: #if (TARGET == PDP11 || TARGET == VAX)
280: bp[j++] = k & MAXBYTE;
281: #else
282: bp[--j] = k & MAXBYTE;
283: #endif
284: k = k >> BYTESIZE;
285: i -= BYTESIZE;
286: }
287: }
288:
289: if (k != 0)
290: #if (TARGET == PDP11 || TARGET == VAX)
291: bp[j++] = k;
292: #else
293: bp[--j] = k;
294: #endif
295:
296: p = mkconst(TYBITSTR);
297: p->vleng = ICON(size);
298: p->const.ccp = bp;
299:
300: return ((expptr) p);
301: }
302:
303:
304:
305: expptr mkstrcon(l,v)
306: int l;
307: register char *v;
308: {
309: register Constp p;
310: register char *s;
311:
312: p = mkconst(TYCHAR);
313: p->vleng = ICON(l);
314: p->const.ccp = s = (char *) ckalloc(l);
315: while(--l >= 0)
316: *s++ = *v++;
317: return( (expptr) p );
318: }
319:
320:
321: expptr mkcxcon(realp,imagp)
322: register expptr realp, imagp;
323: {
324: int rtype, itype;
325: register Constp p;
326:
327: rtype = realp->headblock.vtype;
328: itype = imagp->headblock.vtype;
329:
330: if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
331: {
332: p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX);
333: if( ISINT(rtype) )
334: p->const.cd[0] = realp->constblock.const.ci;
335: else p->const.cd[0] = realp->constblock.const.cd[0];
336: if( ISINT(itype) )
337: p->const.cd[1] = imagp->constblock.const.ci;
338: else p->const.cd[1] = imagp->constblock.const.cd[0];
339: }
340: else
341: {
342: err("invalid complex constant");
343: p = (Constp) errnode();
344: }
345:
346: frexpr(realp);
347: frexpr(imagp);
348: return( (expptr) p );
349: }
350:
351:
352: expptr errnode()
353: {
354: struct Errorblock *p;
355: p = ALLOC(Errorblock);
356: p->tag = TERROR;
357: p->vtype = TYERROR;
358: return( (expptr) p );
359: }
360:
361:
362:
363:
364:
365: expptr mkconv(t, p)
366: register int t;
367: register expptr p;
368: {
369: register expptr q;
370: Addrp r, s;
371: register int pt;
372: expptr opconv();
373:
374: if(t==TYUNKNOWN || t==TYERROR)
375: badtype("mkconv", t);
376: pt = p->headblock.vtype;
377: if(t == pt)
378: return(p);
379:
380: if( pt == TYCHAR && ISNUMERIC(t) )
381: {
382: warn("implicit conversion of character to numeric type");
383:
384: /*
385: * Ugly kluge to copy character values into numerics.
386: */
387: s = mkaltemp(t, ENULL);
388: r = (Addrp) cpexpr(s);
389: r->vtype = TYCHAR;
390: r->varleng = typesize[t];
391: r->vleng = mkintcon(r->varleng);
392: q = mkexpr(OPASSIGN, r, p);
393: q = mkexpr(OPCOMMA, q, s);
394: return(q);
395: }
396:
397: #if SZADDR > SZSHORT
398: if( pt == TYADDR && t == TYSHORT)
399: {
400: err("insufficient precision to hold address type");
401: return( errnode() );
402: }
403: #endif
404: if( pt == TYADDR && ISNUMERIC(t) )
405: warn("implicit conversion of address to numeric type");
406:
407: if( ISCONST(p) && pt!=TYADDR)
408: {
409: q = (expptr) mkconst(t);
410: consconv(t, &(q->constblock.const),
411: p->constblock.vtype, &(p->constblock.const) );
412: frexpr(p);
413: }
414: #if TARGET == PDP11
415: else if(ISINT(t) && pt==TYCHAR)
416: {
417: q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
418: if(t == TYLONG)
419: q = opconv(q, TYLONG);
420: }
421: #endif
422: else
423: q = opconv(p, t);
424:
425: if(t == TYCHAR)
426: q->constblock.vleng = ICON(1);
427: return(q);
428: }
429:
430:
431:
432: /* intrinsic conversions */
433: expptr intrconv(t, p)
434: register int t;
435: register expptr p;
436: {
437: register expptr q;
438: register int pt;
439: expptr opconv();
440:
441: if(t==TYUNKNOWN || t==TYERROR)
442: badtype("intrconv", t);
443: pt = p->headblock.vtype;
444: if(t == pt)
445: return(p);
446:
447: else if( ISCONST(p) && pt!=TYADDR)
448: {
449: q = (expptr) mkconst(t);
450: consconv(t, &(q->constblock.const),
451: p->constblock.vtype, &(p->constblock.const) );
452: frexpr(p);
453: }
454: #if TARGET == PDP11
455: else if(ISINT(t) && pt==TYCHAR)
456: {
457: q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
458: if(t == TYLONG)
459: q = opconv(q, TYLONG);
460: }
461: #endif
462: else
463: q = opconv(p, t);
464:
465: if(t == TYCHAR)
466: q->constblock.vleng = ICON(1);
467: return(q);
468: }
469:
470:
471:
472: expptr opconv(p, t)
473: expptr p;
474: int t;
475: {
476: register expptr q;
477:
478: q = mkexpr(OPCONV, p, PNULL);
479: q->headblock.vtype = t;
480: return(q);
481: }
482:
483:
484:
485: expptr addrof(p)
486: expptr p;
487: {
488: return( mkexpr(OPADDR, p, PNULL) );
489: }
490:
491:
492:
493: tagptr cpexpr(p)
494: register tagptr p;
495: {
496: register tagptr e;
497: int tag;
498: register chainp ep, pp;
499: tagptr cpblock();
500:
501: static int blksize[ ] =
502: { 0,
503: sizeof(struct Nameblock),
504: sizeof(struct Constblock),
505: sizeof(struct Exprblock),
506: sizeof(struct Addrblock),
507: sizeof(struct Tempblock),
508: sizeof(struct Primblock),
509: sizeof(struct Listblock),
510: sizeof(struct Errorblock)
511: };
512:
513: if(p == NULL)
514: return(NULL);
515:
516: if( (tag = p->tag) == TNAME)
517: return(p);
518:
519: e = cpblock( blksize[p->tag] , p);
520:
521: switch(tag)
522: {
523: case TCONST:
524: if(e->constblock.vtype == TYCHAR)
525: {
526: e->constblock.const.ccp =
527: copyn(1+strlen(e->constblock.const.ccp),
528: e->constblock.const.ccp);
529: e->constblock.vleng =
530: (expptr) cpexpr(e->constblock.vleng);
531: }
532: case TERROR:
533: break;
534:
535: case TEXPR:
536: e->exprblock.leftp = (expptr) cpexpr(p->exprblock.leftp);
537: e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
538: e->addrblock.vleng = (expptr) cpexpr(e->addrblock.vleng);
539: break;
540:
541: case TLIST:
542: if(pp = p->listblock.listp)
543: {
544: ep = e->listblock.listp =
545: mkchain( cpexpr(pp->datap), CHNULL);
546: for(pp = pp->nextp ; pp ; pp = pp->nextp)
547: ep = ep->nextp =
548: mkchain( cpexpr(pp->datap), CHNULL);
549: }
550: break;
551:
552: case TADDR:
553: e->addrblock.vleng = (expptr) cpexpr(e->addrblock.vleng);
554: e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset);
555: e->addrblock.istemp = NO;
556: break;
557:
558: case TTEMP:
559: e->tempblock.vleng = (expptr) cpexpr(e->tempblock.vleng);
560: e->tempblock.istemp = NO;
561: break;
562:
563: case TPRIM:
564: e->primblock.argsp = (struct Listblock *)
565: cpexpr(e->primblock.argsp);
566: e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp);
567: e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp);
568: break;
569:
570: default:
571: badtag("cpexpr", tag);
572: }
573:
574: return(e);
575: }
576:
577: frexpr(p)
578: register tagptr p;
579: {
580: register chainp q;
581:
582: if(p == NULL)
583: return;
584:
585: switch(p->tag)
586: {
587: case TCONST:
588: switch (p->constblock.vtype)
589: {
590: case TYBITSTR:
591: case TYCHAR:
592: case TYHOLLERITH:
593: free( (charptr) (p->constblock.const.ccp) );
594: frexpr(p->constblock.vleng);
595: }
596: break;
597:
598: case TADDR:
599: if (!optimflag && p->addrblock.istemp)
600: {
601: frtemp(p);
602: return;
603: }
604: frexpr(p->addrblock.vleng);
605: frexpr(p->addrblock.memoffset);
606: break;
607:
608: case TTEMP:
609: frexpr(p->tempblock.vleng);
610: break;
611:
612: case TERROR:
613: break;
614:
615: case TNAME:
616: return;
617:
618: case TPRIM:
619: frexpr(p->primblock.argsp);
620: frexpr(p->primblock.fcharp);
621: frexpr(p->primblock.lcharp);
622: break;
623:
624: case TEXPR:
625: frexpr(p->exprblock.leftp);
626: if(p->exprblock.rightp)
627: frexpr(p->exprblock.rightp);
628: if(p->exprblock.vleng)
629: frexpr(p->exprblock.vleng);
630: break;
631:
632: case TLIST:
633: for(q = p->listblock.listp ; q ; q = q->nextp)
634: frexpr(q->datap);
635: frchain( &(p->listblock.listp) );
636: break;
637:
638: default:
639: badtag("frexpr", p->tag);
640: }
641:
642: free( (charptr) p );
643: }
644:
645: /* fix up types in expression; replace subtrees and convert
646: names to address blocks */
647:
648: expptr fixtype(p)
649: register tagptr p;
650: {
651:
652: if(p == 0)
653: return(0);
654:
655: switch(p->tag)
656: {
657: case TCONST:
658: return( (expptr) p );
659:
660: case TADDR:
661: p->addrblock.memoffset = fixtype(p->addrblock.memoffset);
662: return( (expptr) p);
663:
664: case TTEMP:
665: return( (expptr) p);
666:
667: case TERROR:
668: return( (expptr) p);
669:
670: default:
671: badtag("fixtype", p->tag);
672:
673: case TEXPR:
674: return( fixexpr(p) );
675:
676: case TLIST:
677: return( (expptr) p );
678:
679: case TPRIM:
680: if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR)
681: {
682: if(p->primblock.namep->vtype == TYSUBR)
683: {
684: dclerr("function invocation of subroutine",
685: p->primblock.namep);
686: return( errnode() );
687: }
688: else
689: return( mkfunct(p) );
690: }
691: else return( mklhs(p) );
692: }
693: }
694:
695:
696:
697:
698:
699: /* special case tree transformations and cleanups of expression trees */
700:
701: expptr fixexpr(p)
702: register Exprp p;
703: {
704: expptr lp;
705: register expptr rp;
706: register expptr q;
707: int opcode, ltype, rtype, ptype, mtype;
708: expptr lconst, rconst;
709: expptr mkpower();
710:
711: if( ISERROR(p) )
712: return( (expptr) p );
713: else if(p->tag != TEXPR)
714: badtag("fixexpr", p->tag);
715: opcode = p->opcode;
716: if (ISCONST(p->leftp))
717: lconst = (expptr) cpexpr(p->leftp);
718: else
719: lconst = NULL;
720: if (p->rightp && ISCONST(p->rightp))
721: rconst = (expptr) cpexpr(p->rightp);
722: else
723: rconst = NULL;
724: lp = p->leftp = fixtype(p->leftp);
725: ltype = lp->headblock.vtype;
726: if(opcode==OPASSIGN && lp->tag!=TADDR && lp->tag!=TTEMP)
727: {
728: err("left side of assignment must be variable");
729: frexpr(p);
730: return( errnode() );
731: }
732:
733: if(p->rightp)
734: {
735: rp = p->rightp = fixtype(p->rightp);
736: rtype = rp->headblock.vtype;
737: }
738: else
739: {
740: rp = NULL;
741: rtype = 0;
742: }
743:
744: if(ltype==TYERROR || rtype==TYERROR)
745: {
746: frexpr(p);
747: frexpr(lconst);
748: frexpr(rconst);
749: return( errnode() );
750: }
751:
752: /* force folding if possible */
753: if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
754: {
755: q = mkexpr(opcode, lp, rp);
756: if( ISCONST(q) )
757: {
758: frexpr(lconst);
759: frexpr(rconst);
760: return(q);
761: }
762: free( (charptr) q ); /* constants did not fold */
763: }
764:
765: if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
766: {
767: frexpr(p);
768: frexpr(lconst);
769: frexpr(rconst);
770: return( errnode() );
771: }
772:
773: switch(opcode)
774: {
775: case OPCONCAT:
776: if(p->vleng == NULL)
777: p->vleng = mkexpr(OPPLUS,
778: cpexpr(lp->headblock.vleng),
779: cpexpr(rp->headblock.vleng) );
780: break;
781:
782: case OPASSIGN:
783: case OPPLUSEQ:
784: case OPSTAREQ:
785: if(ltype == rtype)
786: break;
787: if( ! rconst && ISREAL(ltype) && ISREAL(rtype) )
788: break;
789: if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
790: break;
791: if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
792: #if FAMILY==PCC
793: && typesize[ltype]>=typesize[rtype] )
794: #else
795: && typesize[ltype]==typesize[rtype] )
796: #endif
797: break;
798: if (rconst)
799: {
800: p->rightp = fixtype( mkconv(ptype, cpexpr(rconst)) );
801: frexpr(rp);
802: }
803: else
804: p->rightp = fixtype(mkconv(ptype, rp));
805: break;
806:
807: case OPSLASH:
808: if( ISCOMPLEX(rtype) )
809: {
810: p = (Exprp) call2(ptype,
811: ptype==TYCOMPLEX? "c_div" : "z_div",
812: mkconv(ptype, lp), mkconv(ptype, rp) );
813: break;
814: }
815: case OPPLUS:
816: case OPMINUS:
817: case OPSTAR:
818: case OPMOD:
819: if(ptype==TYDREAL && ( (ltype==TYREAL && ! lconst ) ||
820: (rtype==TYREAL && ! rconst ) ))
821: break;
822: if( ISCOMPLEX(ptype) )
823: break;
824: if(ltype != ptype)
825: if (lconst)
826: {
827: p->leftp = fixtype(mkconv(ptype,
828: cpexpr(lconst)));
829: frexpr(lp);
830: }
831: else
832: p->leftp = fixtype(mkconv(ptype,lp));
833: if(rtype != ptype)
834: if (rconst)
835: {
836: p->rightp = fixtype(mkconv(ptype,
837: cpexpr(rconst)));
838: frexpr(rp);
839: }
840: else
841: p->rightp = fixtype(mkconv(ptype,rp));
842: break;
843:
844: case OPPOWER:
845: return( mkpower(p) );
846:
847: case OPLT:
848: case OPLE:
849: case OPGT:
850: case OPGE:
851: case OPEQ:
852: case OPNE:
853: if(ltype == rtype)
854: break;
855: mtype = cktype(OPMINUS, ltype, rtype);
856: if(mtype==TYDREAL && ( (ltype==TYREAL && ! lconst) ||
857: (rtype==TYREAL && ! rconst) ))
858: break;
859: if( ISCOMPLEX(mtype) )
860: break;
861: if(ltype != mtype)
862: if (lconst)
863: {
864: p->leftp = fixtype(mkconv(mtype,
865: cpexpr(lconst)));
866: frexpr(lp);
867: }
868: else
869: p->leftp = fixtype(mkconv(mtype,lp));
870: if(rtype != mtype)
871: if (rconst)
872: {
873: p->rightp = fixtype(mkconv(mtype,
874: cpexpr(rconst)));
875: frexpr(rp);
876: }
877: else
878: p->rightp = fixtype(mkconv(mtype,rp));
879: break;
880:
881:
882: case OPCONV:
883: if(ISCOMPLEX(p->vtype))
884: {
885: ptype = cktype(OPCONV, p->vtype, ltype);
886: if(p->rightp)
887: ptype = cktype(OPCONV, ptype, rtype);
888: break;
889: }
890: ptype = cktype(OPCONV, p->vtype, ltype);
891: if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA)
892: {
893: lp->exprblock.rightp =
894: fixtype( mkconv(ptype, lp->exprblock.rightp) );
895: free( (charptr) p );
896: p = (Exprp) lp;
897: }
898: break;
899:
900: case OPADDR:
901: if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR)
902: fatal("addr of addr");
903: break;
904:
905: case OPCOMMA:
906: case OPQUEST:
907: case OPCOLON:
908: break;
909:
910: case OPPAREN:
911: p->vleng = (expptr) cpexpr( lp->headblock.vleng );
912: break;
913:
914: case OPMIN:
915: case OPMAX:
916: ptype = p->vtype;
917: break;
918:
919: default:
920: break;
921: }
922:
923: p->vtype = ptype;
924: frexpr(lconst);
925: frexpr(rconst);
926: return((expptr) p);
927: }
928:
929: #if SZINT < SZLONG
930: /*
931: for efficient subscripting, replace long ints by shorts
932: in easy places
933: */
934:
935: expptr shorten(p)
936: register expptr p;
937: {
938: register expptr q;
939:
940: if(p->headblock.vtype != TYLONG)
941: return(p);
942:
943: switch(p->tag)
944: {
945: case TERROR:
946: case TLIST:
947: return(p);
948:
949: case TCONST:
950: case TADDR:
951: return( mkconv(TYINT,p) );
952:
953: case TEXPR:
954: break;
955:
956: default:
957: badtag("shorten", p->tag);
958: }
959:
960: switch(p->exprblock.opcode)
961: {
962: case OPPLUS:
963: case OPMINUS:
964: case OPSTAR:
965: q = shorten( cpexpr(p->exprblock.rightp) );
966: if(q->headblock.vtype == TYINT)
967: {
968: p->exprblock.leftp = shorten(p->exprblock.leftp);
969: if(p->exprblock.leftp->headblock.vtype == TYLONG)
970: frexpr(q);
971: else
972: {
973: frexpr(p->exprblock.rightp);
974: p->exprblock.rightp = q;
975: p->exprblock.vtype = TYINT;
976: }
977: }
978: break;
979:
980: case OPNEG:
981: case OPPAREN:
982: p->exprblock.leftp = shorten(p->exprblock.leftp);
983: if(p->exprblock.leftp->headblock.vtype == TYINT)
984: p->exprblock.vtype = TYINT;
985: break;
986:
987: case OPCALL:
988: case OPCCALL:
989: p = mkconv(TYINT,p);
990: break;
991: default:
992: break;
993: }
994:
995: return(p);
996: }
997: #endif
998:
999: /* fix an argument list, taking due care for special first level cases */
1000:
1001: fixargs(doput, p0)
1002: int doput; /* doput is true if the function is not intrinsic;
1003: was used to decide whether to do a putconst,
1004: but this is no longer done here (Feb82)*/
1005: struct Listblock *p0;
1006: {
1007: register chainp p;
1008: register tagptr q, t;
1009: register int qtag;
1010: int nargs;
1011: Addrp mkscalar();
1012:
1013: nargs = 0;
1014: if(p0)
1015: for(p = p0->listp ; p ; p = p->nextp)
1016: {
1017: ++nargs;
1018: q = p->datap;
1019: qtag = q->tag;
1020: if(qtag == TCONST)
1021: {
1022: if(q->constblock.vtype == TYSHORT)
1023: q = (tagptr) mkconv(tyint, q);
1024: p->datap = q ;
1025: }
1026: else if(qtag==TPRIM && q->primblock.argsp==0 &&
1027: q->primblock.namep->vclass==CLPROC)
1028: p->datap = (tagptr) mkaddr(q->primblock.namep);
1029: else if(qtag==TPRIM && q->primblock.argsp==0 &&
1030: q->primblock.namep->vdim!=NULL)
1031: p->datap = (tagptr) mkscalar(q->primblock.namep);
1032: else if(qtag==TPRIM && q->primblock.argsp==0 &&
1033: q->primblock.namep->vdovar &&
1034: (t = (tagptr) memversion(q->primblock.namep)) )
1035: p->datap = (tagptr) fixtype(t);
1036: else
1037: p->datap = (tagptr) fixtype(q);
1038: }
1039: return(nargs);
1040: }
1041:
1042:
1043: Addrp mkscalar(np)
1044: register Namep np;
1045: {
1046: register Addrp ap;
1047:
1048: vardcl(np);
1049: ap = mkaddr(np);
1050:
1051: #if TARGET == VAX
1052: /* on the VAX, prolog causes array arguments
1053: to point at the (0,...,0) element, except when
1054: subscript checking is on
1055: */
1056: #ifdef SDB
1057: if( !checksubs && !sdbflag && np->vstg==STGARG)
1058: #else
1059: if( !checksubs && np->vstg==STGARG)
1060: #endif
1061: {
1062: register struct Dimblock *dp;
1063: dp = np->vdim;
1064: frexpr(ap->memoffset);
1065: ap->memoffset = mkexpr(OPSTAR,
1066: (np->vtype==TYCHAR ?
1067: cpexpr(np->vleng) :
1068: (tagptr)ICON(typesize[np->vtype]) ),
1069: cpexpr(dp->baseoffset) );
1070: }
1071: #endif
1072: return(ap);
1073: }
1074:
1075:
1076:
1077:
1078:
1079: expptr mkfunct(p)
1080: register struct Primblock *p;
1081: {
1082: struct Entrypoint *ep;
1083: Addrp ap;
1084: struct Extsym *extp;
1085: register Namep np;
1086: register expptr q;
1087: expptr intrcall(), stfcall();
1088: int k, nargs;
1089: int class;
1090:
1091: if(p->tag != TPRIM)
1092: return( errnode() );
1093:
1094: np = p->namep;
1095: class = np->vclass;
1096:
1097: if(class == CLUNKNOWN)
1098: {
1099: np->vclass = class = CLPROC;
1100: if(np->vstg == STGUNKNOWN)
1101: {
1102: if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) )
1103: {
1104: np->vstg = STGINTR;
1105: np->vardesc.varno = k;
1106: np->vprocclass = PINTRINSIC;
1107: }
1108: else
1109: {
1110: extp = mkext( varunder(VL,np->varname) );
1111: extp->extstg = STGEXT;
1112: np->vstg = STGEXT;
1113: np->vardesc.varno = extp - extsymtab;
1114: np->vprocclass = PEXTERNAL;
1115: }
1116: }
1117: else if(np->vstg==STGARG)
1118: {
1119: if(np->vtype!=TYCHAR && !ftn66flag)
1120: warn("Dummy procedure not declared EXTERNAL. Code may be wrong.");
1121: np->vprocclass = PEXTERNAL;
1122: }
1123: }
1124:
1125: if(class != CLPROC)
1126: fatali("invalid class code %d for function", class);
1127: if(p->fcharp || p->lcharp)
1128: {
1129: err("no substring of function call");
1130: goto error;
1131: }
1132: impldcl(np);
1133: nargs = fixargs( np->vprocclass!=PINTRINSIC, p->argsp);
1134:
1135: switch(np->vprocclass)
1136: {
1137: case PEXTERNAL:
1138: ap = mkaddr(np);
1139: call:
1140: q = mkexpr(OPCALL, ap, p->argsp);
1141: if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN)
1142: {
1143: err("attempt to use untyped function");
1144: goto error;
1145: }
1146: if(np->vleng)
1147: q->exprblock.vleng = (expptr) cpexpr(np->vleng);
1148: break;
1149:
1150: case PINTRINSIC:
1151: q = intrcall(np, p->argsp, nargs);
1152: break;
1153:
1154: case PSTFUNCT:
1155: q = stfcall(np, p->argsp);
1156: break;
1157:
1158: case PTHISPROC:
1159: warn("recursive call");
1160: for(ep = entries ; ep ; ep = ep->entnextp)
1161: if(ep->enamep == np)
1162: break;
1163: if(ep == NULL)
1164: fatal("mkfunct: impossible recursion");
1165: ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) );
1166: goto call;
1167:
1168: default:
1169: fatali("mkfunct: impossible vprocclass %d",
1170: (int) (np->vprocclass) );
1171: }
1172: free( (charptr) p );
1173: return(q);
1174:
1175: error:
1176: frexpr(p);
1177: return( errnode() );
1178: }
1179:
1180:
1181:
1182: LOCAL expptr stfcall(np, actlist)
1183: Namep np;
1184: struct Listblock *actlist;
1185: {
1186: register chainp actuals;
1187: int nargs;
1188: chainp oactp, formals;
1189: int type;
1190: expptr q, rhs, ap;
1191: Namep tnp;
1192: register struct Rplblock *rp;
1193: struct Rplblock *tlist;
1194:
1195: if(actlist)
1196: {
1197: actuals = actlist->listp;
1198: free( (charptr) actlist);
1199: }
1200: else
1201: actuals = NULL;
1202: oactp = actuals;
1203:
1204: nargs = 0;
1205: tlist = NULL;
1206: if( (type = np->vtype) == TYUNKNOWN)
1207: {
1208: err("attempt to use untyped statement function");
1209: q = errnode();
1210: goto ret;
1211: }
1212: formals = (chainp) (np->varxptr.vstfdesc->datap);
1213: rhs = (expptr) (np->varxptr.vstfdesc->nextp);
1214:
1215: /* copy actual arguments into temporaries */
1216: while(actuals!=NULL && formals!=NULL)
1217: {
1218: rp = ALLOC(Rplblock);
1219: rp->rplnp = tnp = (Namep) (formals->datap);
1220: ap = fixtype(actuals->datap);
1221: if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR
1222: && (ap->tag==TCONST || ap->tag==TADDR || ap->tag==TTEMP) )
1223: {
1224: rp->rplvp = (expptr) ap;
1225: rp->rplxp = NULL;
1226: rp->rpltag = ap->tag;
1227: }
1228: else {
1229: rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng);
1230: rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) );
1231: if( (rp->rpltag = rp->rplxp->tag) == TERROR)
1232: err("disagreement of argument types in statement function call");
1233: else if(tnp->vtype!=ap->headblock.vtype)
1234: warn("argument type mismatch in statement function");
1235: }
1236: rp->rplnextp = tlist;
1237: tlist = rp;
1238: actuals = actuals->nextp;
1239: formals = formals->nextp;
1240: ++nargs;
1241: }
1242:
1243: if(actuals!=NULL || formals!=NULL)
1244: err("statement function definition and argument list differ");
1245:
1246: /*
1247: now push down names involved in formal argument list, then
1248: evaluate rhs of statement function definition in this environment
1249: */
1250:
1251: if(tlist) /* put tlist in front of the rpllist */
1252: {
1253: for(rp = tlist; rp->rplnextp; rp = rp->rplnextp)
1254: ;
1255: rp->rplnextp = rpllist;
1256: rpllist = tlist;
1257: }
1258:
1259: q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) );
1260:
1261: /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
1262: while(--nargs >= 0)
1263: {
1264: if(rpllist->rplxp)
1265: q = mkexpr(OPCOMMA, rpllist->rplxp, q);
1266: rp = rpllist->rplnextp;
1267: frexpr(rpllist->rplvp);
1268: free(rpllist);
1269: rpllist = rp;
1270: }
1271:
1272: ret:
1273: frchain( &oactp );
1274: return(q);
1275: }
1276:
1277:
1278:
1279:
1280: Addrp mkplace(np)
1281: register Namep np;
1282: {
1283: register Addrp s;
1284: register struct Rplblock *rp;
1285: int regn;
1286:
1287: /* is name on the replace list? */
1288:
1289: for(rp = rpllist ; rp ; rp = rp->rplnextp)
1290: {
1291: if(np == rp->rplnp)
1292: {
1293: if(rp->rpltag == TNAME)
1294: {
1295: np = (Namep) (rp->rplvp);
1296: break;
1297: }
1298: else return( (Addrp) cpexpr(rp->rplvp) );
1299: }
1300: }
1301:
1302: /* is variable a DO index in a register ? */
1303:
1304: if(np->vdovar && ( (regn = inregister(np)) >= 0) )
1305: if(np->vtype == TYERROR)
1306: return( (Addrp) errnode() );
1307: else
1308: {
1309: s = ALLOC(Addrblock);
1310: s->tag = TADDR;
1311: s->vstg = STGREG;
1312: s->vtype = TYIREG;
1313: s->issaved = np->vsave;
1314: s->memno = regn;
1315: s->memoffset = ICON(0);
1316: return(s);
1317: }
1318:
1319: vardcl(np);
1320: return(mkaddr(np));
1321: }
1322:
1323:
1324:
1325:
1326: expptr mklhs(p)
1327: register struct Primblock *p;
1328: {
1329: expptr suboffset();
1330: expptr ep = ENULL;
1331: register Addrp s;
1332: Namep np;
1333:
1334: if(p->tag != TPRIM)
1335: return( (expptr) p );
1336: np = p->namep;
1337:
1338: s = mkplace(np);
1339: if(s->tag!=TADDR || s->vstg==STGREG)
1340: {
1341: free( (charptr) p );
1342: return( (expptr) s );
1343: }
1344:
1345: /* do the substring part */
1346:
1347: if(p->fcharp || p->lcharp)
1348: {
1349: if(np->vtype != TYCHAR)
1350: errstr("substring of noncharacter %s", varstr(VL,np->varname));
1351: else {
1352: if(p->lcharp == NULL)
1353: p->lcharp = (expptr) cpexpr(s->vleng);
1354: frexpr(s->vleng);
1355: if(p->fcharp)
1356: {
1357: if(p->fcharp->tag == TPRIM && p->lcharp->tag == TPRIM
1358: && p->fcharp->primblock.namep == p->lcharp->primblock.namep
1359: && p->fcharp->primblock.argsp == NULL
1360: && p->lcharp->primblock.argsp == NULL)
1361: /* A trivial optimization -- upper == lower */
1362: s->vleng = ICON(1);
1363: else
1364: {
1365: if(p->fcharp->tag == TEXPR
1366: || (p->fcharp->tag == TPRIM
1367: && p->fcharp->primblock.argsp != NULL))
1368: {
1369: ep = fixtype(cpexpr(p->fcharp));
1370: p->fcharp = (expptr) mktemp(ep->headblock.vtype, ENULL);
1371: }
1372: s->vleng = mkexpr(OPMINUS, p->lcharp,
1373: mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
1374: }
1375: }
1376: else
1377: s->vleng = p->lcharp;
1378: }
1379: }
1380:
1381: /* compute the address modified by subscripts */
1382:
1383: s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) );
1384: frexpr(p->argsp);
1385: p->argsp = NULL;
1386:
1387: s->vleng = fixtype( s->vleng );
1388: s->memoffset = fixtype( s->memoffset );
1389: if(ep)
1390: /* this code depends on memoffset being evaluated before vleng */
1391: s->memoffset = mkexpr(OPCOMMA, mkexpr(OPASSIGN, cpexpr(p->fcharp), ep), s->memoffset);
1392: frexpr(p->fcharp);
1393: free( (charptr) p );
1394: return( (expptr) s );
1395: }
1396:
1397:
1398:
1399:
1400:
1401: deregister(np)
1402: Namep np;
1403: {
1404: if(nregvar>0 && regnamep[nregvar-1]==np)
1405: {
1406: --nregvar;
1407: #if FAMILY == DMR
1408: putnreg();
1409: #endif
1410: }
1411: }
1412:
1413:
1414:
1415:
1416: Addrp memversion(np)
1417: register Namep np;
1418: {
1419: register Addrp s;
1420:
1421: if(np->vdovar==NO || (inregister(np)<0) )
1422: return(NULL);
1423: np->vdovar = NO;
1424: s = mkplace(np);
1425: np->vdovar = YES;
1426: return(s);
1427: }
1428:
1429:
1430:
1431: inregister(np)
1432: register Namep np;
1433: {
1434: register int i;
1435:
1436: for(i = 0 ; i < nregvar ; ++i)
1437: if(regnamep[i] == np)
1438: return( regnum[i] );
1439: return(-1);
1440: }
1441:
1442:
1443:
1444:
1445: enregister(np)
1446: Namep np;
1447: {
1448: if( inregister(np) >= 0)
1449: return(YES);
1450: if(nregvar >= maxregvar)
1451: return(NO);
1452: vardcl(np);
1453: if( ONEOF(np->vtype, MSKIREG) )
1454: {
1455: regnamep[nregvar++] = np;
1456: if(nregvar > highregvar)
1457: highregvar = nregvar;
1458: #if FAMILY == DMR
1459: putnreg();
1460: #endif
1461: return(YES);
1462: }
1463: else
1464: return(NO);
1465: }
1466:
1467:
1468:
1469:
1470: expptr suboffset(p)
1471: register struct Primblock *p;
1472: {
1473: int n;
1474: expptr size;
1475: expptr oftwo();
1476: chainp cp;
1477: expptr offp, prod;
1478: expptr subcheck();
1479: struct Dimblock *dimp;
1480: expptr sub[MAXDIM+1];
1481: register Namep np;
1482:
1483: np = p->namep;
1484: offp = ICON(0);
1485: n = 0;
1486: if(p->argsp)
1487: for(cp = p->argsp->listp ; cp ; ++n, cp = cp->nextp)
1488: {
1489: sub[n] = fixtype(cpexpr(cp->datap));
1490: if ( ! ISINT(sub[n]->headblock.vtype)) {
1491: errstr("%s: non-integer subscript expression",
1492: varstr(VL, np->varname) );
1493: /* Provide a substitute -- go on to find more errors */
1494: frexpr(sub[n]);
1495: sub[n] = ICON(1);
1496: }
1497: if(n > maxdim)
1498: {
1499: char str[28+VL];
1500: sprintf(str, "%s: more than %d subscripts",
1501: varstr(VL, np->varname), maxdim );
1502: err( str );
1503: break;
1504: }
1505: }
1506:
1507: dimp = np->vdim;
1508: if(n>0 && dimp==NULL)
1509: errstr("%s: subscripts on scalar variable",
1510: varstr(VL, np->varname), maxdim );
1511: else if(dimp && dimp->ndim!=n)
1512: errstr("wrong number of subscripts on %s",
1513: varstr(VL, np->varname) );
1514: else if(n > 0)
1515: {
1516: prod = sub[--n];
1517: while( --n >= 0)
1518: prod = mkexpr(OPPLUS, sub[n],
1519: mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
1520: #if TARGET == VAX
1521: #ifdef SDB
1522: if(checksubs || np->vstg!=STGARG || sdbflag)
1523: #else
1524: if(checksubs || np->vstg!=STGARG)
1525: #endif
1526: prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1527: #else
1528: prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1529: #endif
1530: if(checksubs)
1531: prod = subcheck(np, prod);
1532: size = np->vtype == TYCHAR ?
1533: (expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]);
1534: if (!oftwo(size))
1535: prod = mkexpr(OPSTAR, prod, size);
1536: else
1537: prod = mkexpr(OPLSHIFT,prod,oftwo(size));
1538:
1539: offp = mkexpr(OPPLUS, offp, prod);
1540: }
1541:
1542: if(p->fcharp && np->vtype==TYCHAR)
1543: offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
1544:
1545: return(offp);
1546: }
1547:
1548:
1549:
1550:
1551: expptr subcheck(np, p)
1552: Namep np;
1553: register expptr p;
1554: {
1555: struct Dimblock *dimp;
1556: expptr t, checkvar, checkcond, badcall;
1557:
1558: dimp = np->vdim;
1559: if(dimp->nelt == NULL)
1560: return(p); /* don't check arrays with * bounds */
1561: checkvar = NULL;
1562: checkcond = NULL;
1563: if( ISICON(p) )
1564: {
1565: if(p->constblock.const.ci < 0)
1566: goto badsub;
1567: if( ISICON(dimp->nelt) )
1568: if(p->constblock.const.ci < dimp->nelt->constblock.const.ci)
1569: return(p);
1570: else
1571: goto badsub;
1572: }
1573: if(p->tag==TADDR && p->addrblock.vstg==STGREG)
1574: {
1575: checkvar = (expptr) cpexpr(p);
1576: t = p;
1577: }
1578: else {
1579: checkvar = (expptr) mktemp(p->headblock.vtype, ENULL);
1580: t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
1581: }
1582: checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
1583: if( ! ISICON(p) )
1584: checkcond = mkexpr(OPAND, checkcond,
1585: mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
1586:
1587: badcall = call4(p->headblock.vtype, "s_rnge",
1588: mkstrcon(VL, np->varname),
1589: mkconv(TYLONG, cpexpr(checkvar)),
1590: mkstrcon(XL, procname),
1591: ICON(lineno) );
1592: badcall->exprblock.opcode = OPCCALL;
1593: p = mkexpr(OPQUEST, checkcond,
1594: mkexpr(OPCOLON, checkvar, badcall));
1595:
1596: return(p);
1597:
1598: badsub:
1599: frexpr(p);
1600: errstr("subscript on variable %s out of range", varstr(VL,np->varname));
1601: return ( ICON(0) );
1602: }
1603:
1604:
1605:
1606:
1607: Addrp mkaddr(p)
1608: register Namep p;
1609: {
1610: struct Extsym *extp;
1611: register Addrp t;
1612: Addrp intraddr();
1613:
1614: switch( p->vstg)
1615: {
1616: case STGUNKNOWN:
1617: if(p->vclass != CLPROC)
1618: break;
1619: extp = mkext( varunder(VL, p->varname) );
1620: extp->extstg = STGEXT;
1621: p->vstg = STGEXT;
1622: p->vardesc.varno = extp - extsymtab;
1623: p->vprocclass = PEXTERNAL;
1624:
1625: case STGCOMMON:
1626: case STGEXT:
1627: case STGBSS:
1628: case STGINIT:
1629: case STGEQUIV:
1630: case STGARG:
1631: case STGLENG:
1632: case STGAUTO:
1633: t = ALLOC(Addrblock);
1634: t->tag = TADDR;
1635: if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)
1636: t->vclass = CLVAR;
1637: else
1638: t->vclass = p->vclass;
1639: t->vtype = p->vtype;
1640: t->vstg = p->vstg;
1641: t->memno = p->vardesc.varno;
1642: t->issaved = p->vsave;
1643: if(p->vdim) t->isarray = YES;
1644: t->memoffset = ICON(p->voffset);
1645: if(p->vleng)
1646: {
1647: t->vleng = (expptr) cpexpr(p->vleng);
1648: if( ISICON(t->vleng) )
1649: t->varleng = t->vleng->constblock.const.ci;
1650: }
1651: if (p->vstg == STGBSS)
1652: t->varsize = p->varsize;
1653: else if (p->vstg == STGEQUIV)
1654: t->varsize = eqvclass[t->memno].eqvleng;
1655: return(t);
1656:
1657: case STGINTR:
1658: return( intraddr(p) );
1659:
1660: }
1661: /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
1662: badstg("mkaddr", p->vstg);
1663: /* NOTREACHED */
1664: }
1665:
1666:
1667:
1668:
1669: Addrp mkarg(type, argno)
1670: int type, argno;
1671: {
1672: register Addrp p;
1673:
1674: p = ALLOC(Addrblock);
1675: p->tag = TADDR;
1676: p->vtype = type;
1677: p->vclass = CLVAR;
1678: p->vstg = (type==TYLENG ? STGLENG : STGARG);
1679: p->memno = argno;
1680: return(p);
1681: }
1682:
1683:
1684:
1685:
1686: expptr mkprim(v, args, substr)
1687: register union
1688: {
1689: struct Paramblock paramblock;
1690: struct Nameblock nameblock;
1691: struct Headblock headblock;
1692: } *v;
1693: struct Listblock *args;
1694: chainp substr;
1695: {
1696: register struct Primblock *p;
1697:
1698: if(v->headblock.vclass == CLPARAM)
1699: {
1700: if(args || substr)
1701: {
1702: errstr("no qualifiers on parameter name %s",
1703: varstr(VL,v->paramblock.varname));
1704: frexpr(args);
1705: if(substr)
1706: {
1707: frexpr(substr->datap);
1708: frexpr(substr->nextp->datap);
1709: frchain(&substr);
1710: }
1711: frexpr(v);
1712: return( errnode() );
1713: }
1714: return( (expptr) cpexpr(v->paramblock.paramval) );
1715: }
1716:
1717: p = ALLOC(Primblock);
1718: p->tag = TPRIM;
1719: p->vtype = v->nameblock.vtype;
1720: p->namep = (Namep) v;
1721: p->argsp = args;
1722: if(substr)
1723: {
1724: p->fcharp = (expptr) substr->datap;
1725: if (p->fcharp != ENULL && ! ISINT(p->fcharp->headblock.vtype))
1726: p->fcharp = mkconv(TYINT, p->fcharp);
1727: p->lcharp = (expptr) substr->nextp->datap;
1728: if (p->lcharp != ENULL && ! ISINT(p->lcharp->headblock.vtype))
1729: p->lcharp = mkconv(TYINT, p->lcharp);
1730: frchain(&substr);
1731: }
1732: return( (expptr) p);
1733: }
1734:
1735:
1736:
1737: vardcl(v)
1738: register Namep v;
1739: {
1740: int nelt;
1741: struct Dimblock *t;
1742: Addrp p;
1743: expptr neltp;
1744: int eltsize;
1745: int varsize;
1746: int tsize;
1747: int align;
1748:
1749: if(v->vdcldone)
1750: return;
1751: if(v->vclass == CLNAMELIST)
1752: return;
1753:
1754: if(v->vtype == TYUNKNOWN)
1755: impldcl(v);
1756: if(v->vclass == CLUNKNOWN)
1757: v->vclass = CLVAR;
1758: else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
1759: {
1760: dclerr("used both as variable and non-variable", v);
1761: return;
1762: }
1763: if(v->vstg==STGUNKNOWN)
1764: v->vstg = implstg[ letter(v->varname[0]) ];
1765:
1766: switch(v->vstg)
1767: {
1768: case STGBSS:
1769: v->vardesc.varno = ++lastvarno;
1770: if (v->vclass != CLVAR)
1771: break;
1772: nelt = 1;
1773: t = v->vdim;
1774: if (t)
1775: {
1776: neltp = t->nelt;
1777: if (neltp && ISICON(neltp))
1778: nelt = neltp->constblock.const.ci;
1779: else
1780: dclerr("improperly dimensioned array", v);
1781: }
1782:
1783: if (v->vtype == TYCHAR)
1784: {
1785: v->vleng = fixtype(v->vleng);
1786: if (v->vleng == NULL)
1787: eltsize = typesize[TYCHAR];
1788: else if (ISICON(v->vleng))
1789: eltsize = typesize[TYCHAR] *
1790: v->vleng->constblock.const.ci;
1791: else if (v->vleng->tag != TERROR)
1792: {
1793: errstr("nonconstant string length on %s",
1794: varstr(VL, v->varname));
1795: eltsize = 0;
1796: }
1797: }
1798: else
1799: eltsize = typesize[v->vtype];
1800:
1801: v->varsize = nelt * eltsize;
1802: break;
1803: case STGAUTO:
1804: if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
1805: break;
1806: nelt = 1;
1807: if(t = v->vdim)
1808: if( (neltp = t->nelt) && ISCONST(neltp) )
1809: nelt = neltp->constblock.const.ci;
1810: else
1811: dclerr("adjustable automatic array", v);
1812: p = autovar(nelt, v->vtype, v->vleng);
1813: v->vardesc.varno = p->memno;
1814: v->voffset = p->memoffset->constblock.const.ci;
1815: frexpr(p);
1816: break;
1817:
1818: default:
1819: break;
1820: }
1821: v->vdcldone = YES;
1822: }
1823:
1824:
1825:
1826:
1827: impldcl(p)
1828: register Namep p;
1829: {
1830: register int k;
1831: int type, leng;
1832:
1833: if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
1834: return;
1835: if(p->vtype == TYUNKNOWN)
1836: {
1837: k = letter(p->varname[0]);
1838: type = impltype[ k ];
1839: leng = implleng[ k ];
1840: if(type == TYUNKNOWN)
1841: {
1842: if(p->vclass == CLPROC)
1843: dclerr("attempt to use function of undefined type", p);
1844: else
1845: dclerr("attempt to use undefined variable", p);
1846: type = TYERROR;
1847: leng = 1;
1848: }
1849: settype(p, type, leng);
1850: }
1851: }
1852:
1853:
1854:
1855:
1856: LOCAL letter(c)
1857: register int c;
1858: {
1859: if( isupper(c) )
1860: c = tolower(c);
1861: return(c - 'a');
1862: }
1863:
1864: #define ICONEQ(z, c) (ISICON(z) && z->constblock.const.ci==c)
1865: #define COMMUTE { e = lp; lp = rp; rp = e; }
1866:
1867:
1868: expptr mkexpr(opcode, lp, rp)
1869: int opcode;
1870: register expptr lp, rp;
1871: {
1872: register expptr e, e1;
1873: int etype;
1874: int ltype, rtype;
1875: int ltag, rtag;
1876: expptr q, q1;
1877: expptr fold();
1878: int k;
1879:
1880: ltype = lp->headblock.vtype;
1881: ltag = lp->tag;
1882: if(rp && opcode!=OPCALL && opcode!=OPCCALL)
1883: {
1884: rtype = rp->headblock.vtype;
1885: rtag = rp->tag;
1886: }
1887: else {
1888: rtype = 0;
1889: rtag = 0;
1890: }
1891:
1892: /*
1893: * Yuck. Why can't we fold constants AFTER
1894: * variables are implicitly declared???
1895: */
1896: if(ltype == TYUNKNOWN && ltag == TPRIM && lp->primblock.argsp == NULL)
1897: {
1898: k = letter(lp->primblock.namep->varname[0]);
1899: ltype = impltype[ k ];
1900: }
1901: if(rtype == TYUNKNOWN && rtag == TPRIM && rp->primblock.argsp == NULL)
1902: {
1903: k = letter(rp->primblock.namep->varname[0]);
1904: rtype = impltype[ k ];
1905: }
1906:
1907: /*
1908: * Eliminate all but the topmost OPPAREN operator when folding constants.
1909: */
1910: if(lp->tag == TEXPR &&
1911: lp->exprblock.opcode == OPPAREN &&
1912: lp->exprblock.leftp->tag == TCONST)
1913: {
1914: q = (expptr) cpexpr(lp->exprblock.leftp);
1915: frexpr(lp);
1916: lp = q;
1917: ltag = TCONST;
1918: ltype = lp->constblock.vtype;
1919: }
1920: if(rp &&
1921: rp->tag == TEXPR &&
1922: rp->exprblock.opcode == OPPAREN &&
1923: rp->exprblock.leftp->tag == TCONST)
1924: {
1925: q = (expptr) cpexpr(rp->exprblock.leftp);
1926: frexpr(rp);
1927: rp = q;
1928: rtag = TCONST;
1929: rtype = rp->constblock.vtype;
1930: }
1931:
1932: etype = cktype(opcode, ltype, rtype);
1933: if(etype == TYERROR)
1934: goto error;
1935:
1936: if(ltag==TCONST && (rp==0 || rtag==TCONST) )
1937: goto makenode;
1938: if(etype == TYUNKNOWN)
1939: goto makenode;
1940:
1941: switch(opcode)
1942: {
1943: /* check for multiplication by 0 and 1 and addition to 0 */
1944:
1945: case OPSTAR:
1946: if( ISCONST(lp) )
1947: COMMUTE
1948:
1949: if( ISICON(rp) )
1950: {
1951: if(rp->constblock.const.ci == 0)
1952: {
1953: if(etype == TYUNKNOWN)
1954: break;
1955: rp = mkconv(etype, rp);
1956: goto retright;
1957: }
1958: if ((lp->tag == TEXPR) &&
1959: ((lp->exprblock.opcode == OPPLUS) ||
1960: (lp->exprblock.opcode == OPMINUS)) &&
1961: ISCONST(lp->exprblock.rightp) &&
1962: ISINT(lp->exprblock.rightp->constblock.vtype))
1963: {
1964: q1 = mkexpr(OPSTAR, lp->exprblock.rightp,
1965: cpexpr(rp));
1966: q = mkexpr(OPSTAR, lp->exprblock.leftp, rp);
1967: q = mkexpr(lp->exprblock.opcode, q, q1);
1968: free ((char *) lp);
1969: return q;
1970: }
1971: else
1972: goto mulop;
1973: }
1974: break;
1975:
1976: case OPSLASH:
1977: case OPMOD:
1978: if( ICONEQ(rp, 0) )
1979: {
1980: err("attempted division by zero");
1981: rp = ICON(1);
1982: break;
1983: }
1984: if(opcode == OPMOD)
1985: break;
1986:
1987:
1988: mulop:
1989: if( ISICON(rp) )
1990: {
1991: if(rp->constblock.const.ci == 1)
1992: goto retleft;
1993:
1994: if(rp->constblock.const.ci == -1)
1995: {
1996: frexpr(rp);
1997: return( mkexpr(OPNEG, lp, PNULL) );
1998: }
1999: }
2000:
2001: if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) )
2002: {
2003: if(opcode == OPSTAR)
2004: e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
2005: else if(ISICON(rp) &&
2006: (lp->exprblock.rightp->constblock.const.ci %
2007: rp->constblock.const.ci) == 0)
2008: e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
2009: else break;
2010:
2011: e1 = lp->exprblock.leftp;
2012: free( (charptr) lp );
2013: return( mkexpr(OPSTAR, e1, e) );
2014: }
2015: break;
2016:
2017:
2018: case OPPLUS:
2019: if( ISCONST(lp) )
2020: COMMUTE
2021: goto addop;
2022:
2023: case OPMINUS:
2024: if( ICONEQ(lp, 0) )
2025: {
2026: frexpr(lp);
2027: return( mkexpr(OPNEG, rp, ENULL) );
2028: }
2029:
2030: if( ISCONST(rp) )
2031: {
2032: opcode = OPPLUS;
2033: consnegop(rp);
2034: }
2035:
2036: addop:
2037: if( ISICON(rp) )
2038: {
2039: if(rp->constblock.const.ci == 0)
2040: goto retleft;
2041: if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
2042: {
2043: e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
2044: e1 = lp->exprblock.leftp;
2045: free( (charptr) lp );
2046: return( mkexpr(OPPLUS, e1, e) );
2047: }
2048: }
2049: break;
2050:
2051:
2052: case OPPOWER:
2053: break;
2054:
2055: case OPNEG:
2056: if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
2057: {
2058: e = lp->exprblock.leftp;
2059: free( (charptr) lp );
2060: return(e);
2061: }
2062: break;
2063:
2064: case OPNOT:
2065: if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
2066: {
2067: e = lp->exprblock.leftp;
2068: free( (charptr) lp );
2069: return(e);
2070: }
2071: break;
2072:
2073: case OPCALL:
2074: case OPCCALL:
2075: etype = ltype;
2076: if(rp!=NULL && rp->listblock.listp==NULL)
2077: {
2078: free( (charptr) rp );
2079: rp = NULL;
2080: }
2081: break;
2082:
2083: case OPAND:
2084: case OPOR:
2085: if( ISCONST(lp) )
2086: COMMUTE
2087:
2088: if( ISCONST(rp) )
2089: {
2090: if(rp->constblock.const.ci == 0)
2091: if(opcode == OPOR)
2092: goto retleft;
2093: else
2094: goto retright;
2095: else if(opcode == OPOR)
2096: goto retright;
2097: else
2098: goto retleft;
2099: }
2100: case OPLSHIFT:
2101: if (ISICON(rp))
2102: {
2103: if (rp->constblock.const.ci == 0)
2104: goto retleft;
2105: if ((lp->tag == TEXPR) &&
2106: ((lp->exprblock.opcode == OPPLUS) ||
2107: (lp->exprblock.opcode == OPMINUS)) &&
2108: ISICON(lp->exprblock.rightp))
2109: {
2110: q1 = mkexpr(OPLSHIFT, lp->exprblock.rightp,
2111: cpexpr(rp));
2112: q = mkexpr(OPLSHIFT, lp->exprblock.leftp, rp);
2113: q = mkexpr(lp->exprblock.opcode, q, q1);
2114: free((char *) lp);
2115: return q;
2116: }
2117: }
2118:
2119: case OPEQV:
2120: case OPNEQV:
2121:
2122: case OPBITAND:
2123: case OPBITOR:
2124: case OPBITXOR:
2125: case OPBITNOT:
2126: case OPRSHIFT:
2127:
2128: case OPLT:
2129: case OPGT:
2130: case OPLE:
2131: case OPGE:
2132: break;
2133:
2134: case OPEQ:
2135: case OPNE:
2136: /*
2137: * This warning is here instead of in cktype because
2138: * cktype repeats warnings (it can be run more
2139: * than once on an expression).
2140: */
2141: if (ltype == TYLOGICAL)
2142: warn("logical operand of nonlogical operator");
2143: break;
2144:
2145: case OPCONCAT:
2146:
2147: case OPMIN:
2148: case OPMAX:
2149:
2150: case OPASSIGN:
2151: case OPPLUSEQ:
2152: case OPSTAREQ:
2153:
2154: case OPCONV:
2155: case OPADDR:
2156:
2157: case OPCOMMA:
2158: case OPQUEST:
2159: case OPCOLON:
2160:
2161: case OPPAREN:
2162: break;
2163:
2164: default:
2165: badop("mkexpr", opcode);
2166: }
2167:
2168: makenode:
2169:
2170: e = (expptr) ALLOC(Exprblock);
2171: e->exprblock.tag = TEXPR;
2172: e->exprblock.opcode = opcode;
2173: e->exprblock.vtype = etype;
2174: e->exprblock.leftp = lp;
2175: e->exprblock.rightp = rp;
2176: if(ltag==TCONST && (rp==0 || rtag==TCONST) )
2177: e = fold(e);
2178: return(e);
2179:
2180: retleft:
2181: frexpr(rp);
2182: return(lp);
2183:
2184: retright:
2185: frexpr(lp);
2186: return(rp);
2187:
2188: error:
2189: frexpr(lp);
2190: if(rp && opcode!=OPCALL && opcode!=OPCCALL)
2191: frexpr(rp);
2192: return( errnode() );
2193: }
2194:
2195: #define ERR(s) { errs = s; goto error; }
2196:
2197: cktype(op, lt, rt)
2198: register int op, lt, rt;
2199: {
2200: char *errs;
2201:
2202: if(lt==TYERROR || rt==TYERROR)
2203: goto error1;
2204:
2205: if(lt==TYUNKNOWN)
2206: return(TYUNKNOWN);
2207: if(rt==TYUNKNOWN)
2208: if (op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL &&
2209: op!=OPCCALL && op!=OPADDR && op!=OPPAREN)
2210: return(TYUNKNOWN);
2211:
2212: switch(op)
2213: {
2214: case OPPLUS:
2215: case OPMINUS:
2216: case OPSTAR:
2217: case OPSLASH:
2218: case OPPOWER:
2219: case OPMOD:
2220: if( ISNUMERIC(lt) && ISNUMERIC(rt) )
2221: return( maxtype(lt, rt) );
2222: ERR("nonarithmetic operand of arithmetic operator")
2223:
2224: case OPNEG:
2225: if( ISNUMERIC(lt) )
2226: return(lt);
2227: ERR("nonarithmetic operand of negation")
2228:
2229: case OPNOT:
2230: if(lt == TYLOGICAL)
2231: return(TYLOGICAL);
2232: ERR("NOT of nonlogical")
2233:
2234: case OPAND:
2235: case OPOR:
2236: case OPEQV:
2237: case OPNEQV:
2238: if(lt==TYLOGICAL && rt==TYLOGICAL)
2239: return(TYLOGICAL);
2240: ERR("nonlogical operand of logical operator")
2241:
2242: case OPLT:
2243: case OPGT:
2244: case OPLE:
2245: case OPGE:
2246: case OPEQ:
2247: case OPNE:
2248: if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
2249: {
2250: if(lt != rt)
2251: ERR("illegal comparison")
2252: if(lt == TYLOGICAL)
2253: {
2254: if(op!=OPEQ && op!=OPNE)
2255: ERR("order comparison of complex data")
2256: }
2257: }
2258:
2259: else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
2260: {
2261: if(op!=OPEQ && op!=OPNE)
2262: ERR("order comparison of complex data")
2263: }
2264:
2265: else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
2266: ERR("comparison of nonarithmetic data")
2267: return(TYLOGICAL);
2268:
2269: case OPCONCAT:
2270: if(lt==TYCHAR && rt==TYCHAR)
2271: return(TYCHAR);
2272: ERR("concatenation of nonchar data")
2273:
2274: case OPCALL:
2275: case OPCCALL:
2276: return(lt);
2277:
2278: case OPADDR:
2279: return(TYADDR);
2280:
2281: case OPCONV:
2282: if(ISCOMPLEX(lt))
2283: {
2284: if(ISNUMERIC(rt))
2285: return(lt);
2286: ERR("impossible conversion")
2287: }
2288: if(rt == 0)
2289: return(0);
2290: if(lt==TYCHAR && ISINT(rt) )
2291: return(TYCHAR);
2292: case OPASSIGN:
2293: case OPPLUSEQ:
2294: case OPSTAREQ:
2295: if( ISINT(lt) && rt==TYCHAR)
2296: return(lt);
2297: if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
2298: if(op!=OPASSIGN || lt!=rt)
2299: {
2300: /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
2301: /* debug fatal("impossible conversion. possible compiler bug"); */
2302: ERR("impossible conversion")
2303: }
2304: return(lt);
2305:
2306: case OPMIN:
2307: case OPMAX:
2308: case OPBITOR:
2309: case OPBITAND:
2310: case OPBITXOR:
2311: case OPBITNOT:
2312: case OPLSHIFT:
2313: case OPRSHIFT:
2314: case OPPAREN:
2315: return(lt);
2316:
2317: case OPCOMMA:
2318: case OPQUEST:
2319: case OPCOLON:
2320: return(rt);
2321:
2322: default:
2323: badop("cktype", op);
2324: }
2325: error: err(errs);
2326: error1: return(TYERROR);
2327: }
2328:
2329: #if HERE == VAX
2330: #include <signal.h>
2331: #include <setjmp.h>
2332: #define setfpe() ;asm("bispsw $0x60")
2333: jmp_buf jmp_fpe;
2334:
2335: LOCAL int fold_fpe_handler( sig, code )
2336: int sig;
2337: int code;
2338: {
2339: char *message;
2340:
2341: switch ( code )
2342: {
2343: case FPE_INTOVF_TRAP:
2344: message = "integer overflow"; break;
2345: case FPE_INTDIV_TRAP:
2346: message = "integer divide by zero"; break;
2347: case FPE_FLTOVF_TRAP:
2348: case FPE_FLTOVF_FAULT:
2349: message = "floating overflow"; break;
2350: case FPE_FLTDIV_TRAP:
2351: case FPE_FLTDIV_FAULT:
2352: message = "floating divide by zero"; break;
2353: case FPE_FLTUND_TRAP:
2354: case FPE_FLTUND_FAULT:
2355: message = "floating underflow"; break;
2356: default:
2357: message = "arithmetic exception";
2358: }
2359: errstr("%s in constant expression", message);
2360: longjmp(jmp_fpe, 1);
2361: }
2362: #endif
2363:
2364: #ifndef setfpe
2365: #define setfpe()
2366: #endif
2367:
2368: LOCAL expptr fold(e)
2369: register expptr e;
2370: {
2371: Constp p;
2372: register expptr lp, rp;
2373: int etype, mtype, ltype, rtype, opcode;
2374: int i, ll, lr;
2375: char *q, *s;
2376: union Constant lcon, rcon;
2377:
2378: #if HERE == VAX
2379: int (*fpe_handler)();
2380:
2381: if(setjmp(jmp_fpe))
2382: {
2383: (void) signal(SIGFPE, fpe_handler);
2384: frexpr(e);
2385: return(errnode());
2386: }
2387: fpe_handler = signal(SIGFPE, fold_fpe_handler);
2388: setfpe();
2389: #endif
2390:
2391: opcode = e->exprblock.opcode;
2392: etype = e->exprblock.vtype;
2393:
2394: lp = e->exprblock.leftp;
2395: ltype = lp->headblock.vtype;
2396: rp = e->exprblock.rightp;
2397:
2398: if(rp == 0)
2399: switch(opcode)
2400: {
2401: case OPNOT:
2402: lp->constblock.const.ci = ! lp->constblock.const.ci;
2403: return(lp);
2404:
2405: case OPBITNOT:
2406: lp->constblock.const.ci = ~ lp->constblock.const.ci;
2407: return(lp);
2408:
2409: case OPNEG:
2410: consnegop(lp);
2411: return(lp);
2412:
2413: case OPCONV:
2414: case OPADDR:
2415: case OPPAREN:
2416: return(e);
2417:
2418: default:
2419: badop("fold", opcode);
2420: }
2421:
2422: rtype = rp->headblock.vtype;
2423:
2424: p = ALLOC(Constblock);
2425: p->tag = TCONST;
2426: p->vtype = etype;
2427: p->vleng = e->exprblock.vleng;
2428:
2429: switch(opcode)
2430: {
2431: case OPCOMMA:
2432: case OPQUEST:
2433: case OPCOLON:
2434: return(e);
2435:
2436: case OPAND:
2437: p->const.ci = lp->constblock.const.ci &&
2438: rp->constblock.const.ci;
2439: break;
2440:
2441: case OPOR:
2442: p->const.ci = lp->constblock.const.ci ||
2443: rp->constblock.const.ci;
2444: break;
2445:
2446: case OPEQV:
2447: p->const.ci = lp->constblock.const.ci ==
2448: rp->constblock.const.ci;
2449: break;
2450:
2451: case OPNEQV:
2452: p->const.ci = lp->constblock.const.ci !=
2453: rp->constblock.const.ci;
2454: break;
2455:
2456: case OPBITAND:
2457: p->const.ci = lp->constblock.const.ci &
2458: rp->constblock.const.ci;
2459: break;
2460:
2461: case OPBITOR:
2462: p->const.ci = lp->constblock.const.ci |
2463: rp->constblock.const.ci;
2464: break;
2465:
2466: case OPBITXOR:
2467: p->const.ci = lp->constblock.const.ci ^
2468: rp->constblock.const.ci;
2469: break;
2470:
2471: case OPLSHIFT:
2472: p->const.ci = lp->constblock.const.ci <<
2473: rp->constblock.const.ci;
2474: break;
2475:
2476: case OPRSHIFT:
2477: p->const.ci = lp->constblock.const.ci >>
2478: rp->constblock.const.ci;
2479: break;
2480:
2481: case OPCONCAT:
2482: ll = lp->constblock.vleng->constblock.const.ci;
2483: lr = rp->constblock.vleng->constblock.const.ci;
2484: p->const.ccp = q = (char *) ckalloc(ll+lr);
2485: p->vleng = ICON(ll+lr);
2486: s = lp->constblock.const.ccp;
2487: for(i = 0 ; i < ll ; ++i)
2488: *q++ = *s++;
2489: s = rp->constblock.const.ccp;
2490: for(i = 0; i < lr; ++i)
2491: *q++ = *s++;
2492: break;
2493:
2494:
2495: case OPPOWER:
2496: if( ! ISINT(rtype) )
2497: return(e);
2498: conspower(&(p->const), lp, rp->constblock.const.ci);
2499: break;
2500:
2501:
2502: default:
2503: if(ltype == TYCHAR)
2504: {
2505: lcon.ci = cmpstr(lp->constblock.const.ccp,
2506: rp->constblock.const.ccp,
2507: lp->constblock.vleng->constblock.const.ci,
2508: rp->constblock.vleng->constblock.const.ci);
2509: rcon.ci = 0;
2510: mtype = tyint;
2511: }
2512: else {
2513: mtype = maxtype(ltype, rtype);
2514: consconv(mtype, &lcon, ltype, &(lp->constblock.const) );
2515: consconv(mtype, &rcon, rtype, &(rp->constblock.const) );
2516: }
2517: consbinop(opcode, mtype, &(p->const), &lcon, &rcon);
2518: break;
2519: }
2520:
2521: frexpr(e);
2522: return( (expptr) p );
2523: }
2524:
2525:
2526:
2527: /* assign constant l = r , doing coercion */
2528:
2529: consconv(lt, lv, rt, rv)
2530: int lt, rt;
2531: register union Constant *lv, *rv;
2532: {
2533: switch(lt)
2534: {
2535: case TYCHAR:
2536: *(lv->ccp = (char *) ckalloc(1)) = rv->ci;
2537: break;
2538:
2539: case TYSHORT:
2540: case TYLONG:
2541: if(rt == TYCHAR)
2542: lv->ci = rv->ccp[0];
2543: else if( ISINT(rt) )
2544: lv->ci = rv->ci;
2545: else lv->ci = rv->cd[0];
2546: break;
2547:
2548: case TYCOMPLEX:
2549: case TYDCOMPLEX:
2550: switch(rt)
2551: {
2552: case TYSHORT:
2553: case TYLONG:
2554: /* fall through and do real assignment of
2555: first element
2556: */
2557: case TYREAL:
2558: case TYDREAL:
2559: lv->cd[1] = 0; break;
2560: case TYCOMPLEX:
2561: case TYDCOMPLEX:
2562: lv->cd[1] = rv->cd[1]; break;
2563: }
2564:
2565: case TYREAL:
2566: case TYDREAL:
2567: if( ISINT(rt) )
2568: lv->cd[0] = rv->ci;
2569: else lv->cd[0] = rv->cd[0];
2570: if( lt == TYREAL)
2571: {
2572: float f = lv->cd[0];
2573: lv->cd[0] = f;
2574: }
2575: break;
2576:
2577: case TYLOGICAL:
2578: lv->ci = rv->ci;
2579: break;
2580: }
2581: }
2582:
2583:
2584:
2585: consnegop(p)
2586: register Constp p;
2587: {
2588: setfpe();
2589:
2590: switch(p->vtype)
2591: {
2592: case TYSHORT:
2593: case TYLONG:
2594: p->const.ci = - p->const.ci;
2595: break;
2596:
2597: case TYCOMPLEX:
2598: case TYDCOMPLEX:
2599: p->const.cd[1] = - p->const.cd[1];
2600: /* fall through and do the real parts */
2601: case TYREAL:
2602: case TYDREAL:
2603: p->const.cd[0] = - p->const.cd[0];
2604: break;
2605: default:
2606: badtype("consnegop", p->vtype);
2607: }
2608: }
2609:
2610:
2611:
2612: LOCAL conspower(powp, ap, n)
2613: register union Constant *powp;
2614: Constp ap;
2615: ftnint n;
2616: {
2617: register int type;
2618: union Constant x;
2619:
2620: switch(type = ap->vtype) /* pow = 1 */
2621: {
2622: case TYSHORT:
2623: case TYLONG:
2624: powp->ci = 1;
2625: break;
2626: case TYCOMPLEX:
2627: case TYDCOMPLEX:
2628: powp->cd[1] = 0;
2629: case TYREAL:
2630: case TYDREAL:
2631: powp->cd[0] = 1;
2632: break;
2633: default:
2634: badtype("conspower", type);
2635: }
2636:
2637: if(n == 0)
2638: return;
2639: if(n < 0)
2640: {
2641: if( ISINT(type) )
2642: {
2643: if (ap->const.ci == 0)
2644: err("zero raised to a negative power");
2645: else if (ap->const.ci == 1)
2646: return;
2647: else if (ap->const.ci == -1)
2648: {
2649: if (n < -2)
2650: n = n + 2;
2651: n = -n;
2652: if (n % 2 == 1)
2653: powp->ci = -1;
2654: }
2655: else
2656: powp->ci = 0;
2657: return;
2658: }
2659: n = - n;
2660: consbinop(OPSLASH, type, &x, powp, &(ap->const));
2661: }
2662: else
2663: consbinop(OPSTAR, type, &x, powp, &(ap->const));
2664:
2665: for( ; ; )
2666: {
2667: if(n & 01)
2668: consbinop(OPSTAR, type, powp, powp, &x);
2669: if(n >>= 1)
2670: consbinop(OPSTAR, type, &x, &x, &x);
2671: else
2672: break;
2673: }
2674: }
2675:
2676:
2677:
2678: /* do constant operation cp = a op b */
2679:
2680:
2681: LOCAL consbinop(opcode, type, cp, ap, bp)
2682: int opcode, type;
2683: register union Constant *ap, *bp, *cp;
2684: {
2685: int k;
2686: double temp;
2687:
2688: setfpe();
2689:
2690: switch(opcode)
2691: {
2692: case OPPLUS:
2693: switch(type)
2694: {
2695: case TYSHORT:
2696: case TYLONG:
2697: cp->ci = ap->ci + bp->ci;
2698: break;
2699: case TYCOMPLEX:
2700: case TYDCOMPLEX:
2701: cp->cd[1] = ap->cd[1] + bp->cd[1];
2702: case TYREAL:
2703: case TYDREAL:
2704: cp->cd[0] = ap->cd[0] + bp->cd[0];
2705: break;
2706: }
2707: break;
2708:
2709: case OPMINUS:
2710: switch(type)
2711: {
2712: case TYSHORT:
2713: case TYLONG:
2714: cp->ci = ap->ci - bp->ci;
2715: break;
2716: case TYCOMPLEX:
2717: case TYDCOMPLEX:
2718: cp->cd[1] = ap->cd[1] - bp->cd[1];
2719: case TYREAL:
2720: case TYDREAL:
2721: cp->cd[0] = ap->cd[0] - bp->cd[0];
2722: break;
2723: }
2724: break;
2725:
2726: case OPSTAR:
2727: switch(type)
2728: {
2729: case TYSHORT:
2730: case TYLONG:
2731: cp->ci = ap->ci * bp->ci;
2732: break;
2733: case TYREAL:
2734: case TYDREAL:
2735: cp->cd[0] = ap->cd[0] * bp->cd[0];
2736: break;
2737: case TYCOMPLEX:
2738: case TYDCOMPLEX:
2739: temp = ap->cd[0] * bp->cd[0] -
2740: ap->cd[1] * bp->cd[1] ;
2741: cp->cd[1] = ap->cd[0] * bp->cd[1] +
2742: ap->cd[1] * bp->cd[0] ;
2743: cp->cd[0] = temp;
2744: break;
2745: }
2746: break;
2747: case OPSLASH:
2748: switch(type)
2749: {
2750: case TYSHORT:
2751: case TYLONG:
2752: cp->ci = ap->ci / bp->ci;
2753: break;
2754: case TYREAL:
2755: case TYDREAL:
2756: cp->cd[0] = ap->cd[0] / bp->cd[0];
2757: break;
2758: case TYCOMPLEX:
2759: case TYDCOMPLEX:
2760: zdiv(cp,ap,bp);
2761: break;
2762: }
2763: break;
2764:
2765: case OPMOD:
2766: if( ISINT(type) )
2767: {
2768: cp->ci = ap->ci % bp->ci;
2769: break;
2770: }
2771: else
2772: fatal("inline mod of noninteger");
2773:
2774: default: /* relational ops */
2775: switch(type)
2776: {
2777: case TYSHORT:
2778: case TYLONG:
2779: if(ap->ci < bp->ci)
2780: k = -1;
2781: else if(ap->ci == bp->ci)
2782: k = 0;
2783: else k = 1;
2784: break;
2785: case TYREAL:
2786: case TYDREAL:
2787: if(ap->cd[0] < bp->cd[0])
2788: k = -1;
2789: else if(ap->cd[0] == bp->cd[0])
2790: k = 0;
2791: else k = 1;
2792: break;
2793: case TYCOMPLEX:
2794: case TYDCOMPLEX:
2795: if(ap->cd[0] == bp->cd[0] &&
2796: ap->cd[1] == bp->cd[1] )
2797: k = 0;
2798: else k = 1;
2799: break;
2800: case TYLOGICAL:
2801: if(ap->ci == bp->ci)
2802: k = 0;
2803: else k = 1;
2804: break;
2805: }
2806:
2807: switch(opcode)
2808: {
2809: case OPEQ:
2810: cp->ci = (k == 0);
2811: break;
2812: case OPNE:
2813: cp->ci = (k != 0);
2814: break;
2815: case OPGT:
2816: cp->ci = (k == 1);
2817: break;
2818: case OPLT:
2819: cp->ci = (k == -1);
2820: break;
2821: case OPGE:
2822: cp->ci = (k >= 0);
2823: break;
2824: case OPLE:
2825: cp->ci = (k <= 0);
2826: break;
2827: default:
2828: badop ("consbinop", opcode);
2829: }
2830: break;
2831: }
2832: }
2833:
2834:
2835:
2836:
2837: conssgn(p)
2838: register expptr p;
2839: {
2840: if( ! ISCONST(p) )
2841: fatal( "sgn(nonconstant)" );
2842:
2843: switch(p->headblock.vtype)
2844: {
2845: case TYSHORT:
2846: case TYLONG:
2847: if(p->constblock.const.ci > 0) return(1);
2848: if(p->constblock.const.ci < 0) return(-1);
2849: return(0);
2850:
2851: case TYREAL:
2852: case TYDREAL:
2853: if(p->constblock.const.cd[0] > 0) return(1);
2854: if(p->constblock.const.cd[0] < 0) return(-1);
2855: return(0);
2856:
2857: case TYCOMPLEX:
2858: case TYDCOMPLEX:
2859: return(p->constblock.const.cd[0]!=0 || p->constblock.const.cd[1]!=0);
2860:
2861: default:
2862: badtype( "conssgn", p->constblock.vtype);
2863: }
2864: /* NOTREACHED */
2865: }
2866:
2867: char *powint[ ] = { "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
2868:
2869:
2870: LOCAL expptr mkpower(p)
2871: register expptr p;
2872: {
2873: register expptr q, lp, rp;
2874: int ltype, rtype, mtype;
2875: struct Listblock *args, *mklist();
2876: Addrp ap;
2877:
2878: lp = p->exprblock.leftp;
2879: rp = p->exprblock.rightp;
2880: ltype = lp->headblock.vtype;
2881: rtype = rp->headblock.vtype;
2882:
2883: if(ISICON(rp))
2884: {
2885: if(rp->constblock.const.ci == 0)
2886: {
2887: frexpr(p);
2888: if( ISINT(ltype) )
2889: return( ICON(1) );
2890: else
2891: {
2892: expptr pp;
2893: pp = mkconv(ltype, ICON(1));
2894: return( pp );
2895: }
2896: }
2897: if(rp->constblock.const.ci < 0)
2898: {
2899: if( ISINT(ltype) )
2900: {
2901: frexpr(p);
2902: err("integer**negative");
2903: return( errnode() );
2904: }
2905: rp->constblock.const.ci = - rp->constblock.const.ci;
2906: p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));
2907: }
2908: if(rp->constblock.const.ci == 1)
2909: {
2910: frexpr(rp);
2911: free( (charptr) p );
2912: return(lp);
2913: }
2914:
2915: if( ONEOF(ltype, MSKINT|MSKREAL) )
2916: {
2917: p->exprblock.vtype = ltype;
2918: return(p);
2919: }
2920: }
2921: if( ISINT(rtype) )
2922: {
2923: if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
2924: q = call2(TYSHORT, "pow_hh", lp, rp);
2925: else {
2926: if(ltype == TYSHORT)
2927: {
2928: ltype = TYLONG;
2929: lp = mkconv(TYLONG,lp);
2930: }
2931: q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
2932: }
2933: }
2934: else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
2935: {
2936: args = mklist( mkchain( mkconv(TYDREAL,lp), mkchain( mkconv(TYDREAL,rp), CHNULL ) ) );
2937: fixargs(YES, args );
2938: ap = builtin( TYDREAL, "pow" );
2939: ap->vstg = STGINTR;
2940: q = fixexpr( mkexpr(OPCCALL, ap, args ));
2941: q->exprblock.vtype = mtype;
2942: }
2943: else {
2944: q = call2(TYDCOMPLEX, "pow_zz",
2945: mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
2946: if(mtype == TYCOMPLEX)
2947: q = mkconv(TYCOMPLEX, q);
2948: }
2949: free( (charptr) p );
2950: return(q);
2951: }
2952:
2953:
2954:
2955: /* Complex Division. Same code as in Runtime Library
2956: */
2957:
2958: struct dcomplex { double dreal, dimag; };
2959:
2960:
2961: LOCAL zdiv(c, a, b)
2962: register struct dcomplex *a, *b, *c;
2963: {
2964: double ratio, den;
2965: double abr, abi;
2966:
2967: setfpe();
2968:
2969: if( (abr = b->dreal) < 0.)
2970: abr = - abr;
2971: if( (abi = b->dimag) < 0.)
2972: abi = - abi;
2973: if( abr <= abi )
2974: {
2975: if(abi == 0)
2976: fatal("complex division by zero");
2977: ratio = b->dreal / b->dimag ;
2978: den = b->dimag * (1 + ratio*ratio);
2979: c->dreal = (a->dreal*ratio + a->dimag) / den;
2980: c->dimag = (a->dimag*ratio - a->dreal) / den;
2981: }
2982:
2983: else
2984: {
2985: ratio = b->dimag / b->dreal ;
2986: den = b->dreal * (1 + ratio*ratio);
2987: c->dreal = (a->dreal + a->dimag*ratio) / den;
2988: c->dimag = (a->dimag - a->dreal*ratio) / den;
2989: }
2990:
2991: }
2992:
2993: expptr oftwo(e)
2994: expptr e;
2995: {
2996: int val,res;
2997:
2998: if (! ISCONST (e))
2999: return (0);
3000:
3001: val = e->constblock.const.ci;
3002: switch (val)
3003: {
3004: case 2: res = 1; break;
3005: case 4: res = 2; break;
3006: case 8: res = 3; break;
3007: case 16: res = 4; break;
3008: case 32: res = 5; break;
3009: case 64: res = 6; break;
3010: case 128: res = 7; break;
3011: case 256: res = 8; break;
3012: default: return (0);
3013: }
3014: return (ICON (res));
3015: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.