Home
       code.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR Submodules
   DIR README
   DIR LICENSE
       ---
       code.c (15299B)
       ---
            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 }