scc

simple C compiler
git clone git://git.2f30.org/scc
Log | Files | Refs | README | LICENSE

code.c (9208B)


      1 static char sccsid[] = "@(#) ./cc1/code.c";
      2 #include <ctype.h>
      3 #include <stdio.h>
      4 #include <stdlib.h>
      5 #include <stdarg.h>
      6 
      7 #include "../inc/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] = "\tb\n",
     70 	[OBLOOP] = "\te\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 void
    169 prtree(Node *np)
    170 {
    171 	outfp = stderr;
    172 	fputs("DBG prtree", outfp);
    173 	emitnode(np);
    174 	putc('\n', outfp);
    175 	outfp = stdout;
    176 }
    177 
    178 void
    179 emit(int op, void *arg)
    180 {
    181 	extern int failure;
    182 
    183 	if (failure || onlycpp || onlyheader)
    184 		return;
    185 	(*opcode[op])(op, arg);
    186 }
    187 
    188 static void
    189 emitvar(Symbol *sym)
    190 {
    191 	int c;
    192 	short flags = sym->flags;
    193 
    194 	if (flags & SLOCAL)
    195 		c = 'T';
    196 	else if (flags & SPRIVATE)
    197 		c =  'Y';
    198 	else if (flags & SGLOBAL)
    199 		c = 'G';
    200 	else if (flags & SREGISTER)
    201 		c = 'R';
    202 	else if (flags & SFIELD)
    203 		c = 'M';
    204 	else if (flags & SEXTERN)
    205 		c = 'X';
    206 	else
    207 		c = 'A';
    208 	fprintf(outfp, "%c%u", c, sym->id);
    209 }
    210 
    211 static void
    212 emitconst(Node *np)
    213 {
    214 	Symbol *sym = np->sym;
    215 	Type *tp = np->type;
    216 	TUINT u;
    217 
    218 	switch (tp->op) {
    219 	case PTR:
    220 	case INT:
    221 	case ENUM:
    222 		u = (tp->prop & TSIGNED) ? (TUINT) sym->u.i : sym->u.u;
    223 		fprintf(outfp,
    224 		        "#%c%llX",
    225 		        np->type->letter,
    226 		        (long long) u & ones(tp->size));
    227 		break;
    228 	default:
    229 		abort();
    230 	}
    231 }
    232 
    233 static void
    234 emitsym(int op, void *arg)
    235 {
    236 	Node *np = arg;
    237 
    238 	if ((np->sym->flags & SINITLST) == 0) {
    239 		/*
    240 		 * When we have a compound literal we are going
    241 		 * to call to emitnode for every element of it,
    242 		 * and it means that we will have two '\t'
    243 		 * for the first element
    244 		 */
    245 		putc('\t', outfp);
    246 	}
    247 	(np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
    248 }
    249 
    250 static void
    251 emitletter(Type *tp)
    252 {
    253 	int letter;
    254 
    255 	letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter;
    256 	putc(letter, outfp);
    257 	switch (tp->op) {
    258 	case ARY:
    259 	case STRUCT:
    260 	case UNION:
    261 		fprintf(outfp, "%u", tp->id);
    262 	}
    263 }
    264 
    265 static void
    266 emittype(int op, void *arg)
    267 {
    268 	TINT n;
    269 	Symbol **sp;
    270 	char *tag;
    271 	Type *tp = arg;
    272 
    273 	if (!(tp->prop & TDEFINED))
    274 		return;
    275 
    276 	switch (tp->op) {
    277 	case ARY:
    278 		emitletter(tp);
    279 		putc('\t', outfp);
    280 		emitletter(tp->type);
    281 		fprintf(outfp,
    282 		        "\t#%c%llX\n",
    283 		        sizettype->letter, (long long) tp->n.elem);
    284 		return;
    285 	case UNION:
    286 	case STRUCT:
    287 		emitletter(tp);
    288 		tag = tp->tag->name;
    289 		fprintf(outfp,
    290 		       "\t\"%s\t#%c%lX\t#%c%X\n",
    291 		       (tag) ? tag : "",
    292 		       sizettype->letter,
    293 		       tp->size,
    294 		       sizettype->letter,
    295 		       tp->align);
    296 		n = tp->n.elem;
    297 		for (sp = tp->p.fields; n-- > 0; ++sp)
    298 			emit(ODECL, *sp);
    299 		break;
    300 	case PTR:
    301 	case FTN:
    302 	case ENUM:
    303 		return;
    304 	default:
    305 		abort();
    306 	}
    307 }
    308 
    309 static void
    310 emitstring(Symbol *sym, Type *tp)
    311 {
    312 	char *bp, *s, *lim;
    313 	int n;
    314 
    315 	bp = sym->u.s;
    316 	lim = &sym->u.s[tp->n.elem];
    317 	while (bp < lim) {
    318 		s = bp;
    319 		while (bp < lim && isprint(*bp))
    320 			++bp;
    321 		if ((n = bp - s) > 1)
    322 			fprintf(outfp, "\t#\"%.*s\n", n, s);
    323 		else
    324 			bp = s;
    325 		if (bp == lim)
    326 			break;
    327 		do {
    328 			fprintf(outfp,
    329 			        "\t#%c%02X\n",
    330 			        chartype->letter, (*bp++) & 0xFF);
    331 		} while (bp < lim && !isprint(*bp));
    332 	}
    333 }
    334 
    335 static void
    336 emitdesig(Node *np, Type *tp)
    337 {
    338 	Symbol *sym;
    339 	size_t n; /* TODO: This should be SIZET */
    340 	Node *aux;
    341 	Type *p;
    342 
    343 	if (!np) {
    344 		sym = NULL;
    345 	} else {
    346 		if (!np->sym)
    347 			goto emit_expression;
    348 		sym = np->sym;
    349 		if (sym->flags & SSTRING) {
    350 			emitstring(sym, tp);
    351 			return;
    352 		}
    353 		if ((sym->flags & SINITLST) == 0)
    354 			goto emit_expression;
    355 	}
    356 
    357 	switch (tp->op) {
    358 	case PTR:
    359 	case INT:
    360 	case ENUM:
    361 		aux = (sym) ? *sym->u.init : convert(constnode(zero), tp, 0);
    362 		emitexp(OEXPR, aux);
    363 		break;
    364 	case UNION:
    365 		n = tp->n.elem-1;
    366 		aux = (sym) ? sym->u.init[0] : NULL;
    367 		emitdesig(aux, aux->type);
    368 		break;
    369 	case STRUCT:
    370 	case ARY:
    371 		for (n = 0; n < tp->n.elem; ++n) {
    372 			aux = (sym) ? sym->u.init[n] : NULL;
    373 			p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
    374 			emitdesig(aux, p);
    375 		}
    376 		break;
    377 	default:
    378 		abort();
    379 	}
    380 
    381 	if (sym) {
    382 		free(sym->u.init);
    383 		sym->u.init = NULL;
    384 	}
    385 	freetree(np);
    386 	return;
    387 
    388 emit_expression:
    389 	emitexp(OEXPR, np);
    390 }
    391 
    392 static void
    393 emitinit(int op, void *arg)
    394 {
    395 	Node *np = arg;
    396 
    397 	fputs("\t(\n", outfp);
    398 	emitdesig(np, np->type);
    399 	fputs(")\n", outfp);
    400 }
    401 
    402 static void
    403 emitdcl(int op, void *arg)
    404 {
    405 	Symbol *sym = arg;
    406 
    407 	if (sym->flags & SEMITTED)
    408 		return;
    409 	emitvar(sym);
    410 	putc('\t', outfp);
    411 	if (sym->type->op == FTN) {
    412 		emitletter(sym->type->type);
    413 		putc('\t', outfp);
    414 	}
    415 	emitletter(sym->type);
    416 	fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
    417 	if (sym->flags & SFIELD)
    418 		fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
    419 	sym->flags |= SEMITTED;
    420 	if ((sym->flags & SHASINIT) == 0)
    421 		putc('\n', outfp);
    422 }
    423 
    424 static void
    425 emitcast(int op, void *arg)
    426 {
    427 	Node *np = arg, *lp = np->left;
    428 
    429 	emitnode(lp);
    430 	if (np->type != voidtype)
    431 		fprintf(outfp, "\tg%c", np->type->letter);
    432 }
    433 
    434 static void
    435 emitbin(int op, void *arg)
    436 {
    437 	Node *np = arg;
    438 	char *s;
    439 
    440 	emitnode(np->left);
    441 	emitnode(np->right);
    442 	if ((s = optxt[op]) != NULL)  {      /* do not print in OCOLON case */
    443 		fprintf(outfp, "\t%s", s);
    444 		emitletter(np->type);
    445 	}
    446 }
    447 
    448 static void
    449 emitbuilt(int op, void *arg)
    450 {
    451 	Node *np = arg;
    452 
    453 	emitnode(np->left);
    454 	emitnode(np->right);
    455 	fprintf(outfp, "\t\"%s\tm", np->sym->name);
    456 	emitletter(np->type);
    457 }
    458 
    459 
    460 static void
    461 emitexp(int op, void *arg)
    462 {
    463 	Node *np = arg;
    464 
    465 	emitnode(np);
    466 	putc('\n', outfp);
    467 	freetree(np);
    468 }
    469 
    470 static void
    471 emitfun(int op, void *arg)
    472 {
    473 	Symbol *sym = arg, **sp;
    474 
    475 	emitdcl(op, arg);
    476 	fputs("{\n", outfp);
    477 
    478 	for (sp = sym->u.pars; sp && *sp; ++sp)
    479 		emit(ODECL, *sp);
    480 	fputs("\\\n", outfp);
    481 }
    482 
    483 static void
    484 emittext(int op, void *arg)
    485 {
    486 	fputs(optxt[op], outfp);
    487 }
    488 
    489 static void
    490 emitsymid(int op, void *arg)
    491 {
    492 	Symbol *sym = arg;
    493 	fprintf(outfp, optxt[op], sym->id);
    494 }
    495 
    496 Node *
    497 node(int op, Type *tp, Node *lp, Node *rp)
    498 {
    499 	Node *np;
    500 
    501 	np = xmalloc(sizeof(*np));
    502 	np->op = op;
    503 	np->type = tp;
    504 	np->sym = NULL;
    505 	np->flags = 0;
    506 	np->left = lp;
    507 	np->right = rp;
    508 
    509 	if (lp)
    510 		np->flags |= lp->flags & NEFFECT;
    511 	if (rp)
    512 		np->flags |= rp->flags & NEFFECT;
    513 	return np;
    514 }
    515 
    516 Node *
    517 varnode(Symbol *sym)
    518 {
    519 	Node *np;
    520 	Type *tp = sym->type;
    521 
    522 	np = node(OSYM, sym->type, NULL, NULL);
    523 	np->type = sym->type;
    524 	np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
    525 	np->sym = sym;
    526 	return np;
    527 }
    528 
    529 Node *
    530 constnode(Symbol *sym)
    531 {
    532 	Node *np;
    533 
    534 	np = node(OSYM, sym->type, NULL, NULL);
    535 	np->type = sym->type;
    536 	np->flags = NCONST;
    537 	np->sym = sym;
    538 	return np;
    539 }
    540 
    541 Node *
    542 sizeofnode(Type *tp)
    543 {
    544 	Symbol *sym;
    545 
    546 	sym = newsym(NS_IDEN, NULL);
    547 	sym->type = sizettype;
    548 	sym->u.i = tp->size;
    549 	return constnode(sym);
    550 }