code.c - scc - simple c99 compiler
(HTM) git clone git://git.simple-cc.org/scc
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) Submodules
(DIR) README
(DIR) LICENSE
---
code.c (9893B)
---
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 Symbol *sym = np->sym;
219 Type *tp = np->type;
220 TUINT u;
221
222 switch (tp->op) {
223 case PTR:
224 case INT:
225 case ENUM:
226 u = (tp->prop & TSIGNED) ? (TUINT) sym->u.i : sym->u.u;
227 fprintf(outfp,
228 "#%c%llX",
229 np->type->letter,
230 (long long) u & ones(tp->size));
231 break;
232 default:
233 abort();
234 }
235 }
236
237 static void
238 emitsym(int op, void *arg)
239 {
240 Node *np = arg;
241
242 if ((np->sym->flags & SINITLST) == 0) {
243 /*
244 * When we have a compound literal we are going
245 * to call to emitnode for every element of it,
246 * and it means that we will have two '\t'
247 * for the first element
248 */
249 putc('\t', outfp);
250 }
251 (np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
252 }
253
254 static void
255 emitletter(Type *tp)
256 {
257 int letter;
258
259 letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter;
260 putc(letter, outfp);
261 switch (tp->op) {
262 case ARY:
263 case STRUCT:
264 case UNION:
265 fprintf(outfp, "%u", tp->id);
266 }
267 }
268
269 static void
270 emittype(int op, void *arg)
271 {
272 TINT n;
273 Symbol **sp;
274 char *tag;
275 Type *tp = arg;
276
277 if (!(tp->prop & TDEFINED))
278 return;
279
280 switch (tp->op) {
281 case ARY:
282 emitletter(tp);
283 putc('\t', outfp);
284 emitletter(tp->type);
285 fprintf(outfp,
286 "\t#%c%llX\n",
287 sizettype->letter, (long long) tp->n.elem);
288 return;
289 case UNION:
290 case STRUCT:
291 emitletter(tp);
292 tag = tp->tag->name;
293 fprintf(outfp,
294 "\t\"%s\t#%c%lX\t#%c%X\n",
295 (tag) ? tag : "",
296 sizettype->letter,
297 tp->size,
298 sizettype->letter,
299 tp->align);
300 n = tp->n.elem;
301 for (sp = tp->p.fields; n-- > 0; ++sp)
302 emit(ODECL, *sp);
303 break;
304 case PTR:
305 case FTN:
306 case ENUM:
307 return;
308 default:
309 abort();
310 }
311 }
312
313 static void
314 emitstring(Symbol *sym, Type *tp)
315 {
316 char *bp, *s, *lim;
317 int n;
318
319 bp = sym->u.s;
320 lim = &sym->u.s[tp->n.elem];
321 while (bp < lim) {
322 s = bp;
323 while (bp < lim && isprint(*bp))
324 ++bp;
325 if ((n = bp - s) > 1)
326 fprintf(outfp, "\t#\"%.*s\n", n, s);
327 else
328 bp = s;
329 if (bp == lim)
330 break;
331 do {
332 fprintf(outfp,
333 "\t#%c%02X\n",
334 chartype->letter, (*bp++) & 0xFF);
335 } while (bp < lim && !isprint(*bp));
336 }
337 }
338
339 static Node *
340 zeronode(Type *tp)
341 {
342 return simplify(convert(constnode(zero), tp, 0));
343 }
344
345 static int
346 emitpadding(Type *tp, SIZET *addr)
347 {
348 SIZET n;
349 int i;
350
351 n = *addr & tp->align-1;
352 for (i = 0; i < n; i++)
353 emitexp(OEXPR, zeronode(chartype));
354 *addr += n;
355
356 return n;
357 }
358
359 static void
360 emitdesig(Node *np, Type *tp, SIZET *addr)
361 {
362 Symbol *sym;
363 SIZET n;
364 Node *aux;
365 Type *p;
366
367 emitpadding(tp, addr);
368
369 if (!np) {
370 sym = NULL;
371 } else {
372 if (!np->sym)
373 goto emit_expression;
374 sym = np->sym;
375 if (sym->flags & SSTRING) {
376 emitstring(sym, tp);
377 *addr += tp->n.elem;
378 return;
379 }
380 if ((sym->flags & SINITLST) == 0)
381 goto emit_expression;
382 }
383
384 switch (tp->op) {
385 case PTR:
386 case INT:
387 case ENUM:
388 aux = sym ? *sym->u.init : zeronode(tp);
389 *addr += aux->type->size;
390 emitexp(OEXPR, aux);
391 break;
392 case UNION:
393 aux = (sym) ? sym->u.init[0] : NULL;
394 p = (aux) ? aux->type : tp->p.fields[0]->type;
395 emitdesig(aux, p, addr);
396 emitpadding(tp, addr);
397 break;
398 case STRUCT:
399 case ARY:
400 for (n = 0; n < tp->n.elem; ++n) {
401 aux = (sym) ? sym->u.init[n] : NULL;
402 p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
403 emitdesig(aux, p, addr);
404 }
405 emitpadding(tp, addr);
406 break;
407 default:
408 abort();
409 }
410
411 if (sym) {
412 free(sym->u.init);
413 sym->u.init = NULL;
414 }
415 freetree(np);
416 return;
417
418 emit_expression:
419 emitexp(OEXPR, np);
420 *addr += tp->size;
421 }
422
423 static void
424 emitinit(int op, void *arg)
425 {
426 Node *np = arg;
427 SIZET addr = 0;
428
429 fputs("\t(\n", outfp);
430 emitdesig(np, np->type, &addr);
431 fputs(")\n", outfp);
432 }
433
434 static void
435 emitdcl(int op, void *arg)
436 {
437 Symbol *sym = arg;
438
439 if (sym->flags & SEMITTED)
440 return;
441 emitvar(sym);
442 putc('\t', outfp);
443 if (sym->type->op == FTN) {
444 emitletter(sym->type->type);
445 putc('\t', outfp);
446 }
447 emitletter(sym->type);
448 fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
449 if (sym->flags & SFIELD)
450 fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
451 sym->flags |= SEMITTED;
452 if ((sym->flags & SHASINIT) == 0)
453 putc('\n', outfp);
454 }
455
456 static void
457 emitcast(int op, void *arg)
458 {
459 Node *np = arg, *lp = np->left;
460
461 emitnode(lp);
462 if (np->type != voidtype)
463 fprintf(outfp, "\tg%c", np->type->letter);
464 }
465
466 static void
467 emitbin(int op, void *arg)
468 {
469 Node *np = arg;
470 char *s;
471
472 emitnode(np->left);
473 emitnode(np->right);
474
475 /* do not print in OCOLON case */
476 if ((s = optxt[op]) != NULL) {
477 fprintf(outfp, "\t%s", s);
478 emitletter(np->type);
479 }
480 }
481
482 static void
483 emitbuilt(int op, void *arg)
484 {
485 Node *np = arg;
486
487 emitnode(np->left);
488 emitnode(np->right);
489 fprintf(outfp, "\t\"%s\tm", np->sym->name);
490 emitletter(np->type);
491 }
492
493
494 static void
495 emitexp(int op, void *arg)
496 {
497 Node *np = arg;
498
499 emitnode(np);
500 putc('\n', outfp);
501 freetree(np);
502 }
503
504 static void
505 emitfun(int op, void *arg)
506 {
507 Symbol *sym = arg, **sp;
508
509 emitdcl(op, arg);
510 fputs("{\n", outfp);
511
512 for (sp = sym->u.pars; sp && *sp; ++sp)
513 emit(ODECL, *sp);
514 fputs("\\\n", outfp);
515 }
516
517 static void
518 emittext(int op, void *arg)
519 {
520 fputs(optxt[op], outfp);
521 }
522
523 static void
524 emitsymid(int op, void *arg)
525 {
526 Symbol *sym = arg;
527 fprintf(outfp, optxt[op], sym->id);
528 }
529
530 Node *
531 node(int op, Type *tp, Node *lp, Node *rp)
532 {
533 Node *np;
534
535 np = xmalloc(sizeof(*np));
536 np->op = op;
537 np->type = tp;
538 np->sym = NULL;
539 np->flags = 0;
540 np->left = lp;
541 np->right = rp;
542
543 if (lp)
544 np->flags |= lp->flags & NEFFECT;
545 if (rp)
546 np->flags |= rp->flags & NEFFECT;
547 return np;
548 }
549
550 Node *
551 varnode(Symbol *sym)
552 {
553 Node *np;
554 Type *tp = sym->type;
555
556 np = node(OSYM, sym->type, NULL, NULL);
557 np->type = sym->type;
558 np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
559 np->sym = sym;
560 return np;
561 }
562
563 Node *
564 constnode(Symbol *sym)
565 {
566 Node *np;
567
568 np = node(OSYM, sym->type, NULL, NULL);
569 np->flags = NCONST;
570 np->sym = sym;
571 return np;
572 }
573
574 Node *
575 sizeofnode(Type *tp)
576 {
577 Symbol *sym;
578
579 sym = newsym(NS_IDEN, NULL);
580 sym->type = sizettype;
581 sym->u.u = tp->size;
582 DBG("EXPR sizeof %llu", sym->u.u);
583 return constnode(sym);
584 }
585
586 Node *
587 offsetnode(Symbol *field, Type *tp)
588 {
589 Symbol *sym;
590
591 assert(field->flags & SFIELD);
592 sym = newsym(NS_IDEN, NULL);
593 sym->type = tp;
594 sym->flags |= SCONSTANT;
595 sym->u.u = field->u.u;
596
597 return constnode(sym);
598 }