|
|
1.1 root 1: #include <ctype.h>
2: #include "defs"
3:
4:
5: /* basic simplifying procedure */
6:
7: ptr simple(t,e)
8: int t; /* take on the values LVAL, RVAL, and SUBVAL */
9: register ptr e; /* points to an expression */
10: {
11: int tag, subtype;
12: ptr lp, rp;
13: int ltag;
14: int lsubt;
15: ptr p, e1;
16: ptr exio(), exioop(), dblop(), setfield(), gentemp();
17: int a,b,c;
18:
19: top:
20:
21: if(e == 0) return(0);
22:
23: tag = e->tag;
24: subtype = e->subtype;
25: if(lp = e->leftp)
26: {
27: ltag = lp->tag;
28: lsubt = lp->subtype;
29: }
30: rp = e->rightp;
31:
32: TEST fprintf(diagfile, "simple(%d; tag %d,%d)\n", t,tag,subtype);
33:
34: switch(tag){
35:
36: case TNOTOP:
37: switch(ltag) {
38:
39: case TNOTOP: /* not not = yes */
40: frexpblock(e);
41: e = lp->leftp;
42: frexpblock(lp);
43: goto top;
44:
45: case TLOGOP: /* de Morgan's Law */
46: lp->subtype = (OPOR+OPAND) - lp->subtype;
47: lp->leftp = mknode(TNOTOP,OPNOT,lp->leftp, PNULL);
48: lp->rightp=mknode(TNOTOP,OPNOT,lp->rightp, PNULL);
49: frexpblock(e);
50: e = lp;
51: goto top;
52:
53: case TRELOP: /* reverse the condition */
54: lp->subtype = (OPEQ+OPNE) - lp->subtype;
55: frexpblock(e);
56: e = lp;
57: goto top;
58:
59: case TCALL:
60: case TASGNOP:
61: e->leftp = simple(RVAL,lp);
62:
63: case TNAME:
64: case TFTNBLOCK:
65: lp = simple(RVAL,lp);
66:
67: case TTEMP:
68: if(t == LVAL)
69: e = simple(LVAL,
70: mknode(TASGNOP,0, gentemp(e->leftp), e));
71: break;
72:
73: case TCONST:
74: if(equals(lp->leftp, ".false."))
75: e->leftp = copys(".true.");
76: else if(equals(lp->leftp, ".true."))
77: e->leftp = copys(".false.");
78: else goto typerr;
79:
80: e->tag = TCONST;
81: e->subtype = 0;
82: cfree(lp->leftp);
83: frexpblock(lp);
84: break;
85:
86: default: goto typerr;
87: }
88: break;
89:
90:
91:
92:
93: case TLOGOP: switch(subtype) {
94: case OPOR:
95: case OPAND:
96: goto binop;
97:
98: case OP2OR:
99: case OP2AND:
100: lp = e->leftp = simple(RVAL, lp);
101: if(lp->tag != TTEMP)
102: lp = simple(RVAL,
103: mknode(TASGNOP,0, gent(TYLOG,0),lp));
104: return( simple(LVAL, mknode(TASGNOP,subtype,lp,rp)) );
105: default:
106: fatal("impossible logical operator");
107: }
108:
109: case TNEGOP:
110: lp = e->leftp = simple(RVAL,lp);
111: ltag = lp->tag;
112: lsubt = lp->subtype;
113:
114: if(ltag==TNEGOP)
115: {
116: frexpblock(e);
117: e = lp->leftp;
118: frexpblock(lp);
119: goto top;
120: }
121: else goto lvcheck;
122:
123: case TAROP:
124: case TRELOP:
125:
126: binop:
127:
128: e->leftp = simple(RVAL,lp);
129: lp = e->leftp;
130: ltag = lp->tag;
131: lsubt = lp->subtype;
132:
133: e->rightp= simple(RVAL,rp);
134: rp = e->rightp;
135:
136: if(tag==TAROP && isicon(rp,&b) )
137: { /* simplify a*1, a/1 , a+0, a-0 */
138: if( ((subtype==OPSTAR||subtype==OPSLASH) && b==1) ||
139: ((subtype==OPPLUS||subtype==OPMINUS) && b==0) )
140: {
141: frexpr(rp);
142: mvexpr(lp,e);
143: goto top;
144: }
145:
146: if(isicon(lp, &a)) /* try folding const op const */
147: {
148: e1 = fold(e);
149: if(e1!=e || e1->tag!=TAROP)
150: {
151: e = e1;
152: goto top;
153: }
154: }
155: if(ltag==TAROP && lp->needpar==0 && isicon(lp->rightp,&a) )
156: { /* look for cases of (e op const ) op' const */
157:
158: if( (subtype==OPPLUS||subtype==OPMINUS) &&
159: (lsubt==OPPLUS||lsubt==OPMINUS) )
160: { /* (e +- const) +- const */
161: c = (subtype==OPPLUS ? 1 : -1) * b +
162: (lsubt==OPPLUS? 1 : -1) * a;
163: if(c > 0)
164: subtype = OPPLUS;
165: else {
166: subtype = OPMINUS;
167: c = -c;
168: }
169: fixexpr:
170: frexpr(rp);
171: frexpr(lp->rightp);
172: frexpblock(e);
173: e = lp;
174: e->subtype = subtype;
175: e->rightp = mkint(c);
176: goto top;
177: }
178:
179: else if(lsubt==OPSTAR &&
180: ( (subtype==OPSTAR) ||
181: (subtype==OPSLASH && a%b==0)) )
182: { /* (e * const ) (* or /) const */
183: c = (subtype==OPSTAR ? a*b : a/b );
184: subtype = OPSTAR;
185: goto fixexpr;
186: }
187: }
188: if(ltag==TAROP && (lsubt==OPPLUS || lsubt==OPMINUS) &&
189: subtype==OPSLASH && divides(lp,conval(rp)) )
190: {
191: e->leftp = mknode(TAROP,OPSLASH,lp->leftp, cpexpr(rp));
192: e->rightp = mknode(TAROP,OPSLASH,lp->rightp, rp);
193: e->subtype = lsubt;
194: goto top;
195: }
196: }
197:
198: else if( tag==TRELOP && isicon(lp,&a) && isicon(rp,&b) )
199: {
200: e1 = fold(e);
201: if(e1!=e || e1->tag!=TRELOP)
202: {
203: e = e1;
204: goto top;
205: }
206: }
207:
208: lvcheck:
209: if(t == LVAL)
210: e = simple(LVAL, mknode(TASGNOP,0, gentemp(e),e));
211: else if(t == SUBVAL)
212: { /* test for legal Fortran c*v +-c form */
213: if(tailor.ftn77 && e->vtype==TYINT)
214: break;
215: if(tag==TAROP && (subtype==OPPLUS || subtype==OPMINUS))
216: if(rp->tag==TCONST && rp->vtype==TYINT)
217: {
218: if(!cvform(lp))
219: e->leftp = simple(SUBVAL, lp);
220: }
221: else goto makesub;
222: else if( !cvform(e) ) goto makesub;
223: }
224: break;
225:
226: case TCALL:
227: if( lp->tag!=TFTNBLOCK && ioop(lp->sthead->namep) )
228: {
229: e = exioop(e, YES);
230: exlab(0);
231: break;
232: }
233: e->rightp = simple(RVAL, rp);
234: if(t == SUBVAL)
235: goto makesub;
236: if(t == LVAL)
237: e = simple(RVAL, mknode(TASGNOP,0, gentemp(e),e));
238: break;
239:
240:
241: case TNAME:
242: if(e->voffset)
243: fixsubs(e);
244: if(e->vsubs)
245: e->vsubs = simple(SUBVAL, e->vsubs);
246: if(t==SUBVAL && !vform(e))
247: goto makesub;
248:
249: case TTEMP:
250: case TFTNBLOCK:
251: case TCONST:
252: if(t==SUBVAL && e->vtype!=TYINT)
253: goto makesub;
254: break;
255:
256: case TASGNOP:
257: lp = e->leftp = simple(LVAL,lp);
258: if(subtype==OP2OR || subtype==OP2AND)
259: e = dblop(e);
260:
261: else {
262: rp = e->rightp = simple(RVAL,rp);
263: if(e->vtype == TYCHAR)
264: excall(mkcall(mkftnblock(TYSUBR,"ef1asc"), arg4(cpexpr(lp),rp)));
265: else if(e->vtype == TYSTRUCT)
266: {
267: if(lp->vtypep->strsize != rp->vtypep->strsize)
268: fatal("simple: attempt to assign incompatible structures");
269: e1 = mkchain(cpexpr(lp),mkchain(rp,
270: mkchain(mkint(lp->vtypep->strsize),CHNULL)));
271: excall(mkcall(mkftnblock(TYSUBR,"ef1ass"),
272: mknode(TLIST, 0, e1, PNULL) ));
273: }
274: else if(lp->vtype == TYFIELD)
275: lp = setfield(e);
276: else {
277: if(subtype != OPASGN) /* but is one of += etc */
278: {
279: rp = e->rightp = simple(RVAL, mknode(
280: (subtype<=OPPOWER?TAROP:TLOGOP),subtype,
281: cpexpr(e->leftp),e->rightp));
282: e->subtype = OPASGN;
283: }
284: exlab(0);
285: prexpr(e);
286: frexpr(rp);
287: }
288: frexpblock(e);
289: e = lp;
290: if(t == SUBVAL) goto top;
291: }
292:
293: break;
294:
295: case TLIST:
296: for(p=lp ; p ; p = p->nextp)
297: p->datap = simple(t, p->datap);
298: break;
299:
300: case TIOSTAT:
301: e = exio(e, 1);
302: break;
303:
304: default:
305: break;
306: }
307:
308: return(e);
309:
310:
311: typerr:
312: exprerr("type match error", CNULL);
313: return(e);
314:
315: makesub:
316: if(t==SUBVAL && e->vtype!=TYINT)
317: warn1("Line %d. Non-integer subscript", yylineno);
318: return( simple(RVAL, mknode(TASGNOP,0,gent(TYINT,PNULL),e)) );
319: }
320:
321: ptr fold(e)
322: register ptr e;
323: {
324: int a, b, c;
325: register ptr lp, rp;
326:
327: lp = e->leftp;
328: rp = e->rightp;
329:
330: if(lp->tag!=TCONST && lp->tag!=TNEGOP)
331: return(e);
332:
333: if(rp->tag!=TCONST && rp->tag!=TNEGOP)
334: return(e);
335:
336:
337: switch(e->tag)
338: {
339: case TAROP:
340: if( !isicon(lp,&a) || !isicon(rp,&b) )
341: return(e);
342:
343: switch(e->subtype)
344: {
345: case OPPLUS:
346: c = a + b;break;
347: case OPMINUS:
348: c = a - b; break;
349: case OPSTAR:
350: c = a * b; break;
351: case OPSLASH:
352: if(a%b!=0 && (a<0 || b<0) )
353: return(e);
354: c = a / b; break;
355: case OPPOWER:
356: return(e);
357: default:
358: fatal("fold: illegal binary operator");
359: }
360: frexpr(e);
361:
362: if(c >= 0)
363: return( mkint(c) );
364: else return(mknode(TNEGOP,OPMINUS, mkint(-c), PNULL) );
365:
366: case TRELOP:
367: if( !isicon(lp,&a) || !isicon(rp,&b) )
368: return(e);
369: frexpr(e);
370:
371: switch(e->subtype)
372: {
373: case OPEQ:
374: c = a == b; break;
375: case OPLT:
376: c = a < b ; break;
377: case OPGT:
378: c = a > b; break;
379: case OPLE:
380: c = a <= b; break;
381: case OPGE:
382: c = a >= b; break;
383: case OPNE:
384: c = a != b; break;
385: default:
386: fatal("fold: invalid relational operator");
387: }
388: return( mkconst(TYLOG, (c ? ".true." : ".false.")) );
389:
390:
391: case TLOGOP:
392: if(lp->vtype!=TYLOG || rp->vtype!=TYLOG)
393: return(e);
394: a = equals(lp->leftp, ".true.");
395: b = equals(rp->leftp, ".true.");
396: frexpr(e);
397:
398: switch(e->subtype)
399: {
400: case OPAND:
401: case OP2AND:
402: c = a & b; break;
403: case OPOR:
404: case OP2OR:
405: c = a | b; break;
406: default:
407: fatal("fold: invalid logical operator");
408: }
409: return( mkconst(TYLOG, (c? ".true." : ".false")) );
410:
411: default:
412: return(e);
413: }
414: }
415:
416: #define TO + 100*
417:
418:
419: ptr coerce(t,e) /* coerce expression e to type t */
420: int t;
421: register ptr e;
422: {
423: register int et;
424: int econst;
425: char buff[100];
426: char *s, *s1;
427: ptr conrep(), xfixf();
428:
429: if(e->tag == TNEGOP)
430: {
431: e->leftp = coerce(t, e->leftp);
432: goto settype;
433: }
434:
435: et = e->vtype;
436: econst = (e->tag == TCONST);
437: TEST fprintf(diagfile, "coerce type %d to type %d\n", et, t);
438: if(t == et)
439: return(e);
440:
441: switch( et TO t )
442: {
443: case TYCOMPLEX TO TYINT:
444: case TYLREAL TO TYINT:
445: e = coerce(TYREAL,e);
446: case TYREAL TO TYINT:
447: if(econst)
448: e = xfixf(e);
449: if(e->vtype != TYINT)
450: e = mkcall(builtin(TYINT,"ifix"), arg1(e));
451: break;
452:
453: case TYINT TO TYREAL:
454: if(econst)
455: {
456: e->leftp = conrep(e->leftp, ".");
457: goto settype;
458: }
459: e = mkcall(builtin(TYREAL,"float"), arg1(e));
460: break;
461:
462: case TYLREAL TO TYREAL:
463: if(econst)
464: {
465: for(s=e->leftp ; *s && *s!='d';++s)
466: ;
467: *s = 'e';
468: goto settype;
469: }
470: e = mkcall(builtin(TYREAL,"sngl"), arg1(e));
471: break;
472:
473: case TYCOMPLEX TO TYREAL:
474: if(econst)
475: {
476: s1 = (char *)(e->leftp) + 1;
477: s = buff;
478: while(*s1!=',' && *s1!='\0')
479: *s1++ = *s++;
480: *s = '\0';
481: cfree(e->leftp);
482: e->leftp = copys(buff);
483: goto settype;
484: }
485: else
486: e = mkcall(mkftnblock(TYREAL,"real"), arg1(e));
487: break;
488:
489: case TYINT TO TYLREAL:
490: if(econst)
491: {
492: e->leftp = conrep(e->leftp,"d0");
493: goto settype;
494: }
495: case TYCOMPLEX TO TYLREAL:
496: e = coerce(TYREAL,e);
497: case TYREAL TO TYLREAL:
498: if(econst)
499: {
500: for(s=e->leftp ; *s && *s!='e'; ++s)
501: ;
502: if(*s == 'e')
503: *s = 'd';
504: else e->leftp = conrep(e->leftp,"d0");
505: goto settype;
506: }
507: e = mkcall(builtin(TYLREAL,"dble"), arg1(e));
508: break;
509:
510: case TYINT TO TYCOMPLEX:
511: case TYLREAL TO TYCOMPLEX:
512: e = coerce(TYREAL, e);
513: case TYREAL TO TYCOMPLEX:
514: if(e->tag == TCONST)
515: {
516: sprintf(buff, "(%s,0.)", e->leftp);
517: cfree(e->leftp);
518: e->leftp = copys(buff);
519: goto settype;
520: }
521: else
522: e = mkcall(builtin(TYCOMPLEX,"cmplx"),
523: arg2(e, mkconst(TYREAL,"0.")));
524: break;
525:
526:
527: default:
528: goto mismatch;
529: }
530:
531: return(e);
532:
533:
534: mismatch:
535: exprerr("impossible conversion", "");
536: frexpr(e);
537: return( errnode() );
538:
539:
540: settype:
541: e->vtype = t;
542: return(e);
543: }
544:
545:
546:
547: /* check whether expression is in form c, v, or v*c */
548: cvform(p)
549: register ptr p;
550: {
551: switch(p->tag)
552: {
553: case TCONST:
554: return(p->vtype == TYINT);
555:
556: case TNAME:
557: return(vform(p));
558:
559: case TAROP:
560: if(p->subtype==OPSTAR && p->rightp->tag==TCONST
561: && p->rightp->vtype==TYINT && vform(p->leftp))
562: return(1);
563:
564: default:
565: return(0);
566: }
567: }
568:
569:
570:
571:
572: /* is p a simple integer variable */
573: vform(p)
574: register ptr p;
575: {
576: return( p->tag==TNAME && p->vtype==TYINT && p->vdim==0
577: && p->voffset==0 && p->vsubs==0) ;
578: }
579:
580:
581:
582: ptr dblop(p)
583: ptr p;
584: {
585: ptr q;
586:
587: bgnexec();
588: if(p->subtype == OP2OR)
589: q = mknode(TNOTOP,OPNOT, cpexpr(p->leftp), PNULL);
590: else q = cpexpr(p->leftp);
591:
592: pushctl(STIF, q);
593: bgnexec();
594: exasgn(cpexpr(p->leftp), OPASGN, p->rightp);
595: ifthen();
596: popctl();
597: addexec();
598: return(p->leftp);
599: }
600:
601:
602:
603:
604: divides(a,b)
605: ptr a;
606: int b;
607: {
608: if(a->vtype!=TYINT)
609: return(0);
610:
611: switch(a->tag)
612: {
613: case TNEGOP:
614: return( divides(a->leftp,b) );
615:
616: case TCONST:
617: return( conval(a) % b == 0);
618:
619: case TAROP:
620: switch(a->subtype)
621: {
622: case OPPLUS:
623: case OPMINUS:
624: return(divides(a->leftp,b)&&
625: divides(a->rightp,b) );
626:
627: case OPSTAR:
628: return(divides(a->rightp,b));
629:
630: default:
631: return(0);
632: }
633: default:
634: return(0);
635: }
636: /* NOTREACHED */
637: }
638:
639: /* truncate floating point constant to integer */
640:
641: #define MAXD 100
642:
643: ptr xfixf(e)
644: struct exprblock *e;
645: {
646: char digit[MAXD+1]; /* buffer into which digits are placed */
647: char *first; /* points to first nonzero digit */
648: register char *end; /* points at position past last digit */
649: register char *dot; /* decimal point is immediately to left of this digit */
650: register char *s;
651: int expon;
652:
653: dot = NULL;
654: end = digit;
655: expon = 0;
656:
657: for(s = e->leftp ; *s; ++s)
658: if( isdigit(*s) )
659: {
660: if(end-digit > MAXD)
661: return(e);
662: *end++ = *s;
663: }
664: else if(*s == '.')
665: dot = end;
666: else if(*s=='d' || *s=='e')
667: {
668: expon = convci(s+1);
669: break;
670: }
671: else fatal1("impossible character %d in floating constant", *s);
672:
673: if(dot == NULL)
674: dot = end;
675: dot += expon;
676: if(dot-digit > MAXD)
677: return(e);
678: for(first = digit; first<end && *first=='0' ; ++first)
679: ;
680: if(dot<=first)
681: {
682: dot = first+1;
683: *first = '0';
684: }
685: else while(end < dot)
686: *end++ = '0';
687: *dot = '\0';
688: cfree(e->leftp);
689: e->leftp = copys(first);
690: e->vtype = TYINT;
691: return(e);
692: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.