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 }