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