code.c - scc - simple c99 compiler
HTML git clone git://git.simple-cc.org/scc
DIR Log
DIR Files
DIR Refs
DIR Submodules
DIR README
DIR LICENSE
---
code.c (10400B)
---
1 #include <assert.h>
2 #include <ctype.h>
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <stdarg.h>
6
7 #include <scc/scc.h>
8 #include "cc1.h"
9
10 static void emitbin(int, void *),
11 emitcast(int, void *),
12 emitsym(int, void *),
13 emitexp(int, void *),
14 emitsymid(int, void *),
15 emittext(int, void *),
16 emitfun(int, void *),
17 emitdcl(int, void *),
18 emitinit(int, void *),
19 emittype(int, void *),
20 emitbuilt(int, void *);
21
22 char *optxt[] = {
23 [OADD] = "+",
24 [OSUB] = "-",
25 [OMUL] = "*",
26 [OINC] = ":i",
27 [ODEC] = ":d",
28 [OPTR] = "@",
29 [OMOD] = "%",
30 [ODIV] = "/",
31 [OSHL] = "l",
32 [OSHR] = "r",
33 [OLT] = "<",
34 [OGT] = ">",
35 [OGE] = "]",
36 [OLE] = "[",
37 [OEQ] = "=",
38 [ONE] = "!",
39 [OBAND] = "&",
40 [OBXOR] = "^",
41 [OBOR] = "|",
42 [OASSIGN] = ":",
43 [OA_MUL] = ":*",
44 [OA_DIV] = ":/",
45 [OA_MOD] = ":%",
46 [OA_ADD] = ":+",
47 [OA_SUB] = ":-",
48 [OA_SHL] = ":l",
49 [OA_SHR] = ":r",
50 [OA_AND] = ":&",
51 [OA_XOR] = ":^",
52 [OA_OR] = ":|",
53 [OADDR] = "'",
54 [OSNEG] = "_",
55 [ONEG] = "n",
56 [OCPL] = "~",
57 [OAND] = "a",
58 [OOR] = "o",
59 [OASK] = "?",
60 [OCOMMA] = ",",
61 [OLABEL] = "L%d\n",
62 [ODEFAULT] = "\tf\tL%d\n",
63 [OBSWITCH] = "\ts",
64 [OESWITCH] = "\tt\tL%d\n",
65 [OCASE] = "\tv\tL%d",
66 [OJUMP] = "\tj\tL%d\n",
67 [OBRANCH] = "\ty\tL%d",
68 [OEFUN] = "}\n",
69 [OELOOP] = "\te\n",
70 [OBLOOP] = "\tb\n",
71 [ORET] = "\th",
72 [OPAR] = "p",
73 [OCALL] = "c",
74 [OCALLE] = "z",
75 [OFIELD] = "."
76 };
77
78 void (*opcode[])(int, void *) = {
79 [OADD] = emitbin,
80 [OSUB] = emitbin,
81 [OMUL] = emitbin,
82 [OINC] = emitbin,
83 [ODEC] = emitbin,
84 [OPTR] = emitbin,
85 [OMOD] = emitbin,
86 [ODIV] = emitbin,
87 [OSHL] = emitbin,
88 [OSHR] = emitbin,
89 [OLT] = emitbin,
90 [OGT] = emitbin,
91 [OGE] = emitbin,
92 [OLE] = emitbin,
93 [OEQ] = emitbin,
94 [ONE] = emitbin,
95 [OBAND] = emitbin,
96 [OBXOR] = emitbin,
97 [OBOR] = emitbin,
98 [OASSIGN] = emitbin,
99 [OA_MUL] = emitbin,
100 [OA_DIV] = emitbin,
101 [OA_MOD] = emitbin,
102 [OA_ADD] = emitbin,
103 [OA_SUB] = emitbin,
104 [OA_SHL] = emitbin,
105 [OA_SHR] = emitbin,
106 [OA_AND] = emitbin,
107 [OA_XOR] = emitbin,
108 [OA_OR] = emitbin,
109 [OADDR] = emitbin,
110 [OSNEG] = emitbin,
111 [ONEG] = emitbin,
112 [OCPL] = emitbin,
113 [OAND] = emitbin,
114 [OOR] = emitbin,
115 [OCOMMA] = emitbin,
116 [OCAST] = emitcast,
117 [OSYM] = emitsym,
118 [OASK] = emitbin,
119 [OCOLON] = emitbin,
120 [OFIELD]= emitbin,
121 [OEXPR] = emitexp,
122 [OLABEL] = emitsymid,
123 [ODEFAULT] = emitsymid,
124 [OCASE] = emitsymid,
125 [OJUMP] = emitsymid,
126 [OBRANCH] = emitsymid,
127 [OEFUN] = emittext,
128 [OELOOP] = emittext,
129 [OBLOOP] = emittext,
130 [OFUN] = emitfun,
131 [ORET] = emittext,
132 [ODECL] = emitdcl,
133 [OBSWITCH] = emittext,
134 [OESWITCH] = emitsymid,
135 [OPAR] = emitbin,
136 [OCALL] = emitbin,
137 [OCALLE] = emitbin,
138 [OINIT] = emitinit,
139 [OBUILTIN] = emitbuilt,
140 [OTYP] = emittype,
141 };
142
143 static FILE *outfp;
144
145 void
146 icode(void)
147 {
148 outfp = stdout;
149 }
150
151 void
152 freetree(Node *np)
153 {
154 if (!np)
155 return;
156 freetree(np->left);
157 freetree(np->right);
158 free(np);
159 }
160
161 static void
162 emitnode(Node *np)
163 {
164 if (np)
165 (*opcode[np->op])(np->op, np);
166 }
167
168 Node *
169 prtree(char *s, Node *np)
170 {
171 FILE *tmp = outfp;
172
173 outfp = stderr;
174 fprintf(outfp, "DBG prtree %s", s);
175 emitnode(np);
176 putc('\n', outfp);
177 outfp = tmp;
178
179 return np;
180 }
181
182 void
183 emit(int op, void *arg)
184 {
185 extern int failure;
186
187 if (failure || onlycpp || onlyheader)
188 return;
189 (*opcode[op])(op, arg);
190 }
191
192 static void
193 emitvar(Symbol *sym)
194 {
195 int c;
196 short flags = sym->flags;
197
198 if (flags & SLOCAL)
199 c = 'T';
200 else if (flags & SPRIVATE)
201 c = 'Y';
202 else if (flags & SGLOBAL)
203 c = 'G';
204 else if (flags & SREGISTER)
205 c = 'R';
206 else if (flags & SFIELD)
207 c = 'M';
208 else if (flags & SEXTERN)
209 c = 'X';
210 else
211 c = 'A';
212 fprintf(outfp, "%c%u", c, sym->id);
213 }
214
215 static void
216 emitconst(Node *np)
217 {
218 int n;
219 unsigned char *fp, *p;
220 Symbol *sym = np->sym;
221 Type *tp = np->type;
222 unsigned long long u;
223
224 switch (tp->op) {
225 case FLOAT:
226 if (tp == floattype)
227 u = *(uint32_t *) &sym->u.f;
228 else if (tp == doubletype)
229 u = *(uint64_t *) &sym->u.d;
230 else
231 abort(); /* TODO: What here?? */
232 goto print;
233 case PTR:
234 case INT:
235 case ENUM:
236 u = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
237 print:
238 fprintf(outfp,
239 "#%c%llX",
240 tp->letter,
241 u & ones(tp->size));
242 break;
243 default:
244 abort();
245 }
246 }
247
248 static void
249 emitsym(int op, void *arg)
250 {
251 Node *np = arg;
252
253 if ((np->sym->flags & SINITLST) == 0) {
254 /*
255 * When we have a compound literal we are going
256 * to call to emitnode for every element of it,
257 * and it means that we will have two '\t'
258 * for the first element
259 */
260 putc('\t', outfp);
261 }
262 (np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
263 }
264
265 static void
266 emitletter(Type *tp)
267 {
268 int letter;
269
270 letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter;
271 putc(letter, outfp);
272 switch (tp->op) {
273 case ARY:
274 case STRUCT:
275 case UNION:
276 fprintf(outfp, "%u", tp->id);
277 }
278 }
279
280 static void
281 emittype(int op, void *arg)
282 {
283 long long n;
284 Symbol **sp;
285 char *tag;
286 Type *tp = arg;
287
288 if (!(tp->prop & TDEFINED))
289 return;
290
291 switch (tp->op) {
292 case ARY:
293 emitletter(tp);
294 putc('\t', outfp);
295 emitletter(tp->type);
296 fprintf(outfp,
297 "\t#%c%llX\n",
298 sizettype->letter, (long long) tp->n.elem);
299 return;
300 case UNION:
301 case STRUCT:
302 emitletter(tp);
303 tag = tp->tag->name;
304 fprintf(outfp,
305 "\t\"%s\t#%c%lX\t#%c%X\n",
306 (tag) ? tag : "",
307 sizettype->letter,
308 tp->size,
309 sizettype->letter,
310 tp->align);
311 n = tp->n.elem;
312 for (sp = tp->p.fields; n-- > 0; ++sp)
313 emit(ODECL, *sp);
314 break;
315 case PTR:
316 case FTN:
317 case ENUM:
318 return;
319 default:
320 abort();
321 }
322 }
323
324 static void
325 emitstring(Symbol *sym, Type *tp)
326 {
327 char *bp, *s, *lim;
328 int n;
329
330 bp = sym->u.s;
331 lim = &sym->u.s[tp->n.elem];
332 while (bp < lim) {
333 s = bp;
334 while (bp < lim && isprint(*bp))
335 ++bp;
336 if ((n = bp - s) > 1)
337 fprintf(outfp, "\t#\"%.*s\n", n, s);
338 else
339 bp = s;
340 if (bp == lim)
341 break;
342 do {
343 fprintf(outfp,
344 "\t#%c%X\n",
345 chartype->letter, (*bp++) & 0xFF);
346 } while (bp < lim && !isprint(*bp));
347 }
348 }
349
350 Node *
351 zeronode(Type *tp)
352 {
353 return simplify(convert(constnode(zero), tp, 0));
354 }
355
356 static void
357 emitpadding(Type *tp, unsigned long long *addr)
358 {
359 int i, align;
360 unsigned long long a, n;
361
362 align = tp->align - 1;
363 a = *addr;
364 n = a+align & ~align;
365
366 for ( ; a != n; ++a)
367 emitexp(OEXPR, zeronode(chartype));
368 *addr = n;
369 }
370
371 static void
372 emitdesig(Node *np, Type *tp, unsigned long long *addr)
373 {
374 Symbol *sym;
375 unsigned long long n;
376 Node *aux;
377 Type *p;
378
379 emitpadding(tp, addr);
380
381 if (!np) {
382 sym = NULL;
383 } else {
384 if (!np->sym)
385 goto emit_expression;
386 sym = np->sym;
387 if (sym->flags & SSTRING) {
388 emitstring(sym, tp);
389 *addr += tp->n.elem;
390 return;
391 }
392 if ((sym->flags & SINITLST) == 0)
393 goto emit_expression;
394 }
395
396 switch (tp->op) {
397 case PTR:
398 case INT:
399 case ENUM:
400 aux = sym ? *sym->u.init : zeronode(tp);
401 *addr += aux->type->size;
402 emitexp(OEXPR, aux);
403 break;
404 case UNION:
405 aux = (sym) ? sym->u.init[0] : NULL;
406 p = (aux) ? aux->type : tp->p.fields[0]->type;
407 emitdesig(aux, p, addr);
408 emitpadding(tp, addr);
409 break;
410 case STRUCT:
411 case ARY:
412 for (n = 0; n < tp->n.elem; ++n) {
413 aux = (sym) ? sym->u.init[n] : NULL;
414 p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
415 emitdesig(aux, p, addr);
416 }
417 emitpadding(tp, addr);
418 break;
419 default:
420 abort();
421 }
422
423 if (sym) {
424 free(sym->u.init);
425 sym->u.init = NULL;
426 }
427 freetree(np);
428 return;
429
430 emit_expression:
431 emitexp(OEXPR, np);
432 *addr += tp->size;
433 }
434
435 static void
436 emitinit(int op, void *arg)
437 {
438 Node *np = arg;
439 unsigned long long addr = 0;
440
441 fputs("\t(\n", outfp);
442 emitdesig(np, np->type, &addr);
443 fputs(")\n", outfp);
444 }
445
446 static void
447 emitdcl(int op, void *arg)
448 {
449 Symbol *sym = arg;
450
451 if (sym->flags & SEMITTED)
452 return;
453 emitvar(sym);
454 putc('\t', outfp);
455 if (sym->type->op == FTN) {
456 emitletter(sym->type->type);
457 putc('\t', outfp);
458 }
459 emitletter(sym->type);
460 fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
461 if (sym->flags & SFIELD)
462 fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
463 sym->flags |= SEMITTED;
464 if ((sym->flags & SHASINIT) == 0)
465 putc('\n', outfp);
466 }
467
468 static void
469 emitcast(int op, void *arg)
470 {
471 Node *np = arg, *lp = np->left;
472
473 emitnode(lp);
474 if (np->type != voidtype)
475 fprintf(outfp, "\tg%c", np->type->letter);
476 }
477
478 static void
479 emitbin(int op, void *arg)
480 {
481 Node *np = arg;
482 char *s;
483
484 emitnode(np->left);
485 emitnode(np->right);
486
487 /* do not print in OCOLON case */
488 if ((s = optxt[op]) != NULL) {
489 fprintf(outfp, "\t%s", s);
490 emitletter(np->type);
491 }
492 }
493
494 static void
495 emitbuilt(int op, void *arg)
496 {
497 Node *np = arg;
498
499 emitnode(np->left);
500 emitnode(np->right);
501 fprintf(outfp, "\t\"%s\tm", np->sym->name);
502 emitletter(np->type);
503 }
504
505
506 static void
507 emitexp(int op, void *arg)
508 {
509 Node *np = arg;
510
511 emitnode(np);
512 putc('\n', outfp);
513 freetree(np);
514 }
515
516 static void
517 emitfun(int op, void *arg)
518 {
519 Symbol *sym = arg, **sp;
520
521 emitdcl(op, arg);
522 fputs("{\n", outfp);
523
524 for (sp = sym->u.pars; sp && *sp; ++sp)
525 emit(ODECL, *sp);
526 fputs("\\\n", outfp);
527 }
528
529 static void
530 emittext(int op, void *arg)
531 {
532 fputs(optxt[op], outfp);
533 }
534
535 static void
536 emitsymid(int op, void *arg)
537 {
538 Symbol *sym = arg;
539 fprintf(outfp, optxt[op], sym->id);
540 }
541
542 Node *
543 node(int op, Type *tp, Node *lp, Node *rp)
544 {
545 Node *np;
546
547 np = xmalloc(sizeof(*np));
548 np->op = op;
549 np->type = tp;
550 np->sym = NULL;
551 np->flags = 0;
552 np->left = lp;
553 np->right = rp;
554
555 if (lp)
556 np->flags |= lp->flags & NEFFECT;
557 if (rp)
558 np->flags |= rp->flags & NEFFECT;
559 return np;
560 }
561
562 Node *
563 varnode(Symbol *sym)
564 {
565 Node *np;
566 Type *tp = sym->type;
567
568 np = node(OSYM, sym->type, NULL, NULL);
569 np->type = sym->type;
570 np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
571 np->sym = sym;
572 return np;
573 }
574
575 Node *
576 constnode(Symbol *sym)
577 {
578 Node *np;
579
580 np = node(OSYM, sym->type, NULL, NULL);
581 np->flags = NCONST;
582 np->sym = sym;
583 return np;
584 }
585
586 Node *
587 sizeofnode(Type *tp)
588 {
589 Symbol *sym;
590
591 sym = newsym(NS_IDEN, NULL);
592 sym->type = sizettype;
593 sym->flags |= SCONSTANT;
594 sym->u.u = tp->size;
595 DBG("EXPR sizeof %llu", sym->u.u);
596 return constnode(sym);
597 }
598
599 Node *
600 offsetnode(Symbol *field, Type *tp)
601 {
602 Symbol *sym;
603
604 assert(field->flags & SFIELD);
605 sym = newsym(NS_IDEN, NULL);
606 sym->type = tp;
607 sym->flags |= SCONSTANT;
608 sym->u.u = field->u.u;
609
610 return constnode(sym);
611 }
612
613 Node *
614 addrnode(unsigned long long u)
615 {
616 Symbol *sym;
617
618 sym = newsym(NS_IDEN, NULL);
619 sym->type = pvoidtype;
620 sym->flags |= SCONSTANT;
621 sym->u.u = u;
622
623 return constnode(sym);
624 }