|
|
1.1 root 1: /* INTERMEDIATE CODE GENERATION FOR S. C. JOHNSON C COMPILERS */
2: /* NEW VERSION USING BINARY POLISH POSTFIX INTERMEDIATE */
3: #if FAMILY != PCC
4: WRONG put FILE !!!!
5: #endif
6:
7: #include "defs.h"
8: #include "pccdefs.h"
9: Addrp putcall(), putcxeq(), putcx1(), realpart();
10: expptr imagpart();
11: ftnint lencat();
12:
13: #define FOUR 4
14: extern int ops2[];
15: extern int types2[];
16:
17: #define P2BUFFMAX 128
18: static long int p2buff[P2BUFFMAX];
19: static long int *p2bufp = &p2buff[0];
20: static long int *p2bufend = &p2buff[P2BUFFMAX];
21:
22:
23: puthead(s, class)
24: char *s;
25: int class;
26: {
27: char buff[100];
28: #if TARGET == VAX
29: if(s)
30: p2ps("\t.globl\t_%s", s);
31: #endif
32: /* put out fake copy of left bracket line, to be redone later */
33: if( ! headerdone )
34: {
35: #if FAMILY == PCC
36: p2flush();
37: #endif
38: headoffset = ftell(textfile);
39: prhead(textfile);
40: headerdone = YES;
41: p2triple(P2STMT, (strlen(infname)+FOUR-1)/FOUR, 0);
42: p2str(infname);
43: #if TARGET == PDP11
44: /* fake jump to start the optimizer */
45: if(class != CLBLOCK)
46: putgoto( fudgelabel = newlabel() );
47: #endif
48:
49: #if TARGET == VAX
50: /* jump from top to bottom */
51: if(s!=CNULL && class!=CLBLOCK)
52: {
53: int proflab = newlabel();
54: p2ps("_%s:", s);
55: p2pi("\t.word\tLWM%d", procno);
56: prsave(proflab);
57: p2pi("\tjmp\tL%d", fudgelabel = newlabel());
58: }
59: #endif
60: }
61: }
62:
63:
64:
65:
66:
67: /* It is necessary to precede each procedure with a "left bracket"
68: * line that tells pass 2 how many register variables and how
69: * much automatic space is required for the function. This compiler
70: * does not know how much automatic space is needed until the
71: * entire procedure has been processed. Therefore, "puthead"
72: * is called at the begining to record the current location in textfile,
73: * then to put out a placeholder left bracket line. This procedure
74: * repositions the file and rewrites that line, then puts the
75: * file pointer back to the end of the file.
76: */
77:
78: putbracket()
79: {
80: long int hereoffset;
81:
82: #if FAMILY == PCC
83: p2flush();
84: #endif
85: hereoffset = ftell(textfile);
86: if(fseek(textfile, headoffset, 0))
87: fatal("fseek failed");
88: prhead(textfile);
89: if(fseek(textfile, hereoffset, 0))
90: fatal("fseek failed 2");
91: }
92:
93:
94:
95:
96: putrbrack(k)
97: int k;
98: {
99: p2op(P2RBRACKET, k);
100: }
101:
102:
103:
104: putnreg()
105: {
106: }
107:
108:
109:
110:
111:
112:
113: puteof()
114: {
115: p2op(P2EOF, 0);
116: p2flush();
117: }
118:
119:
120:
121: putstmt()
122: {
123: p2triple(P2STMT, 0, lineno);
124: }
125:
126:
127:
128:
129: /* put out code for if( ! p) goto l */
130: putif(p,l)
131: register expptr p;
132: int l;
133: {
134: register int k;
135:
136: if( ( k = (p = fixtype(p))->headblock.vtype) != TYLOGICAL)
137: {
138: if(k != TYERROR)
139: err("non-logical expression in IF statement");
140: frexpr(p);
141: }
142: else
143: {
144: putex1(p);
145: p2icon( (long int) l , P2INT);
146: p2op(P2CBRANCH, 0);
147: putstmt();
148: }
149: }
150:
151:
152:
153:
154:
155: /* put out code for goto l */
156: putgoto(label)
157: int label;
158: {
159: p2triple(P2GOTO, 1, label);
160: putstmt();
161: }
162:
163:
164: /* branch to address constant or integer variable */
165: putbranch(p)
166: register Addrp p;
167: {
168: #if TARGET == VAX
169: if (p->vstg == STGARG)
170: {
171: putx(p);
172: p2op(P2FORCE, P2LONG);
173: putstmt();
174: p2pass("\tjmp\t*r0");
175: return;
176: }
177: #endif
178: putex1(p);
179: p2op(P2GOTO, P2INT);
180: putstmt();
181: }
182:
183:
184:
185: /* put out label l: */
186: putlabel(label)
187: int label;
188: {
189: p2op(P2LABEL, label);
190: }
191:
192:
193:
194:
195: putexpr(p)
196: expptr p;
197: {
198: putex1(p);
199: putstmt();
200: }
201:
202:
203:
204:
205: putcmgo(index, nlab, labs)
206: expptr index;
207: int nlab;
208: struct Labelblock *labs[];
209: {
210: int i, labarray, skiplabel;
211:
212: if(! ISINT(index->headblock.vtype) )
213: {
214: execerr("computed goto index must be integer", CNULL);
215: return;
216: }
217:
218: #if TARGET == VAX
219: /* use special case instruction */
220: vaxgoto(index, nlab, labs);
221: #else
222: labarray = newlabel();
223: preven(ALIADDR);
224: prlabel(asmfile, labarray);
225: prcona(asmfile, (ftnint) (skiplabel = newlabel()) );
226: for(i = 0 ; i < nlab ; ++i)
227: if( labs[i] )
228: prcona(asmfile, (ftnint)(labs[i]->labelno) );
229: prcmgoto(index, nlab, skiplabel, labarray);
230: putlabel(skiplabel);
231: #endif
232: }
233:
234: putx(p)
235: expptr p;
236: {
237: char *memname();
238: int opc;
239: int ncomma;
240: int type, k;
241:
242: if (!p)
243: return;
244:
245: switch(p->tag)
246: {
247: case TERROR:
248: free( (charptr) p );
249: break;
250:
251: case TCONST:
252: switch(type = p->constblock.vtype)
253: {
254: case TYLOGICAL:
255: type = tyint;
256: case TYLONG:
257: case TYSHORT:
258: p2icon(p->constblock.const.ci, types2[type]);
259: free( (charptr) p );
260: break;
261:
262: case TYADDR:
263: p2triple(P2ICON, 1, P2INT|P2PTR);
264: p2word(0L);
265: p2name(memname(STGCONST,
266: (int) p->constblock.const.ci) );
267: free( (charptr) p );
268: break;
269:
270: default:
271: putx( putconst(p) );
272: break;
273: }
274: break;
275:
276: case TEXPR:
277: switch(opc = p->exprblock.opcode)
278: {
279: case OPCALL:
280: case OPCCALL:
281: if( ISCOMPLEX(p->exprblock.vtype) )
282: putcxop(p);
283: else putcall(p);
284: break;
285:
286: case OPMIN:
287: case OPMAX:
288: putmnmx(p);
289: break;
290:
291:
292: case OPASSIGN:
293: if(ISCOMPLEX(p->exprblock.leftp->headblock.vtype)
294: || ISCOMPLEX(p->exprblock.rightp->headblock.vtype) )
295: frexpr( putcxeq(p) );
296: else if( ISCHAR(p) )
297: putcheq(p);
298: else
299: goto putopp;
300: break;
301:
302: case OPEQ:
303: case OPNE:
304: if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) ||
305: ISCOMPLEX(p->exprblock.rightp->headblock.vtype) )
306: {
307: putcxcmp(p);
308: break;
309: }
310: case OPLT:
311: case OPLE:
312: case OPGT:
313: case OPGE:
314: if(ISCHAR(p->exprblock.leftp))
315: {
316: putchcmp(p);
317: break;
318: }
319: goto putopp;
320:
321: case OPPOWER:
322: putpower(p);
323: break;
324:
325: case OPSTAR:
326: #if FAMILY == PCC
327: /* m * (2**k) -> m<<k */
328: if(INT(p->exprblock.leftp->headblock.vtype) &&
329: ISICON(p->exprblock.rightp) &&
330: ( (k = log2(p->exprblock.rightp->constblock.const.ci))>0) )
331: {
332: p->exprblock.opcode = OPLSHIFT;
333: frexpr(p->exprblock.rightp);
334: p->exprblock.rightp = ICON(k);
335: goto putopp;
336: }
337: #endif
338:
339: case OPMOD:
340: goto putopp;
341: case OPPLUS:
342: case OPMINUS:
343: case OPSLASH:
344: case OPNEG:
345: if( ISCOMPLEX(p->exprblock.vtype) )
346: putcxop(p);
347: else goto putopp;
348: break;
349:
350: case OPCONV:
351: if( ISCOMPLEX(p->exprblock.vtype) )
352: putcxop(p);
353: else if( ISCOMPLEX(p->exprblock.leftp->headblock.vtype) )
354: {
355: ncomma = 0;
356: putx( mkconv(p->exprblock.vtype,
357: realpart(putcx1(p->exprblock.leftp,
358: &ncomma))));
359: putcomma(ncomma, p->exprblock.vtype, NO);
360: free( (charptr) p );
361: }
362: else goto putopp;
363: break;
364:
365: case OPNOT:
366: case OPOR:
367: case OPAND:
368: case OPEQV:
369: case OPNEQV:
370: case OPADDR:
371: case OPPLUSEQ:
372: case OPSTAREQ:
373: case OPCOMMA:
374: case OPQUEST:
375: case OPCOLON:
376: case OPBITOR:
377: case OPBITAND:
378: case OPBITXOR:
379: case OPBITNOT:
380: case OPLSHIFT:
381: case OPRSHIFT:
382: putopp:
383: putop(p);
384: break;
385:
386: case OPPAREN:
387: putx (p->exprblock.leftp);
388: break;
389: default:
390: badop("putx", opc);
391: }
392: break;
393:
394: case TADDR:
395: putaddr(p, YES);
396: break;
397:
398: default:
399: badtag("putx", p->tag);
400: }
401: }
402:
403:
404:
405: LOCAL putop(p)
406: expptr p;
407: {
408: int k;
409: expptr lp, tp;
410: int pt, lt;
411: int comma;
412:
413: switch(p->exprblock.opcode) /* check for special cases and rewrite */
414: {
415: case OPCONV:
416: pt = p->exprblock.vtype;
417: lp = p->exprblock.leftp;
418: lt = lp->headblock.vtype;
419: if (pt == TYREAL && lt == TYDREAL)
420: {
421: putx(lp);
422: p2op(P2CONV, P2REAL);
423: return;
424: }
425: while(p->tag==TEXPR && p->exprblock.opcode==OPCONV &&
426: ( (ISREAL(pt)&&ISREAL(lt)) ||
427: (INT(pt)&&(ONEOF(lt,MSKINT|MSKADDR|MSKCHAR|M(TYSUBR)))) ))
428: {
429: #if SZINT < SZLONG
430: if(lp->tag != TEXPR)
431: {
432: if(pt==TYINT && lt==TYLONG)
433: break;
434: if(lt==TYINT && pt==TYLONG)
435: break;
436: }
437: #endif
438:
439: #if TARGET == VAX
440: if(pt==TYDREAL && lt==TYREAL)
441: {
442: if(lp->tag==TEXPR &&
443: lp->exprblock.opcode==OPCONV &&
444: lp->exprblock.leftp->headblock.vtype==TYDREAL)
445: {
446: putx(lp->exprblock.leftp);
447: p2op(P2CONV, P2REAL);
448: p2op(P2CONV, P2DREAL);
449: free( (charptr) p );
450: return;
451: }
452: else break;
453: }
454: #endif
455: if(lt==TYCHAR && lp->tag==TEXPR &&
456: lp->exprblock.opcode==OPCALL)
457: {
458: p->exprblock.leftp = (expptr) putcall(lp);
459: putop(p);
460: putcomma(1, pt, NO);
461: free( (charptr) p );
462: return;
463: }
464: free( (charptr) p );
465: p = lp;
466: pt = lt;
467: lp = p->exprblock.leftp;
468: lt = lp->headblock.vtype;
469: }
470: if(p->tag==TEXPR && p->exprblock.opcode==OPCONV)
471: break;
472: putx(p);
473: if (types2[pt] != types2[lt])
474: p2op(P2CONV,types2[pt]);
475: return;
476:
477: case OPADDR:
478: comma = NO;
479: lp = p->exprblock.leftp;
480: if(lp->tag != TADDR)
481: {
482: tp = (expptr) mkaltemp
483: (lp->headblock.vtype,lp->headblock.vleng);
484: putx( mkexpr(OPASSIGN, cpexpr(tp), lp) );
485: lp = tp;
486: comma = YES;
487: }
488: putaddr(lp, NO);
489: if(comma)
490: putcomma(1, TYINT, NO);
491: free( (charptr) p );
492: return;
493: #if TARGET == VAX
494: /* take advantage of a glitch in the code generator that does not check
495: the type clash in an assignment or comparison of an integer zero and
496: a floating left operand, and generates optimal code for the correct
497: type. (The PCC has no floating-constant node to encode this correctly.)
498: */
499: case OPASSIGN:
500: case OPLT:
501: case OPLE:
502: case OPGT:
503: case OPGE:
504: case OPEQ:
505: case OPNE:
506: if(ISREAL(p->exprblock.leftp->headblock.vtype) &&
507: ISREAL(p->exprblock.rightp->headblock.vtype) &&
508: ISCONST(p->exprblock.rightp) &&
509: p->exprblock.rightp->constblock.const.cd[0]==0)
510: {
511: p->exprblock.rightp->constblock.vtype = TYINT;
512: p->exprblock.rightp->constblock.const.ci = 0;
513: }
514: #endif
515: }
516:
517: if( (k = ops2[p->exprblock.opcode]) <= 0)
518: badop("putop", p->exprblock.opcode);
519: putx(p->exprblock.leftp);
520: if(p->exprblock.rightp)
521: putx(p->exprblock.rightp);
522: p2op(k, types2[p->exprblock.vtype]);
523:
524: if(p->exprblock.vleng)
525: frexpr(p->exprblock.vleng);
526: free( (charptr) p );
527: }
528:
529: putforce(t, p)
530: int t;
531: expptr p;
532: {
533: p = mkconv(t, fixtype(p));
534: putx(p);
535: p2op(P2FORCE,
536: (t==TYSHORT ? P2SHORT : (t==TYLONG ? P2LONG : P2DREAL)) );
537: putstmt();
538: }
539:
540:
541:
542: LOCAL putpower(p)
543: expptr p;
544: {
545: expptr base;
546: Addrp t1, t2;
547: ftnint k;
548: int type;
549: int ncomma;
550:
551: if(!ISICON(p->exprblock.rightp) ||
552: (k = p->exprblock.rightp->constblock.const.ci)<2)
553: fatal("putpower: bad call");
554: base = p->exprblock.leftp;
555: type = base->headblock.vtype;
556:
557: if ((k == 2) && base->tag == TADDR && ISCONST(base->addrblock.memoffset))
558: {
559: putx( mkexpr(OPSTAR,cpexpr(base),cpexpr(base)));
560:
561: return;
562: }
563: t1 = mkaltemp(type, PNULL);
564: t2 = NULL;
565: ncomma = 1;
566: putassign(cpexpr(t1), cpexpr(base) );
567:
568: for( ; (k&1)==0 && k>2 ; k>>=1 )
569: {
570: ++ncomma;
571: putsteq(t1, t1);
572: }
573:
574: if(k == 2)
575: putx( mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) );
576: else
577: {
578: t2 = mkaltemp(type, PNULL);
579: ++ncomma;
580: putassign(cpexpr(t2), cpexpr(t1));
581:
582: for(k>>=1 ; k>1 ; k>>=1)
583: {
584: ++ncomma;
585: putsteq(t1, t1);
586: if(k & 1)
587: {
588: ++ncomma;
589: putsteq(t2, t1);
590: }
591: }
592: putx( mkexpr(OPSTAR, cpexpr(t2),
593: mkexpr(OPSTAR, cpexpr(t1), cpexpr(t1)) ));
594: }
595: putcomma(ncomma, type, NO);
596: frexpr(t1);
597: if(t2)
598: frexpr(t2);
599: frexpr(p);
600: }
601:
602:
603:
604:
605: LOCAL Addrp intdouble(p, ncommap)
606: Addrp p;
607: int *ncommap;
608: {
609: register Addrp t;
610:
611: t = mkaltemp(TYDREAL, PNULL);
612: ++*ncommap;
613: putassign(cpexpr(t), p);
614: return(t);
615: }
616:
617:
618:
619:
620:
621: LOCAL Addrp putcxeq(p)
622: register expptr p;
623: {
624: register Addrp lp, rp;
625: int ncomma;
626:
627: if(p->tag != TEXPR)
628: badtag("putcxeq", p->tag);
629:
630: ncomma = 0;
631: lp = putcx1(p->exprblock.leftp, &ncomma);
632: rp = putcx1(p->exprblock.rightp, &ncomma);
633: putassign(realpart(lp), realpart(rp));
634: if( ISCOMPLEX(p->exprblock.vtype) )
635: {
636: ++ncomma;
637: putassign(imagpart(lp), imagpart(rp));
638: }
639: putcomma(ncomma, TYREAL, NO);
640: frexpr(rp);
641: free( (charptr) p );
642: return(lp);
643: }
644:
645:
646:
647: LOCAL putcxop(p)
648: expptr p;
649: {
650: Addrp putcx1();
651: int ncomma;
652:
653: ncomma = 0;
654: putaddr( putcx1(p, &ncomma), NO);
655: putcomma(ncomma, TYINT, NO);
656: }
657:
658:
659:
660: LOCAL Addrp putcx1(p, ncommap)
661: register expptr p;
662: int *ncommap;
663: {
664: expptr q;
665: Addrp lp, rp;
666: register Addrp resp;
667: int opcode;
668: int ltype, rtype;
669: expptr mkrealcon();
670:
671: if(p == NULL)
672: return(NULL);
673:
674: switch(p->tag)
675: {
676: case TCONST:
677: if( ISCOMPLEX(p->constblock.vtype) )
678: p = (expptr) putconst(p);
679: return( (Addrp) p );
680:
681: case TADDR:
682: if( ! addressable(p) )
683: {
684: ++*ncommap;
685: resp = mkaltemp(tyint, PNULL);
686: putassign( cpexpr(resp), p->addrblock.memoffset );
687: p->addrblock.memoffset = (expptr)resp;
688: }
689: return( (Addrp) p );
690:
691: case TEXPR:
692: if( ISCOMPLEX(p->exprblock.vtype) )
693: break;
694: ++*ncommap;
695: resp = mkaltemp(TYDREAL, NO);
696: putassign( cpexpr(resp), p);
697: return(resp);
698:
699: default:
700: badtag("putcx1", p->tag);
701: }
702:
703: opcode = p->exprblock.opcode;
704: if(opcode==OPCALL || opcode==OPCCALL)
705: {
706: ++*ncommap;
707: return( putcall(p) );
708: }
709: else if(opcode == OPASSIGN)
710: {
711: ++*ncommap;
712: return( putcxeq(p) );
713: }
714: resp = mkaltemp(p->exprblock.vtype, PNULL);
715: if(lp = putcx1(p->exprblock.leftp, ncommap) )
716: ltype = lp->vtype;
717: if(rp = putcx1(p->exprblock.rightp, ncommap) )
718: rtype = rp->vtype;
719:
720: switch(opcode)
721: {
722: case OPPAREN:
723: frexpr (resp);
724: resp = lp;
725: lp = NULL;
726: break;
727:
728: case OPCOMMA:
729: frexpr(resp);
730: resp = rp;
731: rp = NULL;
732: break;
733:
734: case OPNEG:
735: putassign( realpart(resp), mkexpr(OPNEG, realpart(lp), ENULL) );
736: putassign( imagpart(resp), mkexpr(OPNEG, imagpart(lp), ENULL) );
737: *ncommap += 2;
738: break;
739:
740: case OPPLUS:
741: case OPMINUS:
742: putassign( realpart(resp),
743: mkexpr(opcode, realpart(lp), realpart(rp) ));
744: if(rtype < TYCOMPLEX)
745: putassign( imagpart(resp), imagpart(lp) );
746: else if(ltype < TYCOMPLEX)
747: {
748: if(opcode == OPPLUS)
749: putassign( imagpart(resp), imagpart(rp) );
750: else putassign( imagpart(resp),
751: mkexpr(OPNEG, imagpart(rp), ENULL) );
752: }
753: else
754: putassign( imagpart(resp),
755: mkexpr(opcode, imagpart(lp), imagpart(rp) ));
756:
757: *ncommap += 2;
758: break;
759:
760: case OPSTAR:
761: if(ltype < TYCOMPLEX)
762: {
763: if( ISINT(ltype) )
764: lp = intdouble(lp, ncommap);
765: putassign( realpart(resp),
766: mkexpr(OPSTAR, cpexpr(lp), realpart(rp) ));
767: putassign( imagpart(resp),
768: mkexpr(OPSTAR, cpexpr(lp), imagpart(rp) ));
769: }
770: else if(rtype < TYCOMPLEX)
771: {
772: if( ISINT(rtype) )
773: rp = intdouble(rp, ncommap);
774: putassign( realpart(resp),
775: mkexpr(OPSTAR, cpexpr(rp), realpart(lp) ));
776: putassign( imagpart(resp),
777: mkexpr(OPSTAR, cpexpr(rp), imagpart(lp) ));
778: }
779: else {
780: putassign( realpart(resp), mkexpr(OPMINUS,
781: mkexpr(OPSTAR, realpart(lp), realpart(rp)),
782: mkexpr(OPSTAR, imagpart(lp), imagpart(rp)) ));
783: putassign( imagpart(resp), mkexpr(OPPLUS,
784: mkexpr(OPSTAR, realpart(lp), imagpart(rp)),
785: mkexpr(OPSTAR, imagpart(lp), realpart(rp)) ));
786: }
787: *ncommap += 2;
788: break;
789:
790: case OPSLASH:
791: /* fixexpr has already replaced all divisions
792: * by a complex by a function call
793: */
794: if( ISINT(rtype) )
795: rp = intdouble(rp, ncommap);
796: putassign( realpart(resp),
797: mkexpr(OPSLASH, realpart(lp), cpexpr(rp)) );
798: putassign( imagpart(resp),
799: mkexpr(OPSLASH, imagpart(lp), cpexpr(rp)) );
800: *ncommap += 2;
801: break;
802:
803: case OPCONV:
804: putassign( realpart(resp), realpart(lp) );
805: if( ISCOMPLEX(lp->vtype) )
806: q = imagpart(lp);
807: else if(rp != NULL)
808: q = (expptr) realpart(rp);
809: else
810: q = mkrealcon(TYDREAL, 0.0);
811: putassign( imagpart(resp), q);
812: *ncommap += 2;
813: break;
814:
815: default:
816: badop("putcx1", opcode);
817: }
818:
819: frexpr(lp);
820: frexpr(rp);
821: free( (charptr) p );
822: return(resp);
823: }
824:
825:
826:
827:
828: LOCAL putcxcmp(p)
829: register expptr p;
830: {
831: int opcode;
832: int ncomma;
833: register Addrp lp, rp;
834: expptr q;
835:
836: if(p->tag != TEXPR)
837: badtag("putcxcmp", p->tag);
838:
839: ncomma = 0;
840: opcode = p->exprblock.opcode;
841: lp = putcx1(p->exprblock.leftp, &ncomma);
842: rp = putcx1(p->exprblock.rightp, &ncomma);
843:
844: q = mkexpr( opcode==OPEQ ? OPAND : OPOR ,
845: mkexpr(opcode, realpart(lp), realpart(rp)),
846: mkexpr(opcode, imagpart(lp), imagpart(rp)) );
847: putx( fixexpr(q) );
848: putcomma(ncomma, TYINT, NO);
849:
850: free( (charptr) lp);
851: free( (charptr) rp);
852: free( (charptr) p );
853: }
854:
855: LOCAL Addrp putch1(p, ncommap)
856: register expptr p;
857: int * ncommap;
858: {
859: register Addrp t;
860:
861: switch(p->tag)
862: {
863: case TCONST:
864: return( putconst(p) );
865:
866: case TADDR:
867: return( (Addrp) p );
868:
869: case TEXPR:
870: ++*ncommap;
871:
872: switch(p->exprblock.opcode)
873: {
874: expptr q;
875:
876: case OPCALL:
877: case OPCCALL:
878: t = putcall(p);
879: break;
880:
881: case OPCONCAT:
882: t = mkaltemp(TYCHAR, ICON(lencat(p)) );
883: q = (expptr) cpexpr(p->headblock.vleng);
884: putcat( cpexpr(t), p );
885: /* put the correct length on the block */
886: frexpr(t->vleng);
887: t->vleng = q;
888:
889: break;
890:
891: case OPCONV:
892: if(!ISICON(p->exprblock.vleng)
893: || p->exprblock.vleng->constblock.const.ci!=1
894: || ! INT(p->exprblock.leftp->headblock.vtype) )
895: fatal("putch1: bad character conversion");
896: t = mkaltemp(TYCHAR, ICON(1) );
897: putop( mkexpr(OPASSIGN, cpexpr(t), p) );
898: break;
899: default:
900: badop("putch1", p->exprblock.opcode);
901: }
902: return(t);
903:
904: default:
905: badtag("putch1", p->tag);
906: }
907: /* NOTREACHED */
908: }
909:
910:
911:
912:
913: LOCAL putchop(p)
914: expptr p;
915: {
916: int ncomma;
917:
918: ncomma = 0;
919: putaddr( putch1(p, &ncomma) , NO );
920: putcomma(ncomma, TYCHAR, YES);
921: }
922:
923:
924:
925:
926: LOCAL putcheq(p)
927: register expptr p;
928: {
929: int ncomma;
930: expptr lp, rp;
931:
932: if(p->tag != TEXPR)
933: badtag("putcheq", p->tag);
934:
935: ncomma = 0;
936: lp = p->exprblock.leftp;
937: rp = p->exprblock.rightp;
938: if( rp->tag==TEXPR && rp->exprblock.opcode==OPCONCAT )
939: putcat(lp, rp);
940: else if( ISONE(lp->headblock.vleng) && ISONE(rp->headblock.vleng) )
941: {
942: putaddr( putch1(lp, &ncomma) , YES );
943: putaddr( putch1(rp, &ncomma) , YES );
944: putcomma(ncomma, TYINT, NO);
945: p2op(P2ASSIGN, P2CHAR);
946: }
947: else
948: {
949: putx( call2(TYINT, "s_copy", lp, rp) );
950: putcomma(ncomma, TYINT, NO);
951: }
952:
953: frexpr(p->exprblock.vleng);
954: free( (charptr) p );
955: }
956:
957:
958:
959:
960: LOCAL putchcmp(p)
961: register expptr p;
962: {
963: int ncomma;
964: expptr lp, rp;
965:
966: if(p->tag != TEXPR)
967: badtag("putchcmp", p->tag);
968:
969: ncomma = 0;
970: lp = p->exprblock.leftp;
971: rp = p->exprblock.rightp;
972:
973: if(ISONE(lp->headblock.vleng) && ISONE(rp->headblock.vleng) )
974: {
975: putaddr( putch1(lp, &ncomma) , YES );
976: putaddr( putch1(rp, &ncomma) , YES );
977: p2op(ops2[p->exprblock.opcode], P2CHAR);
978: free( (charptr) p );
979: putcomma(ncomma, TYINT, NO);
980: }
981: else
982: {
983: p->exprblock.leftp = call2(TYINT,"s_cmp", lp, rp);
984: p->exprblock.rightp = ICON(0);
985: putop(p);
986: }
987: }
988:
989:
990:
991:
992:
993: LOCAL putcat(lhs, rhs)
994: register Addrp lhs;
995: register expptr rhs;
996: {
997: int n, ncomma;
998: Addrp lp, cp;
999:
1000: ncomma = 0;
1001: n = ncat(rhs);
1002: lp = mkaltmpn(n, TYLENG, PNULL);
1003: cp = mkaltmpn(n, TYADDR, PNULL);
1004:
1005: n = 0;
1006: putct1(rhs, lp, cp, &n, &ncomma);
1007:
1008: putx( call4(TYSUBR, "s_cat", lhs, cp, lp, mkconv(TYLONG, ICON(n)) ) );
1009: putcomma(ncomma, TYINT, NO);
1010: }
1011:
1012:
1013:
1014:
1015:
1016: LOCAL putct1(q, lp, cp, ip, ncommap)
1017: register expptr q;
1018: register Addrp lp, cp;
1019: int *ip, *ncommap;
1020: {
1021: int i;
1022: Addrp lp1, cp1;
1023:
1024: if(q->tag==TEXPR && q->exprblock.opcode==OPCONCAT)
1025: {
1026: putct1(q->exprblock.leftp, lp, cp, ip, ncommap);
1027: putct1(q->exprblock.rightp, lp, cp , ip, ncommap);
1028: frexpr(q->exprblock.vleng);
1029: free( (charptr) q );
1030: }
1031: else
1032: {
1033: i = (*ip)++;
1034: lp1 = (Addrp) cpexpr(lp);
1035: lp1->memoffset = mkexpr(OPPLUS,lp1->memoffset, ICON(i*SZLENG));
1036: cp1 = (Addrp) cpexpr(cp);
1037: cp1->memoffset = mkexpr(OPPLUS, cp1->memoffset, ICON(i*SZADDR));
1038: putassign( lp1, cpexpr(q->headblock.vleng) );
1039: putassign( cp1, addrof(putch1(q,ncommap)) );
1040: *ncommap += 2;
1041: }
1042: }
1043:
1044: LOCAL putaddr(p, indir)
1045: register Addrp p;
1046: int indir;
1047: {
1048: int type, type2, funct;
1049: ftnint offset, simoffset();
1050: expptr offp, shorten();
1051:
1052: if( p->tag==TERROR || (p->memoffset!=NULL && ISERROR(p->memoffset)) )
1053: {
1054: frexpr(p);
1055: return;
1056: }
1057: if (p->tag != TADDR) badtag ("putaddr",p->tag);
1058:
1059: type = p->vtype;
1060: type2 = types2[type];
1061: funct = (p->vclass==CLPROC ? P2FUNCT<<2 : 0);
1062:
1063: offp = (p->memoffset ? (expptr) cpexpr(p->memoffset) : (expptr)NULL );
1064:
1065:
1066: #if (FUDGEOFFSET != 1)
1067: if(offp)
1068: offp = mkexpr(OPSTAR, ICON(FUDGEOFFSET), offp);
1069: #endif
1070:
1071: offset = simoffset( &offp );
1072: #if SZINT < SZLONG
1073: if(offp)
1074: if(shortsubs)
1075: offp = shorten(offp);
1076: else
1077: offp = mkconv(TYINT, offp);
1078: #else
1079: if(offp)
1080: offp = mkconv(TYINT, offp);
1081: #endif
1082:
1083: if (p->vclass == CLVAR
1084: && (p->vstg == STGBSS || p->vstg == STGEQUIV)
1085: && SMALLVAR(p->varsize)
1086: && offset >= -32768 && offset <= 32767)
1087: {
1088: anylocals = YES;
1089: if (indir && !offp)
1090: p2ldisp(offset, memname(p->vstg, p->memno), type2);
1091: else
1092: {
1093: p2reg(11, type2 | P2PTR);
1094: p2triple(P2ICON, 1, P2INT);
1095: p2word(offset);
1096: p2ndisp(memname(p->vstg, p->memno));
1097: p2op(P2PLUS, type2 | P2PTR);
1098: if (offp)
1099: {
1100: putx(offp);
1101: p2op(P2PLUS, type2 | P2PTR);
1102: }
1103: if (indir)
1104: p2op(P2INDIRECT, type2);
1105: }
1106: frexpr((tagptr) p);
1107: return;
1108: }
1109:
1110: switch(p->vstg)
1111: {
1112: case STGAUTO:
1113: if(indir && !offp)
1114: {
1115: p2oreg(offset, AUTOREG, type2);
1116: break;
1117: }
1118:
1119: if(!indir && !offp && !offset)
1120: {
1121: p2reg(AUTOREG, type2 | P2PTR);
1122: break;
1123: }
1124:
1125: p2reg(AUTOREG, type2 | P2PTR);
1126: if(offp)
1127: {
1128: putx(offp);
1129: if(offset)
1130: p2icon(offset, P2INT);
1131: }
1132: else
1133: p2icon(offset, P2INT);
1134: if(offp && offset)
1135: p2op(P2PLUS, type2 | P2PTR);
1136: p2op(P2PLUS, type2 | P2PTR);
1137: if(indir)
1138: p2op(P2INDIRECT, type2);
1139: break;
1140:
1141: case STGARG:
1142: p2oreg(
1143: #ifdef ARGOFFSET
1144: ARGOFFSET +
1145: #endif
1146: (ftnint) (FUDGEOFFSET*p->memno),
1147: ARGREG, type2 | P2PTR | funct );
1148:
1149: based:
1150: if(offset)
1151: {
1152: p2icon(offset, P2INT);
1153: p2op(P2PLUS, type2 | P2PTR);
1154: }
1155: if(offp)
1156: {
1157: putx(offp);
1158: p2op(P2PLUS, type2 | P2PTR);
1159: }
1160: if(indir)
1161: p2op(P2INDIRECT, type2);
1162: break;
1163:
1164: case STGLENG:
1165: if(indir)
1166: {
1167: p2oreg(
1168: #ifdef ARGOFFSET
1169: ARGOFFSET +
1170: #endif
1171: (ftnint) (FUDGEOFFSET*p->memno),
1172: ARGREG, type2 );
1173: }
1174: else {
1175: p2reg(ARGREG, type2 | P2PTR );
1176: p2icon(
1177: #ifdef ARGOFFSET
1178: ARGOFFSET +
1179: #endif
1180: (ftnint) (FUDGEOFFSET*p->memno), P2INT);
1181: p2op(P2PLUS, type2 | P2PTR );
1182: }
1183: break;
1184:
1185:
1186: case STGBSS:
1187: case STGINIT:
1188: case STGEXT:
1189: case STGCOMMON:
1190: case STGEQUIV:
1191: case STGCONST:
1192: if(offp)
1193: {
1194: putx(offp);
1195: putmem(p, P2ICON, offset);
1196: p2op(P2PLUS, type2 | P2PTR);
1197: if(indir)
1198: p2op(P2INDIRECT, type2);
1199: }
1200: else
1201: putmem(p, (indir ? P2NAME : P2ICON), offset);
1202:
1203: break;
1204:
1205: case STGREG:
1206: if(indir)
1207: p2reg(p->memno, type2);
1208: else
1209: fatal("attempt to take address of a register");
1210: break;
1211:
1212: case STGPREG:
1213: if(indir && !offp)
1214: p2oreg(offset, p->memno, type2);
1215: else
1216: {
1217: p2reg(p->memno, type2 | P2PTR);
1218: goto based;
1219: }
1220: break;
1221:
1222: default:
1223: badstg("putaddr", p->vstg);
1224: }
1225: frexpr(p);
1226: }
1227:
1228:
1229:
1230:
1231: LOCAL putmem(p, class, offset)
1232: expptr p;
1233: int class;
1234: ftnint offset;
1235: {
1236: int type2;
1237: int funct;
1238: char *name, *memname();
1239:
1240: funct = (p->headblock.vclass==CLPROC ? P2FUNCT<<2 : 0);
1241: type2 = types2[p->headblock.vtype];
1242: if(p->headblock.vclass == CLPROC)
1243: type2 |= (P2FUNCT<<2);
1244: name = memname(p->addrblock.vstg, p->addrblock.memno);
1245: if(class == P2ICON)
1246: {
1247: p2triple(P2ICON, name[0]!='\0', type2|P2PTR);
1248: p2word(offset);
1249: if(name[0])
1250: p2name(name);
1251: }
1252: else
1253: {
1254: p2triple(P2NAME, offset!=0, type2);
1255: if(offset != 0)
1256: p2word(offset);
1257: p2name(name);
1258: }
1259: }
1260:
1261:
1262:
1263: LOCAL Addrp putcall(p)
1264: register Exprp p;
1265: {
1266: chainp arglist, charsp, cp;
1267: int n, first;
1268: Addrp t;
1269: register expptr q;
1270: Addrp fval;
1271: int type, type2, ctype, qtype, indir;
1272:
1273: type2 = types2[type = p->vtype];
1274: charsp = NULL;
1275: indir = (p->opcode == OPCCALL);
1276: n = 0;
1277: first = YES;
1278:
1279: if(p->rightp)
1280: {
1281: arglist = p->rightp->listblock.listp;
1282: free( (charptr) (p->rightp) );
1283: }
1284: else
1285: arglist = NULL;
1286:
1287: for(cp = arglist ; cp ; cp = cp->nextp)
1288: {
1289: q = (expptr) cp->datap;
1290: if(indir)
1291: ++n;
1292: else {
1293: q = (expptr) (cp->datap);
1294: if( ISCONST(q) )
1295: {
1296: q = (expptr) putconst(q);
1297: cp->datap = (tagptr) q;
1298: }
1299: if( ISCHAR(q) && q->headblock.vclass!=CLPROC )
1300: {
1301: charsp = hookup(charsp,
1302: mkchain(cpexpr(q->headblock.vleng),
1303: CHNULL));
1304: n += 2;
1305: }
1306: else
1307: n += 1;
1308: }
1309: }
1310:
1311: if(type == TYCHAR)
1312: {
1313: if( ISICON(p->vleng) )
1314: {
1315: fval = mkaltemp(TYCHAR, p->vleng);
1316: n += 2;
1317: }
1318: else {
1319: err("adjustable character function");
1320: return;
1321: }
1322: }
1323: else if( ISCOMPLEX(type) )
1324: {
1325: fval = mkaltemp(type, PNULL);
1326: n += 1;
1327: }
1328: else
1329: fval = NULL;
1330:
1331: ctype = (fval ? P2INT : type2);
1332: putaddr(p->leftp, NO);
1333:
1334: if(fval)
1335: {
1336: first = NO;
1337: putaddr( cpexpr(fval), NO);
1338: if(type==TYCHAR)
1339: {
1340: putx( mkconv(TYLENG,p->vleng) );
1341: p2op(P2LISTOP, type2);
1342: }
1343: }
1344:
1345: for(cp = arglist ; cp ; cp = cp->nextp)
1346: {
1347: q = (expptr) (cp->datap);
1348: if(q->tag==TADDR && (indir || q->addrblock.vstg!=STGREG) )
1349: putaddr(q, indir && q->addrblock.vtype!=TYCHAR);
1350: else if( ISCOMPLEX(q->headblock.vtype) )
1351: putcxop(q);
1352: else if (ISCHAR(q) )
1353: putchop(q);
1354: else if( ! ISERROR(q) )
1355: {
1356: if(indir)
1357: putx(q);
1358: else {
1359: t = mkaltemp(qtype = q->headblock.vtype,
1360: q->headblock.vleng);
1361: putassign( cpexpr(t), q );
1362: putaddr(t, NO);
1363: putcomma(1, qtype, YES);
1364: }
1365: }
1366: if(first)
1367: first = NO;
1368: else
1369: p2op(P2LISTOP, type2);
1370: }
1371:
1372: if(arglist)
1373: frchain(&arglist);
1374: for(cp = charsp ; cp ; cp = cp->nextp)
1375: {
1376: putx( mkconv(TYLENG,cp->datap) );
1377: p2op(P2LISTOP, type2);
1378: }
1379: frchain(&charsp);
1380: p2op(n>0 ? P2CALL : P2CALL0 , ctype);
1381: free( (charptr) p );
1382: return(fval);
1383: }
1384:
1385:
1386:
1387: LOCAL putmnmx(p)
1388: register expptr p;
1389: {
1390: int op, type;
1391: int ncomma;
1392: expptr qp;
1393: chainp p0, p1;
1394: Addrp sp, tp;
1395:
1396: if(p->tag != TEXPR)
1397: badtag("putmnmx", p->tag);
1398:
1399: type = p->exprblock.vtype;
1400: op = (p->exprblock.opcode==OPMIN ? OPLT : OPGT );
1401: p0 = p->exprblock.leftp->listblock.listp;
1402: free( (charptr) (p->exprblock.leftp) );
1403: free( (charptr) p );
1404:
1405: sp = mkaltemp(type, PNULL);
1406: tp = mkaltemp(type, PNULL);
1407: qp = mkexpr(OPCOLON, cpexpr(tp), cpexpr(sp));
1408: qp = mkexpr(OPQUEST, mkexpr(op, cpexpr(tp),cpexpr(sp)), qp);
1409: qp = fixexpr(qp);
1410:
1411: ncomma = 1;
1412: putassign( cpexpr(sp), p0->datap );
1413:
1414: for(p1 = p0->nextp ; p1 ; p1 = p1->nextp)
1415: {
1416: ++ncomma;
1417: putassign( cpexpr(tp), p1->datap );
1418: if(p1->nextp)
1419: {
1420: ++ncomma;
1421: putassign( cpexpr(sp), cpexpr(qp) );
1422: }
1423: else
1424: putx(qp);
1425: }
1426:
1427: putcomma(ncomma, type, NO);
1428: frtemp(sp);
1429: frtemp(tp);
1430: frchain( &p0 );
1431: }
1432:
1433:
1434:
1435:
1436: LOCAL putcomma(n, type, indir)
1437: int n, type, indir;
1438: {
1439: type = types2[type];
1440: if(indir)
1441: type |= P2PTR;
1442: while(--n >= 0)
1443: p2op(P2COMOP, type);
1444: }
1445:
1446:
1447:
1448:
1449: ftnint simoffset(p0)
1450: expptr *p0;
1451: {
1452: ftnint offset, prod;
1453: register expptr p, lp, rp;
1454:
1455: offset = 0;
1456: p = *p0;
1457: if(p == NULL)
1458: return(0);
1459:
1460: if( ! ISINT(p->headblock.vtype) )
1461: return(0);
1462:
1463: if(p->tag==TEXPR && p->exprblock.opcode==OPSTAR)
1464: {
1465: lp = p->exprblock.leftp;
1466: rp = p->exprblock.rightp;
1467: if(ISICON(rp) && lp->tag==TEXPR &&
1468: lp->exprblock.opcode==OPPLUS && ISICON(lp->exprblock.rightp))
1469: {
1470: p->exprblock.opcode = OPPLUS;
1471: lp->exprblock.opcode = OPSTAR;
1472: prod = rp->constblock.const.ci *
1473: lp->exprblock.rightp->constblock.const.ci;
1474: lp->exprblock.rightp->constblock.const.ci = rp->constblock.const.ci;
1475: rp->constblock.const.ci = prod;
1476: }
1477: }
1478:
1479: if(p->tag==TEXPR && p->exprblock.opcode==OPPLUS &&
1480: ISICON(p->exprblock.rightp))
1481: {
1482: rp = p->exprblock.rightp;
1483: lp = p->exprblock.leftp;
1484: offset += rp->constblock.const.ci;
1485: frexpr(rp);
1486: free( (charptr) p );
1487: *p0 = lp;
1488: }
1489:
1490: if( ISCONST(p) )
1491: {
1492: offset += p->constblock.const.ci;
1493: frexpr(p);
1494: *p0 = NULL;
1495: }
1496:
1497: return(offset);
1498: }
1499:
1500:
1501:
1502:
1503:
1504: p2op(op, type)
1505: int op, type;
1506: {
1507: p2triple(op, 0, type);
1508: }
1509:
1510: p2icon(offset, type)
1511: ftnint offset;
1512: int type;
1513: {
1514: p2triple(P2ICON, 0, type);
1515: p2word(offset);
1516: }
1517:
1518:
1519:
1520:
1521: p2oreg(offset, reg, type)
1522: ftnint offset;
1523: int reg, type;
1524: {
1525: p2triple(P2OREG, reg, type);
1526: p2word(offset);
1527: p2name("");
1528: }
1529:
1530:
1531:
1532:
1533: p2reg(reg, type)
1534: int reg, type;
1535: {
1536: p2triple(P2REG, reg, type);
1537: }
1538:
1539:
1540:
1541: p2pi(s, i)
1542: char *s;
1543: int i;
1544: {
1545: char buff[100];
1546: sprintf(buff, s, i);
1547: p2pass(buff);
1548: }
1549:
1550:
1551:
1552: p2pij(s, i, j)
1553: char *s;
1554: int i, j;
1555: {
1556: char buff[100];
1557: sprintf(buff, s, i, j);
1558: p2pass(buff);
1559: }
1560:
1561:
1562:
1563:
1564: p2ps(s, t)
1565: char *s, *t;
1566: {
1567: char buff[100];
1568: sprintf(buff, s, t);
1569: p2pass(buff);
1570: }
1571:
1572:
1573:
1574:
1575: p2pass(s)
1576: char *s;
1577: {
1578: p2triple(P2PASS, (strlen(s) + FOUR-1)/FOUR, 0);
1579: p2str(s);
1580: }
1581:
1582:
1583:
1584:
1585: p2str(s)
1586: register char *s;
1587: {
1588: union { long int word; char str[FOUR]; } u;
1589: register int i;
1590:
1591: i = 0;
1592: u.word = 0;
1593: while(*s)
1594: {
1595: u.str[i++] = *s++;
1596: if(i == FOUR)
1597: {
1598: p2word(u.word);
1599: u.word = 0;
1600: i = 0;
1601: }
1602: }
1603: if(i > 0)
1604: p2word(u.word);
1605: }
1606:
1607:
1608:
1609:
1610: p2triple(op, var, type)
1611: int op, var, type;
1612: {
1613: register long word;
1614: word = op | (var<<8);
1615: word |= ( (long int) type) <<16;
1616: p2word(word);
1617: }
1618:
1619:
1620:
1621:
1622:
1623: p2name(s)
1624: register char *s;
1625: {
1626: register int i;
1627:
1628: #ifdef UCBPASS2
1629: /* arbitrary length names, terminated by a null,
1630: padded to a full word */
1631:
1632: # define WL sizeof(long int)
1633: union { long int word; char str[WL]; } w;
1634:
1635: w.word = 0;
1636: i = 0;
1637: while(w.str[i++] = *s++)
1638: if(i == WL)
1639: {
1640: p2word(w.word);
1641: w.word = 0;
1642: i = 0;
1643: }
1644: if(i > 0)
1645: p2word(w.word);
1646: #else
1647: /* standard intermediate, names are 8 characters long */
1648:
1649: union { long int word[2]; char str[8]; } u;
1650:
1651: u.word[0] = u.word[1] = 0;
1652: for(i = 0 ; i<8 && *s ; ++i)
1653: u.str[i] = *s++;
1654: p2word(u.word[0]);
1655: p2word(u.word[1]);
1656:
1657: #endif
1658:
1659: }
1660:
1661:
1662:
1663:
1664: p2word(w)
1665: long int w;
1666: {
1667: *p2bufp++ = w;
1668: if(p2bufp >= p2bufend)
1669: p2flush();
1670: }
1671:
1672:
1673:
1674: p2flush()
1675: {
1676: if(p2bufp > p2buff)
1677: write(fileno(textfile), p2buff, (p2bufp-p2buff)*sizeof(long int));
1678: p2bufp = p2buff;
1679: }
1680:
1681:
1682:
1683: LOCAL
1684: p2ldisp(offset, vname, type)
1685: ftnint offset;
1686: char *vname;
1687: int type;
1688: {
1689: char buff[100];
1690:
1691: sprintf(buff, "%s-v.%d", vname, bsslabel);
1692: p2triple(P2OREG, 11, type);
1693: p2word(offset);
1694: p2name(buff);
1695: }
1696:
1697:
1698:
1699: p2ndisp(vname)
1700: char *vname;
1701: {
1702: char buff[100];
1703:
1704: sprintf(buff, "%s-v.%d", vname, bsslabel);
1705: p2name(buff);
1706: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.