* tiny
[mascara-docs.git] / compilers / q3 / lcc / src / symbolic.c
blobaffa67a08e9d4c95a70c01ec7da0bd34c2750eba
1 #include <time.h>
2 #include <ctype.h>
3 #include "c.h"
5 #define I(f) s_##f
7 static Node *tail;
8 static int off, maxoff, uid = 0, verbose = 0, html = 0;
10 static const char *yyBEGIN(const char *tag) {
11 if (html)
12 print("<%s>", tag);
13 return tag;
16 static void yyEND(const char *tag) {
17 if (html)
18 print("</%s>", tag);
19 if (isupper(*tag))
20 print("\n");
23 #define BEGIN(tag) do { const char *yytag=yyBEGIN(#tag);
24 #define END yyEND(yytag); } while (0)
25 #define ITEM BEGIN(li)
26 #define START BEGIN(LI)
27 #define ANCHOR(attr,code) do { const char *yytag="a"; if (html) { printf("<a " #attr "=\""); code; print("\">"); }
28 #define NEWLINE print(html ? "<br>\n" : "\n")
30 static void emitCoord(Coordinate src) {
31 if (src.file && *src.file) {
32 ANCHOR(href,print("%s", src.file)); print("%s", src.file); END;
33 print(":");
35 print("%d.%d", src.y, src.x);
38 static void emitString(int len, const char *s) {
39 for ( ; len-- > 0; s++)
40 if (*s == '&' && html)
41 print("&amp;");
42 else if (*s == '<' && html)
43 print("&lt;");
44 else if (*s == '>' && html)
45 print("&lt;");
46 else if (*s == '"' || *s == '\\')
47 print("\\%c", *s);
48 else if (*s >= ' ' && *s < 0177)
49 print("%c", *s);
50 else
51 print("\\%d%d%d", (*s>>6)&3, (*s>>3)&7, *s&7);
54 static void emitSymRef(Symbol p) {
55 (*IR->defsymbol)(p);
56 ANCHOR(href,print("#%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
59 static void emitSymbol(Symbol p) {
60 (*IR->defsymbol)(p);
61 ANCHOR(name,print("%s", p->x.name)); BEGIN(code); print("%s", p->name); END; END;
62 BEGIN(ul);
63 #define xx(field,code) ITEM; if (!html) print(" "); print(#field "="); code; END
64 if (verbose && (src.y || src.x))
65 xx(src,emitCoord(p->src));
66 xx(type,print("%t", p->type));
67 xx(sclass,print("%k", p->sclass));
68 switch (p->scope) {
69 case CONSTANTS: xx(scope,print("CONSTANTS")); break;
70 case LABELS: xx(scope,print("LABELS")); break;
71 case GLOBAL: xx(scope,print("GLOBAL")); break;
72 case PARAM: xx(scope,print("PARAM")); break;
73 case LOCAL: xx(scope,print("LOCAL")); break;
74 default:
75 if (p->scope > LOCAL)
76 xx(scope,print("LOCAL+%d", p->scope-LOCAL));
77 else
78 xx(scope,print("%d", p->scope));
80 if (p->scope >= PARAM && p->sclass != STATIC)
81 xx(offset,print("%d", p->x.offset));
82 xx(ref,print("%f", p->ref));
83 if (p->temporary && p->u.t.cse)
84 xx(u.t.cse,print("%p", p->u.t.cse));
85 END;
86 #undef xx
89 /* address - initialize q for addressing expression p+n */
90 static void I(address)(Symbol q, Symbol p, long n) {
91 q->name = stringf("%s%s%D", p->name, n > 0 ? "+" : "", n);
92 (*IR->defsymbol)(q);
93 START; print("address "); emitSymbol(q); END;
96 /* blockbeg - start a block */
97 static void I(blockbeg)(Env *e) {
98 e->offset = off;
99 START; print("blockbeg off=%d", off); END;
102 /* blockend - start a block */
103 static void I(blockend)(Env *e) {
104 if (off > maxoff)
105 maxoff = off;
106 START; print("blockend off=%d", off); END;
107 off = e->offset;
110 /* defaddress - initialize an address */
111 static void I(defaddress)(Symbol p){
112 START; print("defaddress "); emitSymRef(p); END;
115 /* defconst - define a constant */
116 static void I(defconst)(int suffix, int size, Value v) {
117 START;
118 print("defconst ");
119 switch (suffix) {
120 case I:
121 print("int.%d ", size);
122 BEGIN(code);
123 if (size > sizeof (int))
124 print("%D", v.i);
125 else
126 print("%d", (int)v.i);
127 END;
128 break;
129 case U:
130 print("unsigned.%d ", size);
131 BEGIN(code);
132 if (size > sizeof (unsigned))
133 print("%U", v.u);
134 else
135 print("%u", (unsigned)v.u);
136 END;
137 break;
138 case P: print("void*.%d ", size); BEGIN(code); print("%p", v.p); END; break;
139 case F: print("float.%d ", size); BEGIN(code); print("%g", (double)v.d); END; break;
140 default: assert(0);
142 END;
145 /* defstring - emit a string constant */
146 static void I(defstring)(int len, char *s) {
147 START; print("defstring ");
148 BEGIN(code); print("\""); emitString(len, s); print("\""); END;
149 END;
152 /* defsymbol - define a symbol: initialize p->x */
153 static void I(defsymbol)(Symbol p) {
154 if (p->x.name == NULL)
155 p->x.name = stringd(++uid);
158 /* emit - emit the dags on list p */
159 static void I(emit)(Node p){
160 ITEM;
161 if (!html)
162 print(" ");
163 for (; p; p = p->x.next) {
164 if (p->op == LABEL+V) {
165 assert(p->syms[0]);
166 ANCHOR(name,print("%s", p->syms[0]->x.name));
167 BEGIN(code); print("%s", p->syms[0]->name); END;
168 END;
169 print(":");
170 } else {
171 int i;
172 if (p->x.listed) {
173 BEGIN(strong); print("%d", p->x.inst); END; print("'");
174 print(" %s", opname(p->op));
175 } else
176 print("%d. %s", p->x.inst, opname(p->op));
177 if (p->count > 1)
178 print(" count=%d", p->count);
179 for (i = 0; i < NELEMS(p->kids) && p->kids[i]; i++)
180 print(" #%d", p->kids[i]->x.inst);
181 if (generic(p->op) == CALL && p->syms[0] && p->syms[0]->type)
182 print(" {%t}", p->syms[0]->type);
183 else
184 for (i = 0; i < NELEMS(p->syms) && p->syms[i]; i++) {
185 print(" ");
186 if (p->syms[i]->scope == CONSTANTS)
187 print(p->syms[i]->name);
188 else
189 emitSymRef(p->syms[i]);
192 NEWLINE;
194 END;
197 /* export - announce p as exported */
198 static void I(export)(Symbol p) {
199 START; print("export "); emitSymRef(p); END;
202 /* function - generate code for a function */
203 static void I(function)(Symbol f, Symbol caller[], Symbol callee[], int ncalls) {
204 int i;
206 (*IR->defsymbol)(f);
207 off = 0;
208 for (i = 0; caller[i] && callee[i]; i++) {
209 off = roundup(off, caller[i]->type->align);
210 caller[i]->x.offset = callee[i]->x.offset = off;
211 off += caller[i]->type->size;
213 if (!html) {
214 print("function ");
215 emitSymbol(f);
216 print(" ncalls=%d\n", ncalls);
217 for (i = 0; caller[i]; i++)
218 START; print("caller "); emitSymbol(caller[i]); END;
219 for (i = 0; callee[i]; i++)
220 START; print("callee "); emitSymbol(callee[i]); END;
221 } else {
222 START;
223 print("function");
224 BEGIN(UL);
225 #define xx(field,code) ITEM; print(#field "="); code; END
226 xx(f,emitSymbol(f));
227 xx(ncalls,print("%d", ncalls));
228 if (caller[0]) {
229 ITEM; print("caller"); BEGIN(OL);
230 for (i = 0; caller[i]; i++)
231 ITEM; emitSymbol(caller[i]); END;
232 END; END;
233 ITEM; print("callee"); BEGIN(OL);
234 for (i = 0; callee[i]; i++)
235 ITEM; emitSymbol(callee[i]); END;
236 END; END;
237 } else {
238 xx(caller,BEGIN(em); print("empty"); END);
239 xx(callee,BEGIN(em); print("empty"); END);
241 END;
242 END;
244 maxoff = off = 0;
245 gencode(caller, callee);
246 if (html)
247 START; print("emitcode"); BEGIN(ul); emitcode(); END; END;
248 else
249 emitcode();
250 START; print("maxoff=%d", maxoff); END;
251 #undef xx
254 /* visit - generate code for *p */
255 static int visit(Node p, int n) {
256 if (p && p->x.inst == 0) {
257 p->x.inst = ++n;
258 n = visit(p->kids[0], n);
259 n = visit(p->kids[1], n);
260 *tail = p;
261 tail = &p->x.next;
263 return n;
266 /* gen0 - generate code for the dags on list p */
267 static Node I(gen)(Node p) {
268 int n;
269 Node nodelist;
271 tail = &nodelist;
272 for (n = 0; p; p = p->link) {
273 switch (generic(p->op)) { /* check for valid forest */
274 case CALL:
275 assert(IR->wants_dag || p->count == 0);
276 break;
277 case ARG:
278 case ASGN: case JUMP: case LABEL: case RET:
279 case EQ: case GE: case GT: case LE: case LT: case NE:
280 assert(p->count == 0);
281 break;
282 case INDIR:
283 assert(IR->wants_dag && p->count > 0);
284 break;
285 default:
286 assert(0);
288 check(p);
289 p->x.listed = 1;
290 n = visit(p, n);
292 *tail = 0;
293 return nodelist;
296 /* global - announce a global */
297 static void I(global)(Symbol p) {
298 START; print("global "); emitSymbol(p); END;
301 /* import - import a symbol */
302 static void I(import)(Symbol p) {
303 START; print("import "); emitSymRef(p); END;
306 /* local - local variable */
307 static void I(local)(Symbol p) {
308 if (p->temporary)
309 p->name = stringf("t%s", p->name);
310 (*IR->defsymbol)(p);
311 off = roundup(off, p->type->align);
312 p->x.offset = off;
313 off += p->type->size;
314 START; print(p->temporary ? "temporary " : "local "); emitSymbol(p); END;
317 /* progbeg - beginning of program */
318 static void I(progbeg)(int argc, char *argv[]) {
319 int i;
321 for (i = 1; i < argc; i++)
322 if (strcmp(argv[i], "-v") == 0)
323 verbose++;
324 else if (strcmp(argv[i], "-html") == 0)
325 html++;
326 if (html) {
327 print("<!DOCTYPE HTML PUBLIC \"-//W3C//DTD HTML 3.2 Final//EN\">\n");
328 print("<html>");
329 BEGIN(head);
330 if (firstfile && *firstfile)
331 BEGIN(title); emitString(strlen(firstfile), firstfile); END;
332 print("<link rev=made href=\"mailto:drh@microsoft.com\">\n");
333 END;
334 print("<body>\n");
335 if (firstfile && *firstfile)
336 BEGIN(h1); emitString(strlen(firstfile), firstfile); END;
337 BEGIN(P); BEGIN(em);
338 print("Links lead from uses of identifiers and labels to their definitions.");
339 END; END;
340 print("<ul>\n");
341 START;
342 print("progbeg");
343 BEGIN(ol);
344 for (i = 1; i < argc; i++) {
345 ITEM;
346 BEGIN(code); print("\""); emitString(strlen(argv[i]), argv[i]); print("\""); END;
347 END;
349 END;
350 END;
354 /* progend - end of program */
355 static void I(progend)(void) {
356 START; print("progend"); END;
357 if (html) {
358 time_t t;
359 print("</ul>\n");
360 time(&t);
361 print("<hr><address>%s</address>\n", ctime(&t));
362 print("</body></html>\n");
366 /* segment - switch to segment s */
367 static void I(segment)(int s) {
368 START; print("segment %s", &"text\0bss\0.data\0lit\0.sym\0."[5*s-5]); END;
371 /* space - initialize n bytes of space */
372 static void I(space)(int n) {
373 START; print("space %d", n); END;
376 static void I(stabblock)(int brace, int lev, Symbol *p) {}
378 /* stabend - finalize stab output */
379 static void I(stabend)(Coordinate *cp, Symbol p, Coordinate **cpp, Symbol *sp, Symbol *stab) {
380 int i;
382 if (p)
383 emitSymRef(p);
384 print("\n");
385 if (cpp && sp)
386 for (i = 0; cpp[i] && sp[i]; i++) {
387 print("%w.%d: ", cpp[i], cpp[i]->x);
388 emitSymRef(sp[i]);
389 print("\n");
393 static void I(stabfend)(Symbol p, int lineno) {}
394 static void I(stabinit)(char *file, int argc, char *argv[]) {}
396 /* stabline - emit line number information for source coordinate *cp */
397 static void I(stabline)(Coordinate *cp) {
398 if (cp->file)
399 print("%s:", cp->file);
400 print("%d.%d:\n", cp->y, cp->x);
403 static void I(stabsym)(Symbol p) {}
404 static void I(stabtype)(Symbol p) {}
406 Interface symbolicIR = {
407 {1, 1, 0}, /* char */
408 {2, 2, 0}, /* short */
409 {4, 4, 0}, /* int */
410 {4, 4, 0}, /* long */
411 {4, 4, 0}, /* long long */
412 {4, 4, 1}, /* float */
413 {8, 8, 1}, /* double */
414 {8, 8, 1}, /* long double */
415 {4, 4, 0}, /* T* */
416 {0, 4, 0}, /* struct */
417 0, /* little_endian */
418 0, /* mulops_calls */
419 0, /* wants_callb */
420 1, /* wants_argb */
421 1, /* left_to_right */
422 1, /* wants_dag */
423 0, /* unsigned_char */
424 I(address),
425 I(blockbeg),
426 I(blockend),
427 I(defaddress),
428 I(defconst),
429 I(defstring),
430 I(defsymbol),
431 I(emit),
432 I(export),
433 I(function),
434 I(gen),
435 I(global),
436 I(import),
437 I(local),
438 I(progbeg),
439 I(progend),
440 I(segment),
441 I(space),
442 I(stabblock),
443 I(stabend),
444 I(stabfend),
445 I(stabinit),
446 I(stabline),
447 I(stabsym),
448 I(stabtype)
451 Interface symbolic64IR = {
452 {1, 1, 0}, /* char */
453 {2, 2, 0}, /* short */
454 {4, 4, 0}, /* int */
455 {8, 8, 0}, /* long */
456 {8, 8, 0}, /* long long */
457 {4, 4, 1}, /* float */
458 {8, 8, 1}, /* double */
459 {8, 8, 1}, /* long double */
460 {8, 8, 0}, /* T* */
461 {0, 1, 0}, /* struct */
462 1, /* little_endian */
463 0, /* mulops_calls */
464 0, /* wants_callb */
465 1, /* wants_argb */
466 1, /* left_to_right */
467 1, /* wants_dag */
468 0, /* unsigned_char */
469 I(address),
470 I(blockbeg),
471 I(blockend),
472 I(defaddress),
473 I(defconst),
474 I(defstring),
475 I(defsymbol),
476 I(emit),
477 I(export),
478 I(function),
479 I(gen),
480 I(global),
481 I(import),
482 I(local),
483 I(progbeg),
484 I(progend),
485 I(segment),
486 I(space),
487 I(stabblock),
488 I(stabend),
489 I(stabfend),
490 I(stabinit),
491 I(stabline),
492 I(stabsym),
493 I(stabtype)