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