scc

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