URI:
       code.c - scc - simple c99 compiler
  HTML git clone git://git.simple-cc.org/scc
   DIR Log
   DIR Files
   DIR Refs
   DIR README
   DIR LICENSE
       ---
       code.c (10751B)
       ---
            1 #include <assert.h>
            2 #include <inttypes.h>
            3 #include <ctype.h>
            4 #include <stdio.h>
            5 #include <stdlib.h>
            6 #include <stdarg.h>
            7 
            8 #include <scc/scc.h>
            9 #include "cc1.h"
           10 
           11 static void emitbin(int, void *),
           12             emitcast(int, void *),
           13             emitsym(int, void *),
           14             emitexp(int, void *),
           15             emitsymid(int, void *),
           16             emittext(int, void *),
           17             emitfun(int, void *),
           18             emitdcl(int, void *),
           19             emitinit(int, void *),
           20             emittype(int, void *),
           21             emitbuilt(int, void *);
           22 
           23 char *optxt[] = {
           24         [OADD] = "+",
           25         [OSUB] = "-",
           26         [OMUL] = "*",
           27         [OINC] = ":i",
           28         [ODEC] =  ":d",
           29         [OPTR] = "@",
           30         [OMOD] = "%",
           31         [ODIV] = "/",
           32         [OSHL] = "l",
           33         [OSHR]  = "r",
           34         [OLT] = "<",
           35         [OGT] = ">",
           36         [OGE] = "]",
           37         [OLE] =  "[",
           38         [OEQ] = "=",
           39         [ONE] = "!",
           40         [OBAND] = "&",
           41         [OBXOR]  = "^",
           42         [OBOR] = "|",
           43         [OASSIGN] = ":",
           44         [OA_MUL] = ":*",
           45         [OA_DIV] = ":/",
           46         [OA_MOD] = ":%",
           47         [OA_ADD] = ":+",
           48         [OA_SUB] = ":-",
           49         [OA_SHL] = ":l",
           50         [OA_SHR] = ":r",
           51         [OA_AND] = ":&",
           52         [OA_XOR] = ":^",
           53         [OA_OR] = ":|",
           54         [OADDR] = "'",
           55         [OSNEG] = "_",
           56         [ONEG] = "n",
           57         [OCPL] = "~",
           58         [OAND] = "a",
           59         [OOR] = "o",
           60         [OASK] = "?",
           61         [OCOMMA] = ",",
           62         [OLABEL] = "L%d\n",
           63         [ODEFAULT] = "\tf\tL%d\n",
           64         [OBSWITCH] = "\ts",
           65         [OESWITCH] = "\tt\tL%d\n",
           66         [OCASE] = "\tv\tL%d",
           67         [OJUMP] = "\tj\tL%d\n",
           68         [OBRANCH] = "\ty\tL%d",
           69         [OEFUN] = "}\n",
           70         [OELOOP] = "\te\n",
           71         [OBLOOP] = "\tb\n",
           72         [ORET] = "\th",
           73         [OPAR] = "p",
           74         [OCALL] = "c",
           75         [OCALLE] = "z",
           76         [OFIELD] = "."
           77 };
           78 
           79 void (*opcode[])(int, void *) = {
           80         [OADD] = emitbin,
           81         [OSUB] = emitbin,
           82         [OMUL] = emitbin,
           83         [OINC] = emitbin,
           84         [ODEC] =  emitbin,
           85         [OPTR] = emitbin,
           86         [OMOD] = emitbin,
           87         [ODIV] = emitbin,
           88         [OSHL] = emitbin,
           89         [OSHR]  = emitbin,
           90         [OLT] = emitbin,
           91         [OGT] = emitbin,
           92         [OGE] = emitbin,
           93         [OLE] =  emitbin,
           94         [OEQ] = emitbin,
           95         [ONE] = emitbin,
           96         [OBAND] = emitbin,
           97         [OBXOR]  = emitbin,
           98         [OBOR] = emitbin,
           99         [OASSIGN] = emitbin,
          100         [OA_MUL] = emitbin,
          101         [OA_DIV] = emitbin,
          102         [OA_MOD] = emitbin,
          103         [OA_ADD] = emitbin,
          104         [OA_SUB] = emitbin,
          105         [OA_SHL] = emitbin,
          106         [OA_SHR] = emitbin,
          107         [OA_AND] = emitbin,
          108         [OA_XOR] = emitbin,
          109         [OA_OR] = emitbin,
          110         [OADDR] = emitbin,
          111         [OSNEG] = emitbin,
          112         [ONEG] = emitbin,
          113         [OCPL] = emitbin,
          114         [OAND] = emitbin,
          115         [OOR] = emitbin,
          116         [OCOMMA] = emitbin,
          117         [OCAST] = emitcast,
          118         [OSYM] = emitsym,
          119         [OASK] = emitbin,
          120         [OCOLON] = emitbin,
          121         [OFIELD]= emitbin,
          122         [OEXPR] = emitexp,
          123         [OLABEL] = emitsymid,
          124         [ODEFAULT] = emitsymid,
          125         [OCASE] = emitsymid,
          126         [OJUMP] = emitsymid,
          127         [OBRANCH] = emitsymid,
          128         [OEFUN] = emittext,
          129         [OELOOP] = emittext,
          130         [OBLOOP] = emittext,
          131         [OFUN] = emitfun,
          132         [ORET] = emittext,
          133         [ODECL] = emitdcl,
          134         [OBSWITCH] = emittext,
          135         [OESWITCH] = emitsymid,
          136         [OPAR] = emitbin,
          137         [OCALL] = emitbin,
          138         [OCALLE] = emitbin,
          139         [OINIT] = emitinit,
          140         [OBUILTIN] = emitbuilt,
          141         [OTYP] = emittype,
          142 };
          143 
          144 static FILE *outfp;
          145 
          146 void
          147 icode(void)
          148 {
          149         outfp = stdout;
          150 }
          151 
          152 void
          153 freetree(Node *np)
          154 {
          155         if (!np)
          156                 return;
          157         freetree(np->left);
          158         freetree(np->right);
          159         free(np);
          160 }
          161 
          162 static void
          163 emitnode(Node *np)
          164 {
          165         if (np)
          166                 (*opcode[np->op])(np->op, np);
          167 }
          168 
          169 Node *
          170 prtree(char *s, Node *np)
          171 {
          172         FILE *tmp = outfp;
          173 
          174         outfp = stderr;
          175         fprintf(outfp, "DBG prtree %s", s);
          176         emitnode(np);
          177         putc('\n', outfp);
          178         outfp = tmp;
          179 
          180         return np;
          181 }
          182 
          183 void
          184 emit(int op, void *arg)
          185 {
          186         extern int failure;
          187 
          188         if (failure || onlycpp || onlyheader)
          189                 return;
          190         (*opcode[op])(op, arg);
          191 }
          192 
          193 static void
          194 emitvar(Symbol *sym)
          195 {
          196         int c;
          197         short flags = sym->flags;
          198 
          199         if (flags & SLOCAL)
          200                 c = 'T';
          201         else if (flags & SPRIVATE)
          202                 c =  'Y';
          203         else if (flags & SGLOBAL)
          204                 c = 'G';
          205         else if (flags & SREGISTER)
          206                 c = 'R';
          207         else if (flags & SFIELD)
          208                 c = 'M';
          209         else if (flags & SEXTERN)
          210                 c = 'X';
          211         else
          212                 c = 'A';
          213         fprintf(outfp, "%c%u", c, sym->id);
          214 }
          215 
          216 static void
          217 emitconst(Node *np)
          218 {
          219         int n;
          220         unsigned char *fp, *p;
          221         Symbol *sym = np->sym;
          222         Type *tp = np->type;
          223         unsigned long long u;
          224 
          225         switch (tp->op) {
          226         case FLOAT:
          227                 if (tp == floattype)
          228                         u = *(uint32_t *) &sym->u.f;
          229                 else if (tp == doubletype)
          230                         u = *(uint64_t *) &sym->u.d;
          231                 else
          232                         abort(); /* TODO: What here?? */
          233                 goto print;
          234         case PTR:
          235         case INT:
          236         case ENUM:
          237                 u = (tp->prop & TSIGNED) ? sym->u.i : sym->u.u;
          238         print:
          239                 fprintf(outfp,
          240                         "#%c%llX",
          241                         tp->letter,
          242                         u & ones(tp->size));
          243                 break;
          244         default:
          245                 abort();
          246         }
          247 }
          248 
          249 static void
          250 emitsym(int op, void *arg)
          251 {
          252         Node *np = arg;
          253 
          254         if ((np->sym->flags & SINITLST) == 0) {
          255                 /*
          256                  * When we have a compound literal we are going
          257                  * to call to emitnode for every element of it,
          258                  * and it means that we will have two '\t'
          259                  * for the first element
          260                  */
          261                 putc('\t', outfp);
          262         }
          263         (np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);
          264 }
          265 
          266 static void
          267 emitletter(Type *tp)
          268 {
          269         int letter;
          270 
          271         letter = (tp->prop&TELLIPSIS) ? 'E' : tp->letter;
          272         putc(letter, outfp);
          273         switch (tp->op) {
          274         case ARY:
          275         case STRUCT:
          276         case UNION:
          277                 fprintf(outfp, "%u", tp->id);
          278         }
          279 }
          280 
          281 static void
          282 emittype(int op, void *arg)
          283 {
          284         long long n;
          285         Symbol **sp;
          286         char *tag;
          287         Type *tp = arg;
          288 
          289         if (!(tp->prop & TDEFINED))
          290                 return;
          291 
          292         switch (tp->op) {
          293         case ARY:
          294                 emitletter(tp);
          295                 putc('\t', outfp);
          296                 emitletter(tp->type);
          297                 fprintf(outfp,
          298                         "\t#%c%llX\n",
          299                         sizettype->letter, (long long) tp->n.elem);
          300                 return;
          301         case UNION:
          302         case STRUCT:
          303                 emitletter(tp);
          304                 tag = tp->tag->name;
          305                 fprintf(outfp,
          306                        "\t\"%s\t#%c%lX\t#%c%X\n",
          307                        (tag) ? tag : "",
          308                        sizettype->letter,
          309                        tp->size,
          310                        sizettype->letter,
          311                        tp->align);
          312                 n = tp->n.elem;
          313                 for (sp = tp->p.fields; n-- > 0; ++sp)
          314                         emit(ODECL, *sp);
          315                 break;
          316         case PTR:
          317         case FTN:
          318         case ENUM:
          319                 return;
          320         default:
          321                 abort();
          322         }
          323 }
          324 
          325 static void
          326 emitrstring(Symbol *sym, Type *tp)
          327 {
          328         Rune *bp, *lim;
          329 
          330         bp = sym->u.rs;
          331         lim = &sym->u.rs[tp->n.elem];
          332         while (bp < lim) {
          333                 fprintf(outfp,
          334                         "\t#%c%" PRIX32 "\n",
          335                         wchartype->letter, *bp++);
          336         }
          337 }
          338 
          339 static void
          340 emitstring(Symbol *sym, Type *tp)
          341 {
          342         char *bp, *s, *lim;
          343         int n;
          344 
          345         bp = sym->u.s;
          346         lim = &sym->u.s[tp->n.elem];
          347         while (bp < lim) {
          348                 s = bp;
          349                 while (bp < lim && isprint(*bp))
          350                         ++bp;
          351                 if ((n = bp - s) > 1)
          352                         fprintf(outfp, "\t#\"%.*s\n", n, s);
          353                 else
          354                         bp = s;
          355                 if (bp == lim)
          356                         break;
          357                 do {
          358                         fprintf(outfp,
          359                                 "\t#%c%X\n",
          360                                 chartype->letter, (*bp++) & 0xFF);
          361                 } while (bp < lim && !isprint(*bp));
          362         }
          363 }
          364 
          365 Node *
          366 zeronode(Type *tp)
          367 {
          368         return simplify(convert(constnode(zero), tp, 0));
          369 }
          370 
          371 static void
          372 emitpadding(Type *tp, unsigned long long *addr)
          373 {
          374         int i, align;
          375         unsigned long long a, n;
          376 
          377         align = tp->align - 1;
          378         a = *addr;
          379         n = a+align & ~align;
          380 
          381         for ( ; a != n; ++a)
          382                 emitexp(OEXPR, zeronode(chartype));
          383         *addr = n;
          384 }
          385 
          386 static void
          387 emitdesig(Node *np, Type *tp, unsigned long long *addr)
          388 {
          389         Symbol *sym;
          390         unsigned long long n;
          391         Node *aux;
          392         Type *p;
          393 
          394         emitpadding(tp, addr);
          395 
          396         if (!np) {
          397                 sym = NULL;
          398         } else {
          399                 if (!np->sym)
          400                         goto emit_expression;
          401                 sym = np->sym;
          402                 if (sym->flags & SSTRING) {
          403                         emitstring(sym, tp);
          404                         *addr += tp->n.elem;
          405                         return;
          406                 }
          407                 if (sym->flags & SRSTRING) {
          408                         emitrstring(sym, tp);
          409                         *addr += tp->n.elem * wchartype->size;
          410                         return;
          411                 }
          412                 
          413                 if ((sym->flags & SINITLST) == 0)
          414                         goto emit_expression;
          415         }
          416 
          417         switch (tp->op) {
          418         case PTR:
          419         case INT:
          420         case ENUM:
          421                 aux = sym ? *sym->u.init : zeronode(tp);
          422                 *addr += aux->type->size;
          423                 emitexp(OEXPR, aux);
          424                 break;
          425         case UNION:
          426                 aux = (sym) ? sym->u.init[0] : NULL;
          427                 p = (aux) ? aux->type : tp->p.fields[0]->type;
          428                 emitdesig(aux, p, addr);
          429                 emitpadding(tp, addr);
          430                 break;
          431         case STRUCT:
          432         case ARY:
          433                 for (n = 0; n < tp->n.elem; ++n) {
          434                         aux = (sym) ? sym->u.init[n] : NULL;
          435                         p = (tp->op == ARY) ? tp->type : tp->p.fields[n]->type;
          436                         emitdesig(aux, p, addr);
          437                 }
          438                 emitpadding(tp, addr);
          439                 break;
          440         default:
          441                 abort();
          442         }
          443 
          444         if (sym) {
          445                 free(sym->u.init);
          446                 sym->u.init = NULL;
          447         }
          448         freetree(np);
          449         return;
          450 
          451 emit_expression:
          452         emitexp(OEXPR, np);
          453         *addr += tp->size;
          454 }
          455 
          456 static void
          457 emitinit(int op, void *arg)
          458 {
          459         Node *np = arg;
          460         unsigned long long addr = 0;
          461 
          462         fputs("\t(\n", outfp);
          463         emitdesig(np, np->type, &addr);
          464         fputs(")\n", outfp);
          465 }
          466 
          467 static void
          468 emitdcl(int op, void *arg)
          469 {
          470         Symbol *sym = arg;
          471 
          472         if (sym->flags & SEMITTED)
          473                 return;
          474         emitvar(sym);
          475         putc('\t', outfp);
          476         if (sym->type->op == FTN) {
          477                 emitletter(sym->type->type);
          478                 putc('\t', outfp);
          479         }
          480         emitletter(sym->type);
          481         fprintf(outfp, "\t\"%s", (sym->name) ? sym->name : "");
          482         if (sym->flags & SFIELD)
          483                 fprintf(outfp, "\t#%c%llX", sizettype->letter, sym->u.i);
          484         sym->flags |= SEMITTED;
          485         if ((sym->flags & SHASINIT) == 0)
          486                 putc('\n', outfp);
          487 }
          488 
          489 static void
          490 emitcast(int op, void *arg)
          491 {
          492         Node *np = arg, *lp = np->left;
          493 
          494         emitnode(lp);
          495         if (np->type != voidtype)
          496                 fprintf(outfp, "\tg%c", np->type->letter);
          497 }
          498 
          499 static void
          500 emitbin(int op, void *arg)
          501 {
          502         Node *np = arg;
          503         char *s;
          504 
          505         emitnode(np->left);
          506         emitnode(np->right);
          507 
          508         /* do not print in OCOLON case */
          509         if ((s = optxt[op]) != NULL)  {
          510                 fprintf(outfp, "\t%s", s);
          511                 emitletter(np->type);
          512         }
          513 }
          514 
          515 static void
          516 emitbuilt(int op, void *arg)
          517 {
          518         Node *np = arg;
          519 
          520         emitnode(np->left);
          521         emitnode(np->right);
          522         fprintf(outfp, "\t\"%s\tm", np->sym->name);
          523         emitletter(np->type);
          524 }
          525 
          526 
          527 static void
          528 emitexp(int op, void *arg)
          529 {
          530         Node *np = arg;
          531 
          532         emitnode(np);
          533         putc('\n', outfp);
          534         freetree(np);
          535 }
          536 
          537 static void
          538 emitfun(int op, void *arg)
          539 {
          540         Symbol *sym = arg, **sp;
          541 
          542         emitdcl(op, arg);
          543         fputs("{\n", outfp);
          544 
          545         for (sp = sym->u.pars; sp && *sp; ++sp)
          546                 emit(ODECL, *sp);
          547         fputs("\\\n", outfp);
          548 }
          549 
          550 static void
          551 emittext(int op, void *arg)
          552 {
          553         fputs(optxt[op], outfp);
          554 }
          555 
          556 static void
          557 emitsymid(int op, void *arg)
          558 {
          559         Symbol *sym = arg;
          560         fprintf(outfp, optxt[op], sym->id);
          561 }
          562 
          563 Node *
          564 node(int op, Type *tp, Node *lp, Node *rp)
          565 {
          566         Node *np;
          567 
          568         np = xmalloc(sizeof(*np));
          569         np->op = op;
          570         np->type = tp;
          571         np->sym = NULL;
          572         np->flags = 0;
          573         np->left = lp;
          574         np->right = rp;
          575 
          576         if (lp)
          577                 np->flags |= lp->flags & NEFFECT;
          578         if (rp)
          579                 np->flags |= rp->flags & NEFFECT;
          580         return np;
          581 }
          582 
          583 Node *
          584 varnode(Symbol *sym)
          585 {
          586         Node *np;
          587         Type *tp = sym->type;
          588 
          589         np = node(OSYM, sym->type, NULL, NULL);
          590         np->type = sym->type;
          591         np->flags = (tp->op != FTN && tp->op != ARY) ? NLVAL : 0;
          592         np->sym = sym;
          593         return np;
          594 }
          595 
          596 Node *
          597 constnode(Symbol *sym)
          598 {
          599         Node *np;
          600 
          601         np = node(OSYM, sym->type, NULL, NULL);
          602         np->flags = NCONST;
          603         np->sym = sym;
          604         return np;
          605 }
          606 
          607 Node *
          608 sizeofnode(Type *tp)
          609 {
          610         Symbol *sym;
          611 
          612         sym = newsym(NS_IDEN, NULL);
          613         sym->type = sizettype;
          614         sym->flags |= SCONSTANT;
          615         sym->u.u = tp->size;
          616         DBG("EXPR sizeof %llu", sym->u.u);
          617         return constnode(sym);
          618 }
          619 
          620 Node *
          621 offsetnode(Symbol *field, Type *tp)
          622 {
          623         Symbol *sym;
          624 
          625         assert(field->flags & SFIELD);
          626         sym = newsym(NS_IDEN, NULL);
          627         sym->type = tp;
          628         sym->flags |= SCONSTANT;
          629         sym->u.u = field->u.u;
          630 
          631         return constnode(sym);
          632 }
          633 
          634 Node *
          635 addrnode(unsigned long long u)
          636 {
          637         Symbol *sym;
          638 
          639         sym = newsym(NS_IDEN, NULL);
          640         sym->type = pvoidtype;
          641         sym->flags |= SCONSTANT;
          642         sym->u.u = u;
          643 
          644         return constnode(sym);
          645 }