scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | Submodules | README | 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 }