scc

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

cgen.c (12306B)


      1 #include <assert.h>
      2 #include <stdlib.h>
      3 
      4 #include <scc/cstd.h>
      5 #include <scc/scc.h>
      6 
      7 #include "../cc2.h"
      8 #include "arch.h"
      9 
     10 #define I1BYTES 0
     11 #define I2BYTES 1
     12 #define I4BYTES 2
     13 #define I8BYTES 3
     14 
     15 static Node *cgen(Node *);
     16 
     17 static unsigned char opasmw[][2] = {
     18 	[OADD] = {ASADDW, ASADDW},
     19 	[OSUB] = {ASSUBW, ASSUBW},
     20 	[OMUL] = {ASMULW, ASMULW},
     21 	[OMOD] = {ASMODW, ASUMODW},
     22 	[ODIV] = {ASDIVW, ASUDIVW},
     23 	[OSHL] = {ASSHLW, ASSHLW},
     24 	[OSHR] = {ASSHRW, ASUSHRW},
     25 	[OLT] = {ASLTW, ASULTW},
     26 	[OGT] = {ASGTW, ASUGTW},
     27 	[OLE] = {ASLEW, ASULEW},
     28 	[OGE] = {ASGEW, ASUGEW},
     29 	[OEQ] = {ASEQW, ASEQW},
     30 	[ONE] = {ASNEW, ASNEW},
     31 	[OBAND] = {ASBANDW, ASBANDW},
     32 	[OBOR] = {ASBORW, ASBORW},
     33 	[OBXOR] = {ASBXORW, ASBXORW},
     34 	[OSNEG] = {ASNEGW, ASNEGW},
     35 };
     36 
     37 static unsigned char opasml[][2] = {
     38 	[OADD] = {ASADDL, ASADDL},
     39 	[OSUB] = {ASSUBL, ASSUBL},
     40 	[OMUL] = {ASMULL, ASMULL},
     41 	[OMOD] = {ASMODL, ASUMODL},
     42 	[ODIV] = {ASDIVL, ASUDIVL},
     43 	[OSHL] = {ASSHLL, ASSHLL},
     44 	[OSHR] = {ASSHRL, ASUSHRL},
     45 	[OLT] = {ASLTL, ASULTL},
     46 	[OGT] = {ASGTL, ASUGTL},
     47 	[OLE] = {ASLEL, ASULEL},
     48 	[OGE] = {ASGEL, ASUGEL},
     49 	[OEQ] = {ASEQL, ASEQL},
     50 	[ONE] = {ASNEL, ASNEL},
     51 	[OBAND] = {ASBANDL, ASBANDL},
     52 	[OBOR] = {ASBORL, ASBORL},
     53 	[OBXOR] = {ASBXORL, ASBXORL},
     54 	[OSNEG] = {ASNEGL, ASNEGL},
     55 };
     56 
     57 static unsigned char opasms[][2] = {
     58 	[OADD] = {ASADDS, ASADDS},
     59 	[OSUB] = {ASSUBS, ASSUBS},
     60 	[OMUL] = {ASMULS, ASMULS},
     61 	[ODIV] = {ASDIVS, ASDIVS},
     62 	[OLT] = {ASLTS, ASLTS},
     63 	[OGT] = {ASGTS, ASGTS},
     64 	[OLE] = {ASLES, ASLES},
     65 	[OGE] = {ASGES, ASGES},
     66 	[OEQ] = {ASEQS, ASEQS},
     67 	[ONE] = {ASNES, ASNES},
     68 	[OSNEG] = {ASNEGS, ASNEGS},
     69 };
     70 
     71 static unsigned char opasmd[][2] = {
     72 	[OADD] = {ASADDD, ASADDD},
     73 	[OSUB] = {ASSUBD, ASSUBD},
     74 	[OMUL] = {ASMULD, ASMULD},
     75 	[ODIV] = {ASDIVD, ASDIVD},
     76 	[OLT] = {ASLTD, ASLTD},
     77 	[OGT] = {ASGTD, ASGTD},
     78 	[OLE] = {ASLED, ASLED},
     79 	[OGE] = {ASGED, ASGED},
     80 	[OEQ] = {ASEQD, ASEQD},
     81 	[ONE] = {ASNED, ASNED},
     82 	[OSNEG] = {ASNEGD, ASNEGD},
     83 };
     84 
     85 static unsigned char (*opbin[][2])[2] = {
     86 	{opasmw, opasml},
     87 	{opasms, opasmd},
     88 };
     89 
     90 static unsigned char i2i_conv[4][4][2] = {
     91 	[I1BYTES] = {
     92 		[I4BYTES] = {ASEXTBW, ASUEXTBW},
     93 		[I8BYTES] = {ASEXTBL, ASUEXTBL},
     94 	},
     95 	[I2BYTES] = {
     96 		[I4BYTES] = {ASEXTHW, ASUEXTHW},
     97 		[I8BYTES] = {ASEXTHL, ASUEXTHL},
     98 	},
     99 	[I4BYTES] = {
    100 		[I8BYTES] = {ASEXTWL, ASUEXTWL},
    101 	}
    102 };
    103 
    104 static unsigned char f2i_conv[4][4][2] = {
    105 	[I4BYTES] = {
    106 		[I4BYTES] = {ASSTOW, ASSTOUW},
    107 		[I8BYTES] = {ASSTOL, ASDTOUL},
    108 	},
    109 	[I8BYTES] = {
    110 		[I4BYTES] = {ASDTOW, ASDTOUW},
    111 		[I8BYTES] = {ASDTOL, ASDTOUL},
    112 	}
    113 };
    114 
    115 static unsigned char i2f_conv[4][4][2] = {
    116 	[I4BYTES] = {
    117 		[I4BYTES] = {ASSWTOS, ASUWTOS},
    118 		[I8BYTES] = {ASSWTOD, ASUWTOD},
    119 	},
    120 	[I8BYTES] = {
    121 		[I4BYTES] = {ASSLTOS, ASULTOS},
    122 		[I8BYTES] = {ASSLTOD, ASULTOD},
    123 	}
    124 };
    125 
    126 /*
    127  * This is strongly influenced by
    128  * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps)
    129  * calculate addresability as follows
    130  *     AUTO => 11          value+fp
    131  *     REG => 11           reg
    132  *     STATIC => 11        (value)
    133  *     CONST => 11         $value
    134  * These values of addressability are not used in the code generation.
    135  * They are only used to calculate the Sethi-Ullman numbers. Since
    136  * QBE is AMD64 targered we could do a better job there, and try to
    137  * detect some of the complex addressing modes of these processors.
    138  */
    139 Node *
    140 tsethi(Node *np)
    141 {
    142 	int op;
    143 	Node *l, *r;
    144 
    145 	l = np->left;
    146 	r = np->right;
    147 
    148 	switch (np->op) {
    149 	case OAUTO:
    150 	case OREG:
    151 	case OMEM:
    152 	case OCONST:
    153 		np->address = 11;
    154 		break;
    155 	case OASSIG:
    156 		assert(l->op != OCAST);
    157 		goto binary;
    158 	case OCPL:
    159 		assert(np->type.flags & INTF);
    160 		np->op = OBXOR;
    161 		r = constnode(NULL, ~(TUINT) 0, &np->type);
    162 		goto binary;
    163 	case OEFUN:
    164 		/*
    165 		 * In QBE we need at the end of a basic block
    166 		 * a jump, so we have to ensure that the last
    167 		 * statement of the function is a ret, a jmp
    168 		 * or a branch.
    169 		 */
    170 
    171 		op = np->prev->op;
    172 		if (op == ONOP || op == OBRANCH || (op != ORET && op != OJMP))
    173 			addstmt(node(ORET));
    174 		break;
    175 	default:
    176 	binary:
    177 		l = sethi(l);
    178 		r = sethi(r);
    179 		break;
    180 	}
    181 	np->left = l;
    182 	np->right = r;
    183 
    184 	return np;
    185 }
    186 
    187 static int
    188 bytes2idx(int nbytes)
    189 {
    190 	if (nbytes== 1)
    191 		return I1BYTES;
    192 	else if (nbytes == 2)
    193 		return I2BYTES;
    194 	else if (nbytes == 4)
    195 		return I4BYTES;
    196 	else if (nbytes == 8)
    197 		return I8BYTES;
    198 	else
    199 		abort();
    200 }
    201 
    202 static Node *
    203 load(Type *tp, Node *np)
    204 {
    205 	int op;
    206 	Node *new;
    207 	int flags = tp->flags;
    208 
    209 	if (flags & (AGGRF|FUNF|ARRF|PTRF))
    210 		return np;
    211 
    212 	switch (tp->size) {
    213 	case 1:
    214 		op = ASLDSB;
    215 		break;
    216 	case 2:
    217 		op = ASLDSH;
    218 		break;
    219 	case 4:
    220 		op = (flags & FLOATF) ? ASLDS : ASLDSW;
    221 		break;
    222 	case 8:
    223 		op = (flags & FLOATF) ? ASLDD : ASLDL;
    224 		break;
    225 	default:
    226 		abort();
    227 	}
    228 	/*
    229 	 * unsigned version of operations are always +1 the
    230 	 * signed version
    231 	 */
    232 	if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8)
    233 		++op;
    234 
    235 	new = tmpnode(tp, NULL);
    236 	code(op, new, np, NULL);
    237 
    238 	return new;
    239 }
    240 
    241 static Node *rhs(Node *np);
    242 
    243 static Node *
    244 cast(Type *td, Node *np)
    245 {
    246 	Type *ts;
    247 	Node *tmp;
    248 	int op, d_isint, s_isint, sidx, didx, sign;
    249 
    250 	ts = &np->type;
    251 	d_isint = (td->flags & INTF) != 0;
    252 	s_isint = (ts->flags & INTF) != 0;
    253 
    254 	sidx = bytes2idx(ts->size);
    255 	didx = bytes2idx(td->size);
    256 
    257 	sign = (ts->flags & SIGNF) == 0;
    258 
    259 	if (d_isint && s_isint) {
    260 		/* conversion from int to int */
    261 		if (didx < I4BYTES)
    262 			didx = bytes2idx(4);
    263 
    264 		if (didx <= sidx) {
    265 			np->type = *td;
    266 			return np;
    267 		}
    268 
    269 		op = i2i_conv[sidx][didx][sign];
    270 	} else if (d_isint) {
    271 		/* conversion from float to int */
    272 		if (didx < I4BYTES)
    273 			didx = bytes2idx(4);
    274 
    275 		op = f2i_conv[sidx][didx][sign];
    276 	} else if (s_isint) {
    277 		/* conversion from int to float */
    278 		if (sidx == I1BYTES || sidx == I2BYTES) {
    279 			ts = (ts->flags&SIGNF) ? &int32type : &uint32type;
    280 			np = cast(ts, np);
    281 		}
    282 		op = i2f_conv[sidx][didx][sign];
    283 	} else {
    284 		/* conversion from float to float */
    285 		op = (didx == I4BYTES) ? ASEXTS : ASTRUNCD;
    286 	}
    287 
    288 	assert(op != 0);
    289 	tmp = tmpnode(td, NULL);
    290 	code(op, tmp, np, NULL);
    291 
    292 	return tmp;
    293 }
    294 
    295 static Node *
    296 call(Node *np, Node *fun)
    297 {
    298 	int n, op;
    299 	Type *tp;
    300 	Node **q, *tmp, *p, *pars[NR_FUNPARAM];
    301 
    302 	for (n = 0, p = np->right; p; p = p->right)
    303 		pars[n++] = rhs(p->left);
    304 
    305 	tp = &np->type;
    306 	tmp = tmpnode(tp, NULL);
    307 	code(ASCALL, tmp, fun, NULL);
    308 
    309 	for (q = pars; q < &pars[n]; ++q) {
    310 		op = (q == &pars[n-1]) ? ASPARE : ASPAR;
    311 		code(op, NULL, *q, tmpnode(&(*q)->type, NULL));
    312 	}
    313 	code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL);
    314 
    315 	return tmp;
    316 }
    317 
    318 static Node *
    319 copy(Type *tp, Node *to, Node *from)
    320 {
    321 	int op;
    322 
    323 	switch (tp->size) {
    324 	case 0:
    325 		return from;
    326 	case 1:
    327 		op = ASCOPYB;
    328 		break;
    329 	case 2:
    330 		op = ASCOPYH;
    331 		break;
    332 	case 4:
    333 		op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW;
    334 		break;
    335 	case 8:
    336 		op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL;
    337 		break;
    338 	default:
    339 		abort();
    340 	}
    341 	code(op, to, from, NULL);
    342 	return from;
    343 }
    344 
    345 static Node *
    346 field(Node *np, int islhs)
    347 {
    348 	Node *tmp, *addr;
    349 	TUINT offset = np->right->u.sym->u.off;
    350 
    351 	addr = rhs(np->left);
    352 	tmp = node(OADD);
    353 	tmp->type = ptrtype;
    354 	tmp->left = addr;
    355 	tmp->right = constnode(NULL, offset, &ptrtype);
    356 	addr = rhs(tmp);
    357 
    358 	if (!islhs)
    359 		addr = load(&np->type, addr);
    360 	return addr;
    361 }
    362 
    363 static Node *
    364 lhs(Node *np)
    365 {
    366 	switch (np->op) {
    367 	case OREG:
    368 	case OMEM:
    369 	case OAUTO:
    370 		return np;
    371 	case OPTR:
    372 		return rhs(np->left);
    373 	case OFIELD:
    374 		return field(np, 1);
    375 	default:
    376 		abort();
    377 	}
    378 }
    379 
    380 static Node *
    381 function(void)
    382 {
    383 	Node aux;
    384 	Symbol *p;
    385 
    386 	/* allocate stack space for parameters */
    387 	for (p = locals; p; p = p->next) {
    388 		if ((p->type.flags & PARF) == 0)
    389 			continue;
    390 		if ((p->type.flags & AGGRF) != 0)
    391 			continue;
    392 		code(ASALLOC, label2node(&aux, p), NULL, NULL);
    393 	}
    394 
    395 	/* allocate stack space for local variables) */
    396 	for (p = locals; p; p = p->next) {
    397 		if ((p->type.flags & PARF) != 0)
    398 			continue;
    399 		if (p->kind != SAUTO || p->id == TMPSYM)
    400 			continue;
    401 		code(ASALLOC, label2node(&aux, p), NULL, NULL);
    402 	}
    403 
    404 	/* store formal parameters in parameters */
    405 	for (p = locals; p; p = p->next) {
    406 		if ((p->type.flags & PARF) == 0)
    407 			continue;
    408 		if ((p->type.flags & AGGRF) != 0)
    409 			continue;
    410 		if ((p->type.flags & (ARRF|AGGRF)) == 0)
    411 			code(ASFORM, label2node(&aux, p), NULL, NULL);
    412 	}
    413 	return NULL;
    414 }
    415 
    416 static int
    417 assignop(Type *tp)
    418 {
    419 	int flags = tp->flags;
    420 
    421 	if (flags & (AGGRF|FUNF|ARRF))
    422 		return ASSTM;
    423 
    424 	switch (tp->size) {
    425 	case 1:
    426 		return ASSTB;
    427 	case 2:
    428 		return ASSTH;
    429 	case 4:
    430 		return (tp->flags & FLOATF) ? ASSTS : ASSTW;
    431 	case 8:
    432 		return (tp->flags & FLOATF) ? ASSTD : ASSTL;
    433 	default:
    434 		abort();
    435 	}
    436 }
    437 
    438 static void
    439 rhs_rhs(Node **lpp, Node **rpp)
    440 {
    441 	Node *l = *lpp, *r = *rpp;
    442 
    443 	if (l->complex >= r->complex) {
    444 		l = rhs(l);
    445 		r = rhs(r);
    446 	} else {
    447 		r = rhs(r);
    448 		l = rhs(l);
    449 	}
    450 
    451 	*lpp = l, *rpp = r;
    452 }
    453 
    454 static void
    455 lhs_rhs(Node **lpp, Node **rpp)
    456 {
    457 	Node *l = *lpp, *r = *rpp;
    458 
    459 	if (l->complex >= r->complex) {
    460 		l = lhs(l);
    461 		r = rhs(r);
    462 	} else {
    463 		r = rhs(r);
    464 		l = lhs(l);
    465 	}
    466 
    467 	*lpp = l, *rpp = r;
    468 }
    469 
    470 static Node *
    471 assign(Node *np)
    472 {
    473 	Node *ret, aux;
    474 	Node *l = np->left, *r = np->right;
    475 	int op;
    476 
    477 	switch (np->u.subop) {
    478 	case OINC:
    479 		op = OADD;
    480 		goto post_oper;
    481 	case ODEC:
    482 		op = OSUB;
    483 	post_oper:
    484 		lhs_rhs(&l, &r);
    485 		ret = load(&l->type, l);
    486 		aux.op = op;
    487 		aux.left = ret;
    488 		aux.right = r;
    489 		aux.type = np->type;
    490 		r = rhs(sethi(&aux));
    491 		break;
    492 	default:
    493 		/* assign abbreviation */
    494 		assert(l->type.size == r->type.size);
    495 		if (r->type.size < 4) {
    496 			lhs_rhs(&l, &r);
    497 			aux.op = np->u.subop;
    498 			aux.left = load(&r->type, l);
    499 			aux.right = r;
    500 			aux.type = int32type;
    501 			aux.address = np->address;
    502 			ret = r = sethi(rhs(&aux));
    503 			break;
    504 		}
    505 
    506 		aux.op = np->u.subop;
    507 		aux.left = l;
    508 		aux.right = r;
    509 		aux.type = np->type;
    510 		aux.address = np->address;
    511 		r = sethi(&aux);
    512 	case 0:
    513 		if (l->op == OTMP) {
    514 			r = rhs(r);
    515 			copy(&np->type, l, r);
    516 			return r;
    517 		}
    518 
    519 		lhs_rhs(&l, &r);
    520 		ret = r;
    521 		break;
    522 	}
    523 
    524 	code(assignop(&np->type), l, r, NULL);
    525 	return ret;
    526 }
    527 
    528 static Node *
    529 rhs(Node *np)
    530 {
    531 	Node *tmp, aux1, aux2;
    532 	Node *phi, *l = np->left, *r = np->right;
    533 	Type *tp;
    534 	int sign, size, isfloat, op;
    535 	Symbol *true, *false;
    536 
    537 	tp = &np->type;
    538 
    539 	switch (np->op) {
    540 	case OTMP:
    541 	case OCONST:
    542 		return np;
    543 	case OMEM:
    544 	case OREG:
    545 	case OAUTO:
    546 		return load(tp, np);
    547 	case OMOD:
    548 	case OSHL:
    549 	case OBAND:
    550 	case OBOR:
    551 	case OBXOR:
    552 	case OSHR:
    553 		assert(tp->flags & INTF);
    554 	case ODIV:
    555 	case OLT:
    556 	case OGT:
    557 	case OLE:
    558 	case OGE:
    559 	case OADD:
    560 	case OSUB:
    561 	case OMUL:
    562 	case OEQ:
    563 	case ONE:
    564 		assert(tp->size == 4 || tp->size == 8);
    565 
    566 		sign = (tp->flags & SIGNF) == 0;
    567 		size = tp->size == 8;
    568 		isfloat = (tp->flags & FLOATF) != 0;
    569 		op = opbin[isfloat][size][np->op][sign];
    570 		rhs_rhs(&l, &r);
    571 		tmp = tmpnode(tp, NULL);
    572 		code(op, tmp, l, r);
    573 		return tmp;
    574 	case OCALL:
    575 	case OCALLE:
    576 		if (l->op == OPTR)
    577 			l = rhs(l);
    578 		return call(np, l);
    579 	case OCAST:
    580 		return cast(tp, rhs(l));
    581 	case OASSIG:
    582 		return assign(np);
    583 	case OSNEG:
    584 		sign = (tp->flags & SIGNF) == 0;
    585 		size = tp->size == 8;
    586 		isfloat = (tp->flags & FLOATF) != 0;
    587 		op = opbin[isfloat][size][np->op][sign];
    588 		tmp = tmpnode(tp, NULL);
    589 		code(op, tmp, rhs(l), NULL);
    590 		return tmp;
    591 	case OPTR:
    592 		return load(tp, rhs(l));
    593 	case OADDR:
    594 		l = lhs(l);
    595 		l->type = *tp;
    596 		l->type.flags |= PTRF;
    597 		return l;
    598 	case OFIELD:
    599 		return field(np, 0);
    600 	case OBUILTIN:
    601 		switch (np->u.subop) {
    602 		case BVA_START:
    603 			l = rhs(l);
    604 			code(ASVSTAR, NULL, l, NULL);
    605 		case BVA_END:
    606 			return NULL;
    607 		case BVA_ARG:
    608 			l = rhs(l);
    609 			tmp = tmpnode(tp, NULL);
    610 			code(ASVARG, tmp, l, NULL);
    611 			return tmp;
    612 		default:
    613 			abort();
    614 		}
    615 	default:
    616 		abort();
    617 	}
    618 	abort();
    619 }
    620 
    621 static Node *
    622 cgen(Node *np)
    623 {
    624 	Node true, false, *p, *next;
    625 
    626 	setlabel(np->label);
    627 	switch (np->op) {
    628 	case OBFUN:
    629 		return function();
    630 	case ONOP:
    631 	case OBLOOP:
    632 	case OELOOP:
    633 	case OEFUN:
    634 		break;
    635 	case OJMP:
    636 		label2node(&true, np->u.sym);
    637 		code(ASJMP, NULL, &true, NULL);
    638 		break;
    639 	case OBRANCH:
    640 		/*
    641 		 * QBE does not accept labels at the end of a function
    642 		 * (ONOP is used for labels) so we have to add a ret
    643 		 * there, and in the case of branches we need a label
    644 		 * for the next statement.
    645 		 */
    646 		next = np->next;
    647 		if (!next->label)
    648 			labelstmt(next, NULL);
    649 
    650 		label2node(&true, np->u.sym);
    651 		label2node(&false, np->next->label);
    652 		code(ASBRANCH, rhs(np->left), &true, &false);
    653 		break;
    654 	case ORET:
    655 		p = (np->left) ? rhs(np->left) : NULL;
    656 		code(ASRET, NULL, p, NULL);
    657 		break;
    658 	default:
    659 		rhs(np);
    660 		break;
    661 	}
    662 	return NULL;
    663 }
    664 
    665 void
    666 genasm(void)
    667 {
    668 	apply(cgen);
    669 }