pass2.c (16805B)
1 #include "c.h" 2 #include "rcc.h" 3 #if WIN32 4 #include <fcntl.h> 5 #include <io.h> 6 #endif 7 8 9 Interface *IR = NULL; 10 int Aflag; /* >= 0 if -A specified */ 11 int Pflag; /* != 0 if -P specified */ 12 int glevel; /* == [0-9] if -g[0-9] specified */ 13 int xref; /* != 0 for cross-reference data */ 14 Symbol YYnull; /* _YYnull symbol if -n or -nvalidate specified */ 15 Symbol YYcheck; /* _YYcheck symbol if -nvalidate,check specified */ 16 17 static int verbose = 1; 18 #define VERBOSE(n,arg) (verbose >= n ? (void)(arg):(void)0) 19 static int nuids; 20 static rcc_item_ty *items; 21 static void **itemmap; 22 23 static void *uid2type(int uid) { 24 assert(uid >= 0 && uid < nuids); 25 if (itemmap[uid] == NULL) { 26 Type ty; 27 rcc_type_ty type = (void *)items[uid]; 28 assert(items[uid]); 29 assert(items[uid]->uid == uid); 30 assert(items[uid]->kind == rcc_Type_enum); 31 type = items[uid]->v.rcc_Type.type; 32 assert(type); 33 switch (type->kind) { 34 case rcc_INT_enum: 35 ty = btot(INT, type->size); 36 assert(ty->align == type->align); 37 break; 38 case rcc_UNSIGNED_enum: 39 ty = btot(UNSIGNED, type->size); 40 assert(ty->align == type->align); 41 break; 42 case rcc_FLOAT_enum: 43 ty = btot(FLOAT, type->size); 44 assert(ty->align == type->align); 45 break; 46 case rcc_VOID_enum: 47 ty = voidtype; 48 break; 49 case rcc_POINTER_enum: 50 ty = ptr(uid2type(type->v.rcc_POINTER.type)); 51 break; 52 case rcc_ARRAY_enum: 53 ty = uid2type(type->v.rcc_ARRAY.type); 54 assert(ty->size > 0); 55 ty = array(ty, type->size/ty->size, 0); 56 break; 57 case rcc_CONST_enum: 58 ty = qual(CONST, uid2type(type->v.rcc_CONST.type)); 59 break; 60 case rcc_VOLATILE_enum: 61 ty = qual(VOLATILE, uid2type(type->v.rcc_VOLATILE.type)); 62 break; 63 case rcc_ENUM_enum: { 64 int i, n = Seq_length(type->v.rcc_ENUM.ids); 65 ty = newstruct(ENUM, string(type->v.rcc_ENUM.tag)); 66 ty->type = inttype; 67 ty->size = ty->type->size; 68 ty->align = ty->type->align; 69 ty->u.sym->u.idlist = newarray(n + 1, sizeof *ty->u.sym->u.idlist, PERM); 70 for (i = 0; i < n; i++) { 71 rcc_enum__ty e = Seq_remlo(type->v.rcc_ENUM.ids); 72 Symbol p = install(e->id, &identifiers, GLOBAL, PERM); 73 p->type = ty; 74 p->sclass = ENUM; 75 p->u.value = e->value; 76 ty->u.sym->u.idlist[i] = p; 77 free(e); 78 } 79 ty->u.sym->u.idlist[i] = NULL; 80 Seq_free(&type->v.rcc_ENUM.ids); 81 break; 82 } 83 case rcc_STRUCT_enum: case rcc_UNION_enum: { 84 int i, n; 85 Field *tail; 86 list_ty fields; 87 if (type->kind == rcc_STRUCT_enum) { 88 ty = newstruct(STRUCT, string(type->v.rcc_STRUCT.tag)); 89 fields = type->v.rcc_STRUCT.fields; 90 } else { 91 ty = newstruct(UNION, string(type->v.rcc_UNION.tag)); 92 fields = type->v.rcc_UNION.fields; 93 } 94 itemmap[uid] = ty; /* recursive types */ 95 ty->size = type->size; 96 ty->align = type->align; 97 tail = &ty->u.sym->u.s.flist; 98 n = Seq_length(fields); 99 for (i = 0; i < n; i++) { 100 rcc_field_ty field = Seq_remlo(fields); 101 NEW0(*tail, PERM); 102 (*tail)->name = (char *)field->id; 103 (*tail)->type = uid2type(field->type); 104 (*tail)->offset = field->offset; 105 (*tail)->bitsize = field->bitsize; 106 (*tail)->lsb = field->lsb; 107 if (isconst((*tail)->type)) 108 ty->u.sym->u.s.cfields = 1; 109 if (isvolatile((*tail)->type)) 110 ty->u.sym->u.s.vfields = 1; 111 tail = &(*tail)->link; 112 free(field); 113 } 114 Seq_free(&fields); 115 break; 116 } 117 case rcc_FUNCTION_enum: { 118 int n = Seq_length(type->v.rcc_FUNCTION.formals); 119 if (n > 0) { 120 int i; 121 Type *proto = newarray(n + 1, sizeof *proto, PERM); 122 for (i = 0; i < n; i++) { 123 int *formal = Seq_remlo(type->v.rcc_FUNCTION.formals); 124 proto[i] = uid2type(*formal); 125 free(formal); 126 } 127 proto[i] = NULL; 128 ty = func(uid2type(type->v.rcc_FUNCTION.type), proto, 0); 129 } else 130 ty = func(uid2type(type->v.rcc_FUNCTION.type), NULL, 1); 131 Seq_free(&type->v.rcc_FUNCTION.formals); 132 break; 133 } 134 default: assert(0); 135 } 136 if (itemmap[uid] == NULL) { 137 itemmap[uid] = ty; 138 free(type); 139 free(items[uid]); 140 items[uid] = NULL; 141 } else 142 assert(itemmap[uid] == ty); 143 } 144 return itemmap[uid]; 145 } 146 147 static Symbol uid2symbol(int uid) { 148 assert(uid >= 0 && uid < nuids); 149 if (itemmap[uid] == NULL) { 150 Symbol p; 151 rcc_symbol_ty symbol; 152 assert(items[uid]); 153 assert(items[uid]->uid == uid); 154 assert(items[uid]->kind == rcc_Symbol_enum); 155 symbol = items[uid]->v.rcc_Symbol.symbol; 156 assert(symbol); 157 NEW0(p, PERM); 158 p->name = (char *)symbol->id; 159 p->scope = symbol->scope; 160 p->sclass = symbol->sclass; 161 p->type = uid2type(symbol->type); 162 #define xx(f,n) p->f = symbol->flags>>n; 163 xx(structarg,0) 164 xx(addressed,1) 165 xx(computed,2) 166 xx(temporary,3) 167 xx(generated,4) 168 #undef xx 169 p->ref = symbol->ref/10000.0; 170 assert(p->scope != CONSTANTS && p->scope != LABELS); 171 if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN) 172 (*IR->defsymbol)(p); 173 itemmap[uid] = p; 174 free(symbol); 175 free(items[uid]); 176 items[uid] = NULL; 177 } 178 return itemmap[uid]; 179 } 180 181 #define xx(s) static void do##s(rcc_interface_ty); 182 xx(Export) 183 xx(Import) 184 xx(Global) 185 xx(Local) 186 xx(Address) 187 xx(Segment) 188 xx(Defaddress) 189 xx(Deflabel) 190 xx(Defconst) 191 xx(Defconstf) 192 xx(Defstring) 193 xx(Space) 194 xx(Function) 195 xx(Blockbeg) 196 xx(Blockend) 197 xx(Forest) 198 #undef xx 199 static void (*doX[])(rcc_interface_ty in) = { 200 #define xx(s) 0, 201 xx(Export) 202 xx(Import) 203 xx(Global) 204 xx(Local) 205 xx(Address) 206 xx(Segment) 207 xx(Defaddress) 208 xx(Deflabel) 209 xx(Defconst) 210 xx(Defconstf) 211 xx(Defstring) 212 xx(Space) 213 xx(Function) 214 xx(Blockbeg) 215 xx(Blockend) 216 xx(Forest) 217 0 218 #undef xx 219 }; 220 221 static void interface(rcc_interface_ty in) { 222 assert(in); 223 (*doX[in->kind])(in); 224 free(in); 225 } 226 227 static void doExport(rcc_interface_ty in) { 228 (*IR->export)(uid2symbol(in->v.rcc_Export.p)); 229 } 230 231 static void doImport(rcc_interface_ty in) { 232 Symbol p = uid2symbol(in->v.rcc_Export.p); 233 234 (*IR->import)(p); 235 p->defined = 1; 236 } 237 238 static void doGlobal(rcc_interface_ty in) { 239 Symbol p = uid2symbol(in->v.rcc_Global.p); 240 241 p->u.seg = in->v.rcc_Global.seg; 242 (*IR->global)(p); 243 p->defined = 1; 244 } 245 246 static void doLocal(rcc_interface_ty in) { 247 int uid = in->v.rcc_Local.uid; 248 249 assert(uid >= 0 && uid < nuids); 250 assert(items[uid] == NULL); 251 items[uid] = rcc_Symbol(uid, in->v.rcc_Local.p); 252 if (in->v.rcc_Local.p->scope >= LOCAL) 253 addlocal(uid2symbol(uid)); 254 } 255 256 static void doAddress(rcc_interface_ty in) { 257 int uid = in->v.rcc_Address.uid; 258 Symbol p = uid2symbol(in->v.rcc_Address.p); 259 260 assert(uid >= 0 && uid < nuids); 261 assert(items[uid] == NULL); 262 items[uid] = rcc_Symbol(uid, in->v.rcc_Address.q); 263 if (p->scope == GLOBAL || p->sclass == STATIC || p->sclass == EXTERN) 264 (*IR->address)(uid2symbol(uid), p, in->v.rcc_Address.n); 265 else { 266 Code cp = code(Address); 267 cp->u.addr.sym = uid2symbol(uid); 268 cp->u.addr.base = p; 269 cp->u.addr.offset = in->v.rcc_Address.n; 270 } 271 } 272 273 static void doSegment(rcc_interface_ty in) { 274 (*IR->segment)(in->v.rcc_Segment.seg); 275 } 276 277 static void doDefaddress(rcc_interface_ty in) { 278 (*IR->defaddress)(uid2symbol(in->v.rcc_Defaddress.p)); 279 } 280 281 static void doDeflabel(rcc_interface_ty in) { 282 (*IR->defaddress)(findlabel(in->v.rcc_Deflabel.label)); 283 } 284 285 static void doDefconst(rcc_interface_ty in) { 286 Value v; 287 288 v.i = in->v.rcc_Defconst.value; 289 (*IR->defconst)(in->v.rcc_Defconst.suffix, in->v.rcc_Defconst.size, v); 290 } 291 292 static void doDefconstf(rcc_interface_ty in) { 293 Value v; 294 unsigned *p = (unsigned *)&v.d; 295 296 p[swap] = in->v.rcc_Defconstf.value->msb; 297 p[1-swap] = in->v.rcc_Defconstf.value->lsb; 298 (*IR->defconst)(F, in->v.rcc_Defconstf.size, v); 299 free(in->v.rcc_Defconstf.value); 300 } 301 302 static void doDefstring(rcc_interface_ty in) { 303 (*IR->defstring)(in->v.rcc_Defstring.s.len, (char *)in->v.rcc_Defstring.s.str); 304 free((char *)in->v.rcc_Defstring.s.str); 305 } 306 307 static void doSpace(rcc_interface_ty in) { 308 (*IR->space)(in->v.rcc_Space.n); 309 } 310 311 static void doFunction(rcc_interface_ty in) { 312 int i, n; 313 Symbol *caller, *callee; 314 315 /* 316 Initialize: 317 define the function symbol, 318 initialize callee and caller arrays. 319 */ 320 cfunc = uid2symbol(in->v.rcc_Function.f); 321 labels = table(NULL, LABELS); 322 enterscope(); 323 n = Seq_length(in->v.rcc_Function.caller); 324 caller = newarray(n + 1, sizeof *caller, FUNC); 325 for (i = 0; i < n; i++) { 326 int *uid = Seq_remlo(in->v.rcc_Function.caller); 327 caller[i] = uid2symbol(*uid); 328 free(uid); 329 } 330 caller[i] = NULL; 331 Seq_free(&in->v.rcc_Function.caller); 332 callee = newarray(n + 1, sizeof *callee, FUNC); 333 for (i = 0; i < n; i++) { 334 int *uid = Seq_remlo(in->v.rcc_Function.callee); 335 callee[i] = uid2symbol(*uid); 336 free(uid); 337 } 338 callee[i] = NULL; 339 Seq_free(&in->v.rcc_Function.callee); 340 cfunc->u.f.callee = callee; 341 cfunc->defined = 1; 342 /* 343 Initialize the code list, 344 traverse the interfaces inside the function; 345 each call appends code list entries. 346 */ 347 codelist = &codehead; 348 codelist->next = NULL; 349 n = Seq_length(in->v.rcc_Function.codelist); 350 for (i = 0; i < n; i++) 351 interface(Seq_remlo(in->v.rcc_Function.codelist)); 352 Seq_free(&in->v.rcc_Function.codelist); 353 /* 354 Call the back end, 355 Wrap-up. 356 */ 357 exitscope(); 358 (*IR->function)(cfunc, caller, callee, in->v.rcc_Function.ncalls); 359 cfunc = NULL; 360 labels = NULL; 361 } 362 363 static struct block { 364 Code begin; 365 struct block *prev; 366 } *blockstack = NULL; 367 368 static void doBlockbeg(rcc_interface_ty in) { 369 struct block *b; 370 Code cp = code(Blockbeg); 371 372 enterscope(); 373 cp->u.block.level = level; 374 cp->u.block.locals = newarray(1, sizeof *cp->u.block.locals, FUNC); 375 cp->u.block.locals[0] = NULL; 376 cp->u.block.identifiers = NULL; 377 cp->u.block.types = NULL; 378 NEW(b, FUNC); 379 b->begin = cp; 380 b->prev = blockstack; 381 blockstack = b; 382 } 383 384 static void doBlockend(rcc_interface_ty in) { 385 assert(blockstack); 386 code(Blockend)->u.begin = blockstack->begin; 387 blockstack = blockstack->prev; 388 exitscope(); 389 } 390 391 static Node visit(rcc_node_ty node) { 392 int op; 393 Node left = NULL, right = NULL, p = NULL; 394 Symbol sym = NULL; 395 396 switch (node->kind) { 397 #define T(x) rcc_##x##_enum 398 case T(CSE): { 399 Symbol q = uid2symbol(node->v.rcc_CSE.uid); 400 assert(q->temporary); 401 q->u.t.cse = p = visit(node->v.rcc_CSE.node); 402 break; 403 } 404 case T(CNST): { 405 Value v; 406 v.i = node->v.rcc_CNST.value; 407 sym = constant(btot(node->suffix, node->size), v); 408 op = CNST; 409 break; 410 } 411 case T(CNSTF): { 412 Value v; 413 unsigned *p = (unsigned *)&v.d; 414 p[swap] = node->v.rcc_CNSTF.value->msb; 415 p[1-swap] = node->v.rcc_CNSTF.value->lsb; 416 sym = constant(btot(node->suffix, node->size), v); 417 free(node->v.rcc_CNSTF.value); 418 op = CNST; 419 break; 420 } 421 case T(ARG): 422 p = newnode(ARG + node->suffix + sizeop(node->size), 423 visit(node->v.rcc_ARG.left), NULL, 424 intconst(node->v.rcc_ARG.len)); 425 p->syms[1] = intconst(node->v.rcc_ARG.align); 426 break; 427 case T(ASGN): 428 p = newnode(ASGN + node->suffix + sizeop(node->size), 429 visit(node->v.rcc_ASGN.left), visit(node->v.rcc_ASGN.right), 430 intconst(node->v.rcc_ASGN.len)); 431 p->syms[1] = intconst(node->v.rcc_ASGN.align); 432 break; 433 case T(CVT): 434 op = node->v.rcc_CVT.op; 435 left = visit(node->v.rcc_CVT.left); 436 sym = intconst(node->v.rcc_CVT.fromsize); 437 break; 438 case T(CALL): 439 op = CALL; 440 left = visit(node->v.rcc_CALL.left); 441 NEW0(sym, FUNC); 442 sym->type = uid2type(node->v.rcc_CALL.type); 443 break; 444 case T(CALLB): 445 op = CALL; 446 left = visit(node->v.rcc_CALLB.left); 447 right = visit(node->v.rcc_CALLB.right); 448 NEW0(sym, FUNC); 449 sym->type = uid2type(node->v.rcc_CALLB.type); 450 break; 451 case T(RET): 452 op = RET; 453 break; 454 case T(ADDRG): 455 op = ADDRG; 456 sym = uid2symbol(node->v.rcc_ADDRG.uid); 457 break; 458 case T(ADDRL): 459 op = ADDRL; 460 sym = uid2symbol(node->v.rcc_ADDRG.uid); 461 break; 462 case T(ADDRF): 463 op = ADDRF; 464 sym = uid2symbol(node->v.rcc_ADDRG.uid); 465 break; 466 case T(Unary): 467 op = node->v.rcc_Unary.op; 468 left = visit(node->v.rcc_Unary.left); 469 break; 470 case T(Binary): 471 op = node->v.rcc_Binary.op; 472 left = visit(node->v.rcc_Binary.left); 473 right = visit(node->v.rcc_Binary.right); 474 break; 475 case T(Compare): 476 op = node->v.rcc_Compare.op; 477 left = visit(node->v.rcc_Compare.left); 478 right = visit(node->v.rcc_Compare.right); 479 sym = findlabel(node->v.rcc_Compare.label); 480 break; 481 case T(LABEL): 482 op = LABEL; 483 sym = findlabel(node->v.rcc_LABEL.label); 484 break; 485 case T(BRANCH): 486 op = JUMP; 487 left = newnode(ADDRG+P+sizeop(voidptype->size), NULL, NULL, findlabel(node->v.rcc_BRANCH.label)); 488 break; 489 #undef T 490 default: assert(0); 491 } 492 if (p == NULL) 493 p = newnode(op + node->suffix + sizeop(node->size), left, right, sym); 494 free(node); 495 return p; 496 } 497 498 static void doForest(rcc_interface_ty in) { 499 Node *tail = &code(Gen)->u.forest; 500 int i, n = Seq_length(in->v.rcc_Forest.nodes); 501 502 for (i = 0; i < n; i++) { 503 *tail = visit(Seq_remlo(in->v.rcc_Forest.nodes)); 504 assert(*tail); 505 tail = &(*tail)->link; 506 } 507 *tail = NULL; 508 Seq_free(&in->v.rcc_Forest.nodes); 509 } 510 511 int main(int argc, char *argv[]) { 512 int i, version; 513 float stamp = (assert(strstr(rcsid, ",v")), strtod(strstr(rcsid, ",v")+2, NULL)) 514 ; 515 char *infile = NULL, *outfile = NULL; 516 rcc_program_ty pickle; 517 518 for (i = 1; i < argc; i++) 519 if (*argv[i] != '-' || strcmp(argv[i], "-") == 0) { 520 if (infile == NULL) 521 infile = argv[i]; 522 else if (outfile == NULL) 523 outfile = argv[i]; 524 } 525 if (infile != NULL && strcmp(infile, "-") != 0 526 && freopen(infile, "rb", stdin) == NULL) { 527 fprint(stderr, "%s: can't read `%s'\n", argv[0], infile); 528 exit(EXIT_FAILURE); 529 } 530 #if WIN32 531 else 532 _setmode(_fileno(stdin), _O_BINARY); 533 #endif 534 if (outfile != NULL && strcmp(outfile, "-") != 0 535 && freopen(outfile, "w", stdout) == NULL) { 536 fprint(stderr, "%s: can't write `%s'\n", argv[0], outfile); 537 exit(EXIT_FAILURE); 538 } 539 version = read_int(stdin); 540 assert(version/100 == (int)stamp); 541 pickle = rcc_read_program(stdin); 542 argc = pickle->argc; 543 argv = newarray(argc + 1, sizeof *argv, PERM); 544 { 545 for (i = 0; i < argc; i++) { 546 string_ty *arg = Seq_remlo(pickle->argv); 547 argv[i] = (char *)arg->str; 548 free(arg); 549 } 550 argv[i] = NULL; 551 assert(i == argc); 552 Seq_free(&pickle->argv); 553 } 554 for (i = argc - 1; i > 0; i--) 555 if (strncmp(argv[i], "-target=", 8) == 0) 556 break; 557 if (i > 0) { 558 int j; 559 for (j = 0; bindings[j].name && bindings[j].ir; j++) 560 if (strcmp(&argv[i][8], bindings[j].name) == 0) { 561 IR = bindings[j].ir; 562 break; 563 } 564 } 565 if (!IR) { 566 fprint(stderr, "%s: unknown target", argv[0]); 567 if (i > 0) 568 fprint(stderr, " `%s'", &argv[i][8]); 569 fprint(stderr, "; must specify one of\n"); 570 for (i = 0; bindings[i].name; i++) 571 fprint(stderr, "\t-target=%s\n", bindings[i].name); 572 exit(EXIT_FAILURE); 573 } 574 IR->wants_dag = 0; /* pickle's hold trees */ 575 init(argc, argv); 576 genlabel(pickle->nlabels); 577 level = GLOBAL; 578 { 579 int i, count; 580 nuids = pickle->nuids; 581 items = newarray(nuids, sizeof *items, PERM); 582 itemmap = newarray(nuids, sizeof *items, PERM); 583 for (i = 0; i < nuids; i++) { 584 itemmap[i] = NULL; 585 items[i] = NULL; 586 } 587 (*IR->progbeg)(argc, argv); 588 count = Seq_length(pickle->items); 589 for (i = 0; i < count; i++) { 590 rcc_item_ty item = Seq_remlo(pickle->items); 591 int uid = item->uid; 592 assert(uid >= 0 && uid < nuids); 593 assert(items[uid] == NULL); 594 items[uid] = item; 595 } 596 Seq_free(&pickle->items); 597 #define xx(s) assert(rcc_##s##_enum < sizeof doX/sizeof doX[0] && doX[rcc_##s##_enum]==0); \ 598 doX[rcc_##s##_enum] = do##s; 599 xx(Export) 600 xx(Import) 601 xx(Global) 602 xx(Local) 603 xx(Address) 604 xx(Segment) 605 xx(Defaddress) 606 xx(Deflabel) 607 xx(Defconst) 608 xx(Defconstf) 609 xx(Defstring) 610 xx(Space) 611 xx(Function) 612 xx(Blockbeg) 613 xx(Blockend) 614 xx(Forest) 615 #undef xx 616 count = Seq_length(pickle->interfaces); 617 for (i = 0; i < count; i++) 618 interface(Seq_remlo(pickle->interfaces)); 619 Seq_free(&pickle->interfaces); 620 free(pickle); 621 (*IR->progend)(); 622 } 623 deallocate(PERM); 624 return errcnt > 0; 625 } 626 627 /* main_init - process program arguments */ 628 void main_init(int argc, char *argv[]) { 629 int i; 630 static int inited; 631 632 if (inited) 633 return; 634 inited = 1; 635 for (i = 1; i < argc; i++) 636 if (strcmp(argv[i], "-g") == 0 || strcmp(argv[i], "-g2") == 0) 637 glevel = 2; 638 else if (strcmp(argv[i], "-w") == 0) 639 wflag++; 640 else if (strcmp(argv[i], "-v") == 0) { 641 fprint(stderr, "%s %s\n", argv[0], rcsid); 642 verbose++; 643 } else if (strncmp(argv[i], "-errout=", 8) == 0) { 644 FILE *f = fopen(argv[i]+8, "w"); 645 if (f == NULL) { 646 fprint(stderr, "%s: can't write errors to `%s'\n", argv[0], argv[i]+8); 647 exit(EXIT_FAILURE); 648 } 649 fclose(f); 650 f = freopen(argv[i]+8, "w", stderr); 651 assert(f); 652 } else if (strncmp(argv[i], "-e", 2) == 0) { 653 int x; 654 if ((x = strtol(&argv[i][2], NULL, 0)) > 0) 655 errlimit = x; 656 } 657 } 658 659 void init(int argc, char *argv[]) { 660 {extern void main_init(int, char *[]); main_init(argc, argv);} 661 {extern void prof_init(int, char *[]); prof_init(argc, argv);} 662 {extern void trace_init(int, char *[]); trace_init(argc, argv);} 663 {extern void type_init(int, char *[]); type_init(argc, argv);} 664 {extern void x86linux_init(int, char *[]); x86linux_init(argc, argv);} 665 }