scc

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

code.c (15296B)


      1 #include <stdio.h>
      2 #include <stdlib.h>
      3 #include <string.h>
      4 
      5 #include <scc/cstd.h>
      6 #include <scc/scc.h>
      7 
      8 #include "arch.h"
      9 #include "../cc2.h"
     10 
     11 #define ADDR_LEN (INTIDENTSIZ+64)
     12 
     13 static void binary(void), unary(void), store(void), jmp(void), ret(void),
     14             branch(void), call(void), ecall(void), param(void),
     15             asalloc(void), form2local(void), blit(void), vastart(void),
     16             vaarg(void);
     17 
     18 static struct opdata {
     19 	void (*fun)(void);
     20 	char *txt;
     21 	char letter;
     22 } optbl [] = {
     23 	[ASLDSB]  =  {.fun = unary,  .txt = "loadsb", .letter = 'w'},
     24 	[ASLDUB]  =  {.fun = unary,  .txt = "loadub", .letter = 'w'},
     25 	[ASLDSH]  =  {.fun = unary,  .txt = "loadsh", .letter = 'w'},
     26 	[ASLDUH]  =  {.fun = unary,  .txt = "loaduh", .letter = 'w'},
     27 	[ASLDSW]  =  {.fun = unary,  .txt = "loadsw", .letter = 'w'},
     28 	[ASLDUW]  =  {.fun = unary,  .txt = "loaduw", .letter = 'w'},
     29 	[ASLDL]   =  {.fun = unary,  .txt = "loadl", .letter = 'l'},
     30 	[ASLDS]   =  {.fun = unary,  .txt = "loads", .letter = 's'},
     31 	[ASLDD]   =  {.fun = unary,  .txt = "loadd", .letter = 'd'},
     32 
     33 	[ASCOPYB] =  {.fun = unary,  .txt = "copy", .letter = 'b'},
     34 	[ASCOPYH] =  {.fun = unary,  .txt = "copy", .letter = 'h'},
     35 	[ASCOPYW] =  {.fun = unary,  .txt = "copy", .letter = 'w'},
     36 	[ASCOPYL] =  {.fun = unary,  .txt = "copy", .letter = 'l'},
     37 	[ASCOPYS] =  {.fun = unary,  .txt = "copy", .letter = 's'},
     38 	[ASCOPYD] =  {.fun = unary,  .txt = "copy", .letter = 'd'},
     39 
     40 	[ASSTB]   =  {.fun = store,  .txt = "store", .letter = 'b'},
     41 	[ASSTH]   =  {.fun = store,  .txt = "store", .letter = 'h'},
     42 	[ASSTW]   =  {.fun = store,  .txt = "store", .letter = 'w'},
     43 	[ASSTL]   =  {.fun = store,  .txt = "store", .letter = 'l'},
     44 	[ASSTM]   =  {.fun = blit},
     45 	[ASSTS]   =  {.fun = store,  .txt = "store", .letter = 's'},
     46 	[ASSTD]   =  {.fun = store,  .txt = "store", .letter = 'd'},
     47 
     48 	[ASADDW]  =  {.fun = binary, .txt = "add", .letter = 'w'},
     49 	[ASSUBW]  =  {.fun = binary, .txt = "sub", .letter = 'w'},
     50 	[ASMULW]  =  {.fun = binary, .txt = "mul", .letter = 'w'},
     51 	[ASMODW]  =  {.fun = binary, .txt = "rem", .letter = 'w'},
     52 	[ASUMODW] =  {.fun = binary, .txt = "urem", .letter = 'w'},
     53 	[ASDIVW]  =  {.fun = binary, .txt = "div", .letter = 'w'},
     54 	[ASUDIVW] =  {.fun = binary, .txt = "udiv", .letter = 'w'},
     55 	[ASSHLW]  =  {.fun = binary, .txt = "shl", .letter = 'w'},
     56 	[ASSHRW]  =  {.fun = binary, .txt = "sar", .letter = 'w'},
     57 	[ASUSHRW] =  {.fun = binary, .txt = "shr", .letter = 'w'},
     58 	[ASLTW]   =  {.fun = binary, .txt = "csltw", .letter = 'w'},
     59 	[ASULTW]  =  {.fun = binary, .txt = "cultw", .letter = 'w'},
     60 	[ASGTW]   =  {.fun = binary, .txt = "csgtw", .letter = 'w'},
     61 	[ASUGTW]  =  {.fun = binary, .txt = "cugtw", .letter = 'w'},
     62 	[ASLEW]   =  {.fun = binary, .txt = "cslew", .letter = 'w'},
     63 	[ASULEW]  =  {.fun = binary, .txt = "culew", .letter = 'w'},
     64 	[ASGEW]   =  {.fun = binary, .txt = "csgew", .letter = 'w'},
     65 	[ASUGEW]  =  {.fun = binary, .txt = "cugew", .letter = 'w'},
     66 	[ASEQW]   =  {.fun = binary, .txt = "ceqw", .letter = 'w'},
     67 	[ASNEW]   =  {.fun = binary, .txt = "cnew", .letter = 'w'},
     68 	[ASBANDW] =  {.fun = binary, .txt = "and", .letter = 'w'},
     69 	[ASBORW]  =  {.fun = binary, .txt = "or", .letter = 'w'},
     70 	[ASBXORW] =  {.fun = binary, .txt = "xor", .letter = 'w'},
     71 
     72 	[ASADDL]  =  {.fun = binary, .txt = "add", .letter = 'l'},
     73 	[ASSUBL]  =  {.fun = binary, .txt = "sub", .letter = 'l'},
     74 	[ASMULL]  =  {.fun = binary, .txt = "mul", .letter = 'l'},
     75 	[ASMODL]  =  {.fun = binary, .txt = "rem", .letter = 'l'},
     76 	[ASUMODL] =  {.fun = binary, .txt = "urem", .letter = 'l'},
     77 	[ASDIVL]  =  {.fun = binary, .txt = "div", .letter = 'l'},
     78 	[ASUDIVL] =  {.fun = binary, .txt = "udiv", .letter = 'l'},
     79 	[ASSHLL]  =  {.fun = binary, .txt = "shl", .letter = 'l'},
     80 	[ASSHRL]  =  {.fun = binary, .txt = "sar", .letter = 'l'},
     81 	[ASUSHRL] =  {.fun = binary, .txt = "shr", .letter = 'l'},
     82 	[ASLTL]   =  {.fun = binary, .txt = "csltl", .letter = 'w'},
     83 	[ASULTL]  =  {.fun = binary, .txt = "cultl", .letter = 'w'},
     84 	[ASGTL]   =  {.fun = binary, .txt = "csgtl", .letter = 'w'},
     85 	[ASUGTL]  =  {.fun = binary, .txt = "cugtl", .letter = 'w'},
     86 	[ASLEL]   =  {.fun = binary, .txt = "cslel", .letter = 'w'},
     87 	[ASULEL]  =  {.fun = binary, .txt = "culel", .letter = 'w'},
     88 	[ASGEL]   =  {.fun = binary, .txt = "csgel", .letter = 'w'},
     89 	[ASUGEL]  =  {.fun = binary, .txt = "cugel", .letter = 'w'},
     90 	[ASEQL]   =  {.fun = binary, .txt = "ceql", .letter = 'w'},
     91 	[ASNEL]   =  {.fun = binary, .txt = "cnel", .letter = 'w'},
     92 	[ASBANDL] =  {.fun = binary, .txt = "and", .letter = 'l'},
     93 	[ASBORL]  =  {.fun = binary, .txt = "or", .letter = 'l'},
     94 	[ASBXORL] =  {.fun = binary, .txt = "xor", .letter = 'l'},
     95 
     96 	[ASADDS]  =  {.fun = binary, .txt = "add", .letter = 's'},
     97 	[ASSUBS]  =  {.fun = binary, .txt = "sub", .letter = 's'},
     98 	[ASMULS]  =  {.fun = binary, .txt = "mul", .letter = 's'},
     99 	[ASDIVS]  =  {.fun = binary, .txt = "div", .letter = 's'},
    100 	[ASLTS]   =  {.fun = binary, .txt = "clts", .letter = 'w'},
    101 	[ASGTS]   =  {.fun = binary, .txt = "cgts", .letter = 'w'},
    102 	[ASLES]   =  {.fun = binary, .txt = "cles", .letter = 'w'},
    103 	[ASGES]   =  {.fun = binary, .txt = "cges", .letter = 'w'},
    104 	[ASEQS]   =  {.fun = binary, .txt = "ceqs", .letter = 'w'},
    105 	[ASNES]   =  {.fun = binary, .txt = "cnes", .letter = 'w'},
    106 
    107 	[ASADDD]  =  {.fun = binary, .txt = "add", .letter = 'd'},
    108 	[ASSUBD]  =  {.fun = binary, .txt = "sub", .letter = 'd'},
    109 	[ASMULD]  =  {.fun = binary, .txt = "mul", .letter = 'd'},
    110 	[ASDIVD]  =  {.fun = binary, .txt = "div", .letter = 'd'},
    111 	[ASLTD]   =  {.fun = binary, .txt = "cltd", .letter = 'w'},
    112 	[ASGTD]   =  {.fun = binary, .txt = "cgtd", .letter = 'w'},
    113 	[ASLED]   =  {.fun = binary, .txt = "cled", .letter = 'w'},
    114 	[ASGED]   =  {.fun = binary, .txt = "cged", .letter = 'w'},
    115 	[ASEQD]   =  {.fun = binary, .txt = "ceqd", .letter = 'w'},
    116 	[ASNED]   =  {.fun = binary, .txt = "cned", .letter = 'w'},
    117 
    118 	[ASEXTBW] =  {.fun = unary, .txt = "extsb", .letter = 'w'},
    119 	[ASUEXTBW]=  {.fun = unary, .txt = "extub", .letter = 'w'},
    120 	[ASEXTBL] =  {.fun = unary, .txt = "extsb", .letter = 'l'},
    121 	[ASUEXTBL]=  {.fun = unary, .txt = "extub", .letter = 'l'},
    122 	[ASEXTHW] =  {.fun = unary, .txt = "extsh", .letter = 'w'},
    123 	[ASUEXTHW]=  {.fun = unary, .txt = "extuh", .letter = 'w'},
    124 	[ASEXTHL] =  {.fun = unary, .txt = "extsh", .letter = 'l'},
    125 	[ASUEXTHL]=  {.fun = unary, .txt = "extuh", .letter = 'l'},
    126 	[ASEXTWL] =  {.fun = unary, .txt = "extsw", .letter = 'l'},
    127 	[ASUEXTWL]=  {.fun = unary, .txt = "extuw", .letter = 'l'},
    128 
    129 	[ASSTOL] = {.fun = unary, .txt = "stosi", .letter = 'l'},
    130 	[ASSTOUL] = {.fun = unary, .txt = "stoui", .letter = 'l'},
    131 	[ASSTOW] = {.fun = unary, .txt = "stosi", .letter = 'w'},
    132 	[ASSTOUW] = {.fun = unary, .txt = "stoui", .letter = 'w'},
    133 	[ASDTOL] = {.fun = unary, .txt = "dtosi", .letter = 'l'},
    134 	[ASDTOUL] = {.fun = unary, .txt = "dtoui", .letter = 'l'},
    135 	[ASDTOW] = {.fun = unary, .txt = "dtosi", .letter = 'w'},
    136 	[ASDTOUW] = {.fun = unary, .txt = "dtoui", .letter = 'w'},
    137 
    138 	[ASSWTOD] = {.fun = unary, .txt = "swtof", .letter = 'd'},
    139 	[ASUWTOD] = {.fun = unary, .txt = "uwtof", .letter = 'd'},
    140 	[ASSWTOS] = {.fun = unary, .txt = "swtof", .letter = 's'},
    141 	[ASUWTOS] = {.fun = unary, .txt = "uwtof", .letter = 's'},
    142 	[ASSLTOD] = {.fun = unary, .txt = "sltof", .letter = 'd'},
    143 	[ASULTOD] = {.fun = unary, .txt = "ultof", .letter = 'd'},
    144 	[ASSLTOS] = {.fun = unary, .txt = "sltof", .letter = 's'},
    145 	[ASULTOS] = {.fun = unary, .txt = "ultof", .letter = 's'},
    146 
    147 	[ASEXTS] = {.fun = unary, .txt = "exts", .letter = 'd'},
    148 	[ASTRUNCD] = {.fun = unary, .txt = "truncd", .letter = 's'},
    149 
    150 	[ASBRANCH] = {.fun = branch},
    151 	[ASJMP]  = {.fun = jmp},
    152 	[ASRET]  = {.fun = ret},
    153 	[ASCALL] = {.fun = call},
    154 	[ASCALLE] = {.fun = ecall, .txt = ")"},
    155 	[ASCALLEX] = {.fun = ecall, .txt = ", ...)"},
    156 	[ASPAR] = {.fun = param, .txt = "%s %s, "},
    157 	[ASPARE] = {.fun = param, .txt = "%s %s"},
    158 	[ASALLOC] = {.fun = asalloc},
    159 	[ASFORM] = {.fun = form2local},
    160 
    161 	[ASVSTAR] = {.fun = vastart},
    162 	[ASVARG] = {.fun = vaarg},
    163 };
    164 
    165 static char buff[ADDR_LEN];
    166 /*
    167  * : is for user-defined Aggregate Types
    168  * $ is for globals (represented by a pointer)
    169  * % is for function-scope temporaries
    170  * @ is for block labels
    171  */
    172 static char
    173 sigil(Symbol *sym)
    174 {
    175 	switch (sym->kind) {
    176 	case SEXTRN:
    177 	case SGLOB:
    178 	case SPRIV:
    179 	case SLOCAL:
    180 		return '$';
    181 	case SAUTO:
    182 	case STMP:
    183 		return '%';
    184 	case SLABEL:
    185 		return '@';
    186 	default:
    187 		abort();
    188 	}
    189 }
    190 
    191 static char *
    192 symname(Symbol *sym)
    193 {
    194 	char c = sigil(sym);
    195 
    196 	if (sym->name) {
    197 		switch (sym->kind) {
    198 		case SEXTRN:
    199 		case SGLOB:
    200 			sprintf(buff, "%c%s", c, sym->name);
    201 			return buff;
    202 		case SLOCAL:
    203 		case SPRIV:
    204 		case SAUTO:
    205 			sprintf(buff, "%c%s.L%u", c, sym->name, sym->id);
    206 			return buff;
    207 		default:
    208 			abort();
    209 		}
    210 	}
    211 	sprintf(buff, "%c.L%u", c, sym->numid);
    212 
    213 	return buff;
    214 }
    215 
    216 static void
    217 emitconst(Node *np)
    218 {
    219 	switch (np->type.size) {
    220 	case 1:
    221 		printf("%d", (int) np->u.i & 0xFF);
    222 		break;
    223 	case 2:
    224 		printf("%d", (int) np->u.i & 0xFFFF);
    225 		break;
    226 	case 4:
    227 		printf("%ld", (long) np->u.i & 0xFFFFFFFF);
    228 		break;
    229         case 8:
    230                 printf("%lld", (long long) np->u.i);
    231                 break;
    232 	default:
    233 		abort();
    234 	}
    235 }
    236 
    237 static void
    238 emittree(Node *np)
    239 {
    240 	if (!np)
    241 		return;
    242 
    243 	switch (np->op) {
    244 	case OSTRING:
    245 		pprint(np->u.s);
    246 		free(np->u.s);
    247 		np->u.s = NULL;
    248 		break;
    249 	case OCONST:
    250 		emitconst(np);
    251 		break;
    252 	case OADDR:
    253 		emittree(np->left);
    254 		break;
    255 	case OMEM:
    256 		fputs(symname(np->u.sym), stdout);
    257 		break;
    258 	default:
    259 		emittree(np->left);
    260 		printf(" %c ", np->op);
    261 		emittree(np->right);
    262 		break;
    263 	}
    264 }
    265 
    266 static char *
    267 size2asm(Type *tp)
    268 {
    269         static char spec[ADDR_LEN];
    270 
    271 	if (tp->flags & STRF) {
    272 		return "b";
    273 	} else if (tp->flags & INTF) {
    274 		switch (tp->size) {
    275 		case 1:
    276 			return "b";
    277 		case 2:
    278 			return "h";
    279 		case 4:
    280 			return "w";
    281 		case 8:
    282 			return "l";
    283 		}
    284 	} else if (tp->flags & FLOATF) {
    285 		if (tp->size == 4)
    286 			return "s";
    287 		else if (tp->size == 8)
    288 			return "d";
    289 	}
    290 
    291 	abort();
    292 }
    293 
    294 void
    295 defglobal(Symbol *sym)
    296 {
    297 	Type *tp = &sym->type;
    298 
    299 	if (sym->kind == SEXTRN)
    300 		return;
    301 	if (sym->kind == SGLOB)
    302 		fputs("export ", stdout);
    303 	if ((tp->flags & INITF) == 0)
    304 		fputs("common ", stdout);
    305 
    306 	printf("data %s = align %d {\n",
    307 	       symname(sym),
    308 	       tp->align);
    309 	if ((tp->flags & INITF) == 0)
    310 		printf("\tz\t%lu\n}\n", tp->size);
    311 }
    312 
    313 void
    314 defpar(Symbol *sym)
    315 {
    316 	if (sym->kind == SREG)
    317 		sym->kind = SAUTO;
    318 	sym->type.flags |= PARF;
    319 }
    320 
    321 void
    322 defvar(Symbol *sym)
    323 {
    324 	if (sym->kind == SREG)
    325 		sym->kind = SAUTO;
    326 }
    327 
    328 void
    329 data(Node *np)
    330 {
    331 	printf("\t%s\t", size2asm(&np->type));
    332 	emittree(np);
    333 	putchar(',');
    334 	putchar('\n');
    335 }
    336 
    337 static char *
    338 size2stack(Type *tp)
    339 {
    340 	static char spec[ADDR_LEN];
    341 
    342 	if (tp->flags & INTF) {
    343 		switch (tp->size) {
    344 		case 1:
    345 		case 2:
    346 		case 4:
    347 			return "w";
    348 		case 8:
    349 			return "l";
    350 		}
    351 	} else if (tp->flags & FLOATF) {
    352 		if (tp->size == 4)
    353 			return "s";
    354 		else if (tp->size == 8)
    355 			return "d";
    356 	} else if (tp->flags & (ARRF|AGGRF)) {
    357 		sprintf(spec, ":.%u", tp->id);
    358 		return spec;
    359 	} else if (tp->size == 0) {
    360 		return "w";
    361 	}
    362 	abort();
    363 }
    364 
    365 void
    366 deftype(Type *tp)
    367 {
    368 	printf("type :.%u = align %d { %lu }\n",
    369 	       tp->id, tp->align, tp->size);
    370 }
    371 
    372 void
    373 writeout(void)
    374 {
    375 	Symbol *p;
    376 	Type *tp;
    377 	char *sep;
    378 	int haslabel = 0;
    379 
    380 	if (!curfun)
    381 		return;
    382 	if (curfun->kind == SGLOB)
    383 		fputs("export ", stdout);
    384 	printf("function %s %s(", size2stack(&curfun->rtype), symname(curfun));
    385 
    386 	/* declare formal parameters */
    387 	sep = "";
    388 	for (p = locals; p; p = p->next) {
    389 		if ((p->type.flags & PARF) == 0)
    390 			continue;
    391 		printf("%s%s %s%s",
    392 		       sep, size2stack(&p->type),
    393 		       symname(p),
    394 		       (p->type.flags & AGGRF) ? "" : ".val");
    395 		sep = ",";
    396 	}
    397 	printf("%s)\n{\n", (curfun->type.flags&ELLIPS) ? ", ..." : "");
    398 
    399 	/* emit assembler instructions */
    400 	for (pc = prog; pc; pc = pc->next) {
    401 		if (pc->label) {
    402 			haslabel = 1;
    403 			printf("%s\n", symname(pc->label));
    404 		}
    405 		if (pc->op == ASLABEL)
    406 			continue;
    407 		if (pc->flags&BBENTRY && !haslabel)
    408 			printf("%s\n", symname(newlabel()));
    409 		(*optbl[pc->op].fun)();
    410 		if (!pc->label)
    411 			haslabel = 0;
    412 	}
    413 
    414 	puts("}");
    415 }
    416 
    417 static char *
    418 addr2txt(Addr *a)
    419 {
    420 	switch (a->kind) {
    421 	case SCONST:
    422 		sprintf(buff, "%llu", (unsigned long long) a->u.i);
    423 		return buff;
    424 	case SAUTO:
    425 	case SLABEL:
    426 	case STMP:
    427 	case SGLOB:
    428 	case SEXTRN:
    429 	case SPRIV:
    430 	case SLOCAL:
    431 		return symname(a->u.sym);
    432 	default:
    433 		abort();
    434 	}
    435 }
    436 
    437 static void
    438 binary(void)
    439 {
    440 	struct opdata *p = &optbl[pc->op];
    441 	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
    442 
    443 	strcpy(to, addr2txt(&pc->to));
    444 	strcpy(from1, addr2txt(&pc->from1));
    445 	strcpy(from2, addr2txt(&pc->from2));
    446 	printf("\t%s =%c\t%s\t%s,%s\n", to, p->letter, p->txt, from1, from2);
    447 }
    448 
    449 static void
    450 blit(void)
    451 {
    452 	Type *tp = &pc->to.u.sym->type;
    453 	char to[ADDR_LEN], from[ADDR_LEN];
    454 
    455 	strcpy(to, addr2txt(&pc->to));
    456 	strcpy(from, addr2txt(&pc->from1));
    457 	printf("\t\tblit\t%s,%s,%lu\n", from, to, tp->size);
    458 }
    459 
    460 static void
    461 store(void)
    462 {
    463 	struct opdata *p = &optbl[pc->op];
    464 	char to[ADDR_LEN], from[ADDR_LEN];
    465 
    466 	strcpy(to, addr2txt(&pc->to));
    467 	strcpy(from, addr2txt(&pc->from1));
    468 	printf("\t\t%s%c\t%s,%s\n", p->txt, p->letter, from, to);
    469 }
    470 
    471 static void
    472 unary(void)
    473 {
    474 	struct opdata *p = &optbl[pc->op];
    475 	char to[ADDR_LEN], from[ADDR_LEN];
    476 
    477 	strcpy(to, addr2txt(&pc->to));
    478 	strcpy(from, addr2txt(&pc->from1));
    479 	printf("\t%s =%c\t%s\t%s\n", to, p->letter, p->txt, from);
    480 }
    481 
    482 static void
    483 call(void)
    484 {
    485 	char to[ADDR_LEN], from[ADDR_LEN];
    486 	Symbol *sym = pc->to.u.sym;
    487 
    488 	strcpy(to, addr2txt(&pc->to));
    489 	strcpy(from, addr2txt(&pc->from1));
    490 	printf("\t%s =%s\tcall\t%s(",
    491 	       to, size2stack(&sym->type), from);
    492 }
    493 
    494 static void
    495 param(void)
    496 {
    497 	Symbol *sym = pc->from2.u.sym;
    498 
    499 	printf(optbl[pc->op].txt,
    500 	       size2stack(&sym->type), addr2txt(&pc->from1));
    501 }
    502 
    503 static void
    504 ecall(void)
    505 {
    506 	struct opdata *p = &optbl[pc->op];
    507 
    508 	puts(p->txt);
    509 }
    510 
    511 static void
    512 ret(void)
    513 {
    514 	if (pc->from1.kind == SNONE)
    515 		puts("\t\tret");
    516 	else
    517 		printf("\t\tret\t%s\n", addr2txt(&pc->from1));
    518 }
    519 
    520 static void
    521 jmp(void)
    522 {
    523 	printf("\t\tjmp\t%s\n", addr2txt(&pc->from1));
    524 }
    525 
    526 static void
    527 branch(void)
    528 {
    529 	char to[ADDR_LEN], from1[ADDR_LEN], from2[ADDR_LEN];
    530 
    531 	strcpy(to, addr2txt(&pc->to));
    532 	strcpy(from1, addr2txt(&pc->from1));
    533 	strcpy(from2, addr2txt(&pc->from2));
    534 	printf("\t\tjnz\t%s,%s,%s\n", to, from1, from2);
    535 }
    536 
    537 static void
    538 vastart(void)
    539 {
    540 	printf("\t\tvastart %s\n", addr2txt(&pc->from1));
    541 }
    542 
    543 static void
    544 vaarg(void)
    545 {
    546 	Symbol *sym = pc->to.u.sym;
    547 	Type *tp = &sym->type;
    548 	char to[ADDR_LEN], from[ADDR_LEN];
    549 
    550 	strcpy(to, addr2txt(&pc->to));
    551 	strcpy(from, addr2txt(&pc->from1));
    552 	printf("\t\t%s =%s vaarg %s\n", to, size2asm(tp), from);
    553 }
    554 
    555 static void
    556 asalloc(void)
    557 {
    558 	Symbol *sym = pc->to.u.sym;
    559 	Type *tp = &sym->type;
    560 	extern Type ptrtype;
    561 
    562 	printf("\t%s =%s\talloc%lu\t%lu\n",
    563 	       symname(sym), size2asm(&ptrtype), tp->align+3 & ~3, tp->size);
    564 }
    565 
    566 static void
    567 form2local(void)
    568 {
    569 	Symbol *sym = pc->to.u.sym;
    570 	Type *tp = &sym->type;
    571 	char *name = symname(sym);
    572 
    573 	printf("\t\tstore%s\t%s.val,%s\n", size2asm(tp), name, name);
    574 }
    575 
    576 void
    577 endinit(void)
    578 {
    579 	puts("}");
    580 }
    581 
    582 void
    583 getbblocks(void)
    584 {
    585 	Inst *i;
    586 
    587 	if (!prog)
    588 		return;
    589 
    590 	prog->flags |= BBENTRY;
    591 	for (pc = prog; pc; pc = pc->next) {
    592 		switch (pc->op) {
    593 		case ASBRANCH:
    594 			i = pc->from2.u.sym->u.inst;
    595 			i->flags |= BBENTRY;
    596 		case ASJMP:
    597 			i = pc->from1.u.sym->u.inst;
    598 			i->flags |= BBENTRY;
    599 		case ASRET:
    600 			if (pc->next)
    601 				pc->next->flags |= BBENTRY;
    602 			break;
    603 		}
    604 	}
    605 }