scc

simple c99 compiler
git clone git://git.simple-cc.org/scc
Log | Files | Refs | README | LICENSE

code.c (9161B)


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