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