|
|
1.1 root 1: #include "defs"
2:
3: LOCAL expptr fold(), mkpower(), stfcall();
4: LOCAL letter(), conspower(), consbinop(), zdiv();
5:
6: /* little routines to create constant blocks */
7:
8: Constp mkconst(t)
9: register int t;
10: {
11: register Constp p;
12:
13: p = ALLOC(Constblock);
14: p->tag = TCONST;
15: p->vtype = t;
16: return(p);
17: }
18:
19:
20: expptr mklogcon(l)
21: register int l;
22: {
23: register Constp p;
24:
25: p = mkconst(TYLOGICAL);
26: p->Const.ci = l;
27: return( (expptr) p );
28: }
29:
30:
31:
32: expptr mkintcon(l)
33: ftnint l;
34: {
35: register Constp p;
36:
37: p = mkconst(TYLONG);
38: p->Const.ci = l;
39: #ifdef MAXSHORT
40: if(l >= -MAXSHORT && l <= MAXSHORT)
41: p->vtype = TYSHORT;
42: #endif
43: return( (expptr) p );
44: }
45:
46:
47:
48: expptr mkaddcon(l)
49: register int l;
50: {
51: register Constp p;
52:
53: p = mkconst(TYADDR);
54: p->Const.ci = l;
55: return( (expptr) p );
56: }
57:
58:
59:
60: expptr mkrealcon(t, d)
61: register int t;
62: double d;
63: {
64: register Constp p;
65:
66: p = mkconst(t);
67: p->Const.cd[0] = d;
68: return( (expptr) p );
69: }
70:
71:
72: expptr mkbitcon(shift, leng, s)
73: int shift;
74: int leng;
75: char *s;
76: {
77: register Constp p;
78:
79: p = mkconst(TYUNKNOWN);
80: p->Const.ci = 0;
81: while(--leng >= 0)
82: if(*s != ' ')
83: p->Const.ci = (p->Const.ci << shift) | hextoi(*s++);
84: return( (expptr) p );
85: }
86:
87:
88:
89:
90:
91: expptr mkstrcon(l,v)
92: int l;
93: register char *v;
94: {
95: register Constp p;
96: register char *s;
97:
98: p = mkconst(TYCHAR);
99: p->vleng = ICON(l);
100: p->Const.ccp = s = (char *) ckalloc(l);
101: while(--l >= 0)
102: *s++ = *v++;
103: return( (expptr) p );
104: }
105:
106:
107: expptr mkcxcon(realp,imagp)
108: register expptr realp, imagp;
109: {
110: int rtype, itype;
111: register Constp p;
112: expptr errnode();
113:
114: rtype = realp->headblock.vtype;
115: itype = imagp->headblock.vtype;
116:
117: if( ISCONST(realp) && ISNUMERIC(rtype) && ISCONST(imagp) && ISNUMERIC(itype) )
118: {
119: p = mkconst( (rtype==TYDREAL||itype==TYDREAL) ? TYDCOMPLEX : TYCOMPLEX);
120: if( ISINT(rtype) )
121: p->Const.cd[0] = realp->constblock.Const.ci;
122: else p->Const.cd[0] = realp->constblock.Const.cd[0];
123: if( ISINT(itype) )
124: p->Const.cd[1] = imagp->constblock.Const.ci;
125: else p->Const.cd[1] = imagp->constblock.Const.cd[0];
126: }
127: else
128: {
129: err("invalid complex constant");
130: p = (Constp)errnode();
131: }
132:
133: frexpr(realp);
134: frexpr(imagp);
135: return( (expptr) p );
136: }
137:
138:
139: expptr errnode()
140: {
141: struct Errorblock *p;
142: p = ALLOC(Errorblock);
143: p->tag = TERROR;
144: p->vtype = TYERROR;
145: return( (expptr) p );
146: }
147:
148:
149:
150:
151:
152: expptr mkconv(t, p)
153: register int t;
154: register expptr p;
155: {
156: register expptr q;
157: register int pt;
158: expptr opconv();
159:
160: if(t==TYUNKNOWN || t==TYERROR)
161: badtype("mkconv", t);
162: pt = p->headblock.vtype;
163: if(t == pt)
164: return(p);
165:
166: else if( ISCONST(p) && pt!=TYADDR)
167: {
168: q = (expptr) mkconst(t);
169: consconv(t, &(q->constblock.Const),
170: p->constblock.vtype, &(p->constblock.Const) );
171: frexpr(p);
172: }
173: #if TARGET == PDP11
174: else if(ISINT(t) && pt==TYCHAR)
175: {
176: q = mkexpr(OPBITAND, opconv(p,TYSHORT), ICON(255));
177: if(t == TYLONG)
178: q = opconv(q, TYLONG);
179: }
180: #endif
181: else
182: q = opconv(p, t);
183:
184: if(t == TYCHAR)
185: q->constblock.vleng = ICON(1);
186: return(q);
187: }
188:
189:
190:
191: expptr opconv(p, t)
192: expptr p;
193: int t;
194: {
195: register expptr q;
196:
197: q = mkexpr(OPCONV, p, PNULL);
198: q->headblock.vtype = t;
199: return(q);
200: }
201:
202:
203:
204: expptr addrof(p)
205: expptr p;
206: {
207: return( mkexpr(OPADDR, p, PNULL) );
208: }
209:
210:
211:
212: tagptr cpexpr(p)
213: register tagptr p;
214: {
215: register tagptr e;
216: int tag;
217: register chainp ep, pp;
218: tagptr cpblock();
219:
220: static int blksize[ ] =
221: {
222: 0,
223: sizeof(struct Nameblock),
224: sizeof(struct Constblock),
225: sizeof(struct Exprblock),
226: sizeof(struct Addrblock),
227: sizeof(struct Primblock),
228: sizeof(struct Listblock),
229: sizeof(struct Errorblock)
230: };
231:
232: if(p == NULL)
233: return(NULL);
234:
235: if( (tag = p->tag) == TNAME)
236: return(p);
237:
238: e = cpblock( blksize[p->tag] , p);
239:
240: switch(tag)
241: {
242: case TCONST:
243: if(e->constblock.vtype == TYCHAR)
244: {
245: e->constblock.Const.ccp =
246: copyn(e->constblock.vleng->constblock.Const.ci+1,
247: /*was 1+strlen(e->constblock.Const.ccp) */
248: e->constblock.Const.ccp);
249: e->constblock.vleng =
250: (expptr) cpexpr(e->constblock.vleng);
251: }
252: case TERROR:
253: break;
254:
255: case TEXPR:
256: e->exprblock.leftp = (expptr) cpexpr(p->exprblock.leftp);
257: e->exprblock.rightp = (expptr) cpexpr(p->exprblock.rightp);
258: break;
259:
260: case TLIST:
261: if(pp = p->listblock.listp)
262: {
263: ep = e->listblock.listp =
264: mkchain( cpexpr(pp->datap), CHNULL);
265: for(pp = pp->nextp ; pp ; pp = pp->nextp)
266: ep = ep->nextp =
267: mkchain( cpexpr(pp->datap), CHNULL);
268: }
269: break;
270:
271: case TADDR:
272: e->addrblock.vleng = (expptr) cpexpr(e->addrblock.vleng);
273: e->addrblock.memoffset = (expptr)cpexpr(e->addrblock.memoffset);
274: e->addrblock.istemp = NO;
275: break;
276:
277: case TPRIM:
278: e->primblock.argsp = (struct Listblock *)
279: cpexpr(e->primblock.argsp);
280: e->primblock.fcharp = (expptr) cpexpr(e->primblock.fcharp);
281: e->primblock.lcharp = (expptr) cpexpr(e->primblock.lcharp);
282: break;
283:
284: default:
285: badtag("cpexpr", tag);
286: }
287:
288: return(e);
289: }
290:
291: frexpr(p)
292: register tagptr p;
293: {
294: register chainp q;
295:
296: if(p == NULL)
297: return;
298:
299: switch(p->tag)
300: {
301: case TCONST:
302: if( ISCHAR(p) )
303: {
304: free( (charptr) (p->constblock.Const.ccp) );
305: frexpr(p->constblock.vleng);
306: }
307: break;
308:
309: case TADDR:
310: if(p->addrblock.istemp)
311: {
312: frtemp(p);
313: return;
314: }
315: frexpr(p->addrblock.vleng);
316: frexpr(p->addrblock.memoffset);
317: break;
318:
319: case TERROR:
320: break;
321:
322: case TNAME:
323: return;
324:
325: case TPRIM:
326: frexpr(p->primblock.argsp);
327: frexpr(p->primblock.fcharp);
328: frexpr(p->primblock.lcharp);
329: break;
330:
331: case TEXPR:
332: frexpr(p->exprblock.leftp);
333: if(p->exprblock.rightp)
334: frexpr(p->exprblock.rightp);
335: break;
336:
337: case TLIST:
338: for(q = p->listblock.listp ; q ; q = q->nextp)
339: frexpr(q->datap);
340: frchain( &(p->listblock.listp) );
341: break;
342:
343: default:
344: badtag("frexpr", p->tag);
345: }
346:
347: free( (charptr) p );
348: }
349:
350: /* fix up types in expression; replace subtrees and convert
351: names to address blocks */
352:
353: expptr fixtype(p)
354: register tagptr p;
355: {
356:
357: if(p == 0)
358: return(0);
359:
360: switch(p->tag)
361: {
362: case TCONST:
363: if(ONEOF(p->constblock.vtype,MSKINT|MSKLOGICAL|MSKADDR) )
364: return( (expptr) p);
365: #if TARGET == VAX
366: if(ONEOF(p->constblock.vtype,MSKREAL) &&
367: p->constblock.Const.cd[0]==0)
368: return( (expptr) p);
369: #endif
370: return( (expptr) putconst(p) );
371:
372: case TADDR:
373: p->addrblock.memoffset = fixtype(p->addrblock.memoffset);
374: return( (expptr) p);
375:
376: case TERROR:
377: return( (expptr) p);
378:
379: default:
380: badtag("fixtype", p->tag);
381:
382: case TEXPR:
383: return( fixexpr(p) );
384:
385: case TLIST:
386: return( (expptr) p );
387:
388: case TPRIM:
389: if(p->primblock.argsp && p->primblock.namep->vclass!=CLVAR)
390: {
391: if(p->primblock.namep->vtype == TYSUBR)
392: {
393: err("function invocation of subroutine");
394: return( errnode() );
395: }
396: else
397: return( mkfunct(p) );
398: }
399: else return( mklhs(p) );
400: }
401: }
402:
403:
404:
405:
406:
407: /* special case tree transformations and cleanups of expression trees */
408:
409: expptr fixexpr(p)
410: register Exprp p;
411: {
412: expptr lp;
413: register expptr rp;
414: register expptr q;
415: int opcode, ltype, rtype, ptype, mtype;
416:
417: if( ISERROR(p) )
418: return( (expptr) p );
419: else if(p->tag != TEXPR)
420: badtag("fixexpr", p->tag);
421: opcode = p->opcode;
422: lp = p->leftp = fixtype(p->leftp);
423: ltype = lp->headblock.vtype;
424: if(opcode==OPASSIGN && lp->tag!=TADDR)
425: {
426: err("left side of assignment must be variable");
427: frexpr(p);
428: return( errnode() );
429: }
430:
431: if(p->rightp)
432: {
433: rp = p->rightp = fixtype(p->rightp);
434: rtype = rp->headblock.vtype;
435: }
436: else
437: {
438: rp = NULL;
439: rtype = 0;
440: }
441:
442: if(ltype==TYERROR || rtype==TYERROR)
443: {
444: frexpr(p);
445: return( errnode() );
446: }
447:
448: /* force folding if possible */
449: if( ISCONST(lp) && (rp==NULL || ISCONST(rp)) )
450: {
451: q = mkexpr(opcode, lp, rp);
452: if( ISCONST(q) )
453: return(q);
454: free( (charptr) q ); /* constants did not fold */
455: }
456:
457: if( (ptype = cktype(opcode, ltype, rtype)) == TYERROR)
458: {
459: frexpr(p);
460: return( errnode() );
461: }
462:
463: switch(opcode)
464: {
465: case OPCONCAT:
466: if(p->vleng == NULL)
467: p->vleng = mkexpr(OPPLUS,
468: cpexpr(lp->headblock.vleng),
469: cpexpr(rp->headblock.vleng) );
470: break;
471:
472: case OPASSIGN:
473: case OPPLUSEQ:
474: case OPSTAREQ:
475: if(ltype == rtype)
476: break;
477: if( ! ISCONST(rp) && ISREAL(ltype) && ISREAL(rtype) )
478: break;
479: if( ISCOMPLEX(ltype) || ISCOMPLEX(rtype) )
480: break;
481: if( ONEOF(ltype, MSKADDR|MSKINT) && ONEOF(rtype, MSKADDR|MSKINT)
482: #if FAMILY==PCC
483: && typesize[ltype]>=typesize[rtype] )
484: #else
485: && typesize[ltype]==typesize[rtype] )
486: #endif
487: break;
488: p->rightp = fixtype( mkconv(ptype, rp) );
489: break;
490:
491: case OPSLASH:
492: if( ISCOMPLEX(rtype) )
493: {
494: p = (Exprp) call2(ptype,
495: ptype==TYCOMPLEX? "c_div" : "z_div",
496: mkconv(ptype, lp), mkconv(ptype, rp) );
497: break;
498: }
499: case OPPLUS:
500: case OPMINUS:
501: case OPSTAR:
502: case OPMOD:
503: if(ptype==TYDREAL && ( (ltype==TYREAL && ! ISCONST(lp) ) ||
504: (rtype==TYREAL && ! ISCONST(rp) ) ))
505: break;
506: if( ISCOMPLEX(ptype) )
507: break;
508: if(ltype != ptype)
509: p->leftp = fixtype(mkconv(ptype,lp));
510: if(rtype != ptype)
511: p->rightp = fixtype(mkconv(ptype,rp));
512: break;
513:
514: case OPPOWER:
515: return( mkpower(p) );
516:
517: case OPLT:
518: case OPLE:
519: case OPGT:
520: case OPGE:
521: case OPEQ:
522: case OPNE:
523: if(ltype == rtype)
524: break;
525: mtype = cktype(OPMINUS, ltype, rtype);
526: if(mtype==TYDREAL && ( (ltype==TYREAL && ! ISCONST(lp)) ||
527: (rtype==TYREAL && ! ISCONST(rp)) ))
528: break;
529: if( ISCOMPLEX(mtype) )
530: break;
531: if(ltype != mtype)
532: p->leftp = fixtype(mkconv(mtype,lp));
533: if(rtype != mtype)
534: p->rightp = fixtype(mkconv(mtype,rp));
535: break;
536:
537:
538: case OPCONV:
539: ptype = cktype(OPCONV, p->vtype, ltype);
540: if(lp->tag==TEXPR && lp->exprblock.opcode==OPCOMMA)
541: {
542: lp->exprblock.rightp =
543: fixtype( mkconv(ptype, lp->exprblock.rightp) );
544: free( (charptr) p );
545: p = (Exprp) lp;
546: }
547: break;
548:
549: case OPADDR:
550: if(lp->tag==TEXPR && lp->exprblock.opcode==OPADDR)
551: fatal("addr of addr");
552: break;
553:
554: case OPCOMMA:
555: case OPQUEST:
556: case OPCOLON:
557: break;
558:
559: case OPMIN:
560: case OPMAX:
561: ptype = p->vtype;
562: break;
563:
564: default:
565: break;
566: }
567:
568: p->vtype = ptype;
569: return((expptr) p);
570: }
571:
572: #if SZINT < SZLONG
573: /*
574: for efficient subscripting, replace long ints by shorts
575: in easy places
576: */
577:
578: expptr shorten(p)
579: register expptr p;
580: {
581: register expptr q;
582:
583: if(p->headblock.vtype != TYLONG)
584: return(p);
585:
586: switch(p->tag)
587: {
588: case TERROR:
589: case TLIST:
590: return(p);
591:
592: case TCONST:
593: case TADDR:
594: return( mkconv(TYINT,p) );
595:
596: case TEXPR:
597: break;
598:
599: default:
600: badtag("shorten", p->tag);
601: }
602:
603: switch(p->exprblock.opcode)
604: {
605: case OPPLUS:
606: case OPMINUS:
607: case OPSTAR:
608: q = shorten( cpexpr(p->exprblock.rightp) );
609: if(q->headblock.vtype == TYINT)
610: {
611: p->exprblock.leftp = shorten(p->exprblock.leftp);
612: if(p->exprblock.leftp->headblock.vtype == TYLONG)
613: frexpr(q);
614: else
615: {
616: frexpr(p->exprblock.rightp);
617: p->exprblock.rightp = q;
618: p->exprblock.vtype = TYINT;
619: }
620: }
621: break;
622:
623: case OPNEG:
624: p->exprblock.leftp = shorten(p->exprblock.leftp);
625: if(p->exprblock.leftp->headblock.vtype == TYINT)
626: p->exprblock.vtype = TYINT;
627: break;
628:
629: case OPCALL:
630: case OPCCALL:
631: p = mkconv(TYINT,p);
632: break;
633: default:
634: break;
635: }
636:
637: return(p);
638: }
639: #endif
640:
641: /* fix an argument list, taking due care for special first level cases */
642:
643: fixargs(doput, p0)
644: int doput; /* doput is true if the function is not intrinsic */
645: struct Listblock *p0;
646: {
647: register chainp p;
648: register tagptr q, t;
649: register int qtag;
650: int nargs;
651: Addrp mkscalar();
652:
653: nargs = 0;
654: if(p0)
655: for(p = p0->listp ; p ; p = p->nextp)
656: {
657: ++nargs;
658: q = p->datap;
659: qtag = q->tag;
660: if(qtag == TCONST)
661: {
662: if(q->constblock.vtype == TYSHORT)
663: q = (tagptr) mkconv(tyint, q);
664: /* leave constant arguments of intrinsics alone --
665: * the expression might still simplify.
666: */
667: p->datap = doput ? (tagptr) putconst(q) : q ;
668: }
669: else if(qtag==TPRIM && q->primblock.argsp==0 &&
670: q->primblock.namep->vclass==CLPROC)
671: p->datap = (tagptr) mkaddr(q->primblock.namep);
672: else if(qtag==TPRIM && q->primblock.argsp==0 &&
673: q->primblock.namep->vdim!=NULL)
674: p->datap = (tagptr) mkscalar(q->primblock.namep);
675: else if(qtag==TPRIM && q->primblock.argsp==0 &&
676: q->primblock.namep->vdovar &&
677: (t = (tagptr) memversion(q->primblock.namep)) )
678: p->datap = (tagptr) fixtype(t);
679: else
680: p->datap = (tagptr) fixtype(q);
681: }
682: return(nargs);
683: }
684:
685:
686: Addrp mkscalar(np)
687: register Namep np;
688: {
689: register Addrp ap;
690:
691: vardcl(np);
692: ap = mkaddr(np);
693:
694: #if TARGET == VAX
695: /* on the VAX, prolog causes array arguments
696: to point at the (0,...,0) element, except when
697: subscript checking is on
698: */
699: if( !checksubs && np->vstg==STGARG)
700: {
701: register struct Dimblock *dp;
702: dp = np->vdim;
703: frexpr(ap->memoffset);
704: ap->memoffset = mkexpr(OPSTAR,
705: (np->vtype==TYCHAR ?
706: cpexpr(np->vleng) :
707: (tagptr)ICON(typesize[np->vtype]) ),
708: cpexpr(dp->baseoffset) );
709: }
710: #endif
711: return(ap);
712: }
713:
714:
715:
716:
717:
718: expptr mkfunct(p)
719: register struct Primblock *p;
720: {
721: struct Entrypoint *ep;
722: Addrp ap;
723: struct Extsym *extp;
724: register Namep np;
725: register expptr q;
726: expptr intrcall();
727: int k, nargs;
728: int class;
729:
730: if(p->tag != TPRIM)
731: return( errnode() );
732:
733: np = p->namep;
734: class = np->vclass;
735:
736: if(class == CLUNKNOWN)
737: {
738: np->vclass = class = CLPROC;
739: if(np->vstg == STGUNKNOWN)
740: {
741: if(np->vtype!=TYSUBR && (k = intrfunct(np->varname)) )
742: {
743: np->vstg = STGINTR;
744: np->vardesc.varno = k;
745: np->vprocclass = PINTRINSIC;
746: }
747: else
748: {
749: extp = mkext( varunder(VL,np->varname) );
750: extp->extstg = STGEXT;
751: np->vstg = STGEXT;
752: np->vardesc.varno = extp - extsymtab;
753: np->vprocclass = PEXTERNAL;
754: }
755: }
756: else if(np->vstg==STGARG)
757: {
758: if(np->vtype == TYCHAR || bugwarn & 2)
759: warn("Dummy procedure not declared EXTERNAL. Code may be wrong.");
760: np->vprocclass = PEXTERNAL;
761: }
762: }
763:
764: if(class != CLPROC)
765: fatali("invalid class code %d for function", class);
766: if(p->fcharp || p->lcharp)
767: {
768: err("no substring of function call");
769: goto error;
770: }
771: impldcl(np);
772: nargs = fixargs( np->vprocclass!=PINTRINSIC, p->argsp);
773:
774: switch(np->vprocclass)
775: {
776: case PEXTERNAL:
777: ap = mkaddr(np);
778: call:
779: q = mkexpr(OPCALL, ap, p->argsp);
780: if( (q->exprblock.vtype = np->vtype) == TYUNKNOWN)
781: {
782: err("attempt to use untyped function");
783: goto error;
784: }
785: if(np->vleng)
786: q->exprblock.vleng = (expptr) cpexpr(np->vleng);
787: break;
788:
789: case PINTRINSIC:
790: q = intrcall(np, p->argsp, nargs);
791: break;
792:
793: case PSTFUNCT:
794: q = stfcall(np, p->argsp);
795: break;
796:
797: case PTHISPROC:
798: warn("recursive call");
799: for(ep = entries ; ep ; ep = ep->entnextp)
800: if(ep->enamep == np)
801: break;
802: if(ep == NULL)
803: fatal("mkfunct: impossible recursion");
804: ap = builtin(np->vtype, varstr(XL, ep->entryname->extname) );
805: goto call;
806:
807: default:
808: fatali("mkfunct: impossible vprocclass %d",
809: (int) (np->vprocclass) );
810: }
811: free( (charptr) p );
812: return(q);
813:
814: error:
815: frexpr(p);
816: return( errnode() );
817: }
818:
819:
820:
821: LOCAL expptr stfcall(np, actlist)
822: Namep np;
823: struct Listblock *actlist;
824: {
825: register chainp actuals;
826: int nargs;
827: chainp oactp, formals;
828: int type;
829: expptr q, rhs, ap;
830: Namep tnp;
831: register struct Rplblock *rp;
832: struct Rplblock *tlist;
833:
834: if(actlist)
835: {
836: actuals = actlist->listp;
837: free( (charptr) actlist);
838: }
839: else
840: actuals = NULL;
841: oactp = actuals;
842:
843: nargs = 0;
844: tlist = NULL;
845: if( (type = np->vtype) == TYUNKNOWN)
846: {
847: err("attempt to use untyped statement function");
848: q = errnode();
849: goto ret;
850: }
851: formals = (chainp) (np->varxptr.vstfdesc->datap);
852: rhs = (expptr) (np->varxptr.vstfdesc->nextp);
853:
854: /* copy actual arguments into temporaries */
855: while(actuals!=NULL && formals!=NULL)
856: {
857: rp = ALLOC(Rplblock);
858: rp->rplnp = tnp = (Namep) (formals->datap);
859: ap = fixtype(actuals->datap);
860: if(tnp->vtype==ap->headblock.vtype && tnp->vtype!=TYCHAR
861: && (ap->tag==TCONST || ap->tag==TADDR) )
862: {
863: rp->rplvp = (expptr) ap;
864: rp->rplxp = NULL;
865: rp->rpltag = ap->tag;
866: }
867: else {
868: rp->rplvp = (expptr) mktemp(tnp->vtype, tnp->vleng);
869: rp->rplxp = fixtype( mkexpr(OPASSIGN, cpexpr(rp->rplvp), ap) );
870: if( (rp->rpltag = rp->rplxp->tag) == TERROR)
871: err("disagreement of argument types in statement function call");
872: }
873: rp->rplnextp = tlist;
874: tlist = rp;
875: actuals = actuals->nextp;
876: formals = formals->nextp;
877: ++nargs;
878: }
879:
880: if(actuals!=NULL || formals!=NULL)
881: err("statement function definition and argument list differ");
882:
883: /*
884: now push down names involved in formal argument list, then
885: evaluate rhs of statement function definition in this environment
886: */
887:
888: if(tlist) /* put tlist in front of the rpllist */
889: {
890: for(rp = tlist; rp->rplnextp; rp = rp->rplnextp)
891: ;
892: rp->rplnextp = rpllist;
893: rpllist = tlist;
894: }
895:
896: q = (expptr) mkconv(type, fixtype(cpexpr(rhs)) );
897:
898: /* now generate the tree ( t1=a1, (t2=a2,... , f))))) */
899: while(--nargs >= 0)
900: {
901: if(rpllist->rplxp)
902: q = mkexpr(OPCOMMA, rpllist->rplxp, q);
903: rp = rpllist->rplnextp;
904: frexpr(rpllist->rplvp);
905: free(rpllist);
906: rpllist = rp;
907: }
908:
909: ret:
910: frchain( &oactp );
911: return(q);
912: }
913:
914:
915: static int replaced;
916:
917: Addrp mkplace(np)
918: register Namep np;
919: {
920: register Addrp s;
921: register struct Rplblock *rp;
922: int regn;
923:
924: /* is name on the replace list? */
925:
926: for(rp = rpllist ; rp ; rp = rp->rplnextp)
927: {
928: if(np == rp->rplnp)
929: {
930: replaced = 1;
931: if(rp->rpltag == TNAME)
932: {
933: np = (Namep) (rp->rplvp);
934: break;
935: }
936: else return( (Addrp) cpexpr(rp->rplvp) );
937: }
938: }
939:
940: /* is variable a DO index in a register ? */
941:
942: if(np->vdovar && ( (regn = inregister(np)) >= 0) )
943: if(np->vtype == TYERROR)
944: return( (Addrp)errnode() );
945: else
946: {
947: s = ALLOC(Addrblock);
948: s->tag = TADDR;
949: s->vstg = STGREG;
950: s->vtype = TYIREG;
951: s->memno = regn;
952: s->memoffset = ICON(0);
953: return(s);
954: }
955:
956: vardcl(np);
957: return(mkaddr(np));
958: }
959:
960:
961:
962:
963: expptr mklhs(p)
964: register struct Primblock *p;
965: {
966: expptr suboffset();
967: register Addrp s;
968: Namep np;
969:
970: if(p->tag != TPRIM)
971: return( (expptr) p );
972: np = p->namep;
973:
974: replaced = 0;
975: s = mkplace(np);
976: if(s->tag!=TADDR || s->vstg==STGREG)
977: {
978: free( (charptr) p );
979: return( (expptr) s );
980: }
981:
982: /* compute the address modified by subscripts */
983:
984: if (replaced && bugwarn == 1 && (p->argsp || p->namep->vdim))
985: warnb1("old f77 complained at stmt func arg %s",
986: varstr(VL, np->varname));
987: if (!replaced || bugwarn & 2)
988: s->memoffset = mkexpr(OPPLUS, s->memoffset, suboffset(p) );
989: frexpr(p->argsp);
990: p->argsp = NULL;
991:
992: /* now do substring part */
993:
994: if(p->fcharp || p->lcharp)
995: {
996: if(np->vtype != TYCHAR)
997: errstr("substring of noncharacter %s", varstr(VL,np->varname));
998: else {
999: if(p->lcharp == NULL)
1000: p->lcharp = (expptr) cpexpr(s->vleng);
1001: if(p->fcharp)
1002: s->vleng = mkexpr(OPMINUS, p->lcharp,
1003: mkexpr(OPMINUS, p->fcharp, ICON(1) ));
1004: else {
1005: frexpr(s->vleng);
1006: s->vleng = p->lcharp;
1007: }
1008: }
1009: }
1010:
1011: s->vleng = fixtype( s->vleng );
1012: s->memoffset = fixtype( s->memoffset );
1013: free( (charptr) p );
1014: return( (expptr) s );
1015: }
1016:
1017:
1018:
1019:
1020:
1021: deregister(np)
1022: Namep np;
1023: {
1024: if(nregvar>0 && regnamep[nregvar-1]==np)
1025: {
1026: --nregvar;
1027: #if FAMILY == DMR
1028: putnreg();
1029: #endif
1030: }
1031: }
1032:
1033:
1034:
1035:
1036: Addrp memversion(np)
1037: register Namep np;
1038: {
1039: register Addrp s;
1040:
1041: if(np->vdovar==NO || (inregister(np)<0) )
1042: return(NULL);
1043: np->vdovar = NO;
1044: s = mkplace(np);
1045: np->vdovar = YES;
1046: return(s);
1047: }
1048:
1049:
1050:
1051: inregister(np)
1052: register Namep np;
1053: {
1054: register int i;
1055:
1056: for(i = 0 ; i < nregvar ; ++i)
1057: if(regnamep[i] == np)
1058: return( regnum[i] );
1059: return(-1);
1060: }
1061:
1062:
1063:
1064:
1065: enregister(np)
1066: Namep np;
1067: {
1068: if( inregister(np) >= 0)
1069: return(YES);
1070: if(nregvar >= maxregvar)
1071: return(NO);
1072: vardcl(np);
1073: if( ONEOF(np->vtype, MSKIREG) )
1074: {
1075: regnamep[nregvar++] = np;
1076: if(nregvar > highregvar)
1077: highregvar = nregvar;
1078: #if FAMILY == DMR
1079: putnreg();
1080: #endif
1081: return(YES);
1082: }
1083: else
1084: return(NO);
1085: }
1086:
1087:
1088:
1089:
1090: expptr suboffset(p)
1091: register struct Primblock *p;
1092: {
1093: int n;
1094: expptr size;
1095: chainp cp;
1096: expptr offp, prod;
1097: expptr subcheck();
1098: struct Dimblock *dimp;
1099: expptr sub[MAXDIM+1];
1100: register Namep np;
1101:
1102: np = p->namep;
1103: offp = ICON(0);
1104: n = 0;
1105: if(p->argsp)
1106: for(cp = p->argsp->listp ; cp ; cp = cp->nextp)
1107: {
1108: sub[n++] = fixtype(cpexpr(cp->datap));
1109: if(n > maxdim)
1110: {
1111: erri("more than %d subscripts", maxdim);
1112: break;
1113: }
1114: }
1115:
1116: dimp = np->vdim;
1117: if(n>0 && dimp==NULL)
1118: err("subscripts on scalar variable");
1119: else if(dimp && dimp->ndim!=n)
1120: errstr("wrong number of subscripts on %s",
1121: varstr(VL, np->varname) );
1122: else if(n > 0)
1123: {
1124: prod = sub[--n];
1125: while( --n >= 0)
1126: prod = mkexpr(OPPLUS, sub[n],
1127: mkexpr(OPSTAR, prod, cpexpr(dimp->dims[n].dimsize)) );
1128: #if TARGET == VAX
1129: if(checksubs || np->vstg!=STGARG)
1130: prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1131: #else
1132: prod = mkexpr(OPMINUS, prod, cpexpr(dimp->baseoffset));
1133: #endif
1134: if(checksubs)
1135: prod = subcheck(np, prod);
1136: size = np->vtype == TYCHAR ?
1137: (expptr) cpexpr(np->vleng) : ICON(typesize[np->vtype]);
1138: prod = mkexpr(OPSTAR, prod, size);
1139: offp = mkexpr(OPPLUS, offp, prod);
1140: }
1141:
1142: if(p->fcharp && np->vtype==TYCHAR)
1143: offp = mkexpr(OPPLUS, offp, mkexpr(OPMINUS, cpexpr(p->fcharp), ICON(1) ));
1144:
1145: return(offp);
1146: }
1147:
1148:
1149:
1150:
1151: expptr subcheck(np, p)
1152: Namep np;
1153: register expptr p;
1154: {
1155: struct Dimblock *dimp;
1156: expptr t, checkvar, checkcond, badcall;
1157:
1158: dimp = np->vdim;
1159: if(dimp->nelt == NULL)
1160: return(p); /* don't check arrays with * bounds */
1161: checkvar = NULL;
1162: checkcond = NULL;
1163: if( ISICON(p) )
1164: {
1165: if(p->constblock.Const.ci < 0)
1166: goto badsub;
1167: if( ISICON(dimp->nelt) )
1168: if(p->constblock.Const.ci < dimp->nelt->constblock.Const.ci)
1169: return(p);
1170: else
1171: goto badsub;
1172: }
1173: if(p->tag==TADDR && p->addrblock.vstg==STGREG)
1174: {
1175: checkvar = (expptr) cpexpr(p);
1176: t = p;
1177: }
1178: else {
1179: checkvar = (expptr) mktemp(p->headblock.vtype, ENULL);
1180: t = mkexpr(OPASSIGN, cpexpr(checkvar), p);
1181: }
1182: checkcond = mkexpr(OPLT, t, cpexpr(dimp->nelt) );
1183: if( ! ISICON(p) )
1184: checkcond = mkexpr(OPAND, checkcond,
1185: mkexpr(OPLE, ICON(0), cpexpr(checkvar)) );
1186:
1187: badcall = call4(p->headblock.vtype, "s_rnge",
1188: mkstrcon(VL, np->varname),
1189: mkconv(TYLONG, cpexpr(checkvar)),
1190: mkstrcon(XL, procname),
1191: ICON(lineno) );
1192: badcall->exprblock.opcode = OPCCALL;
1193: p = mkexpr(OPQUEST, checkcond,
1194: mkexpr(OPCOLON, checkvar, badcall));
1195:
1196: return(p);
1197:
1198: badsub:
1199: frexpr(p);
1200: errstr("subscript on variable %s out of range", varstr(VL,np->varname));
1201: return ( ICON(0) );
1202: }
1203:
1204:
1205:
1206:
1207: Addrp mkaddr(p)
1208: register Namep p;
1209: {
1210: struct Extsym *extp;
1211: register Addrp t;
1212: Addrp intraddr();
1213:
1214: switch( p->vstg)
1215: {
1216: case STGUNKNOWN:
1217: if(p->vclass != CLPROC)
1218: break;
1219: extp = mkext( varunder(VL, p->varname) );
1220: extp->extstg = STGEXT;
1221: p->vstg = STGEXT;
1222: p->vardesc.varno = extp - extsymtab;
1223: p->vprocclass = PEXTERNAL;
1224:
1225: case STGCOMMON:
1226: case STGEXT:
1227: case STGBSS:
1228: case STGINIT:
1229: case STGEQUIV:
1230: case STGARG:
1231: case STGLENG:
1232: case STGAUTO:
1233: t = ALLOC(Addrblock);
1234: t->tag = TADDR;
1235: if(p->vclass==CLPROC && p->vprocclass==PTHISPROC)
1236: t->vclass = CLVAR;
1237: else
1238: t->vclass = p->vclass;
1239: t->vtype = p->vtype;
1240: t->vstg = p->vstg;
1241: t->memno = p->vardesc.varno;
1242: t->memoffset = ICON(p->voffset);
1243: if(p->vleng)
1244: {
1245: t->vleng = (expptr) cpexpr(p->vleng);
1246: if( ISICON(t->vleng) )
1247: t->varleng = t->vleng->constblock.Const.ci;
1248: }
1249: return(t);
1250:
1251: case STGINTR:
1252: return( intraddr(p) );
1253:
1254: }
1255: /*debug*/fprintf(diagfile,"mkaddr. vtype=%d, vclass=%d\n", p->vtype, p->vclass);
1256: badstg("mkaddr", p->vstg);
1257: /* NOTREACHED */
1258: }
1259:
1260:
1261:
1262:
1263: Addrp mkarg(type, argno)
1264: int type, argno;
1265: {
1266: register Addrp p;
1267:
1268: p = ALLOC(Addrblock);
1269: p->tag = TADDR;
1270: p->vtype = type;
1271: p->vclass = CLVAR;
1272: p->vstg = (type==TYLENG ? STGLENG : STGARG);
1273: p->memno = argno;
1274: return(p);
1275: }
1276:
1277:
1278:
1279:
1280: expptr mkprim(v, args, substr)
1281: register union
1282: {
1283: struct Paramblock paramblock;
1284: struct Nameblock nameblock;
1285: struct Headblock headblock;
1286: } *v;
1287: struct Listblock *args;
1288: chainp substr;
1289: {
1290: register struct Primblock *p;
1291:
1292: if(v->headblock.vclass == CLPARAM)
1293: {
1294: if(args || substr)
1295: {
1296: errstr("no qualifiers on parameter name %s",
1297: varstr(VL,v->paramblock.varname));
1298: frexpr(args);
1299: if(substr)
1300: {
1301: frexpr(substr->datap);
1302: frexpr(substr->nextp->datap);
1303: frchain(&substr);
1304: }
1305: frexpr(v);
1306: return( errnode() );
1307: }
1308: return( (expptr) cpexpr(v->paramblock.paramval) );
1309: }
1310:
1311: p = ALLOC(Primblock);
1312: p->tag = TPRIM;
1313: p->vtype = v->nameblock.vtype;
1314: p->namep = (Namep) v;
1315: p->argsp = args;
1316: if(substr)
1317: {
1318: p->fcharp = (expptr) (substr->datap);
1319: p->lcharp = (expptr) (substr->nextp->datap);
1320: frchain(&substr);
1321: }
1322: return( (expptr) p);
1323: }
1324:
1325:
1326:
1327: vardcl(v)
1328: register Namep v;
1329: {
1330: int nelt;
1331: struct Dimblock *t;
1332: Addrp p;
1333: expptr neltp;
1334:
1335: if(v->vdcldone)
1336: return;
1337: if(v->vclass == CLNAMELIST)
1338: return;
1339:
1340: if(v->vtype == TYUNKNOWN)
1341: impldcl(v);
1342: if(v->vclass == CLUNKNOWN)
1343: v->vclass = CLVAR;
1344: else if(v->vclass!=CLVAR && v->vprocclass!=PTHISPROC)
1345: {
1346: dclerr("used as variable", v);
1347: return;
1348: }
1349: if(v->vstg==STGUNKNOWN)
1350: v->vstg = implstg[ letter(v->varname[0]) ];
1351:
1352: switch(v->vstg)
1353: {
1354: case STGBSS:
1355: v->vardesc.varno = ++lastvarno;
1356: break;
1357: case STGAUTO:
1358: if(v->vclass==CLPROC && v->vprocclass==PTHISPROC)
1359: break;
1360: nelt = 1;
1361: if(t = v->vdim)
1362: if( (neltp = t->nelt) && ISCONST(neltp) )
1363: nelt = neltp->constblock.Const.ci;
1364: else
1365: dclerr("adjustable automatic array", v);
1366: p = autovar(nelt, v->vtype, v->vleng);
1367: v->voffset = p->memoffset->constblock.Const.ci;
1368: frexpr(p);
1369: break;
1370:
1371: default:
1372: break;
1373: }
1374: v->vdcldone = YES;
1375: }
1376:
1377:
1378:
1379:
1380: impldcl(p)
1381: register Namep p;
1382: {
1383: register int k;
1384: int type, leng;
1385:
1386: if(p->vdcldone || (p->vclass==CLPROC && p->vprocclass==PINTRINSIC) )
1387: return;
1388: if(p->vtype == TYUNKNOWN)
1389: {
1390: k = letter(p->varname[0]);
1391: type = impltype[ k ];
1392: leng = implleng[ k ];
1393: if(type == TYUNKNOWN)
1394: {
1395: if(p->vclass == CLPROC)
1396: return;
1397: dclerr("attempt to use undefined variable", p);
1398: type = TYERROR;
1399: leng = 1;
1400: }
1401: settype(p, type, leng);
1402: }
1403: }
1404:
1405:
1406:
1407:
1408: LOCAL letter(c)
1409: register int c;
1410: {
1411: if( isupper(c) )
1412: c = tolower(c);
1413: return(c - 'a');
1414: }
1415:
1416: #define ICONEQ(z, c) (ISICON(z) && z->constblock.Const.ci==c)
1417: #define COMMUTE { e = lp; lp = rp; rp = e; }
1418:
1419:
1420: expptr mkexpr(opcode, lp, rp)
1421: int opcode;
1422: register expptr lp, rp;
1423: {
1424: register expptr e, e1;
1425: int etype;
1426: int ltype, rtype;
1427: int ltag, rtag;
1428:
1429: ltype = lp->headblock.vtype;
1430: ltag = lp->tag;
1431: if(rp && opcode!=OPCALL && opcode!=OPCCALL)
1432: {
1433: rtype = rp->headblock.vtype;
1434: rtag = rp->tag;
1435: }
1436: else rtype = 0;
1437:
1438: etype = cktype(opcode, ltype, rtype);
1439: if(etype == TYERROR)
1440: goto error;
1441:
1442: switch(opcode)
1443: {
1444: /* check for multiplication by 0 and 1 and addition to 0 */
1445:
1446: case OPSTAR:
1447: if( ISCONST(lp) )
1448: COMMUTE
1449:
1450: if( ISICON(rp) )
1451: {
1452: if(rp->constblock.Const.ci == 0)
1453: goto retright;
1454: goto mulop;
1455: }
1456: break;
1457:
1458: case OPSLASH:
1459: case OPMOD:
1460: if( ICONEQ(rp, 0) )
1461: {
1462: err("attempted division by zero");
1463: rp = ICON(1);
1464: break;
1465: }
1466: if(opcode == OPMOD)
1467: break;
1468:
1469:
1470: mulop:
1471: if( ISICON(rp) )
1472: {
1473: if(rp->constblock.Const.ci == 1)
1474: goto retleft;
1475:
1476: if(rp->constblock.Const.ci == -1)
1477: {
1478: frexpr(rp);
1479: return( mkexpr(OPNEG, lp, PNULL) );
1480: }
1481: }
1482:
1483: if( ISSTAROP(lp) && ISICON(lp->exprblock.rightp) )
1484: {
1485: if(opcode == OPSTAR)
1486: e = mkexpr(OPSTAR, lp->exprblock.rightp, rp);
1487: else if(ISICON(rp) &&
1488: (lp->exprblock.rightp->constblock.Const.ci %
1489: rp->constblock.Const.ci) == 0)
1490: e = mkexpr(OPSLASH, lp->exprblock.rightp, rp);
1491: else break;
1492:
1493: e1 = lp->exprblock.leftp;
1494: free( (charptr) lp );
1495: return( mkexpr(OPSTAR, e1, e) );
1496: }
1497: break;
1498:
1499:
1500: case OPPLUS:
1501: if( ISCONST(lp) )
1502: COMMUTE
1503: goto addop;
1504:
1505: case OPMINUS:
1506: if( ICONEQ(lp, 0) )
1507: {
1508: frexpr(lp);
1509: return( mkexpr(OPNEG, rp, ENULL) );
1510: }
1511:
1512: if( ISCONST(rp) )
1513: {
1514: opcode = OPPLUS;
1515: consnegop(rp);
1516: }
1517:
1518: addop:
1519: if( ISICON(rp) )
1520: {
1521: if(rp->constblock.Const.ci == 0)
1522: goto retleft;
1523: if( ISPLUSOP(lp) && ISICON(lp->exprblock.rightp) )
1524: {
1525: e = mkexpr(OPPLUS, lp->exprblock.rightp, rp);
1526: e1 = lp->exprblock.leftp;
1527: free( (charptr) lp );
1528: return( mkexpr(OPPLUS, e1, e) );
1529: }
1530: }
1531: break;
1532:
1533:
1534: case OPPOWER:
1535: break;
1536:
1537: case OPNEG:
1538: if(ltag==TEXPR && lp->exprblock.opcode==OPNEG)
1539: {
1540: e = lp->exprblock.leftp;
1541: free( (charptr) lp );
1542: return(e);
1543: }
1544: break;
1545:
1546: case OPNOT:
1547: if(ltag==TEXPR && lp->exprblock.opcode==OPNOT)
1548: {
1549: e = lp->exprblock.leftp;
1550: free( (charptr) lp );
1551: return(e);
1552: }
1553: break;
1554:
1555: case OPCALL:
1556: case OPCCALL:
1557: etype = ltype;
1558: if(rp!=NULL && rp->listblock.listp==NULL)
1559: {
1560: free( (charptr) rp );
1561: rp = NULL;
1562: }
1563: break;
1564:
1565: case OPAND:
1566: case OPOR:
1567: if( ISCONST(lp) )
1568: COMMUTE
1569:
1570: if( ISCONST(rp) )
1571: {
1572: if(rp->constblock.Const.ci == 0)
1573: if(opcode == OPOR)
1574: goto retleft;
1575: else
1576: goto retright;
1577: else if(opcode == OPOR)
1578: goto retright;
1579: else
1580: goto retleft;
1581: }
1582: case OPEQV:
1583: case OPNEQV:
1584:
1585: case OPBITAND:
1586: case OPBITOR:
1587: case OPBITXOR:
1588: case OPBITNOT:
1589: case OPLSHIFT:
1590: case OPRSHIFT:
1591:
1592: case OPLT:
1593: case OPGT:
1594: case OPLE:
1595: case OPGE:
1596: case OPEQ:
1597: case OPNE:
1598:
1599: case OPCONCAT:
1600: break;
1601: case OPMIN:
1602: case OPMAX:
1603:
1604: case OPASSIGN:
1605: case OPPLUSEQ:
1606: case OPSTAREQ:
1607:
1608: case OPCONV:
1609: case OPADDR:
1610:
1611: case OPCOMMA:
1612: case OPQUEST:
1613: case OPCOLON:
1614: break;
1615:
1616: default:
1617: badop("mkexpr", opcode);
1618: }
1619:
1620: e = (expptr) ALLOC(Exprblock);
1621: e->exprblock.tag = TEXPR;
1622: e->exprblock.opcode = opcode;
1623: e->exprblock.vtype = etype;
1624: e->exprblock.leftp = lp;
1625: e->exprblock.rightp = rp;
1626: if(ltag==TCONST && (rp==0 || rtag==TCONST) )
1627: e = fold(e);
1628: return(e);
1629:
1630: retleft:
1631: frexpr(rp);
1632: return(lp);
1633:
1634: retright:
1635: frexpr(lp);
1636: return(rp);
1637:
1638: error:
1639: frexpr(lp);
1640: if(rp && opcode!=OPCALL && opcode!=OPCCALL)
1641: frexpr(rp);
1642: return( errnode() );
1643: }
1644:
1645: #define ERR(s) { errs = s; goto error; }
1646:
1647: cktype(op, lt, rt)
1648: register int op, lt, rt;
1649: {
1650: char *errs;
1651:
1652: if(lt==TYERROR || rt==TYERROR)
1653: goto error1;
1654:
1655: if(lt==TYUNKNOWN)
1656: return(TYUNKNOWN);
1657: if(rt==TYUNKNOWN)
1658: if(op!=OPNOT && op!=OPBITNOT && op!=OPNEG && op!=OPCALL && op!=OPCCALL && op!=OPADDR)
1659: return(TYUNKNOWN);
1660:
1661: switch(op)
1662: {
1663: case OPPLUS:
1664: case OPMINUS:
1665: case OPSTAR:
1666: case OPSLASH:
1667: case OPPOWER:
1668: case OPMOD:
1669: if( ISNUMERIC(lt) && ISNUMERIC(rt) )
1670: return( maxtype(lt, rt) );
1671: ERR("nonarithmetic operand of arithmetic operator")
1672:
1673: case OPNEG:
1674: if( ISNUMERIC(lt) )
1675: return(lt);
1676: ERR("nonarithmetic operand of negation")
1677:
1678: case OPNOT:
1679: if(lt == TYLOGICAL)
1680: return(TYLOGICAL);
1681: ERR("NOT of nonlogical")
1682:
1683: case OPAND:
1684: case OPOR:
1685: case OPEQV:
1686: case OPNEQV:
1687: if(lt==TYLOGICAL && rt==TYLOGICAL)
1688: return(TYLOGICAL);
1689: ERR("nonlogical operand of logical operator")
1690:
1691: case OPLT:
1692: case OPGT:
1693: case OPLE:
1694: case OPGE:
1695: case OPEQ:
1696: case OPNE:
1697: if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
1698: {
1699: if(lt != rt)
1700: ERR("illegal comparison")
1701: }
1702:
1703: else if( ISCOMPLEX(lt) || ISCOMPLEX(rt) )
1704: {
1705: if(op!=OPEQ && op!=OPNE)
1706: ERR("order comparison of complex data")
1707: }
1708:
1709: else if( ! ISNUMERIC(lt) || ! ISNUMERIC(rt) )
1710: ERR("comparison of nonarithmetic data")
1711: return(TYLOGICAL);
1712:
1713: case OPCONCAT:
1714: if(lt==TYCHAR && rt==TYCHAR)
1715: return(TYCHAR);
1716: ERR("concatenation of nonchar data")
1717:
1718: case OPCALL:
1719: case OPCCALL:
1720: return(lt);
1721:
1722: case OPADDR:
1723: return(TYADDR);
1724:
1725: case OPCONV:
1726: if(rt == 0)
1727: return(0);
1728: if(lt==TYCHAR && ISINT(rt) )
1729: return(TYCHAR);
1730: case OPASSIGN:
1731: case OPPLUSEQ:
1732: case OPSTAREQ:
1733: if( ISINT(lt) && rt==TYCHAR)
1734: return(lt);
1735: if(lt==TYCHAR || rt==TYCHAR || lt==TYLOGICAL || rt==TYLOGICAL)
1736: if(op!=OPASSIGN || lt!=rt)
1737: {
1738: /* debug fprintf(diagfile, " lt=%d, rt=%d, op=%d\n", lt, rt, op); */
1739: /* debug fatal("impossible conversion. possible compiler bug"); */
1740: ERR("impossible conversion")
1741: }
1742: return(lt);
1743:
1744: case OPMIN:
1745: case OPMAX:
1746: case OPBITOR:
1747: case OPBITAND:
1748: case OPBITXOR:
1749: case OPBITNOT:
1750: case OPLSHIFT:
1751: case OPRSHIFT:
1752: return(lt);
1753:
1754: case OPCOMMA:
1755: case OPQUEST:
1756: case OPCOLON:
1757: return(rt);
1758:
1759: default:
1760: badop("cktype", op);
1761: }
1762: error:
1763: err(errs);
1764: error1:
1765: return(TYERROR);
1766: }
1767:
1768: LOCAL expptr fold(e)
1769: register expptr e;
1770: {
1771: Constp p;
1772: register expptr lp, rp;
1773: int etype, mtype, ltype, rtype, opcode;
1774: int i, ll, lr;
1775: char *q, *s;
1776: union Constant lcon, rcon;
1777:
1778: opcode = e->exprblock.opcode;
1779: etype = e->exprblock.vtype;
1780:
1781: lp = e->exprblock.leftp;
1782: ltype = lp->headblock.vtype;
1783: rp = e->exprblock.rightp;
1784:
1785: if(rp == 0)
1786: switch(opcode)
1787: {
1788: case OPNOT:
1789: lp->constblock.Const.ci = ! lp->constblock.Const.ci;
1790: return(lp);
1791:
1792: case OPBITNOT:
1793: lp->constblock.Const.ci = ~ lp->constblock.Const.ci;
1794: return(lp);
1795:
1796: case OPNEG:
1797: consnegop(lp);
1798: return(lp);
1799:
1800: case OPCONV:
1801: case OPADDR:
1802: return(e);
1803:
1804: default:
1805: badop("fold", opcode);
1806: }
1807:
1808: rtype = rp->headblock.vtype;
1809:
1810: p = ALLOC(Constblock);
1811: p->tag = TCONST;
1812: p->vtype = etype;
1813: p->vleng = e->exprblock.vleng;
1814:
1815: switch(opcode)
1816: {
1817: case OPCOMMA:
1818: case OPQUEST:
1819: case OPCOLON:
1820: return(e);
1821:
1822: case OPAND:
1823: p->Const.ci = lp->constblock.Const.ci &&
1824: rp->constblock.Const.ci;
1825: break;
1826:
1827: case OPOR:
1828: p->Const.ci = lp->constblock.Const.ci ||
1829: rp->constblock.Const.ci;
1830: break;
1831:
1832: case OPEQV:
1833: p->Const.ci = lp->constblock.Const.ci ==
1834: rp->constblock.Const.ci;
1835: break;
1836:
1837: case OPNEQV:
1838: p->Const.ci = lp->constblock.Const.ci !=
1839: rp->constblock.Const.ci;
1840: break;
1841:
1842: case OPBITAND:
1843: p->Const.ci = lp->constblock.Const.ci &
1844: rp->constblock.Const.ci;
1845: break;
1846:
1847: case OPBITOR:
1848: p->Const.ci = lp->constblock.Const.ci |
1849: rp->constblock.Const.ci;
1850: break;
1851:
1852: case OPBITXOR:
1853: p->Const.ci = lp->constblock.Const.ci ^
1854: rp->constblock.Const.ci;
1855: break;
1856:
1857: case OPLSHIFT:
1858: p->Const.ci = lp->constblock.Const.ci <<
1859: rp->constblock.Const.ci;
1860: break;
1861:
1862: case OPRSHIFT:
1863: p->Const.ci = lp->constblock.Const.ci >>
1864: rp->constblock.Const.ci;
1865: break;
1866:
1867: case OPCONCAT:
1868: ll = lp->constblock.vleng->constblock.Const.ci;
1869: lr = rp->constblock.vleng->constblock.Const.ci;
1870: p->Const.ccp = q = (char *) ckalloc(ll+lr);
1871: p->vleng = ICON(ll+lr);
1872: s = lp->constblock.Const.ccp;
1873: for(i = 0 ; i < ll ; ++i)
1874: *q++ = *s++;
1875: s = rp->constblock.Const.ccp;
1876: for(i = 0; i < lr; ++i)
1877: *q++ = *s++;
1878: break;
1879:
1880:
1881: case OPPOWER:
1882: if( ! ISINT(rtype) )
1883: return(e);
1884: conspower(&(p->Const), lp, rp->constblock.Const.ci);
1885: break;
1886:
1887:
1888: default:
1889: if(ltype == TYCHAR)
1890: {
1891: lcon.ci = cmpstr(lp->constblock.Const.ccp,
1892: rp->constblock.Const.ccp,
1893: lp->constblock.vleng->constblock.Const.ci,
1894: rp->constblock.vleng->constblock.Const.ci);
1895: rcon.ci = 0;
1896: mtype = tyint;
1897: }
1898: else {
1899: mtype = maxtype(ltype, rtype);
1900: consconv(mtype, &lcon, ltype, &(lp->constblock.Const) );
1901: consconv(mtype, &rcon, rtype, &(rp->constblock.Const) );
1902: }
1903: consbinop(opcode, mtype, &(p->Const), &lcon, &rcon);
1904: break;
1905: }
1906:
1907: frexpr(e);
1908: return( (expptr) p );
1909: }
1910:
1911:
1912:
1913: /* assign constant l = r , doing coercion */
1914:
1915: consconv(lt, lv, rt, rv)
1916: int lt, rt;
1917: register union Constant *lv, *rv;
1918: {
1919: switch(lt)
1920: {
1921: case TYCHAR:
1922: *(lv->ccp = (char *) ckalloc(1)) = rv->ci;
1923: break;
1924:
1925: case TYSHORT:
1926: case TYLONG:
1927: if(rt == TYCHAR)
1928: lv->ci = rv->ccp[0];
1929: else if( ISINT(rt) )
1930: lv->ci = rv->ci;
1931: else lv->ci = rv->cd[0];
1932: break;
1933:
1934: case TYCOMPLEX:
1935: case TYDCOMPLEX:
1936: switch(rt)
1937: {
1938: case TYSHORT:
1939: case TYLONG:
1940: /* fall through and do real assignment of
1941: first element
1942: */
1943: case TYREAL:
1944: case TYDREAL:
1945: lv->cd[1] = 0;
1946: break;
1947: case TYCOMPLEX:
1948: case TYDCOMPLEX:
1949: lv->cd[1] = rv->cd[1];
1950: break;
1951: }
1952:
1953: case TYREAL:
1954: case TYDREAL:
1955: if( ISINT(rt) )
1956: lv->cd[0] = rv->ci;
1957: else lv->cd[0] = rv->cd[0];
1958: break;
1959:
1960: case TYLOGICAL:
1961: lv->ci = rv->ci;
1962: break;
1963: }
1964: }
1965:
1966:
1967:
1968: consnegop(p)
1969: register Constp p;
1970: {
1971: switch(p->vtype)
1972: {
1973: case TYSHORT:
1974: case TYLONG:
1975: p->Const.ci = - p->Const.ci;
1976: break;
1977:
1978: case TYCOMPLEX:
1979: case TYDCOMPLEX:
1980: p->Const.cd[1] = - p->Const.cd[1];
1981: /* fall through and do the real parts */
1982: case TYREAL:
1983: case TYDREAL:
1984: p->Const.cd[0] = - p->Const.cd[0];
1985: break;
1986: default:
1987: badtype("consnegop", p->vtype);
1988: }
1989: }
1990:
1991:
1992:
1993: LOCAL conspower(powp, ap, n)
1994: register union Constant *powp;
1995: Constp ap;
1996: ftnint n;
1997: {
1998: register int type;
1999: union Constant x;
2000:
2001: switch(type = ap->vtype) /* pow = 1 */
2002: {
2003: case TYSHORT:
2004: case TYLONG:
2005: powp->ci = 1;
2006: break;
2007: case TYCOMPLEX:
2008: case TYDCOMPLEX:
2009: powp->cd[1] = 0;
2010: case TYREAL:
2011: case TYDREAL:
2012: powp->cd[0] = 1;
2013: break;
2014: default:
2015: badtype("conspower", type);
2016: }
2017:
2018: if(n == 0)
2019: return;
2020: if(n < 0)
2021: {
2022: if( ISINT(type) )
2023: {
2024: err("integer ** negative power ");
2025: return;
2026: }
2027: n = - n;
2028: consbinop(OPSLASH, type, &x, powp, &(ap->Const));
2029: }
2030: else
2031: consbinop(OPSTAR, type, &x, powp, &(ap->Const));
2032:
2033: for( ; ; )
2034: {
2035: if(n & 01)
2036: consbinop(OPSTAR, type, powp, powp, &x);
2037: if(n >>= 1)
2038: consbinop(OPSTAR, type, &x, &x, &x);
2039: else
2040: break;
2041: }
2042: }
2043:
2044:
2045:
2046: /* do constant operation cp = a op b */
2047:
2048:
2049: LOCAL consbinop(opcode, type, cp, ap, bp)
2050: int opcode, type;
2051: register union Constant *ap, *bp, *cp;
2052: {
2053: int k;
2054: double temp;
2055:
2056: switch(opcode)
2057: {
2058: case OPPLUS:
2059: switch(type)
2060: {
2061: case TYSHORT:
2062: case TYLONG:
2063: cp->ci = ap->ci + bp->ci;
2064: break;
2065: case TYCOMPLEX:
2066: case TYDCOMPLEX:
2067: cp->cd[1] = ap->cd[1] + bp->cd[1];
2068: case TYREAL:
2069: case TYDREAL:
2070: cp->cd[0] = ap->cd[0] + bp->cd[0];
2071: break;
2072: }
2073: break;
2074:
2075: case OPMINUS:
2076: switch(type)
2077: {
2078: case TYSHORT:
2079: case TYLONG:
2080: cp->ci = ap->ci - bp->ci;
2081: break;
2082: case TYCOMPLEX:
2083: case TYDCOMPLEX:
2084: cp->cd[1] = ap->cd[1] - bp->cd[1];
2085: case TYREAL:
2086: case TYDREAL:
2087: cp->cd[0] = ap->cd[0] - bp->cd[0];
2088: break;
2089: }
2090: break;
2091:
2092: case OPSTAR:
2093: switch(type)
2094: {
2095: case TYSHORT:
2096: case TYLONG:
2097: cp->ci = ap->ci * bp->ci;
2098: break;
2099: case TYREAL:
2100: case TYDREAL:
2101: cp->cd[0] = ap->cd[0] * bp->cd[0];
2102: break;
2103: case TYCOMPLEX:
2104: case TYDCOMPLEX:
2105: temp = ap->cd[0] * bp->cd[0] -
2106: ap->cd[1] * bp->cd[1] ;
2107: cp->cd[1] = ap->cd[0] * bp->cd[1] +
2108: ap->cd[1] * bp->cd[0] ;
2109: cp->cd[0] = temp;
2110: break;
2111: }
2112: break;
2113: case OPSLASH:
2114: switch(type)
2115: {
2116: case TYSHORT:
2117: case TYLONG:
2118: cp->ci = ap->ci / bp->ci;
2119: break;
2120: case TYREAL:
2121: case TYDREAL:
2122: cp->cd[0] = ap->cd[0] / bp->cd[0];
2123: break;
2124: case TYCOMPLEX:
2125: case TYDCOMPLEX:
2126: zdiv(cp,ap,bp);
2127: break;
2128: }
2129: break;
2130:
2131: case OPMOD:
2132: if( ISINT(type) )
2133: {
2134: cp->ci = ap->ci % bp->ci;
2135: break;
2136: }
2137: else
2138: fatal("inline mod of noninteger");
2139:
2140: default: /* relational ops */
2141: switch(type)
2142: {
2143: case TYSHORT:
2144: case TYLONG:
2145: if(ap->ci < bp->ci)
2146: k = -1;
2147: else if(ap->ci == bp->ci)
2148: k = 0;
2149: else k = 1;
2150: break;
2151: case TYREAL:
2152: case TYDREAL:
2153: if(ap->cd[0] < bp->cd[0])
2154: k = -1;
2155: else if(ap->cd[0] == bp->cd[0])
2156: k = 0;
2157: else k = 1;
2158: break;
2159: case TYCOMPLEX:
2160: case TYDCOMPLEX:
2161: if(ap->cd[0] == bp->cd[0] &&
2162: ap->cd[1] == bp->cd[1] )
2163: k = 0;
2164: else k = 1;
2165: break;
2166: }
2167:
2168: switch(opcode)
2169: {
2170: case OPEQ:
2171: cp->ci = (k == 0);
2172: break;
2173: case OPNE:
2174: cp->ci = (k != 0);
2175: break;
2176: case OPGT:
2177: cp->ci = (k == 1);
2178: break;
2179: case OPLT:
2180: cp->ci = (k == -1);
2181: break;
2182: case OPGE:
2183: cp->ci = (k >= 0);
2184: break;
2185: case OPLE:
2186: cp->ci = (k <= 0);
2187: break;
2188: }
2189: break;
2190: }
2191: }
2192:
2193:
2194:
2195:
2196: conssgn(p)
2197: register expptr p;
2198: {
2199: if( ! ISCONST(p) )
2200: fatal( "sgn(nonconstant)" );
2201:
2202: switch(p->headblock.vtype)
2203: {
2204: case TYSHORT:
2205: case TYLONG:
2206: if(p->constblock.Const.ci > 0) return(1);
2207: if(p->constblock.Const.ci < 0) return(-1);
2208: return(0);
2209:
2210: case TYREAL:
2211: case TYDREAL:
2212: if(p->constblock.Const.cd[0] > 0) return(1);
2213: if(p->constblock.Const.cd[0] < 0) return(-1);
2214: return(0);
2215:
2216: case TYCOMPLEX:
2217: case TYDCOMPLEX:
2218: return(p->constblock.Const.cd[0]!=0 || p->constblock.Const.cd[1]!=0);
2219:
2220: default:
2221: badtype( "conssgn", p->constblock.vtype);
2222: }
2223: /* NOTREACHED */
2224: }
2225:
2226: char *powint[ ] = {
2227: "pow_ii", "pow_ri", "pow_di", "pow_ci", "pow_zi" };
2228:
2229:
2230: LOCAL expptr mkpower(p)
2231: register expptr p;
2232: {
2233: register expptr q, lp, rp;
2234: int ltype, rtype, mtype;
2235:
2236: lp = p->exprblock.leftp;
2237: rp = p->exprblock.rightp;
2238: ltype = lp->headblock.vtype;
2239: rtype = rp->headblock.vtype;
2240:
2241: if(ISICON(rp))
2242: {
2243: if(rp->constblock.Const.ci == 0)
2244: {
2245: frexpr(p);
2246: if( ISINT(ltype) )
2247: return( ICON(1) );
2248: else
2249: return( (expptr) putconst( mkconv(ltype, ICON(1))) );
2250: }
2251: if(rp->constblock.Const.ci < 0)
2252: {
2253: if( ISINT(ltype) )
2254: {
2255: frexpr(p);
2256: err("integer**negative");
2257: return( errnode() );
2258: }
2259: rp->constblock.Const.ci = - rp->constblock.Const.ci;
2260: p->exprblock.leftp = lp = fixexpr(mkexpr(OPSLASH, ICON(1), lp));
2261: }
2262: if(rp->constblock.Const.ci == 1)
2263: {
2264: frexpr(rp);
2265: free( (charptr) p );
2266: return(lp);
2267: }
2268:
2269: if( ONEOF(ltype, MSKINT|MSKREAL) )
2270: {
2271: p->exprblock.vtype = ltype;
2272: return(p);
2273: }
2274: }
2275: if( ISINT(rtype) )
2276: {
2277: if(ltype==TYSHORT && rtype==TYSHORT && (!ISCONST(lp) || tyint==TYSHORT) )
2278: q = call2(TYSHORT, "pow_hh", lp, rp);
2279: else {
2280: if(ltype == TYSHORT)
2281: {
2282: ltype = TYLONG;
2283: lp = mkconv(TYLONG,lp);
2284: }
2285: q = call2(ltype, powint[ltype-TYLONG], lp, mkconv(TYLONG, rp));
2286: }
2287: }
2288: else if( ISREAL( (mtype = maxtype(ltype,rtype)) ))
2289: q = call2(mtype, "pow_dd", mkconv(TYDREAL,lp), mkconv(TYDREAL,rp));
2290: else {
2291: q = call2(TYDCOMPLEX, "pow_zz",
2292: mkconv(TYDCOMPLEX,lp), mkconv(TYDCOMPLEX,rp));
2293: if(mtype == TYCOMPLEX)
2294: q = mkconv(TYCOMPLEX, q);
2295: }
2296: free( (charptr) p );
2297: return(q);
2298: }
2299:
2300:
2301:
2302: /* Complex Division. Same code as in Runtime Library
2303: */
2304:
2305: struct dcomplex {
2306: double dreal, dimag;
2307: };
2308:
2309:
2310: LOCAL zdiv(c, a, b)
2311: register struct dcomplex *a, *b, *c;
2312: {
2313: double ratio, den;
2314: double abr, abi;
2315:
2316: if( (abr = b->dreal) < 0.)
2317: abr = - abr;
2318: if( (abi = b->dimag) < 0.)
2319: abi = - abi;
2320: if( abr <= abi )
2321: {
2322: if(abi == 0)
2323: fatal("complex division by zero");
2324: ratio = b->dreal / b->dimag ;
2325: den = b->dimag * (1 + ratio*ratio);
2326: c->dreal = (a->dreal*ratio + a->dimag) / den;
2327: c->dimag = (a->dimag*ratio - a->dreal) / den;
2328: }
2329:
2330: else
2331: {
2332: ratio = b->dimag / b->dreal ;
2333: den = b->dreal * (1 + ratio*ratio);
2334: c->dreal = (a->dreal + a->dimag*ratio) / den;
2335: c->dimag = (a->dimag - a->dreal*ratio) / den;
2336: }
2337:
2338: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.