00001 #include <time.h>
00002 #include <ctype.h>
00003 #include "c.h"
00004
00005 #define I(f) s_##f
00006
00007 static Node *tail;
00008 static int off, maxoff, uid = 0, verbose = 0, html = 0;
00009
00010 static const char *yyBEGIN(const char *tag) {
00011 if (html)
00012 print("<%s>", tag);
00013 return tag;
00014 }
00015
00016 static void yyEND(const char *tag) {
00017 if (html)
00018 print("</%s>", tag);
00019 if (isupper(*tag))
00020 print("\n");
00021 }
00022
00023 #define BEGIN(tag) do { const char *yytag=yyBEGIN(#tag);
00024 #define END yyEND(yytag); } while (0)
00025 #define ITEM BEGIN(li)
00026 #define START BEGIN(LI)
00027 #define ANCHOR(attr,code) do { const char *yytag="a"; if (html) { printf("<a " #attr "=\""); code; print("\">"); }
00028 #define NEWLINE print(html ? "<br>\n" : "\n")
00029
00030 static void emitCoord(Coordinate src) {
00031 if (src.file && *src.file) {
00032 ANCHOR(href,print("%s", src.file)); print("%s", src.file); END;
00033 print(":");
00034 }
00035 print("%d.%d", src.y, src.x);
00036 }
00037
00038 static void emitString(int len, const char *s) {
00039 for ( ; len-- > 0; s++)
00040 if (*s == '&' && html)
00041 print("&");
00042 else if (*s == '<' && html)
00043 print("<");
00044 else if (*s == '>' && html)
00045 print("<");
00046 else if (*s == '"' || *s == '\\')
00047 print("\\%c", *s);
00048 else if (*s >= ' ' && *s < 0177)
00049 print("%c", *s);
00050 else
00051 print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7);
00052 }
00053
00054 static void emitSymRef(Symbol p) {
00055 (*IR->defsymbol)(p);
00056 ANCHOR(href,print("#%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
00057 }
00058
00059 static void emitSymbol(Symbol p) {
00060 (*IR->defsymbol)(p);
00061 ANCHOR(name,print("%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
00062 BEGIN(ul);
00063 #define xx(field,code) ITEM; if (!html) print(" "); print(#field "="); code; END
00064 if (verbose && (src.y || src.x))
00065 xx(src,emitCoord(p->src));
00066 xx(type,print("%t", p->type));
00067 xx(sclass,print("%k", p->sclass));
00068 switch (p->scope) {
00069 case CONSTANTS: xx(scope,print("CONSTANTS")); break;
00070 case LABELS: xx(scope,print("LABELS")); break;
00071 case GLOBAL: xx(scope,print("GLOBAL")); break;
00072 case PARAM: xx(scope,print("PARAM")); break;
00073 case LOCAL: xx(scope,print("LOCAL")); break;
00074 default:
00075 if (p->scope > LOCAL)
00076 xx(scope,print("LOCAL+%d", p->scope-LOCAL));
00077 else
00078 xx(scope,print("%d", p->scope));
00079 }
00080 if (p->scope >= PARAM && p->sclass != STATIC)
00081 xx(offset,print("%d", p->x.offset));
00082 xx(ref,print("%f", p->ref));
00083 if (p->temporary && p->u.t.cse)
00084 xx(u.t.cse,print("%p", p->u.t.cse));
00085 END;
00086 #undef xx
00087 }
00088
00089
00090 static void I(address)(Symbol q, Symbol p, long n) {
00091 q->name = stringf("%s%s%D", p->name, n > 0 ? "+" : "", n);
00092 (*IR->defsymbol)(q);
00093 START; print("address "); emitSymbol(q); END;
00094 }
00095
00096
00097 static void I(blockbeg)(Env *e) {
00098 e->offset = off;
00099 START; print("blockbeg off=%d", off); END;
00100 }
00101
00102
00103 static void I(blockend)(Env *e) {
00104 if (off > maxoff)
00105 maxoff = off;
00106 START; print("blockend off=%d", off); END;
00107 off = e->offset;
00108 }
00109
00110
00111 static void I(defaddress)(Symbol p){
00112 START; print("defaddress "); emitSymRef(p); END;
00113 }
00114
00115
00116 static void I(defconst)(int suffix, int size, Value v) {
00117 START;
00118 print("defconst ");
00119 switch (suffix) {
00120 case I:
00121 print("int.%d ", size);
00122 BEGIN(code);
00123 if (size > sizeof (int))
00124 print("%D", v.i);
00125 else
00126 print("%d", (int)v.i);
00127 END;
00128 break;
00129 case U:
00130 print("unsigned.%d ", size);
00131 BEGIN(code);
00132 if (size > sizeof (unsigned))
00133 print("%U", v.u);
00134 else
00135 print("%u", (unsigned)v.u);
00136 END;
00137 break;
00138 case P: print("void*.%d ", size); BEGIN(code); print("%p", v.p); END; break;
00139 case F: print("float.%d ", size); BEGIN(code); print("%g", (double)v.d); END; break;
00140 default: assert(0);
00141 }
00142 END;
00143 }
00144
00145
00146 static void I(defstring)(int len, char *s) {
00147 START; print("defstring ");
00148 BEGIN(code); print("\""); emitString(len, s); print("\""); END;
00149 END;
00150 }
00151
00152
00153 static void I(defsymbol)(Symbol p) {
00154 if (p->x.name == NULL)
00155 p->x.name = stringd(++uid);
00156 }
00157
00158
00159 static void I(emit)(Node p){
00160 ITEM;
00161 if (!html)
00162 print(" ");
00163 for (; p; p = p->x.next) {
00164 if (p->op == LABEL+V) {
00165 assert(p->syms[0]);
00166 ANCHOR(name,print("%s", p->syms[0]->x.name));
00167 BEGIN(code); print("%s", p->syms[0]->name); END;
00168 END;
00169 print(":");
00170 } else {
00171 int i;
00172 if (p->x.listed) {
00173 BEGIN(strong); print("%d", p->x.inst); END; print("'");
00174 print(" %s", opname(p->op));
00175 } else
00176 print("%d. %s", p->x.inst, opname(p->op));
00177 if (p->count > 1)
00178 print(" count=%d", p->count);
00179 for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++)
00180 print(" #%d", p->kids[i]->x.inst);
00181 if (generic(p->op) == CALL && p->syms[0] && p->syms[0]->type)
00182 print(" {%t}", p->syms[0]->type);
00183 else
00184 for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++) {
00185 print(" ");
00186 if (p->syms[i]->scope == CONSTANTS)
00187 print(p->syms[i]->name);
00188 else
00189 emitSymRef(p->syms[i]);
00190 }
00191 }
00192 NEWLINE;
00193 }
00194 END;
00195 }
00196
00197
00198 static void I(export)(Symbol p) {
00199 START; print("export "); emitSymRef(p); END;
00200 }
00201
00202
00203 static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
00204 int i;
00205
00206 (*IR->defsymbol)(f);
00207 off = 0;
00208 for (i = 0; caller[i] && callee[i]; i++) {
00209 off = roundup(off, caller[i]->type->align);
00210 caller[i]->x.offset = callee[i]->x.offset = off;
00211 off += caller[i]->type->size;
00212 }
00213 if (!html) {
00214 print("function ");
00215 emitSymbol(f);
00216 print(" ncalls=%d\n", ncalls);
00217 for (i = 0; caller[i]; i++)
00218 START; print("caller "); emitSymbol(caller[i]); END;
00219 for (i = 0; callee[i]; i++)
00220 START; print("callee "); emitSymbol(callee[i]); END;
00221 } else {
00222 START;
00223 print("function");
00224 BEGIN(UL);
00225 #define xx(field,code) ITEM; print(#field "="); code; END
00226 xx(f,emitSymbol(f));
00227 xx(ncalls,print("%d", ncalls));
00228 if (caller[0]) {
00229 ITEM; print("caller"); BEGIN(OL);
00230 for (i = 0; caller[i]; i++)
00231 ITEM; emitSymbol(caller[i]); END;
00232 END; END;
00233 ITEM; print("callee"); BEGIN(OL);
00234 for (i = 0; callee[i]; i++)
00235 ITEM; emitSymbol(callee[i]); END;
00236 END; END;
00237 } else {
00238 xx(caller,BEGIN(em); print("empty"); END);
00239 xx(callee,BEGIN(em); print("empty"); END);
00240 }
00241 END;
00242 END;
00243 }
00244 maxoff = off = 0;
00245 gencode(caller, callee);
00246 if (html)
00247 START; print("emitcode"); BEGIN(ul); emitcode(); END; END;
00248 else
00249 emitcode();
00250 START; print("maxoff=%d", maxoff); END;
00251 #undef xx
00252 }
00253
00254
00255 static int visit(Node p, int n) {
00256 if (p && p->x.inst == 0) {
00257 p->x.inst = ++n;
00258 n = visit(p->kids[0], n);
00259 n = visit(p->kids[1], n);
00260 *tail = p;
00261 tail = &p->x.next;
00262 }
00263 return n;
00264 }
00265
00266
00267 static Node I(gen)(Node p) {
00268 int n;
00269 Node nodelist;
00270
00271 tail = &nodelist;
00272 for (n = 0; p; p = p->link) {
00273 switch (generic(p->op)) {
00274 case CALL:
00275 assert(IR->wants_dag || p->count == 0);
00276 break;
00277 case ARG:
00278 case ASGN: case JUMP: case LABEL: case RET:
00279 case EQ: case GE: case GT: case LE: case LT: case NE:
00280 assert(p->count == 0);
00281 break;
00282 case INDIR:
00283 assert(IR->wants_dag && p->count > 0);
00284 break;
00285 default:
00286 assert(0);
00287 }
00288 check(p);
00289 p->x.listed = 1;
00290 n = visit(p, n);
00291 }
00292 *tail = 0;
00293 return nodelist;
00294 }
00295
00296
00297 static void I(global)(Symbol p) {
00298 START; print("global "); emitSymbol(p); END;
00299 }
00300
00301
00302 static void I(import)(Symbol p) {
00303 START; print("import "); emitSymRef(p); END;
00304 }
00305
00306
00307 static void I(local)(Symbol p) {
00308 if (p->temporary)
00309 p->name = stringf("t%s", p->name);
00310 (*IR->defsymbol)(p);
00311 off = roundup(off, p->type->align);
00312 p->x.offset = off;
00313 off += p->type->size;
00314 START; print(p->temporary ? "temporary " : "local "); emitSymbol(p); END;
00315 }
00316
00317
00318 static void I(progbeg)(int argc, char *argv[]) {
00319 int i;
00320
00321 for (i = 1; i < argc; i++)
00322 if (strcmp(argv[i], "-v") == 0)
00323 verbose++;
00324 else if (strcmp(argv[i], "-html") == 0)
00325 html++;
00326 if (html) {
00327 print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n");
00328 print("<html>");
00329 BEGIN(head);
00330 if (firstfile && *firstfile)
00331 BEGIN(title); emitString(strlen(firstfile), firstfile); END;
00332 print("<link rev=made href=\"mailto:drh@microsoft.com\">\n");
00333 END;
00334 print("<body>\n");
00335 if (firstfile && *firstfile)
00336 BEGIN(h1); emitString(strlen(firstfile), firstfile); END;
00337 BEGIN(P); BEGIN(em);
00338 print("Links lead from uses of identifiers and labels to their definitions.");
00339 END; END;
00340 print("<ul>\n");
00341 START;
00342 print("progbeg");
00343 BEGIN(ol);
00344 for (i = 1; i < argc; i++) {
00345 ITEM;
00346 BEGIN(code); print("\""); emitString(strlen(argv[i]), argv[i]); print("\""); END;
00347 END;
00348 }
00349 END;
00350 END;
00351 }
00352 }
00353
00354
00355 static void I(progend)(void) {
00356 START; print("progend"); END;
00357 if (html) {
00358 time_t t;
00359 print("</ul>\n");
00360 time(&t);
00361 print("<hr><address>%s</address>\n", ctime(&t));
00362 print("</body></html>\n");
00363 }
00364 }
00365
00366
00367 static void I(segment)(int s) {
00368 START; print("segment %s", &"text\0bss\0.data\0lit\0.sym\0."[5*s-5]); END;
00369 }
00370
00371
00372 static void I(space)(int n) {
00373 START; print("space %d", n); END;
00374 }
00375
00376 static void I(stabblock)(int brace, int lev, Symbol *p) {}
00377
00378
00379 static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
00380 int i;
00381
00382 if (p)
00383 emitSymRef(p);
00384 print("\n");
00385 if (cpp && sp)
00386 for (i = 0; cpp[i] && sp[i]; i++) {
00387 print("%w.%d: ", cpp[i], cpp[i]->x);
00388 emitSymRef(sp[i]);
00389 print("\n");
00390 }
00391 }
00392
00393 static void I(stabfend)(Symbol p, int lineno) {}
00394 static void I(stabinit)(char *file, int argc, char *argv[]) {}
00395
00396
00397 static void I(stabline)(Coordinate *cp) {
00398 if (cp->file)
00399 print("%s:", cp->file);
00400 print("%d.%d:\n", cp->y, cp->x);
00401 }
00402
00403 static void I(stabsym)(Symbol p) {}
00404 static void I(stabtype)(Symbol p) {}
00405
00406 Interface symbolicIR = {
00407 1, 1, 0,
00408 2, 2, 0,
00409 4, 4, 0,
00410 4, 4, 0,
00411 4, 4, 0,
00412 4, 4, 1,
00413 8, 8, 1,
00414 8, 8, 1,
00415 4, 4, 0,
00416 0, 4, 0,
00417 0,
00418 0,
00419 0,
00420 1,
00421 1,
00422 1,
00423 0,
00424 I(address),
00425 I(blockbeg),
00426 I(blockend),
00427 I(defaddress),
00428 I(defconst),
00429 I(defstring),
00430 I(defsymbol),
00431 I(emit),
00432 I(export),
00433 I(function),
00434 I(gen),
00435 I(global),
00436 I(import),
00437 I(local),
00438 I(progbeg),
00439 I(progend),
00440 I(segment),
00441 I(space),
00442 I(stabblock),
00443 I(stabend),
00444 I(stabfend),
00445 I(stabinit),
00446 I(stabline),
00447 I(stabsym),
00448 I(stabtype)
00449 };
00450
00451 Interface symbolic64IR = {
00452 1, 1, 0,
00453 2, 2, 0,
00454 4, 4, 0,
00455 8, 8, 0,
00456 8, 8, 0,
00457 4, 4, 1,
00458 8, 8, 1,
00459 8, 8, 1,
00460 8, 8, 0,
00461 0, 1, 0,
00462 1,
00463 0,
00464 0,
00465 1,
00466 1,
00467 1,
00468 0,
00469 I(address),
00470 I(blockbeg),
00471 I(blockend),
00472 I(defaddress),
00473 I(defconst),
00474 I(defstring),
00475 I(defsymbol),
00476 I(emit),
00477 I(export),
00478 I(function),
00479 I(gen),
00480 I(global),
00481 I(import),
00482 I(local),
00483 I(progbeg),
00484 I(progend),
00485 I(segment),
00486 I(space),
00487 I(stabblock),
00488 I(stabend),
00489 I(stabfend),
00490 I(stabinit),
00491 I(stabline),
00492 I(stabsym),
00493 I(stabtype)
00494 };