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