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 (9852B)
       ---
            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] = "\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 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                 emitdesig(aux, aux->type, addr);
          395                 emitpadding(tp, addr);
          396                 break;
          397         case STRUCT:
          398         case ARY:
          399                 for (n = 0; n < tp->n.elem; ++n) {
          400                         aux = (sym) ? sym->u.init[n] : NULL;
          401                         p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
          402                         emitdesig(aux, p, addr);
          403                 }
          404                 emitpadding(tp, addr);
          405                 break;
          406         default:
          407                 abort();
          408         }
          409 
          410         if (sym) {
          411                 free(sym->u.init);
          412                 sym->u.init = NULL;
          413         }
          414         freetree(np);
          415         return;
          416 
          417 emit_expression:
          418         emitexp(OEXPR, np);
          419         *addr += tp->size;
          420 }
          421 
          422 static void
          423 emitinit(int op, void *arg)
          424 {
          425         Node *np = arg;
          426         SIZET addr = 0;
          427 
          428         fputs("\t(\n", outfp);
          429         emitdesig(np, np->type, &addr);
          430         fputs(")\n", outfp);
          431 }
          432 
          433 static void
          434 emitdcl(int op, void *arg)
          435 {
          436         Symbol *sym = arg;
          437 
          438         if (sym->flags & SEMITTED)
          439                 return;
          440         emitvar(sym);
          441         putc('\t', outfp);
          442         if (sym->type->op == FTN) {
          443                 emitletter(sym->type->type);
          444                 putc('\t', outfp);
          445         }
          446         emitletter(sym->type);
          447         fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
          448         if (sym->flags & SFIELD)
          449                 fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
          450         sym->flags |= SEMITTED;
          451         if ((sym->flags & SHASINIT) == 0)
          452                 putc('\n', outfp);
          453 }
          454 
          455 static void
          456 emitcast(int op, void *arg)
          457 {
          458         Node *np = arg, *lp = np->left;
          459 
          460         emitnode(lp);
          461         if (np->type != voidtype)
          462                 fprintf(outfp, "\tg%c", np->type->letter);
          463 }
          464 
          465 static void
          466 emitbin(int op, void *arg)
          467 {
          468         Node *np = arg;
          469         char *s;
          470 
          471         emitnode(np->left);
          472         emitnode(np->right);
          473 
          474         /* do not print in OCOLON case */
          475         if ((s = optxt[op]) != NULL)  {
          476                 fprintf(outfp, "\t%s", s);
          477                 emitletter(np->type);
          478         }
          479 }
          480 
          481 static void
          482 emitbuilt(int op, void *arg)
          483 {
          484         Node *np = arg;
          485 
          486         emitnode(np->left);
          487         emitnode(np->right);
          488         fprintf(outfp, "\t\"%s\tm", np->sym->name);
          489         emitletter(np->type);
          490 }
          491 
          492 
          493 static void
          494 emitexp(int op, void *arg)
          495 {
          496         Node *np = arg;
          497 
          498         emitnode(np);
          499         putc('\n', outfp);
          500         freetree(np);
          501 }
          502 
          503 static void
          504 emitfun(int op, void *arg)
          505 {
          506         Symbol *sym = arg, **sp;
          507 
          508         emitdcl(op, arg);
          509         fputs("{\n", outfp);
          510 
          511         for (sp = sym->u.pars; sp && *sp; ++sp)
          512                 emit(ODECL, *sp);
          513         fputs("\\\n", outfp);
          514 }
          515 
          516 static void
          517 emittext(int op, void *arg)
          518 {
          519         fputs(optxt[op], outfp);
          520 }
          521 
          522 static void
          523 emitsymid(int op, void *arg)
          524 {
          525         Symbol *sym = arg;
          526         fprintf(outfp, optxt[op], sym->id);
          527 }
          528 
          529 Node *
          530 node(int op, Type *tp, Node *lp, Node *rp)
          531 {
          532         Node *np;
          533 
          534         np = xmalloc(sizeof(*np));
          535         np->op = op;
          536         np->type = tp;
          537         np->sym = NULL;
          538         np->flags = 0;
          539         np->left = lp;
          540         np->right = rp;
          541 
          542         if (lp)
          543                 np->flags |= lp->flags & NEFFECT;
          544         if (rp)
          545                 np->flags |= rp->flags & NEFFECT;
          546         return np;
          547 }
          548 
          549 Node *
          550 varnode(Symbol *sym)
          551 {
          552         Node *np;
          553         Type *tp = sym->type;
          554 
          555         np = node(OSYM, sym->type, NULL, NULL);
          556         np->type = sym->type;
          557         np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
          558         np->sym = sym;
          559         return np;
          560 }
          561 
          562 Node *
          563 constnode(Symbol *sym)
          564 {
          565         Node *np;
          566 
          567         np = node(OSYM, sym->type, NULL, NULL);
          568         np->flags = NCONST;
          569         np->sym = sym;
          570         return np;
          571 }
          572 
          573 Node *
          574 sizeofnode(Type *tp)
          575 {
          576         Symbol *sym;
          577 
          578         sym = newsym(NS_IDEN, NULL);
          579         sym->type = sizettype;
          580         sym->u.u = tp->size;
          581         DBG("EXPR sizeof %llu", sym->u.u);
          582         return constnode(sym);
          583 }
          584 
          585 Node *
          586 offsetnode(Symbol *field, Type *tp)
          587 {
          588         Symbol *sym;
          589 
          590         assert(field->flags & SFIELD);
          591         sym = newsym(NS_IDEN, NULL);
          592         sym->type = tp;
          593         sym->flags |= SCONSTANT;
          594         sym->u.u = field->u.u;
          595 
          596         return constnode(sym);
          597 }