1#include <assert.h>2#include <inttypes.h>3#include <ctype.h>4#include <stdio.h>5#include <stdlib.h>6#include <stdarg.h>78#include <scc/scc.h>9#include "cc1.h"1011static 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 *);2223char *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};7879void (*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};143144static FILE *outfp;145146void147icode(void)148{149 outfp = stdout;150}151152void153freetree(Node *np)154{155 if (!np)156 return;157 freetree(np->left);158 freetree(np->right);159 free(np);160}161162static void163emitnode(Node *np)164{165 if (np)166 (*opcode[np->op])(np->op, np);167}168169Node *170prtree(char *s, Node *np)171{172 FILE *tmp = outfp;173174 outfp = stderr;175 fprintf(outfp, "DBG prtree %s", s);176 emitnode(np);177 putc('\n', outfp);178 outfp = tmp;179180 return np;181}182183void184emit(int op, void *arg)185{186 extern int failure;187188 if (failure || onlycpp || onlyheader)189 return;190 (*opcode[op])(op, arg);191}192193static void194emitvar(Symbol *sym)195{196 int c;197 short flags = sym->flags;198199 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 else212 c = 'A';213 fprintf(outfp, "%c%u", c, sym->id);214}215216static void217emitconst(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;224225 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 else232 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}248249static void250emitsym(int op, void *arg)251{252 Node *np = arg;253254 if ((np->sym->flags & SINITLST) == 0) {255 /*256 * When we have a compound literal we are going257 * to call to emitnode for every element of it,258 * and it means that we will have two '\t'259 * for the first element260 */261 putc('\t', outfp);262 }263 (np->flags & NCONST) ? emitconst(np) : emitvar(np->sym);264}265266static void267emitletter(Type *tp)268{269 int letter;270271 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}280281static void282emittype(int op, void *arg)283{284 long long n;285 Symbol **sp;286 char *tag;287 Type *tp = arg;288289 if (!(tp->prop & TDEFINED))290 return;291292 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}324325static void326emitrstring(Symbol *sym, Type *tp)327{328 Rune *bp, *lim;329330 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}338339static void340emitstring(Symbol *sym, Type *tp)341{342 char *bp, *s, *lim;343 int n;344345 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 else354 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}364365Node *366zeronode(Type *tp)367{368 return simplify(convert(constnode(zero), tp, 0));369}370371static void372emitpadding(Type *tp, unsigned long long *addr)373{374 int i, align;375 unsigned long long a, n;376377 align = tp->align - 1;378 a = *addr;379 n = a+align & ~align;380381 for ( ; a != n; ++a)382 emitexp(OEXPR, zeronode(chartype));383 *addr = n;384}385386static void387emitdesig(Node *np, Type *tp, unsigned long long *addr)388{389 Symbol *sym;390 unsigned long long n;391 Node *aux;392 Type *p;393394 emitpadding(tp, addr);395396 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 }412413 if ((sym->flags & SINITLST) == 0)414 goto emit_expression;415 }416417 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 }443444 if (sym) {445 free(sym->u.init);446 sym->u.init = NULL;447 }448 freetree(np);449 return;450451emit_expression:452 emitexp(OEXPR, np);453 *addr += tp->size;454}455456static void457emitinit(int op, void *arg)458{459 Node *np = arg;460 unsigned long long addr = 0;461462 fputs("\t(\n", outfp);463 emitdesig(np, np->type, &addr);464 fputs(")\n", outfp);465}466467static void468emitdcl(int op, void *arg)469{470 Symbol *sym = arg;471472 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}488489static void490emitcast(int op, void *arg)491{492 Node *np = arg, *lp = np->left;493494 emitnode(lp);495 if (np->type != voidtype)496 fprintf(outfp, "\tg%c", np->type->letter);497}498499static void500emitbin(int op, void *arg)501{502 Node *np = arg;503 char *s;504505 emitnode(np->left);506 emitnode(np->right);507508 /* do not print in OCOLON case */509 if ((s = optxt[op]) != NULL) {510 fprintf(outfp, "\t%s", s);511 emitletter(np->type);512 }513}514515static void516emitbuilt(int op, void *arg)517{518 Node *np = arg;519520 emitnode(np->left);521 emitnode(np->right);522 fprintf(outfp, "\t\"%s\tm", np->sym->name);523 emitletter(np->type);524}525526527static void528emitexp(int op, void *arg)529{530 Node *np = arg;531532 emitnode(np);533 putc('\n', outfp);534 freetree(np);535}536537static void538emitfun(int op, void *arg)539{540 Symbol *sym = arg, **sp;541542 emitdcl(op, arg);543 fputs("{\n", outfp);544545 for (sp = sym->u.pars; sp && *sp; ++sp)546 emit(ODECL, *sp);547 fputs("\\\n", outfp);548}549550static void551emittext(int op, void *arg)552{553 fputs(optxt[op], outfp);554}555556static void557emitsymid(int op, void *arg)558{559 Symbol *sym = arg;560 fprintf(outfp, optxt[op], sym->id);561}562563Node *564node(int op, Type *tp, Node *lp, Node *rp)565{566 Node *np;567568 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;575576 if (lp)577 np->flags |= lp->flags & NEFFECT;578 if (rp)579 np->flags |= rp->flags & NEFFECT;580 return np;581}582583Node *584varnode(Symbol *sym)585{586 Node *np;587 Type *tp = sym->type;588589 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}595596Node *597constnode(Symbol *sym)598{599 Node *np;600601 np = node(OSYM, sym->type, NULL, NULL);602 np->flags = NCONST;603 np->sym = sym;604 return np;605}606607Node *608sizeofnode(Type *tp)609{610 Symbol *sym;611612 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}619620Node *621offsetnode(Symbol *field, Type *tp)622{623 Symbol *sym;624625 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;630631 return constnode(sym);632}633634Node *635addrnode(unsigned long long u)636{637 Symbol *sym;638639 sym = newsym(NS_IDEN, NULL);640 sym->type = pvoidtype;641 sym->flags |= SCONSTANT;642 sym->u.u = u;643644 return constnode(sym);645}