URI:
       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 (10400B)
       ---
            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         int n;
          219         unsigned char *fp, *p;
          220         Symbol *sym = np->sym;
          221         Type *tp = np->type;
          222         unsigned long long u;
          223 
          224         switch (tp->op) {
          225         case FLOAT:
          226                 if (tp == floattype)
          227                         u = *(uint32_t *) &sym->u.f;
          228                 else if (tp == doubletype)
          229                         u = *(uint64_t *) &sym->u.d;
          230                 else
          231                         abort(); /* TODO: What here?? */
          232                 goto print;
          233         case PTR:
          234         case INT:
          235         case ENUM:
          236                 u = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
          237         print:
          238                 fprintf(outfp,
          239                         "#%c%llX",
          240                         tp->letter,
          241                         u & ones(tp->size));
          242                 break;
          243         default:
          244                 abort();
          245         }
          246 }
          247 
          248 static void
          249 emitsym(int op, void *arg)
          250 {
          251         Node *np = arg;
          252 
          253         if ((np->sym->flags & SINITLST) == 0) {
          254                 /*
          255                  * When we have a compound literal we are going
          256                  * to call to emitnode for every element of it,
          257                  * and it means that we will have two '\t'
          258                  * for the first element
          259                  */
          260                 putc('\t', outfp);
          261         }
          262         (np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
          263 }
          264 
          265 static void
          266 emitletter(Type *tp)
          267 {
          268         int letter;
          269 
          270         letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter;
          271         putc(letter, outfp);
          272         switch (tp->op) {
          273         case ARY:
          274         case STRUCT:
          275         case UNION:
          276                 fprintf(outfp, "%u", tp->id);
          277         }
          278 }
          279 
          280 static void
          281 emittype(int op, void *arg)
          282 {
          283         long long n;
          284         Symbol **sp;
          285         char *tag;
          286         Type *tp = arg;
          287 
          288         if (!(tp->prop & TDEFINED))
          289                 return;
          290 
          291         switch (tp->op) {
          292         case ARY:
          293                 emitletter(tp);
          294                 putc('\t', outfp);
          295                 emitletter(tp->type);
          296                 fprintf(outfp,
          297                         "\t#%c%llX\n",
          298                         sizettype->letter, (long long) tp->n.elem);
          299                 return;
          300         case UNION:
          301         case STRUCT:
          302                 emitletter(tp);
          303                 tag = tp->tag->name;
          304                 fprintf(outfp,
          305                        "\t\"%s\t#%c%lX\t#%c%X\n",
          306                        (tag) ? tag : "",
          307                        sizettype->letter,
          308                        tp->size,
          309                        sizettype->letter,
          310                        tp->align);
          311                 n = tp->n.elem;
          312                 for (sp = tp->p.fields; n-- > 0; ++sp)
          313                         emit(ODECL, *sp);
          314                 break;
          315         case PTR:
          316         case FTN:
          317         case ENUM:
          318                 return;
          319         default:
          320                 abort();
          321         }
          322 }
          323 
          324 static void
          325 emitstring(Symbol *sym, Type *tp)
          326 {
          327         char *bp, *s, *lim;
          328         int n;
          329 
          330         bp = sym->u.s;
          331         lim = &sym->u.s[tp->n.elem];
          332         while (bp < lim) {
          333                 s = bp;
          334                 while (bp < lim && isprint(*bp))
          335                         ++bp;
          336                 if ((n = bp - s) > 1)
          337                         fprintf(outfp, "\t#\"%.*s\n", n, s);
          338                 else
          339                         bp = s;
          340                 if (bp == lim)
          341                         break;
          342                 do {
          343                         fprintf(outfp,
          344                                 "\t#%c%X\n",
          345                                 chartype->letter, (*bp++) & 0xFF);
          346                 } while (bp < lim && !isprint(*bp));
          347         }
          348 }
          349 
          350 Node *
          351 zeronode(Type *tp)
          352 {
          353         return simplify(convert(constnode(zero), tp, 0));
          354 }
          355 
          356 static void
          357 emitpadding(Type *tp, unsigned long long *addr)
          358 {
          359         int i, align;
          360         unsigned long long a, n;
          361 
          362         align = tp->align - 1;
          363         a = *addr;
          364         n = a+align & ~align;
          365 
          366         for ( ; a != n; ++a)
          367                 emitexp(OEXPR, zeronode(chartype));
          368         *addr = n;
          369 }
          370 
          371 static void
          372 emitdesig(Node *np, Type *tp, unsigned long long *addr)
          373 {
          374         Symbol *sym;
          375         unsigned long long n;
          376         Node *aux;
          377         Type *p;
          378 
          379         emitpadding(tp, addr);
          380 
          381         if (!np) {
          382                 sym = NULL;
          383         } else {
          384                 if (!np->sym)
          385                         goto emit_expression;
          386                 sym = np->sym;
          387                 if (sym->flags & SSTRING) {
          388                         emitstring(sym, tp);
          389                         *addr += tp->n.elem;
          390                         return;
          391                 }
          392                 if ((sym->flags & SINITLST) == 0)
          393                         goto emit_expression;
          394         }
          395 
          396         switch (tp->op) {
          397         case PTR:
          398         case INT:
          399         case ENUM:
          400                 aux = sym ? *sym->u.init : zeronode(tp);
          401                 *addr += aux->type->size;
          402                 emitexp(OEXPR, aux);
          403                 break;
          404         case UNION:
          405                 aux = (sym) ? sym->u.init[0] : NULL;
          406                 p = (aux) ? aux->type : tp->p.fields[0]->type;
          407                 emitdesig(aux, p, addr);
          408                 emitpadding(tp, addr);
          409                 break;
          410         case STRUCT:
          411         case ARY:
          412                 for (n = 0; n < tp->n.elem; ++n) {
          413                         aux = (sym) ? sym->u.init[n] : NULL;
          414                         p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
          415                         emitdesig(aux, p, addr);
          416                 }
          417                 emitpadding(tp, addr);
          418                 break;
          419         default:
          420                 abort();
          421         }
          422 
          423         if (sym) {
          424                 free(sym->u.init);
          425                 sym->u.init = NULL;
          426         }
          427         freetree(np);
          428         return;
          429 
          430 emit_expression:
          431         emitexp(OEXPR, np);
          432         *addr += tp->size;
          433 }
          434 
          435 static void
          436 emitinit(int op, void *arg)
          437 {
          438         Node *np = arg;
          439         unsigned long long addr = 0;
          440 
          441         fputs("\t(\n", outfp);
          442         emitdesig(np, np->type, &addr);
          443         fputs(")\n", outfp);
          444 }
          445 
          446 static void
          447 emitdcl(int op, void *arg)
          448 {
          449         Symbol *sym = arg;
          450 
          451         if (sym->flags & SEMITTED)
          452                 return;
          453         emitvar(sym);
          454         putc('\t', outfp);
          455         if (sym->type->op == FTN) {
          456                 emitletter(sym->type->type);
          457                 putc('\t', outfp);
          458         }
          459         emitletter(sym->type);
          460         fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
          461         if (sym->flags & SFIELD)
          462                 fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
          463         sym->flags |= SEMITTED;
          464         if ((sym->flags & SHASINIT) == 0)
          465                 putc('\n', outfp);
          466 }
          467 
          468 static void
          469 emitcast(int op, void *arg)
          470 {
          471         Node *np = arg, *lp = np->left;
          472 
          473         emitnode(lp);
          474         if (np->type != voidtype)
          475                 fprintf(outfp, "\tg%c", np->type->letter);
          476 }
          477 
          478 static void
          479 emitbin(int op, void *arg)
          480 {
          481         Node *np = arg;
          482         char *s;
          483 
          484         emitnode(np->left);
          485         emitnode(np->right);
          486 
          487         /* do not print in OCOLON case */
          488         if ((s = optxt[op]) != NULL)  {
          489                 fprintf(outfp, "\t%s", s);
          490                 emitletter(np->type);
          491         }
          492 }
          493 
          494 static void
          495 emitbuilt(int op, void *arg)
          496 {
          497         Node *np = arg;
          498 
          499         emitnode(np->left);
          500         emitnode(np->right);
          501         fprintf(outfp, "\t\"%s\tm", np->sym->name);
          502         emitletter(np->type);
          503 }
          504 
          505 
          506 static void
          507 emitexp(int op, void *arg)
          508 {
          509         Node *np = arg;
          510 
          511         emitnode(np);
          512         putc('\n', outfp);
          513         freetree(np);
          514 }
          515 
          516 static void
          517 emitfun(int op, void *arg)
          518 {
          519         Symbol *sym = arg, **sp;
          520 
          521         emitdcl(op, arg);
          522         fputs("{\n", outfp);
          523 
          524         for (sp = sym->u.pars; sp && *sp; ++sp)
          525                 emit(ODECL, *sp);
          526         fputs("\\\n", outfp);
          527 }
          528 
          529 static void
          530 emittext(int op, void *arg)
          531 {
          532         fputs(optxt[op], outfp);
          533 }
          534 
          535 static void
          536 emitsymid(int op, void *arg)
          537 {
          538         Symbol *sym = arg;
          539         fprintf(outfp, optxt[op], sym->id);
          540 }
          541 
          542 Node *
          543 node(int op, Type *tp, Node *lp, Node *rp)
          544 {
          545         Node *np;
          546 
          547         np = xmalloc(sizeof(*np));
          548         np->op = op;
          549         np->type = tp;
          550         np->sym = NULL;
          551         np->flags = 0;
          552         np->left = lp;
          553         np->right = rp;
          554 
          555         if (lp)
          556                 np->flags |= lp->flags & NEFFECT;
          557         if (rp)
          558                 np->flags |= rp->flags & NEFFECT;
          559         return np;
          560 }
          561 
          562 Node *
          563 varnode(Symbol *sym)
          564 {
          565         Node *np;
          566         Type *tp = sym->type;
          567 
          568         np = node(OSYM, sym->type, NULL, NULL);
          569         np->type = sym->type;
          570         np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
          571         np->sym = sym;
          572         return np;
          573 }
          574 
          575 Node *
          576 constnode(Symbol *sym)
          577 {
          578         Node *np;
          579 
          580         np = node(OSYM, sym->type, NULL, NULL);
          581         np->flags = NCONST;
          582         np->sym = sym;
          583         return np;
          584 }
          585 
          586 Node *
          587 sizeofnode(Type *tp)
          588 {
          589         Symbol *sym;
          590 
          591         sym = newsym(NS_IDEN, NULL);
          592         sym->type = sizettype;
          593         sym->flags |= SCONSTANT;
          594         sym->u.u = tp->size;
          595         DBG("EXPR sizeof %llu", sym->u.u);
          596         return constnode(sym);
          597 }
          598 
          599 Node *
          600 offsetnode(Symbol *field, Type *tp)
          601 {
          602         Symbol *sym;
          603 
          604         assert(field->flags & SFIELD);
          605         sym = newsym(NS_IDEN, NULL);
          606         sym->type = tp;
          607         sym->flags |= SCONSTANT;
          608         sym->u.u = field->u.u;
          609 
          610         return constnode(sym);
          611 }
          612 
          613 Node *
          614 addrnode(unsigned long long u)
          615 {
          616         Symbol *sym;
          617 
          618         sym = newsym(NS_IDEN, NULL);
          619         sym->type = pvoidtype;
          620         sym->flags |= SCONSTANT;
          621         sym->u.u = u;
          622 
          623         return constnode(sym);
          624 }