|
|
1.1 root 1: /* @(#) local.c: 1.7 3/19/84 */
2: /* local.c - machine dependent stuff for front end
3: *
4: * WE 32000
5: *
6: */
7:
8: #include <signal.h>
9: #include "mfile1.h"
10:
11: int dsflag = 0; /* symbol info initially enabled */
12: static int dlflag = 0; /* line number info initially enabled */
13:
14: /* location counters for PROG, DATA, ADATA, ISTRNG, STRNG */
15: char *locnames[] =
16: {
17: " .text\n",
18: " .data\n",
19: " .data\n",
20: " .data 1\n",
21: " .data 1\n",
22: };
23:
24: int minrvar = TOTREGS;
25:
26: static char *tmpfn;
27: static FILE *outfile = stdout;
28: static FILE *tmpfp;
29:
30: #ifdef M32B
31: int wloop_level = LL_BOT; /* place "while" test at loop end */
32: int floop_level = LL_BOT; /* place "for" test at loop end */
33: #else
34: int wloop_level = LL_BOT; /* place "while" test at loop end */
35: int floop_level = LL_BOT; /* place "for" test at top and bot */
36: #endif
37:
38:
39: myexit(n)
40: {
41: unlink(tmpfn);
42: if (n == 1)
43: n = 51;
44: exit(n);
45: }
46:
47: getout()
48: {
49: myexit(55);
50: }
51:
52: FILE *fopen();
53: static int proflag;
54:
55: main(argc, argv)
56: int argc;
57: char **argv;
58: {
59: int j, m, n;
60: char buf[BUFSIZ], *gotnm = NULL, *findnm;
61:
62: /* catch signals if they're not now being ignored */
63:
64: if (signal(SIGHUP, SIG_IGN) != SIG_IGN)
65: signal(SIGHUP, getout);
66: if (signal(SIGINT, SIG_IGN) != SIG_IGN)
67: signal(SIGINT, getout);
68: if (signal(SIGQUIT, SIG_IGN) != SIG_IGN)
69: signal(SIGQUIT, getout);
70: if (signal(SIGTERM, SIG_IGN) != SIG_IGN)
71: signal(SIGTERM, getout);
72:
73: for (m = 1; m < argc && argv[m][0] == '-'; ++m)
74: {
75: switch( argv[m][1] )
76: {
77: case 'i': /* input file name */
78: if (!freopen(argv[m+1], "r", stdin))
79: {
80: fprintf(stderr, "Can't open %s\n", argv[m+1]);
81: myexit(2);
82: }
83: n = 2;
84: break;
85:
86: case 'o': /* output file name */
87: if (!freopen(argv[m+1], "w", stdout))
88: {
89: fprintf(stderr, "Can't open %s\n", argv[m+1]);
90: myexit(2);
91: }
92: n = 2;
93: break;
94:
95: case 'f': /* .c source file name */
96: for (gotnm = findnm = argv[m+1]; *findnm; ++findnm)
97: if (*findnm == '/')
98: gotnm = findnm + 1;
99: n = 2;
100: break;
101:
102: case 'd': /* prevent symbolic debug output */
103: if (argv[m][2] == 'l' || argv[m][3] == 'l')
104: dlflag = 1;
105: if (argv[m][2] == 's' || argv[m][3] == 's')
106: dsflag = 1;
107: n = 1;
108: break;
109:
110: case '1': /* debug flags to front */
111: argv[m][1] = 'X';
112: continue;
113:
114: case '2': /* debug flags to back */
115: argv[m]++;
116: argv[m][0] = '-';
117: continue;
118:
119: case 'V': /* print version info */
120: fputs("WE32000 pcc2 compiler: @(#)local.c SVR2\n",
121: stderr);
122: n = 1;
123: break;
124:
125: case 'p':
126: ++proflag;
127: n = 1;
128: break;
129:
130: default:
131: continue;
132:
133: }
134:
135: argc -= n;
136: for( j = m; j < argc; ++j )
137: argv[j] = argv[j+n];
138: m--;
139: }
140:
141: if (gotnm != NULL)
142: {
143: strcpy(ftitle, "\"");
144: strcat(ftitle, gotnm);
145: strcat(ftitle, "\"");
146: }
147: n = mainp1(argc, argv);
148: fclose(tmpfp);
149: if (!(tmpfp = fopen(tmpfn, "r")))
150: cerror("string file disappeared???");
151: while (m = fread(buf, 1, BUFSIZ, tmpfp))
152: fwrite(buf, 1, m, stdout);
153: myexit(n);
154: }
155:
156: beg_file()
157: {
158: /* called as the very first thing by the parser to do machine
159: * dependent stuff
160: */
161: register char *p, *s;
162: char *mktemp();
163:
164: /* note: double quotes already in ftitle... */
165: p = ftitle + strlen( ftitle ) - 2;
166: s = p - 14; /* max name length */
167: while ( p > s && *p != '"' && *p != '/' )
168: --p;
169: printf( "\t.file\t\"%.15s\n", p + 1 );
170: if(!(tmpfp= fopen(tmpfn = mktemp("pcc2SXXXXXX"), "w")))
171: cerror("can't create string file\n");
172: }
173:
174: locctr(l) /* output the location counter */
175: {
176: static int lastloc = PROG, lastpd = PROG;
177: int retval = lastloc; /* value to return at end */
178:
179: curloc = l;
180: switch (l)
181: {
182: case PROG:
183: if (lastloc == PROG)
184: break;
185: if (lastpd == DATA)
186: puts(" .text");
187: lastpd = PROG;
188: outfile = stdout;
189: break;
190:
191: case DATA:
192: case ADATA:
193: if (lastloc == DATA || lastloc == ADATA)
194: break;
195: if (lastpd == PROG)
196: puts(" .data");
197: lastpd = DATA;
198: outfile = stdout;
199: break;
200:
201: case STRNG:
202: case ISTRNG:
203: /* output string initializers to a temporary file for now
204: * don't update lastloc
205: */
206:
207: outfile = tmpfp;
208: break;
209:
210: default:
211: cerror( "illegal location counter" );
212: }
213:
214: lastloc = l;
215: return( retval ); /* declare previous loc. ctr. */
216: }
217:
218: NODE *
219: treecpy(p) /* first pass version of tcopy() */
220: register NODE *p;
221: {
222: /* make a fresh copy of p */
223: register NODE *q;
224:
225: q = talloc();
226: *q = *p;
227: switch (optype(q->in.op))
228: {
229: case BITYPE:
230: q->in.right = treecpy(p->in.right);
231: case UTYPE:
232: q->in.left = treecpy(p->in.left);
233: }
234: return (q);
235: }
236:
237:
238: NODE *
239: clocal(p) /* manipulate the parse tree for local xforms */
240: register NODE *p;
241: {
242: register NODE *l, *r;
243:
244: #if defined(M32B) && defined(IMPREGAL)
245: if ((p->in.op == VAUTO || p->in.op == VPARAM) && p->in.pad[0] == '@')
246: {
247: raname(p);
248: p->in.pad[0] = '~'; /*has been raname()'d*/
249: }
250: #endif
251: if (!asgbinop(p->in.op) && p->in.op != ASSIGN)
252: return (p);
253: r = p->in.right;
254: if (optype(r->in.op) == LTYPE)
255: return (p);
256: l = r->in.left;
257: if (r->in.op == QUEST ||
258: (r->in.op == CONV && l->in.op == QUEST) ||
259: (r->in.op == CONV && l->in.op == CONV &&
260: l->in.left->in.op == QUEST))
261: /* distribute assigns over colons */
262: {
263: register NODE *pwork;
264: NODE *pcpy = treecpy(p), *pnew;
265: #ifndef NODBG
266: extern int xdebug, eprint();
267:
268: if (xdebug)
269: {
270: puts("Entering [op]=?: distribution");
271: eprint(p);
272: }
273: #endif
274: pnew = pcpy->in.right;
275: while (pnew->in.op != QUEST)
276: pnew = pnew->in.left;
277: /*
278: * pnew is top of new tree
279: */
280: if ((pwork = p)->in.right->in.op == QUEST)
281: {
282: tfree(pwork->in.right);
283: pwork->in.right = pnew->in.right->in.left;
284: pnew->in.right->in.left = pwork;
285: /* at this point, 1/2 distributed. Tree looks like:
286: * ASSIGN|ASGOP
287: * LVAL QUEST
288: * EXPR1 COLON
289: * ASSIGN|ASGOP EXPR3
290: * LVAL EXPR2
291: * pnew "holds" new tree from QUEST node
292: */
293: }
294: else
295: {
296: NODE *pholdtop = pwork;
297:
298: pwork = pwork->in.right;
299: while (pwork->in.left->in.op != QUEST)
300: pwork = pwork->in.left;
301: tfree(pwork->in.left);
302: pwork->in.left = pnew->in.right->in.left;
303: pnew->in.right->in.left = pholdtop;
304: /* at this point, 1/2 distributed. Tree looks like:
305: * ASSIGN|ASGOP
306: * LVAL ANY # OF CONVs
307: * QUEST
308: * EXPR1 COLON
309: * ASSIGN|ASGOP EXPR3
310: * LVAL ANY # OF CONVs
311: * EXPR2
312: * pnew "holds" new tree from QUEST node
313: */
314: }
315: if ((pwork = pcpy)->in.right->in.op == QUEST)
316: {
317: pwork->in.right = pnew->in.right->in.right;
318: pnew->in.right->in.right = pwork;
319: /*
320: * done with the easy case
321: */
322: }
323: else
324: {
325: NODE *pholdtop = pwork;
326:
327: pwork = pwork->in.right;
328: while (pwork->in.left->in.op != QUEST)
329: pwork = pwork->in.left;
330: pwork->in.left = pnew->in.right->in.right;
331: pnew->in.right->in.right = pholdtop;
332: /*
333: * done with the CONVs case
334: */
335: }
336: p = pnew;
337: #ifndef NODBG
338: if (xdebug)
339: {
340: puts("Leaving [op]=?: distribution");
341: eprint(p);
342: }
343: #endif
344: }
345: return(p);
346: }
347:
348:
349: cisreg(t) /* can auto of type t go in reg */
350: TWORD t;
351: {
352: int nregs;
353:
354: /*
355: * Only allow register basic types or pointers.
356: * Someday, maybe allow register small-struct
357: */
358: switch (t)
359: {
360: case CHAR: case SHORT: case INT: case LONG:
361: case UCHAR: case USHORT: case UNSIGNED: case ULONG:
362: case FLOAT: case DOUBLE:
363: break;
364: default:
365: if (ISPTR(t))
366: break;
367: return (0);
368: }
369: nregs = (t == DOUBLE ? 2 : 1);
370: if (regvar + nregs <= TOTREGS-NRGS) /* check for too many */
371: {
372: regvar += nregs; /* number now in use */
373: if ((TOTREGS - regvar) < minrvar)
374: minrvar -= nregs;
375: nextrvar = TOTREGS - regvar;
376: return (1);
377: }
378: else
379: return (0);
380: }
381:
382: incode( p, sz )
383: register NODE *p;
384: {
385: /* generate initialization code for assigning a constant c
386: * to a field of width sz
387: * we assume that the proper alignment has been obtained and sz < SZINT
388: * inoff is updated to have the proper final value
389: */
390: if (inoff % SZINT == 0 )
391: printf(" .word %d:%d", sz, p->tn.lval);
392: else
393: printf(",%d:%d", sz, p->tn.lval);
394: inoff += sz;
395: if (inoff % SZINT == 0)
396: putchar('\n');
397: }
398:
399: vfdzero(n) /* define n bits of zeros in a vfd */
400: int n;
401: {
402: if( n <= 0 )
403: return;
404: if (inoff % SZINT == 0 )
405: printf(" .word %d:0", n);
406: else
407: printf(",%d:0", n);
408: inoff += n;
409: if (inoff % SZINT == 0)
410: putchar('\n');
411: }
412:
413: fincode(d, sz) /* floating initialization */
414: double d;
415: int sz;
416: {
417: #if defined(u3b) || defined(u3b5) || defined(u3b2)
418: union { double d; float f; int i[2] } cheat;
419:
420: if (sz == SZDOUBLE)
421: {
422: cheat.d = d;
423: printf(" .word 0x%x,0x%x\n", cheat.i[0], cheat.i[1]);
424: }
425: else
426: {
427: cheat.f = d;
428: printf(" .word 0x%x\n", cheat.i[0]);
429: }
430: #else
431: printf("\t.%s\t%.15e\n", sz == SZDOUBLE ? "double" : "float", d);
432: #endif
433: inoff += sz;
434: }
435:
436:
437: char *
438: exname(p) /* a name using external naming conventions */
439: char *p;
440: {
441: return( p );
442: }
443:
444:
445: commdec(id) /* generate a .comm from stab index id */
446: int id;
447: {
448: register struct symtab *psym;
449: OFFSZ n;
450:
451: psym = &stab[id];
452: n = tsize(psym->stype, psym->dimoff, psym->sizoff) / SZCHAR;
453: # ifndef NOSYMB
454: if ( psym->slevel == 0)
455: prdef(psym, dsflag); /* output debug info */
456: # endif
457: if (psym->sclass == STATIC)
458: printf(" .bss %s,%ld,%ld\n", exname(psym->sname),
459: n, nalign(psym->stype));
460: else if (psym->sclass == EXTERN)
461: printf(" .comm %s,%ld\n", exname(psym->sname), n);
462:
463:
464: else
465: cerror("Non-static/external in common");
466: }
467:
468:
469: static
470: nalign(t) /* figure alignment for type t */
471: TWORD t;
472: {
473: int aln;
474:
475: if (ISPTR(t))
476: aln = ALPOINT;
477: else switch (BTYPE(t))
478: {
479: case CHAR:
480: case UCHAR:
481: aln = ALCHAR;
482: break;
483: case SHORT:
484: case USHORT:
485: aln = ALSHORT;
486: break;
487: case INT:
488: case UNSIGNED:
489: case ENUMTY:
490: aln = ALINT;
491: break;
492: case LONG:
493: case ULONG:
494: aln = ALLONG;
495: break;
496: case FLOAT:
497: aln = ALFLOAT;
498: break;
499: case DOUBLE:
500: aln = ALDOUBLE;
501: break;
502: case STRTY:
503: case UNIONTY:
504: aln = ALSTRUCT;
505: break;
506: default:
507: cerror("Confused type in nalign");
508: /*NOTREACHED*/
509: }
510: return (aln / SZCHAR);
511: }
512:
513:
514: branch(n) /* branch to label n or return */
515: int n;
516: {
517: if (!reached) /* return <expr>; } comes here 2x */
518: return;
519: else
520: printf(" jmp .L%d\n", n);
521: }
522:
523:
524: defalign(n) /* align to multiple of n */
525: int n;
526: {
527: if ((n /= SZCHAR) > 1)
528: printf(" .align %d\n", n);
529: }
530:
531:
532: deflab(n) /* label n */
533: int n;
534: {
535: fprintf(outfile, ".L%d:\n", n);
536: }
537:
538:
539: efcode() /* wind up a function */
540: {
541: extern int maxboff, maxtemp, maxarg;
542: extern int strftn; /* non-zero if function is structure function,
543: ** contains label number of local static value
544: */
545: register int i, enterval;
546:
547: deflab(retlab);
548:
549: efdebug(); /* end of function debug info */
550:
551: if (strftn) /* return addr in 1st auto */
552: printf(" movw 0(%%fp),%%r0\n", ftnno);
553: printf("\t.set\t.F%d,%d\n\t.set\t.R%d,%d\n\tret\t&.R%d\n", ftnno,
554: (maxtemp + maxboff) / SZCHAR, ftnno, TOTREGS - minrvar, ftnno);
555: minrvar = TOTREGS;
556: }
557:
558:
559: bfcode(a, n) /* begin function code. a is array of n stab */
560: int a[], n; /* indices corresponding to incoming args */
561: {
562: int temp;
563:
564: #if defined(M32B) && defined(IMPREGAL)
565: rainit();
566: #endif
567: printf(" save &.R%d\n", ftnno);
568: if (proflag)
569: {
570: puts(" .data");
571: temp = getlab();
572: deflab(temp);
573: puts("\t.align\t4\n\t.word 0\n .text");
574: printf(" movw &.L%d,%%r0\n",temp);
575: puts(" jsb _mcount");
576: }
577: printf(" addw2 &.F%d,%%sp\n", ftnno);
578: retlab = getlab();
579: bfdebug( a, n, dsflag ); /* do debug info at fcn begin */
580: }
581:
582:
583: defnam(psym) /* current location is name from psym */
584: register struct symtab *psym;
585: {
586: /* define the current location as the name psym->sname
587: * first give the debugging info for external definitions
588: */
589: if( psym->slevel == 0 ) /* make sure it's external */
590: ISFTN(psym->stype) ? prdef(psym,0) : prdef(psym,dsflag);
591:
592: if (psym->sclass == EXTDEF)
593: printf(" .globl %s\n", exname(psym->sname));
594: printf("%s:\n", exname(psym->sname));
595: }
596:
597:
598: bycode(ch, loc) /* byte ch into string location loc */
599: int ch, loc;
600: {
601: if (ch < 0) /* eos */
602: {
603: if (loc)
604: putc('\n', outfile);
605: }
606: else
607: {
608: if ((loc % 10) == 0)
609: fputs("\n .byte ", outfile);
610: else
611: putc(',', outfile);
612: fprintf(outfile, "%d", ch);
613: }
614: }
615:
616: zecode(n) /* n words of 0 */
617: register int n;
618: {
619: if (n <= 0) /* this is possible, folks */
620: return;
621: printf(" .zero %d\n", (SZINT / SZCHAR) * n);
622: inoff += n * SZINT;
623: }
624:
625: struct sw heapsw[SWITSZ]; /* heap for switches */
626:
627: genswitch(p, n)
628: register struct sw *p;
629: int n;
630: {
631: /* p points to an array of structures, each consisting */
632: /* of a constant value and a label. */
633: /* The first is >=0 if there is a default label; its */
634: /* value is the label number. The entries p[1] to p[n] */
635: /* are the nontrivial cases */
636:
637: register int i;
638: register CONSZ j, range;
639: register int dlab, swlab;
640:
641: range = p[n].sval-p[1].sval;
642: if (range > 0 && range <= (3 * n) && n >= 4)
643: { /* implement a direct switch */
644: dlab = (p->slab >= 0) ? p->slab : getlab();
645: if (p[1].sval)
646: #if defined(M32B) && defined(IMPSWREG)
647: {
648: printf("\tsubw3\t&%ld,%%r%d,%%r0\n\tjneg\t.L%d\n",
649: p[1].sval, swregno, dlab);
650: swregno = 0;
651: }
652: #else
653: printf("\tsubw2\t&%ld,%%r0\n\tjneg\t.L%d\n",
654: p[1].sval, dlab);
655: #endif
656: swlab = getlab();
657: #if defined(M32B) && defined(IMPSWREG)
658: printf("\tcmpw\t%%r%d,&%d\n\tjg\t.L%d\n\tALSW3\t&2,%%r%d,%%r0\n"
659: , swregno, range, dlab, swregno);
660: printf("\tcmpw\t%%r%d,&0\n\tjneg\t.L%d\n",
661: swregno, dlab);
662: #else
663: printf("\tcmpw\t%%r0,&%d\n\tjg\t.L%d\n\tALSW3\t&2,%%r0,%%r0\n",
664: range, dlab);
665: printf("\tcmpw\t%%r0,&0 \n\tjneg\t.L%d\n", dlab);
666: #endif
667: printf("\tjmp\t*.L%d(%%r0)\n", swlab);
668: locctr(ADATA); /* output table */
669: defalign(ALPOINT);
670: puts("#SWBEG");
671: deflab(swlab);
672: for (i = 1, j = p[1].sval; i <= n; ++j)
673: printf(" .word .L%d\n",
674: (j == p[i].sval) ? p[i++].slab : dlab );
675: puts("#SWEND");
676: locctr(PROG);
677: if (p->slab < 0)
678: deflab(dlab);
679: }
680: else if ( n > 8 )
681: {
682: heapsw[0].slab = dlab = p->slab >= 0 ? p->slab : getlab();
683: makeheap( p, n, 1 ); /* build heap */
684: walkheap( 1, n ); /* produce code */
685: if( p->slab >= 0 )
686: branch( dlab );
687: else
688: deflab( dlab );
689: }
690: else /* simple switch code */
691: {
692: for (i = 1; i <= n; ++i)
693: #if defined(M32B) && defined(IMPSWREG)
694: printf("\tcmpw\t&%ld,%%r%d\n\tje\t.L%d\n",
695: p[i].sval, swregno, p[i].slab);
696: #else
697: printf("\tcmpw\t&%ld,%%r0\n\tje\t.L%d\n",
698: p[i].sval, p[i].slab);
699: #endif
700: if (p->slab >= 0)
701: branch(p->slab);
702: }
703: }
704:
705: makeheap( p, m, n )
706: register struct sw *p;
707: {
708: register int q;
709:
710: if( n >= SWITSZ )
711: cerror( "heap switch size exceeded" );
712: q = select( m );
713: heapsw[n] = p[q];
714: if( q > 1 )
715: makeheap( p, q-1, 2*n );
716: if( q < m )
717: makeheap( p+q, m-q, 2*n+1 );
718: }
719:
720: select( m )
721: {
722: register int l, i, k;
723:
724: for( i=1; ; i*=2 )
725: if( (i-1) > m ) break;
726: l = ((k = i/2 - 1) + 1)/2;
727: return( l + (m-k < l ? m-k : l) );
728: }
729:
730: walkheap( start, limit )
731: {
732: int label;
733:
734: if( start > limit )
735: return;
736: #if defined(M32B) && defined(IMPSWREG)
737: fprintf( outfile, "\tcmpw\t%%r%d,&%ld\n\tje\t.L%d\n",
738: swregno, heapsw[start].sval, heapsw[start].slab );
739: #else
740: fprintf( outfile, "\tcmpw\t%%r0,&%ld\n\tje\t.L%d\n",
741: heapsw[start].sval, heapsw[start].slab );
742: #endif
743: if( (2*start) > limit )
744: {
745: fprintf( outfile, " jmp .L%d\n", heapsw[0].slab );
746: return;
747: }
748: if( (2*start+1) <= limit )
749: {
750: label = getlab();
751: fprintf( outfile, " jg .L%d\n", label );
752: }
753: else
754: fprintf( outfile, " jg .L%d\n", heapsw[0].slab );
755: walkheap( 2*start, limit );
756: if( (2*start+1) <= limit )
757: {
758: fprintf( outfile, ".L%d:\n", label );
759: walkheap( 2*start+1, limit );
760: }
761: }
762:
763: #ifdef M32B
764: NODE *
765: setswreg( p )
766: NODE *p;
767: {
768: NODE *q;
769:
770: swregno = 0;
771: #ifdef IMPSWREG
772: if (p->in.op == ASSIGN && p->in.left->in.op == SNODE)
773: {
774: q = p->in.right;
775: if( q->in.op == REG )
776: {
777: swregno = q->tn.rval;
778: p->in.op = FREE;
779: p->in.left->in.op = FREE;
780: p = q;
781: }
782: }
783: #endif
784: return( p );
785: }
786:
787: NODE *
788: myand(p)
789: NODE *p;
790: {
791: #ifdef IMPREGAL
792: raua(p);
793: #endif
794: return(p);
795: }
796: #endif
797:
798:
799:
800: /* interface routines to debug output */
801:
802: fixdef(p)
803: struct symtab * p;
804: {
805: fix1def(p,dsflag); /* pass along flag */
806: return;
807: }
808:
809: strend(dimst)
810: int dimst;
811: {
812: str1end( dimst, dsflag ); /* pass along flag */
813: return;
814: }
815:
816: sdbline()
817: {
818: sdbln1( dlflag ); /* pass along flag */
819: return;
820: }
821:
822: aoend()
823: {
824: aoend1( dsflag ); /* pass along flag */
825: return;
826: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.