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