|
|
1.1 root 1: /* C compiler: main program */
2:
3: #include "version.h"
4: #include "c.h"
5:
6: Interface *IR;
7:
8: int Aflag; /* >= 0 if -A specified */
9: int Pflag; /* != 0 if -P specified */
10: int glevel; /* == [0-9] if -g[0-9] specified */
11: int xref; /* != 0 for cross-reference data */
12: Symbol YYnull; /* symbol for _YYnull if -n specified */
13:
14: static char *infile; /* input file */
15: static char *outfile; /* output file */
16: static char *progname; /* argv[0] */
17:
18: List loci, tables; /* current (locus,table) lists */
19:
20: dclproto(static void compile,(char *));
21: dclproto(static int doargs,(int, char **));
22: dclproto(static void emitYYnull,(void));
23: dclproto(static Type ftype,(Type, Type));
24: dclproto(static void typestab,(Symbol, Generic));
25:
26: int main(argc, argv) char *argv[]; {
27: Symbol symroot = 0; /* root of the global symbols */
28: static Events z;
29: int i, infd = 0, outfd = 1;
30:
31: assert(MAXKIDS >= 2);
32: assert(MAXSYMS >= 2);
33: progname = argv[0];
34: level = GLOBAL;
35: IR = interfaces[0];
36: for (i = 1; i < argc; i++)
37: if (strncmp(argv[i], "target=", 7) == 0) {
38: int k;
39: for (k = 0; interfaces[k]; k++)
40: if (strcmp(&argv[i][7], interfaces[k]->target) == 0)
41: break;
42: if (interfaces[k])
43: IR = interfaces[k];
44: else
45: fprint(2, "%s: unknown target `%s'\n", argv[0], &argv[i][7]);
46: }
47: assert(IR);
48: typeInit();
49: assert(inttype->size >= voidptype->size);
50: argc = doargs(argc, argv);
51: if (infile && *infile != '-') {
52: close(infd);
53: if ((infd = open(infile, 0)) < 0) {
54: fprint(2, "%s: can't read %s\n", argv[0], infile);
55: exit(1);
56: }
57: }
58: if (outfile && *outfile != '-') {
59: close(outfd);
60: if ((outfd = creat(outfile, 0666)) < 0) {
61: fprint(2, "%s: can't write %s\n", argv[0], outfile);
62: exit(1);
63: }
64: }
65: inputInit(infd);
66: outputInit(outfd);
67: t = gettok();
68: (*IR->progbeg)(argc, argv);
69: if (glevel && IR->stabinit)
70: (*IR->stabinit)(firstfile, argc, argv);
71: program();
72: if (events.end)
73: apply(events.end, (Generic)0, (Generic)0);
74: events = z;
75: emitYYnull();
76: finalize();
77: if (glevel || xref) {
78: Coordinate src;
79: foreach(types, GLOBAL, typestab, (Generic)&symroot);
80: foreach(identifiers, GLOBAL, typestab, (Generic)&symroot);
81: src.file = firstfile;
82: src.x = 0;
83: src.y = lineno;
84: if ((glevel > 2 || xref) && IR->stabend)
85: (*IR->stabend)(&src, symroot, (Coordinate **)ltoa(append((Generic)0, loci), 0),
86: (Symbol *)ltoa(append((Generic)0, tables), 0),
87: symbols ? (Symbol *)ltoa(symbols, 0) : (Symbol *)0);
88: else if (IR->stabend)
89: (*IR->stabend)(&src, 0, 0, 0, 0);
90: }
91: (*IR->progend)();
92: outflush();
93: exit(errcnt > 0);
94: return 0;
95: }
96:
97: /* compile - compile str */
98: static void compile(str) char *str; {
99: inputstring(str);
100: t = gettok();
101: program();
102: }
103:
104: /* doargs - process program arguments, removing top-half arguments from argv */
105: static int doargs(argc, argv) char *argv[]; {
106: char *s;
107: int i, j, x;
108: Symbol p;
109:
110: for (i = j = 1; i < argc; i++)
111: if (strcmp(argv[i], "-g") == 0)
112: glevel = 2;
113: else if (strncmp(argv[i], "-g", 2) == 0
114: && argv[i][2] && argv[i][2] >= '0' && argv[i][2] <= '9')
115: glevel = argv[i][2] - '0';
116: else if (strcmp(argv[i], "-x") == 0)
117: xref++;
118: else if (strcmp(argv[i], "-A") == 0)
119: Aflag++;
120: else if (strcmp(argv[i], "-P") == 0)
121: Pflag++;
122: else if (strcmp(argv[i], "-w") == 0)
123: wflag++;
124: else if (strcmp(argv[i], "-b") == 0 || strcmp(argv[i], "-C") == 0
125: || strncmp(argv[i], "-a", 2) == 0)
126: bbinit(argv[i]);
127: else if (strcmp(argv[i], "-n") == 0) {
128: if (!YYnull) {
129: YYnull = mksymbol(EXTERN, "_YYnull", ftype(voidtype, inttype));
130: YYnull->sclass = STATIC;
131: }
132: } else if (strncmp(argv[i], "-t", 2) == 0)
133: traceinit(&argv[i][2]);
134: else if (strcmp(argv[i], "-v") == 0)
135: fprint(2, "%s target='%s' version %d.%d\n", progname, IR->target,
136: VERSION>>8, VERSION&0xff);
137: else if (strncmp(argv[i], "-s", 2) == 0)
138: density = strtod(&argv[i][2], (char **)0);
139: else if (strncmp(argv[i], "-e", 2) == 0) {
140: if ((x = strtol(&argv[i][2], (char **)0, 0)) > 0)
141: errlimit = x;
142: } else if (strncmp(argv[i], "target=", 7) == 0)
143: ;
144: else if (strcmp(argv[i], "-nodag") == 0)
145: IR->no_dag = !IR->no_dag;
146: else if (strcmp(argv[i], "-") == 0 || *argv[i] != '-') {
147: if (infile == 0)
148: infile = argv[i];
149: else if (outfile == 0)
150: outfile = argv[i];
151: else
152: argv[j++] = argv[i];
153: } else {
154: if (strcmp(argv[i], "-XP") == 0)
155: argv[i] = "-p";
156: else if (strncmp(argv[i], "-X", 2) == 0)
157: *++argv[i] = '-';
158: argv[j++] = argv[i];
159: }
160: argv[j] = 0;
161: return j;
162: }
163:
164: /* emitYYnull - compile definition for _YYnull, if referenced */
165: static void emitYYnull() {
166: if (YYnull && YYnull->ref) {
167: Aflag = 0;
168: YYnull->defined = 0;
169: YYnull = 0;
170: compile(stringf("static char *_YYfile = \"%s\";\n", file));
171: compile("static void _YYnull(int line,...) {\n\
172: char buf[200];\n\
173: sprintf(buf, \"null pointer dereferenced @%s:%d\\n\", _YYfile, line);\n\
174: write(2, buf, strlen(buf));\n\
175: abort();\n\
176: }\n");
177: } else if (YYnull)
178: YYnull->ref = 1;
179: }
180:
181: /* ftype - return a function type for `rty function (ty,...)' */
182: static Type ftype(rty, ty) Type rty, ty; {
183: List list = append(ty, 0);
184:
185: list = append(voidtype, list);
186: return func(rty, (Type *)ltoa(list, (Generic *)alloc((length(list) + 1)*sizeof (Type))), 0);
187: }
188:
189: /* mkstr - make a string constant */
190: Symbol mkstr(str) char *str; {
191: Value v;
192: Symbol p;
193:
194: v.p = str;
195: p = constant(array(chartype, strlen(v.p) + 1, 0), v);
196: if (p->u.c.loc == 0)
197: p->u.c.loc = genident(STATIC, p->type, GLOBAL);
198: return p;
199: }
200:
201: /* mksymbol - make a symbol for name, install in &globals if sclass==EXTERN */
202: Symbol mksymbol(sclass, name, ty) char *name; Type ty; {
203: Symbol p;
204:
205: if (sclass == EXTERN)
206: p = install(string(name), &globals, 1);
207: else {
208: p = (Symbol)alloc(sizeof *p);
209: BZERO(p, struct symbol);
210: p->name = string(name);
211: p->scope = GLOBAL;
212: }
213: p->sclass = sclass;
214: p->type = ty;
215: (*IR->defsymbol)(p);
216: p->defined = 1;
217: return p;
218: }
219:
220: /* typestab - emit stab entries for p */
221: static void typestab(p, cl) Symbol p; Generic cl; {
222: if (*(Symbol *)cl == 0 && p->sclass && p->sclass != TYPEDEF)
223: *(Symbol *)cl = p;
224: if ((p->sclass == TYPEDEF || p->sclass == 0) && IR->stabtype)
225: (*IR->stabtype)(p);
226: }
227:
228: struct callsite {
229: char *file, *name;
230: union coordinate {
231: unsigned int coord;
232: struct { unsigned int y:16,x:10,index:6; } le;
233: struct { unsigned int index:6,x:10,y:16; } be;
234: } u;
235: };
236: struct func {
237: struct func *link;
238: struct caller *callers;
239: char *name;
240: union coordinate src;
241: };
242: struct map { /* source code map; 200 coordinates/map */
243: int size;
244: union coordinate u[200];
245: };
246: int npoints; /* # of execution points if -b specified */
247: int ncalled = -1; /* #times prof.out says current function was called */
248: static Symbol YYlink; /* symbol for file's struct _bbdata */
249: static Symbol YYcounts; /* symbol for _YYcounts if -b specified */
250: static List maplist; /* list of struct map *'s */
251: static List filelist; /* list of file names */
252: static Symbol funclist; /* list of struct func *'s */
253: static Symbol afunc; /* current function's struct func */
254:
255: dclproto(static void bbcall,(Symbol, Coordinate *, Tree *));
256: dclproto(static void bbentry,(Symbol, Symbol));
257: dclproto(static void bbexit,(Symbol, Symbol, Tree));
258: dclproto(static int bbfile,(char *));
259: dclproto(static void bbfunc,(Symbol, Symbol));
260: dclproto(static void bbincr,(Symbol, Coordinate *, Tree *));
261: dclproto(static void bbvars,(Symbol));
262:
263: /* bbcall - build tree to set _callsite at call site *cp, emit call site data */
264: static void bbcall(yycounts, cp, e) Symbol yycounts; Coordinate *cp; Tree *e; {
265: static Symbol caller;
266: Value v;
267: union coordinate u;
268: Symbol p = genident(STATIC, array(voidptype, 0, 0), GLOBAL);
269:
270: defglobal(p, LIT);
271: defpointer(cp->file ? mkstr(cp->file)->u.c.loc : (Symbol)0);
272: defpointer(mkstr(cfunc->name)->u.c.loc);
273: if (IR->little_endian) {
274: u.le.x = cp->x;
275: u.le.y = cp->y;
276: } else {
277: u.be.x = cp->x;
278: u.be.y = cp->y;
279: }
280: (*IR->defconst)(U, (v.u = u.coord, v));
281: if (caller == 0)
282: caller = mksymbol(EXTERN, "_caller", ptr(voidptype));
283: *e = right(asgn(caller, idnode(p)), *e);
284: }
285:
286: /* bbentry - return tree for `_prologue(&afunc, &YYlink)' */
287: static void bbentry(yylink, f) Symbol yylink, f; {
288: static Symbol p;
289:
290: afunc = genident(STATIC, array(voidptype, 4, 0), GLOBAL);
291: if (p == 0)
292: p = mksymbol(EXTERN, "_prologue", ftype(inttype, voidptype));
293: walk(callnode(pointer(idnode(p)), freturn(p->type),
294: tree(ARG+P, ptr(unsignedtype), idnode(yylink),
295: tree(ARG+P, ptr(unsignedtype), idnode(afunc), 0))), 0, 0);
296: }
297:
298: /* bbexit - return tree for `_epilogue(&afunc)' */
299: static void bbexit(yylink, f, e) Symbol yylink, f; Tree e; {
300: static Symbol p;
301:
302: if (p == 0)
303: p = mksymbol(EXTERN, "_epilogue", ftype(inttype, voidptype));
304: walk(callnode(pointer(idnode(p)), freturn(p->type),
305: tree(ARG+P, ptr(unsignedtype), idnode(afunc), 0)), 0, 0);
306: }
307:
308: /* bbfile - add file to list of file names, return its index */
309: static int bbfile(file) char *file; {
310: if (file) {
311: List lp;
312: int i = 1;
313: if (lp = filelist)
314: do {
315: lp = lp->link;
316: if (((Symbol)lp->x)->u.c.v.p == file)
317: return i;
318: i++;
319: } while (lp != filelist);
320: filelist = append(mkstr(file), filelist);
321: return i;
322: }
323: return 0;
324: }
325:
326: /* bbfunc - emit function name and src coordinates */
327: static void bbfunc(yylink, f) Symbol yylink, f; {
328: Value v;
329: union coordinate u;
330:
331: defglobal(afunc, DATA);
332: defpointer(funclist);
333: defpointer(0);
334: defpointer(mkstr(f->name)->u.c.loc);
335: if (IR->little_endian) {
336: u.le.x = f->u.f.pt[2].x;
337: u.le.y = f->u.f.pt[2].y;
338: u.le.index = bbfile(f->u.f.pt[2].file);
339: } else {
340: u.be.x = f->u.f.pt[2].x;
341: u.be.y = f->u.f.pt[2].y;
342: u.be.index = bbfile(f->u.f.pt[2].file);
343: }
344: (*IR->defconst)(U, (v.u = u.coord, v));
345: funclist = afunc;
346: }
347:
348: /* bbincr - build tree to increment execution point at *cp */
349: static void bbincr(yycounts, cp, e) Symbol yycounts; Coordinate *cp; Tree *e; {
350: struct map *mp = (struct map *)maplist->x;
351:
352: /* append *cp to source map */
353: if (mp->size >= sizeof mp->u/sizeof mp->u[0]) {
354: mp = (struct map *)alloc(sizeof *mp);
355: mp->size = 0;
356: maplist = append((Generic *)mp, maplist);
357: }
358: if (IR->little_endian) {
359: mp->u[mp->size].le.x = cp->x;
360: mp->u[mp->size].le.y = cp->y;
361: mp->u[mp->size++].le.index = bbfile(cp->file);
362: } else {
363: mp->u[mp->size].be.x = cp->x;
364: mp->u[mp->size].be.y = cp->y;
365: mp->u[mp->size++].be.index = bbfile(cp->file);
366: }
367: *e = right(incr('+', rvalue((*opnode['+'])(ADD, pointer(idnode(yycounts)),
368: constnode(npoints++, inttype))), constnode(1, inttype)), *e);
369: }
370:
371: /* bbinit - initialize basic block counting options */
372: void bbinit(opt) char *opt; {
373: if (strncmp(opt, "-a", 2) == 0) {
374: if (ncalled == -1 && process(opt[2] ? &opt[2] : "prof.out") > 0)
375: ncalled = 0;
376: } else if ((strcmp(opt, "-b") == 0 || strcmp(opt, "-C") == 0) && YYlink == 0) {
377: YYlink = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL);
378: attach((Apply)bbentry, (Generic)YYlink, &events.entry);
379: attach((Apply)bbexit, (Generic)YYlink, &events.returns);
380: attach((Apply)bbfunc, (Generic)YYlink, &events.exit);
381: attach((Apply)bbvars, (Generic)YYlink, &events.end);
382: if (strcmp(opt, "-b") == 0) {
383: YYcounts = genident(STATIC, array(unsignedtype, 0, 0), GLOBAL);
384: maplist = append((Generic)alloc(sizeof(struct map)), maplist);
385: ((struct map *)maplist->x)->size = 0;
386: attach((Apply)bbcall, (Generic)YYcounts, &events.calls);
387: attach((Apply)bbincr, (Generic)YYcounts, &events.points);
388: }
389: }
390: }
391:
392: /* bbvars - emit definition for basic block counting data */
393: static void bbvars(yylink) Symbol yylink; {
394: int i, j, n = npoints;
395: Value v;
396: struct map **mp;
397: Symbol coords, files, *p;
398:
399: if (!YYcounts && !yylink)
400: return;
401: if (YYcounts) {
402: if (n <= 0)
403: n = 1;
404: defglobal(YYcounts, BSS);
405: (*IR->space)(n*YYcounts->type->type->size);
406: }
407: files = genident(STATIC, array(ptr(chartype), 1, 0), GLOBAL);
408: defglobal(files, LIT);
409: for (p = (Symbol *)ltoa(filelist, 0); *p; p++)
410: defpointer((*p)->u.c.loc);
411: defpointer(0);
412: coords = genident(STATIC, array(unsignedtype, n, 0), GLOBAL);
413: defglobal(coords, LIT);
414: for (i = n, mp = (struct map **)ltoa(maplist, 0); *mp; i -= (*mp)->size, mp++)
415: for (j = 0; j < (*mp)->size; j++)
416: (*IR->defconst)(U, (v.u = (*mp)->u[j].coord, v));
417: if (i > 0)
418: (*IR->space)(i*coords->type->type->size);
419: defpointer(0);
420: defglobal(yylink, DATA);
421: defpointer(0);
422: (*IR->defconst)(U, (v.u = n, v));
423: defpointer(YYcounts);
424: defpointer(coords);
425: defpointer(files);
426: defpointer(funclist);
427: }
428:
429: static char *fmt, *fp, *fmtend; /* format string, current & limit pointer */
430: static Tree args; /* printf arguments */
431: static Symbol frameno; /* local holding frame number */
432:
433: dclproto(static void appendstr,(char *));
434: dclproto(static void tracecall,(Symbol, Symbol));
435: dclproto(static void tracefinis,(Symbol));
436: dclproto(static void tracereturn,(Symbol, Symbol, Tree));
437: dclproto(static void tracevalue,(Tree, int));
438:
439: /* appendstr - append str to the evolving format string, expanding it if necessary */
440: static void appendstr(str) char *str; {
441: do
442: if (fp == fmtend)
443: if (fp) {
444: char *s = (char *)talloc(2*(fmtend - fmt));
445: strncpy(s, fmt, fmtend - fmt);
446: fp = s + (fmtend - fmt);
447: fmtend = s + 2*(fmtend - fmt);
448: fmt = s;
449: } else {
450: fp = fmt = (char *)talloc(80);
451: fmtend = fmt + 80;
452: }
453: while (*fp++ = *str++);
454: fp--;
455: }
456:
457: /* tracecall - generate code to trace entry to f */
458: static void tracecall(printer, f) Symbol printer, f; {
459: int i;
460: Symbol counter = genident(STATIC, inttype, GLOBAL);
461:
462: defglobal(counter, BSS);
463: (*IR->space)(counter->type->size);
464: frameno = genident(AUTO, inttype, level);
465: addlocal(frameno);
466: appendstr(f->name); appendstr("#");
467: tracevalue(asgn(frameno, incr(INCR, idnode(counter), constnode(1, inttype))), 0);
468: appendstr("(");
469: for (i = 0; f->u.f.callee[i]; i++) {
470: if (i)
471: appendstr(",");
472: appendstr(f->u.f.callee[i]->name); appendstr("=");
473: tracevalue(idnode(f->u.f.callee[i]), 0);
474: }
475: if (variadic(f->type))
476: appendstr(",...");
477: appendstr(") called\n");
478: tracefinis(printer);
479: }
480:
481: /* tracefinis - complete & generate the trace call to print */
482: static void tracefinis(printer) Symbol printer; {
483: Tree *ap;
484: Symbol p;
485:
486: *fp = 0;
487: p = mkstr(string(fmt));
488: for (ap = &args; *ap; ap = &(*ap)->kids[1])
489: ;
490: *ap = tree(ARG+P, ptr(chartype), pointer(idnode(p->u.c.loc)), 0);
491: walk(callnode(pointer(idnode(printer)), freturn(printer->type), args), 0, 0);
492: args = 0;
493: fp = fmtend = 0;
494: }
495:
496: /* traceinit - initialize for tracing */
497: void traceinit(print) char *print; {
498: static Symbol printer;
499:
500: if (!printer) {
501: printer = mksymbol(STATIC, print && *print ? print : "printf",
502: ftype(voidtype, ptr(chartype)));
503: printer->sclass = EXTERN;
504: attach((Apply)tracecall, (Generic)printer, &events.entry);
505: attach((Apply)tracereturn, (Generic)printer, &events.returns);
506: }
507: }
508:
509: /* tracereturn - generate code to trace return e */
510: static void tracereturn(printer, f, e) Symbol printer, f; Tree e; {
511: appendstr(f->name); appendstr("#");
512: tracevalue(idnode(frameno), 0);
513: appendstr(" returned");
514: if (freturn(f->type) != voidtype && e) {
515: appendstr(" ");
516: tracevalue(e, 0);
517: }
518: appendstr("\n");
519: tracefinis(printer);
520: }
521:
522: /* tracevalue - append format and argument to print the value of e */
523: static void tracevalue(e, lev) Tree e; {
524: Type ty = unqual(e->type);
525:
526: switch (ty->op) {
527: case CHAR:
528: appendstr("'\\x%2x'");
529: break;
530: case SHORT:
531: if (ty == unsignedshort)
532: appendstr("0x%x");
533: else /* fall thru */
534: case INT:
535: appendstr("%d");
536: break;
537: case UNSIGNED:
538: appendstr("0x%x");
539: break;
540: case FLOAT: case DOUBLE:
541: appendstr("%g");
542: break;
543: case POINTER:
544: if (unqual(ty->type) == chartype) {
545: static Symbol null;
546: if (null == 0)
547: null = mkstr("(null)");
548: tracevalue(constnode(0, unsignedtype), lev + 1);
549: appendstr(" \"%s\"");
550: e = condnode(e, e, pointer(idnode(null->u.c.loc)));
551: } else {
552: appendstr("("); appendstr(typestring(ty, "")); appendstr(")0x%x");
553: }
554: break;
555: case STRUCT: {
556: Field q;
557: appendstr("("); appendstr(typestring(ty, "")); appendstr("){");
558: for (q = ty->u.sym->u.s.flist; q; q = q->link) {
559: appendstr(q->name); appendstr("=");
560: tracevalue(field(addrof(e), q->name), lev + 1);
561: if (q->link)
562: appendstr(",");
563: }
564: appendstr("}");
565: return;
566: }
567: case UNION:
568: appendstr("("); appendstr(typestring(ty, "")); appendstr("){...}");
569: return;
570: case ARRAY:
571: if (lev && ty->type->size > 0) {
572: int i;
573: e = pointer(e);
574: appendstr("{");
575: for (i = 0; i < ty->size/ty->type->size; i++) {
576: Tree p = (*opnode['+'])(ADD, e, constnode(i, inttype));
577: if (isptr(p->type) && isarray(p->type->type))
578: p = retype(p, p->type->type);
579: else
580: p = rvalue(p);
581: if (i)
582: appendstr(",");
583: tracevalue(p, lev + 1);
584: }
585: appendstr("}");
586: } else
587: appendstr(typestring(ty, ""));
588: return;
589: default:
590: assert(0);
591: }
592: if (ty == floattype)
593: e = cast(e, doubletype);
594: else if ((isint(ty) || isenum(ty)) && ty->size != inttype->size)
595: e = cast(e, promote(ty));
596: args = tree(ARG + widen(e->type), e->type, e, args);
597: }
598: Events events;
599:
600: struct entry {
601: Apply func;
602: Generic cl;
603: };
604:
605: void attach(func, cl, list) Apply func; Generic cl; List *list; {
606: struct entry *p = (struct entry *)alloc(sizeof *p);
607:
608: p->func = func;
609: p->cl = cl;
610: *list = append((Generic)p, *list);
611: }
612: void apply(list, arg1, arg2) List list; Generic arg1, arg2; {
613: if (list) {
614: List lp = list;
615: do {
616: struct entry *p = (struct entry *)lp->x;
617: (*p->func)(p->cl, arg1, arg2);
618: lp = lp->link;
619: } while (lp != list);
620: }
621: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.