|
|
1.1 root 1: /* INTERMEDIATE CODE GENERATION FOR D. M. RITCHIE C COMPILERS */
2: #if FAMILY != DMR
3: WRONG put FILE !!!!
4: #endif
5:
6: #include "defs"
7: #include "dmrdefs"
8: struct Addrblock *imagpart();
9:
10:
11: extern int ops2[];
12: extern int types2[];
13:
14:
15: puthead(s, class)
16: char *s;
17: int class;
18: {
19: if( ! headerdone )
20: {
21: p2op2(P2SETREG, ARGREG-maxregvar);
22: p2op(P2PROG);
23: headerdone = YES;
24: #if TARGET == PDP11
25: /* fake jump to start the optimizer */
26: if(class != CLBLOCK)
27: putgoto( fudgelabel = newlabel() );
28: #endif
29: }
30: }
31:
32:
33:
34:
35: putnreg()
36: {
37: p2op2(P2SETREG, ARGREG-nregvar);
38: }
39:
40:
41:
42:
43:
44:
45: puteof()
46: {
47: p2op(P2EOF);
48: }
49:
50:
51:
52: putstmt()
53: {
54: p2op2(P2EXPR, lineno);
55: }
56:
57:
58:
59:
60: /* put out code for if( ! p) goto l */
61: putif(p,l)
62: register expptr p;
63: int l;
64: {
65: register int k;
66: if( (k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL)
67: {
68: if(k != TYERROR)
69: err("non-logical expression in IF statement");
70: frexpr(p);
71: }
72: else
73: {
74: putex1(p);
75: p2op2(P2CBRANCH, l);
76: p2i(0);
77: p2i(lineno);
78: }
79: }
80:
81:
82:
83:
84:
85: /* put out code for goto l */
86: putgoto(label)
87: int label;
88: {
89: p2op2(P2GOTO, label);
90: }
91:
92:
93: /* branch to address constant or integer variable */
94: putbranch(p)
95: register struct Addrblock *p;
96: {
97: register int type;
98:
99: type = p->vtype;
100: if(p->tag != TADDR)
101: fatal("invalid goto label");
102: putaddr(p, YES);
103: if(type != TYINT)
104: p2op2(P2LTOI, P2INT);
105: p2op2(P2INDIRECT, P2INT);
106: p2op2(P2JUMP, P2INT);
107: putstmt();
108: }
109:
110:
111:
112: /* put out label l: */
113: putlabel(label)
114: int label;
115: {
116: p2op2(P2LABEL, label);
117: }
118:
119:
120:
121:
122: putexpr(p)
123: expptr p;
124: {
125: putex1(p);
126: putstmt();
127: }
128:
129:
130:
131:
132:
133: prarif(p, neg, zero, pos)
134: expptr p;
135: int neg ,zero, pos;
136: {
137: putx(p);
138: p2op(P2ARIF);
139: p2i(neg);
140: p2i(zero);
141: p2i(pos);
142: p2i(lineno);
143: }
144:
145:
146:
147: putcmgo(index, nlab, labs)
148: expptr index;
149: int nlab;
150: struct Labelblock *labs[];
151: {
152: register int i;
153: int skiplabel;
154:
155: if(! ISINT(index->headblock.vtype) )
156: {
157: execerr("computed goto index must be integer", NULL);
158: return;
159: }
160:
161: putforce(TYINT, mkconv(TYINT, index) );
162: p2op(P2SWITCH);
163: p2i(skiplabel = newlabel() );
164: p2i(lineno);
165: for(i = 0 ; i<nlab ; ++i)
166: if( labs[i] )
167: {
168: p2i(labs[i]->labelno);
169: p2i(i+1);
170: }
171: p2i(0);
172: putlabel(skiplabel);
173: }
174:
175: putx(p)
176: register expptr p;
177: {
178: struct Addrblock *putcall(), *putcx1(), *realpart();
179: expptr q;
180: char *memname();
181: int opc;
182: int type, ncomma;
183:
184: switch(p->headblock.tag)
185: {
186: case TERROR:
187: free(p);
188: break;
189:
190: case TCONST:
191: switch(type = p->constblock.vtype)
192: {
193: case TYLOGICAL:
194: type = tylogical;
195: case TYLONG:
196: case TYSHORT:
197: if(type == TYSHORT)
198: {
199: p2op2(P2ICON, P2SHORT);
200: p2i( (short)(p->constblock.const.ci) );
201: }
202: else
203: {
204: p2op2(P2LCON, P2LONG);
205: p2li(p->constblock.const.ci);
206: }
207: free(p);
208: break;
209:
210: case TYADDR:
211: p2op(P2NAME);
212: p2i(P2STATIC);
213: p2i(P2INT);
214: p2i( (int) p->constblock.const.ci);
215: p2op2(P2ADDR, P2PTR);
216: free(p);
217: break;
218:
219: default:
220: putx( putconst(p) );
221: break;
222: }
223: break;
224:
225: case TEXPR:
226: switch(opc = p->exprblock.opcode)
227: {
228: case OPCALL:
229: case OPCCALL:
230: if( ISCOMPLEX(p->exprblock.vtype) )
231: putcxop(p);
232: else putcall(p);
233: break;
234:
235: case OPMIN:
236: case OPMAX:
237: putmnmx(p);
238: break;
239:
240:
241: case OPASSIGN:
242: if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) ||
243: ISCOMPLEX(p->exprblock.rightp->headblock.vtype) )
244: frexpr( putcxeq(p) );
245: else if( ISCHAR(p) )
246: putcheq(p);
247: else
248: goto putopp;
249: break;
250:
251: case OPEQ:
252: case OPNE:
253: if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) ||
254: ISCOMPLEX(p->exprblock.rightp->headblock.vtype) )
255: {
256: putcxcmp(p);
257: break;
258: }
259: case OPLT:
260: case OPLE:
261: case OPGT:
262: case OPGE:
263: if(ISCHAR(p->exprblock.leftp))
264: putchcmp(p);
265: else
266: goto putopp;
267: break;
268:
269: case OPPOWER:
270: putpower(p);
271: break;
272:
273: case OPMOD:
274: goto putopp;
275: case OPSTAR:
276:
277: case OPPLUS:
278: case OPMINUS:
279: case OPSLASH:
280: case OPNEG:
281: if( ISCOMPLEX(p->exprblock.vtype) )
282: putcxop(p);
283: else goto putopp;
284: break;
285:
286: case OPCONV:
287: if( ISCOMPLEX(p->exprblock.vtype) )
288: putcxop(p);
289: else if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) )
290: {
291: ncomma = 0;
292: putx( mkconv(p->exprblock.vtype,
293: realpart(putcx1(p->exprblock.leftp, &ncomma))));
294: putcomma(ncomma, p->exprblock.vtype, NO);
295: free(p);
296: }
297: /* in special case double(single(double)), need a spcial
298: write-around due to code generator problem; put out tree
299: double( temp = val, temp)
300: */
301: else if(p->exprblock.vtype == TYDREAL
302: &&p->exprblock.leftp->headblock.tag==TEXPR
303: &&p->exprblock.leftp->headblock.opcode==OPCONV
304: &&p->exprblock.leftp->exprblock.vtype==TYREAL
305: &&p->exprblock.leftp->exprblock.leftp->vtype==TYDREAL)
306: {
307: q = mktemp(TYREAL, NULL);
308: p->exprblock.leftp = mkexpr(OPCOMMA,
309: mkexpr(OPASSIGN, cpexpr(q),
310: p->exprblock.leftp),
311: q);
312: goto putopp;
313: }
314: else goto putopp;
315: break;
316:
317: case OPNOT:
318: case OPOR:
319: case OPAND:
320: case OPEQV:
321: case OPNEQV:
322: case OPADDR:
323: case OPPLUSEQ:
324: case OPSTAREQ:
325: case OPCOMMA:
326: case OPQUEST:
327: case OPCOLON:
328: case OPBITOR:
329: case OPBITAND:
330: case OPBITXOR:
331: case OPBITNOT:
332: case OPLSHIFT:
333: case OPRSHIFT:
334: putopp:
335: putop(p);
336: break;
337:
338: default:
339: fatali("putx: invalid opcode %d", opc);
340: }
341: break;
342:
343: case TADDR:
344: putaddr(p, YES);
345: break;
346:
347: default:
348: fatali("putx: impossible tag %d", p->headblock.tag);
349: }
350: }
351:
352:
353:
354: LOCAL putop(p)
355: register expptr p;
356: {
357: int k, ncomma;
358: int type2, ptype, ltype;
359: int convop;
360: register expptr lp, tp;
361:
362: switch(p->exprblock.opcode) /* check for special cases and rewrite */
363: {
364:
365: case OPCONV:
366: lp = p->exprblock.leftp;
367: while(p->headblock.tag==TEXPR && p->exprblock.opcode==OPCONV &&
368: ( ( (ptype = p->exprblock.vtype) == (ltype = lp->headblock.vtype) ) ||
369: (ISREAL(ptype)&&ISREAL(ltype)) ||
370: (ONEOF(ptype, M(TYSHORT)|M(TYADDR)) &&
371: ONEOF(ltype, M(TYSHORT)|M(TYADDR))) ||
372: (ptype==TYINT && ONEOF(ltype, M(TYSUBR)|M(TYCHAR))) ))
373: {
374:
375: if(ltype==TYCHAR && lp->headblock.tag==TEXPR &&
376: lp->exprblock.opcode==OPCALL)
377: {
378: p->exprblock.leftp = putcall(lp);
379: putop(p);
380: putcomma(1, ptype, NO);
381: free(p);
382: return;
383: }
384: free(p);
385: p = lp;
386: lp = p->exprblock.leftp;
387: }
388: if(p->headblock.tag!=TEXPR || p->exprblock.opcode!=OPCONV ||
389: ISCOMPLEX((ltype = lp->headblock.vtype)) )
390: {
391: putx(p);
392: return;
393: }
394:
395: ltype = lp->headblock.vtype;
396:
397: switch(ptype = p->exprblock.vtype)
398: {
399: case TYCHAR:
400: p->exprblock.leftp = lp = mkconv(TYSHORT, lp);
401: convop = P2ITOC;
402: break;
403:
404: case TYSHORT:
405: case TYADDR:
406: switch(ltype)
407: {
408: case TYLONG:
409: convop = P2LTOI; break;
410: case TYREAL:
411: case TYDREAL:
412: convop = P2FTOI; break;
413: default:
414: goto badconv;
415: }
416: break;
417:
418: case TYLONG:
419: switch(ltype)
420: {
421: case TYCHAR:
422: case TYSHORT:
423: case TYADDR:
424: convop = P2ITOL; break;
425: case TYREAL:
426: case TYDREAL:
427: convop = P2FTOL; break;
428: default:
429: goto badconv;
430: }
431: break;
432:
433: case TYREAL:
434: case TYDREAL:
435: switch(ltype)
436: {
437: case TYCHAR:
438: case TYSHORT:
439: case TYADDR:
440: convop = P2ITOF; break;
441: case TYLONG:
442: convop = P2LTOF; break;
443: default:
444: goto badconv;
445: }
446: break;
447:
448: default:
449: badconv:
450: fatal("putop: impossible conversion");
451: }
452: putx(lp);
453: p2op2(convop, types2[ptype]);
454: free(p);
455: return;
456:
457: case OPADDR:
458: lp = p->exprblock.leftp;
459: if(lp->headblock.tag != TADDR)
460: {
461: tp = mktemp(lp->headblock.vtype, lp->headblock.vleng);
462: putx( mkexpr(OPASSIGN, cpexpr(tp), lp) );
463: ncomma = 1;
464: lp = tp;
465: }
466: else ncomma = 0;
467: putaddr(lp, NO);
468: putcomma(ncomma, TYINT, NO);
469: free(p);
470: return;
471:
472: case OPASSIGN:
473: if(p->exprblock.vtype==TYLOGICAL && tylogical!=TYINT &&
474: p->exprblock.rightp->headblock.tag==TEXPR &&
475: p->exprblock.rightp->exprblock.opcode!=OPCALL &&
476: p->exprblock.rightp->exprblock.opcode!=OPCCALL )
477: {
478: p->exprblock.rightp->exprblock.vtype = TYINT;
479: p->exprblock.rightp =
480: mkconv(tylogical, p->exprblock.rightp);
481: }
482: break;
483: }
484:
485: if( (k = ops2[p->exprblock.opcode]) <= 0)
486: fatali("putop: invalid opcode %d", p->exprblock.opcode);
487: putx(p->exprblock.leftp);
488: if(p->exprblock.rightp)
489: putx(p->exprblock.rightp);
490: type2 = (p->exprblock.opcode!=OPASSIGN && p->exprblock.vtype==TYLOGICAL ?
491: P2INT : types2[p->exprblock.vtype] );
492: p2op2(k, type2);
493:
494: if(p->exprblock.vleng)
495: frexpr(p->exprblock.vleng);
496: free(p);
497: }
498:
499: putforce(t, p)
500: int t;
501: expptr p;
502: {
503: p = mkconv(t, fixtype(p));
504: putx(p);
505: p2op2(P2FORCE, (t==TYSHORT ? P2SHORT : (t==TYLONG ? P2LONG : P2DREAL)) );
506: putstmt();
507: }
508:
509:
510:
511: LOCAL putpower(p)
512: expptr p;
513: {
514: expptr base;
515: struct Addrblock *t1, *t2;
516: ftnint k;
517: int type;
518: int ncomma;
519:
520: if(!ISICON(p->exprblock.rightp) ||
521: (k = p->exprblock.rightp->constblock.const.ci)<2)
522: fatal("putpower: bad call");
523: base = p->exprblock.leftp;
524: type = base->headblock.vtype;
525: t1 = mktemp(type, NULL);
526: t2 = NULL;
527: ncomma = 1;
528: putassign(cpexpr(t1), cpexpr(base) );
529:
530: for( ; (k&1)==0 && k>2 ; k>>=1 )
531: {
532: ++ncomma;
533: putsteq(t1, t1);
534: }
535:
536: if(k == 2)
537: putx( mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) );
538: else
539: {
540: t2 = mktemp(type, NULL);
541: ++ncomma;
542: putassign(cpexpr(t2), cpexpr(t1));
543:
544: for(k>>=1 ; k>1 ; k>>=1)
545: {
546: ++ncomma;
547: putsteq(t1, t1);
548: if(k & 1)
549: {
550: ++ncomma;
551: putsteq(t2, t1);
552: }
553: }
554: putx( mkexpr(OPSTAR, cpexpr(t2),
555: mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) ));
556: }
557: putcomma(ncomma, type, NO);
558: frexpr(t1);
559: if(t2)
560: frexpr(t2);
561: frexpr(p);
562: }
563:
564:
565:
566:
567: LOCAL struct Addrblock *intdouble(p, ncommap)
568: struct Addrblock *p;
569: int *ncommap;
570: {
571: register struct Addrblock *t;
572:
573: t = mktemp(TYDREAL, NULL);
574: ++*ncommap;
575: putassign(cpexpr(t), p);
576: return(t);
577: }
578:
579:
580:
581:
582:
583: LOCAL putcxeq(p)
584: register struct Exprblock *p;
585: {
586: register struct Addrblock *lp, *rp;
587: int ncomma;
588:
589: ncomma = 0;
590: lp = putcx1(p->leftp, &ncomma);
591: rp = putcx1(p->rightp, &ncomma);
592: putassign(realpart(lp), realpart(rp));
593: if( ISCOMPLEX(p->vtype) )
594: {
595: ++ncomma;
596: putassign(imagpart(lp), imagpart(rp));
597: }
598: putcomma(ncomma, TYREAL, NO);
599: frexpr(rp);
600: free(p);
601: return(lp);
602: }
603:
604:
605:
606: LOCAL putcxop(p)
607: expptr p;
608: {
609: struct Addrblock *putcx1();
610: int ncomma;
611:
612: ncomma = 0;
613: putaddr( putcx1(p, &ncomma), NO);
614: putcomma(ncomma, TYINT, NO);
615: }
616:
617:
618:
619: LOCAL struct Addrblock *putcx1(p, ncommap)
620: register expptr p;
621: int *ncommap;
622: {
623: struct Addrblock *q, *lp, *rp;
624: register struct Addrblock *resp;
625: int opcode;
626: int ltype, rtype;
627: struct Constblock *mkrealcon();
628:
629: if(p == NULL)
630: return(NULL);
631:
632: switch(p->headblock.tag)
633: {
634: case TCONST:
635: if( ISCOMPLEX(p->constblock.vtype) )
636: p = putconst(p);
637: return( p );
638:
639: case TADDR:
640: if( ! addressable(p) )
641: {
642: ++*ncommap;
643: resp = mktemp(tyint, NULL);
644: putassign( cpexpr(resp), p->addrblock.memoffset );
645: p->addrblock.memoffset = resp;
646: }
647: return( p );
648:
649: case TEXPR:
650: if( ISCOMPLEX(p->exprblock.vtype) )
651: break;
652: ++*ncommap;
653: resp = mktemp(TYDREAL, NO);
654: putassign( cpexpr(resp), p);
655: return(resp);
656:
657: default:
658: fatali("putcx1: bad tag %d", p->headblock.tag);
659: }
660:
661: opcode = p->exprblock.opcode;
662: if(opcode==OPCALL || opcode==OPCCALL)
663: {
664: ++*ncommap;
665: return( putcall(p) );
666: }
667: else if(opcode == OPASSIGN)
668: {
669: ++*ncommap;
670: return( putcxeq(p) );
671: }
672: resp = mktemp(p->exprblock.vtype, NULL);
673: if(lp = putcx1(p->exprblock.leftp, ncommap) )
674: ltype = lp->vtype;
675: if(rp = putcx1(p->exprblock.rightp, ncommap) )
676: rtype = rp->vtype;
677:
678: switch(opcode)
679: {
680: case OPCOMMA:
681: frexpr(resp);
682: resp = rp;
683: rp = NULL;
684: break;
685:
686: case OPNEG:
687: putassign( realpart(resp), mkexpr(OPNEG, realpart(lp), NULL) );
688: putassign( imagpart(resp), mkexpr(OPNEG, imagpart(lp), NULL) );
689: *ncommap += 2;
690: break;
691:
692: case OPPLUS:
693: case OPMINUS:
694: putassign( realpart(resp),
695: mkexpr(opcode, realpart(lp), realpart(rp) ));
696: if(rtype < TYCOMPLEX)
697: putassign( imagpart(resp), imagpart(lp) );
698: else if(ltype < TYCOMPLEX)
699: {
700: if(opcode == OPPLUS)
701: putassign( imagpart(resp), imagpart(rp) );
702: else putassign( imagpart(resp),
703: mkexpr(OPNEG, imagpart(rp), NULL) );
704: }
705: else
706: putassign( imagpart(resp),
707: mkexpr(opcode, imagpart(lp), imagpart(rp) ));
708:
709: *ncommap += 2;
710: break;
711:
712: case OPSTAR:
713: if(ltype < TYCOMPLEX)
714: {
715: if( ISINT(ltype) )
716: lp = intdouble(lp, ncommap);
717: putassign( realpart(resp),
718: mkexpr(OPSTAR, cpexpr(lp), realpart(rp) ));
719: putassign( imagpart(resp),
720: mkexpr(OPSTAR, cpexpr(lp), imagpart(rp) ));
721: }
722: else if(rtype < TYCOMPLEX)
723: {
724: if( ISINT(rtype) )
725: rp = intdouble(rp, ncommap);
726: putassign( realpart(resp),
727: mkexpr(OPSTAR, cpexpr(rp), realpart(lp) ));
728: putassign( imagpart(resp),
729: mkexpr(OPSTAR, cpexpr(rp), imagpart(lp) ));
730: }
731: else {
732: putassign( realpart(resp), mkexpr(OPMINUS,
733: mkexpr(OPSTAR, realpart(lp), realpart(rp)),
734: mkexpr(OPSTAR, imagpart(lp), imagpart(rp)) ));
735: putassign( imagpart(resp), mkexpr(OPPLUS,
736: mkexpr(OPSTAR, realpart(lp), imagpart(rp)),
737: mkexpr(OPSTAR, imagpart(lp), realpart(rp)) ));
738: }
739: *ncommap += 2;
740: break;
741:
742: case OPSLASH:
743: /* fixexpr has already replaced all divisions
744: * by a complex by a function call
745: */
746: if( ISINT(rtype) )
747: rp = intdouble(rp, ncommap);
748: putassign( realpart(resp),
749: mkexpr(OPSLASH, realpart(lp), cpexpr(rp)) );
750: putassign( imagpart(resp),
751: mkexpr(OPSLASH, imagpart(lp), cpexpr(rp)) );
752: *ncommap += 2;
753: break;
754:
755: case OPCONV:
756: putassign( realpart(resp), realpart(lp) );
757: if( ISCOMPLEX(lp->vtype) )
758: q = imagpart(lp);
759: else if(rp != NULL)
760: q = realpart(rp);
761: else
762: q = mkrealcon(TYDREAL, 0.0);
763: putassign( imagpart(resp), q);
764: *ncommap += 2;
765: break;
766:
767: default:
768: fatali("putcx1 of invalid opcode %d", opcode);
769: }
770:
771: frexpr(lp);
772: frexpr(rp);
773: free(p);
774: return(resp);
775: }
776:
777:
778:
779:
780: LOCAL putcxcmp(p)
781: register struct Exprblock *p;
782: {
783: int opcode;
784: int ncomma;
785: register struct Addrblock *lp, *rp;
786: struct Exprblock *q;
787:
788: ncomma = 0;
789: opcode = p->opcode;
790: lp = putcx1(p->leftp, &ncomma);
791: rp = putcx1(p->rightp, &ncomma);
792:
793: q = mkexpr( opcode==OPEQ ? OPAND : OPOR ,
794: mkexpr(opcode, realpart(lp), realpart(rp)),
795: mkexpr(opcode, imagpart(lp), imagpart(rp)) );
796: putx( fixexpr(q) );
797: putcomma(ncomma, TYINT, NO);
798:
799: free(lp);
800: free(rp);
801: free(p);
802: }
803:
804: LOCAL struct Addrblock *putch1(p, ncommap)
805: register expptr p;
806: int * ncommap;
807: {
808: register struct Addrblock *t;
809:
810: switch(p->headblock.tag)
811: {
812: case TCONST:
813: return( putconst(p) );
814:
815: case TADDR:
816: return(p);
817:
818: case TEXPR:
819: ++*ncommap;
820:
821: switch(p->exprblock.opcode)
822: {
823: case OPCALL:
824: case OPCCALL:
825: t = putcall(p);
826: break;
827:
828: case OPCONCAT:
829: t = mktemp(TYCHAR, cpexpr(p->vleng) );
830: putcat( cpexpr(t), p );
831: break;
832:
833: case OPCONV:
834: if(!ISICON(p->exprblock.vleng) ||
835: p->exprblock.vleng->constblock.const.ci!=1
836: ||
837: ! INT(p->exprblock.leftp->headblock.vtype) )
838: fatal("putch1: bad character conversion");
839: t = mktemp(TYCHAR, ICON(1) );
840: putop( mkexpr(OPASSIGN, cpexpr(t), p) );
841: break;
842: default:
843: fatali("putch1: invalid opcode %d",
844: p->exprblock.opcode);
845: }
846: return(t);
847:
848: default:
849: fatali("putch1: bad tag %d", p->headblock.tag);
850: }
851: /* NOTREACHED */
852: }
853:
854:
855:
856:
857: LOCAL putchop(p)
858: expptr p;
859: {
860: int ncomma;
861:
862: ncomma = 0;
863: putaddr( putch1(p, &ncomma) , NO );
864: putcomma(ncomma, TYCHAR, YES);
865: }
866:
867:
868:
869:
870: LOCAL putcheq(p)
871: register struct Exprblock *p;
872: {
873: int ncomma;
874:
875: ncomma = 0;
876: if( p->rightp->headblock.tag==TEXPR && p->rightp->exprblock.opcode==OPCONCAT )
877: putcat(p->leftp, p->rightp);
878: else if( ISONE(p->leftp->headblock.vleng) && ISONE(p->rightp->headblock.vleng) )
879: {
880: putaddr( putch1(p->leftp, &ncomma) , YES );
881: putaddr( putch1(p->rightp, &ncomma) , YES );
882: putcomma(ncomma, TYINT, NO);
883: p2op2(P2ASSIGN, P2CHAR);
884: }
885: else
886: {
887: putx( call2(TYINT, "s_copy", p->leftp, p->rightp) );
888: putcomma(ncomma, TYINT, NO);
889: }
890: frexpr(p->vleng);
891: free(p);
892: }
893:
894:
895:
896:
897: LOCAL putchcmp(p)
898: register struct Exprblock *p;
899: {
900: int ncomma;
901:
902: ncomma = 0;
903: if(ISONE(p->leftp->headblock.vleng) && ISONE(p->rightp->headblock.vleng) )
904: {
905: putaddr( putch1(p->leftp, &ncomma) , YES );
906: putaddr( putch1(p->rightp, &ncomma) , YES );
907: p2op2(ops2[p->opcode], P2CHAR);
908: free(p);
909: putcomma(ncomma, TYINT, NO);
910: }
911: else
912: {
913: p->leftp = call2(TYINT,"s_cmp", p->leftp, p->rightp);
914: p->rightp = ICON(0);
915: putop(p);
916: }
917: }
918:
919:
920:
921:
922:
923: LOCAL putcat(lhs, rhs)
924: register struct Addrblock *lhs;
925: register expptr rhs;
926: {
927: int n, ncomma;
928: struct Addrblock *lp, *cp;
929:
930: ncomma = 0;
931: n = ncat(rhs);
932: lp = mktmpn(n, TYLENG, NULL);
933: cp = mktmpn(n, TYADDR, NULL);
934:
935: n = 0;
936: putct1(rhs, lp, cp, &n, &ncomma);
937:
938: putx( call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n)) ) );
939: putcomma(ncomma, TYINT, NO);
940: }
941:
942:
943:
944:
945:
946: LOCAL ncat(p)
947: register expptr p;
948: {
949: if(p->headblock.tag==TEXPR && p->exprblock.opcode==OPCONCAT)
950: return( ncat(p->exprblock.leftp) + ncat(p->exprblock.rightp) );
951: else return(1);
952: }
953:
954:
955:
956:
957: LOCAL putct1(q, lp, cp, ip, ncommap)
958: register expptr q;
959: register struct Addrblock *lp, *cp;
960: int *ip, *ncommap;
961: {
962: int i;
963: struct Addrblock *lp1, *cp1;
964:
965: if(q->headblock.tag==TEXPR && q->exprblock.opcode==OPCONCAT)
966: {
967: putct1(q->exprblock.leftp, lp, cp, ip, ncommap);
968: putct1(q->exprblock.rightp, lp, cp , ip, ncommap);
969: frexpr(q->exprblock.vleng);
970: free(q);
971: }
972: else
973: {
974: i = (*ip)++;
975: lp1 = cpexpr(lp);
976: lp1->memoffset = mkexpr(OPPLUS, lp1->memoffset, ICON(i*SZLENG));
977: cp1 = cpexpr(cp);
978: cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR));
979: putassign( lp1, cpexpr(q->headblock.vleng) );
980: putassign( cp1, addrof(putch1(q,ncommap)) );
981: *ncommap += 2;
982: }
983: }
984:
985: LOCAL putaddr(p, indir)
986: register struct Addrblock *p;
987: int indir;
988: {
989: int type, type2, funct;
990: expptr offp;
991:
992: if( ISERROR(p) || (p->memoffset!=NULL && ISERROR(p->memoffset)) )
993: {
994: frexpr(p);
995: return;
996: }
997:
998: type = p->vtype;
999: type2 = types2[type];
1000: if(p->vclass == CLPROC)
1001: {
1002: funct = P2FUNCT;
1003: if(type == TYUNKNOWN)
1004: type2 = P2INT;
1005: }
1006: else
1007: funct = 0;
1008: if(p->memoffset && (!ISICON(p->memoffset) || p->memoffset->constblock.const.ci!=0) )
1009: offp = cpexpr(p->memoffset);
1010: else
1011: offp = NULL;
1012:
1013: #if FUDGEOFFSET != 1
1014: if(offp)
1015: offp = mkexpr(OPSTAR, ICON(FUDGEOFFSET), offp);
1016: #endif
1017:
1018: switch(p->vstg)
1019: {
1020: case STGAUTO:
1021: p2reg(AUTOREG, P2PTR);
1022: p2offset(type2|P2PTR, offp);
1023: if(indir)
1024: p2op2(P2INDIRECT, type2);
1025: break;
1026:
1027: case STGLENG:
1028: case STGARG:
1029: p2reg(ARGREG, type2|P2PTR|((funct?funct:P2PTR)<<2));
1030: if(p->memno)
1031: {
1032: putx( ICON(p->memno) );
1033: p2op2(P2PLUS, type2|P2PTR|(funct<<2));
1034: }
1035: if(p->vstg == STGARG)
1036: {
1037: p2op2(P2INDIRECT, type2|P2PTR);
1038: p2offset(type2|P2PTR|(funct<<2), offp);
1039: }
1040: if(indir)
1041: p2op2(P2INDIRECT, type2|funct);
1042: break;
1043:
1044: case STGBSS:
1045: case STGINIT:
1046: case STGEXT:
1047: case STGCOMMON:
1048: case STGEQUIV:
1049: case STGCONST:
1050: p2op(P2NAME);
1051: p2i(P2EXTERN);
1052: p2i(type2|funct);
1053: p2str( memname(p->vstg,p->memno) );
1054: if(!indir || offp!=NULL)
1055: p2op2(P2ADDR, type2|P2PTR);
1056: p2offset(type2|P2PTR, offp);
1057: if(indir && offp!=NULL)
1058: p2op2(P2INDIRECT, type2);
1059: break;
1060:
1061: case STGREG:
1062: if(indir)
1063: p2reg(p->memno, type2);
1064: break;
1065:
1066: default:
1067: fatali("putaddr: invalid vstg %d", p->vstg);
1068: }
1069: frexpr(p);
1070: }
1071:
1072:
1073:
1074:
1075:
1076: LOCAL struct Addrblock *putcall(p)
1077: register struct Exprblock *p;
1078: {
1079: chainp arglist, charsp, cp;
1080: int first;
1081: struct Addrblock *t;
1082: register struct Exprblock *q;
1083: struct Exprblock *fval;
1084: int type, type2, ctype, indir;
1085:
1086: if( (type = p->vtype) == TYLOGICAL)
1087: type = tylogical;
1088: type2 = types2[type];
1089: charsp = NULL;
1090: first = YES;
1091: indir = (p->opcode == OPCCALL);
1092:
1093: if(p->rightp)
1094: {
1095: arglist = p->rightp->listblock.listp;
1096: free(p->rightp);
1097: }
1098: else
1099: arglist = NULL;
1100:
1101: if(!indir) for(cp = arglist ; cp ; cp = cp->nextp)
1102: {
1103: q = cp->datap;
1104: if( ISCONST(q) )
1105: {
1106: if(q->vtype == TYSHORT)
1107: q = mkconv(tyint, q);
1108: cp->datap = q = putconst(q);
1109: }
1110: if( ISCHAR(q) )
1111: charsp = hookup(charsp, mkchain(cpexpr(q->vleng), 0) );
1112: else if(q->vclass == CLPROC)
1113: charsp = hookup(charsp, mkchain( ICON(0) , 0));
1114: }
1115:
1116: if(type == TYCHAR)
1117: {
1118: if( ISICON(p->vleng) )
1119: fval = mktemp(TYCHAR, p->vleng);
1120: else {
1121: err("adjustable character function");
1122: return(NULL);
1123: }
1124: }
1125: else if( ISCOMPLEX(type) )
1126: fval = mktemp(type, NULL);
1127: else
1128: fval = NULL;
1129:
1130: ctype = (fval ? P2INT : type2);
1131: putaddr(p->leftp, YES);
1132:
1133: if(fval)
1134: {
1135: first = NO;
1136: putaddr( cpexpr(fval), NO);
1137: if(type==TYCHAR)
1138: {
1139: putx( mkconv(TYLENG, p->vleng) );
1140: p2op2(P2LISTOP, P2INT);
1141: }
1142: }
1143:
1144: for(cp = arglist ; cp ; cp = cp->nextp)
1145: {
1146: q = cp->datap;
1147: if(q->tag==TADDR && (indir || q->vstg!=STGREG) )
1148: putaddr(q, indir && q->vtype!=TYCHAR);
1149: else if( ISCOMPLEX(q->vtype) )
1150: putcxop(q);
1151: else if (ISCHAR(q) )
1152: putchop(q);
1153: else if( ! ISERROR(q) )
1154: {
1155: if(indir)
1156: putx(q);
1157: else {
1158: t = mktemp(q->vtype, q->vleng);
1159: putassign( cpexpr(t), q );
1160: putaddr(t, NO);
1161: putcomma(1, q->vtype, YES);
1162: }
1163: }
1164: if(first)
1165: first = NO;
1166: else
1167: p2op2(P2LISTOP, P2INT);
1168: }
1169:
1170: if(arglist)
1171: frchain(&arglist);
1172: for(cp = charsp ; cp ; cp = cp->nextp)
1173: {
1174: putx( mkconv(TYLENG, cp->datap) );
1175: if(first)
1176: first = NO;
1177: else
1178: p2op2(P2LISTOP, P2INT);
1179: }
1180: frchain(&charsp);
1181:
1182: if(first)
1183: p2op(P2NULL);
1184: p2op2(P2CALL, ctype);
1185: free(p);
1186: return(fval);
1187: }
1188:
1189:
1190:
1191: LOCAL putmnmx(p)
1192: register struct Exprblock *p;
1193: {
1194: int op, type;
1195: int ncomma;
1196: struct Exprblock *qp;
1197: chainp p0, p1;
1198: struct Addrblock *sp, *tp;
1199:
1200: type = p->vtype;
1201: op = (p->opcode==OPMIN ? OPLT : OPGT );
1202: p0 = p->leftp->listblock.listp;
1203: free(p->leftp);
1204: free(p);
1205:
1206: sp = mktemp(type, NULL);
1207: tp = mktemp(type, NULL);
1208: qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp));
1209: qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp);
1210: qp = fixexpr(qp);
1211:
1212: ncomma = 1;
1213: putassign( cpexpr(sp), p0->datap );
1214:
1215: for(p1 = p0->nextp ; p1 ; p1 = p1->nextp)
1216: {
1217: ++ncomma;
1218: putassign( cpexpr(tp), p1->datap );
1219: if(p1->nextp)
1220: {
1221: ++ncomma;
1222: putassign( cpexpr(sp), cpexpr(qp) );
1223: }
1224: else
1225: putx(qp);
1226: }
1227:
1228: putcomma(ncomma, type, NO);
1229: frtemp(sp);
1230: frtemp(tp);
1231: frchain( &p0 );
1232: }
1233:
1234:
1235:
1236:
1237: LOCAL putcomma(n, type, indir)
1238: int n, type, indir;
1239: {
1240: type = types2[type];
1241: if(indir)
1242: type |= P2PTR;
1243: while(--n >= 0)
1244: p2op2(P2COMOP, type);
1245: }
1246:
1247: /*
1248: * routines that put bytes on the pass2 input stream
1249: */
1250:
1251:
1252: p2i(k)
1253: int k;
1254: {
1255: register char *s;
1256: s = &k;
1257:
1258: putc(*s++, textfile);
1259: putc(*s, textfile);
1260: }
1261:
1262:
1263:
1264:
1265: p2op(op)
1266: int op;
1267: {
1268: putc(op, textfile);
1269: putc(0376, textfile); /* MAGIC NUMBER */
1270: }
1271:
1272:
1273:
1274:
1275: p2str(s)
1276: register char *s;
1277: {
1278: do
1279: putc(*s, textfile);
1280: while(*s++);
1281: }
1282:
1283:
1284:
1285: p2op2(op, i)
1286: int op, i;
1287: {
1288: p2op(op);
1289: p2i(i);
1290: }
1291:
1292:
1293:
1294: p2reg(k, type)
1295: int k;
1296: {
1297: p2op2(P2NAME, P2REG);
1298: p2i(type);
1299: p2i(k);
1300: }
1301:
1302:
1303:
1304: LOCAL p2li(n)
1305: long int n;
1306: {
1307: register int *p, i;
1308:
1309: p = &n;
1310: for(i = 0 ; i< sizeof(long int)/sizeof(int) ; ++i)
1311: p2i(*p++);
1312: }
1313:
1314:
1315:
1316: LOCAL p2offset(type, offp)
1317: int type;
1318: register expptr offp;
1319: {
1320: expptr shorten();
1321:
1322: if(offp)
1323: {
1324: #if SZINT < SZLONG
1325: if(shortsubs)
1326: offp = shorten(offp);
1327: #endif
1328: if(offp->headblock.vtype != TYLONG)
1329: offp = mkconv(TYINT, offp);
1330: if(offp->headblock.vtype == TYLONG)
1331: {
1332: putx(offp);
1333: p2op2(P2LTOI, P2INT);
1334: }
1335: else
1336: putx( offp );
1337: p2op2(P2PLUS, type);
1338: }
1339: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.