cgen.c (13906B)
1 #include <assert.h> 2 #include <stdlib.h> 3 4 #include <scc/cstd.h> 5 #include <scc/scc.h> 6 7 #include "arch.h" 8 #include "../../cc2.h" 9 10 #define I1BYTES 0 11 #define I2BYTES 1 12 #define I4BYTES 2 13 #define I8BYTES 3 14 15 static unsigned char opasmw[][2] = { 16 [OADD] = {ASADDW, ASADDW}, 17 [OSUB] = {ASSUBW, ASSUBW}, 18 [OMUL] = {ASMULW, ASMULW}, 19 [OMOD] = {ASMODW, ASUMODW}, 20 [ODIV] = {ASDIVW, ASUDIVW}, 21 [OSHL] = {ASSHLW, ASSHLW}, 22 [OSHR] = {ASSHRW, ASUSHRW}, 23 [OLT] = {ASLTW, ASULTW}, 24 [OGT] = {ASGTW, ASUGTW}, 25 [OLE] = {ASLEW, ASULEW}, 26 [OGE] = {ASGEW, ASUGEW}, 27 [OEQ] = {ASEQW, ASEQW}, 28 [ONE] = {ASNEW, ASNEW}, 29 [OBAND] = {ASBANDW, ASBANDW}, 30 [OBOR] = {ASBORW, ASBORW}, 31 [OBXOR] = {ASBXORW, ASBXORW}, 32 }; 33 34 static unsigned char opasml[][2] = { 35 [OADD] = {ASADDL, ASADDL}, 36 [OSUB] = {ASSUBL, ASSUBL}, 37 [OMUL] = {ASMULL, ASMULL}, 38 [OMOD] = {ASMODL, ASUMODL}, 39 [ODIV] = {ASDIVL, ASUDIVL}, 40 [OSHL] = {ASSHLL, ASSHLL}, 41 [OSHR] = {ASSHRL, ASUSHRL}, 42 [OLT] = {ASLTL, ASULTL}, 43 [OGT] = {ASGTL, ASUGTL}, 44 [OLE] = {ASLEL, ASULEL}, 45 [OGE] = {ASGEL, ASUGEL}, 46 [OEQ] = {ASEQL, ASEQL}, 47 [ONE] = {ASNEL, ASNEL}, 48 [OBAND] = {ASBANDL, ASBANDL}, 49 [OBOR] = {ASBORL, ASBORL}, 50 [OBXOR] = {ASBXORL, ASBXORL}, 51 }; 52 53 static unsigned char opasms[][2] = { 54 [OADD] = {ASADDS, ASADDS}, 55 [OSUB] = {ASSUBS, ASSUBS}, 56 [OMUL] = {ASMULS, ASMULS}, 57 [ODIV] = {ASDIVS, ASDIVS}, 58 [OLT] = {ASLTS, ASLTS}, 59 [OGT] = {ASGTS, ASGTS}, 60 [OLE] = {ASLES, ASLES}, 61 [OGE] = {ASGES, ASGES}, 62 [OEQ] = {ASEQS, ASEQS}, 63 [ONE] = {ASNES, ASNES}, 64 }; 65 66 static unsigned char opasmd[][2] = { 67 [OADD] = {ASADDD, ASADDD}, 68 [OSUB] = {ASSUBD, ASSUBD}, 69 [OMUL] = {ASMULD, ASMULD}, 70 [ODIV] = {ASDIVD, ASDIVD}, 71 [OLT] = {ASLTD, ASLTD}, 72 [OGT] = {ASGTD, ASGTD}, 73 [OLE] = {ASLED, ASLED}, 74 [OGE] = {ASGED, ASGED}, 75 [OEQ] = {ASEQD, ASEQD}, 76 [ONE] = {ASNED, ASNED}, 77 }; 78 79 static unsigned char (*opbin[][2])[2] = { 80 {opasmw, opasml}, 81 {opasms, opasmd}, 82 }; 83 84 static unsigned char i2i_conv[4][4][2] = { 85 [I1BYTES] = { 86 [I4BYTES] = {ASEXTBW, ASUEXTBW}, 87 [I8BYTES] = {ASEXTBL, ASUEXTBL}, 88 }, 89 [I2BYTES] = { 90 [I4BYTES] = {ASEXTHW, ASUEXTHW}, 91 [I8BYTES] = {ASEXTHL, ASUEXTHL}, 92 }, 93 [I4BYTES] = { 94 [I8BYTES] = {ASEXTWL, ASUEXTWL}, 95 } 96 }; 97 98 static unsigned char f2i_conv[4][4][2] = { 99 [I4BYTES] = { 100 [I4BYTES] = {ASSTOW, ASSTOUW}, 101 [I8BYTES] = {ASSTOL, ASDTOUL}, 102 }, 103 [I8BYTES] = { 104 [I4BYTES] = {ASDTOW, ASDTOUW}, 105 [I8BYTES] = {ASDTOL, ASDTOUL}, 106 } 107 }; 108 109 static unsigned char i2f_conv[4][4][2] = { 110 [I4BYTES] = { 111 [I4BYTES] = {ASSWTOS, ASUWTOS}, 112 [I8BYTES] = {ASSWTOD, ASUWTOD}, 113 }, 114 [I8BYTES] = { 115 [I4BYTES] = {ASSLTOS, ASULTOS}, 116 [I8BYTES] = {ASSLTOD, ASULTOD}, 117 } 118 }; 119 120 extern Type int32type, uint32type, ptrtype; 121 122 /* 123 * This is strongly influenced by 124 * http://plan9.bell-labs.com/sys/doc/compiler.ps (/sys/doc/compiler.ps) 125 * calculate addresability as follows 126 * AUTO => 11 value+fp 127 * REG => 11 reg 128 * STATIC => 11 (value) 129 * CONST => 11 $value 130 * These values of addressability are not used in the code generation. 131 * They are only used to calculate the Sethi-Ullman numbers. Since 132 * QBE is AMD64 targered we could do a better job there, and try to 133 * detect some of the complex addressing modes of these processors. 134 */ 135 static Node * 136 complex(Node *np) 137 { 138 Node *lp = np->left, *rp = np->right; 139 140 if (np->address > 10) 141 return np; 142 if (lp) 143 np->complex = lp->complex; 144 if (rp) { 145 int d = np->complex - rp->complex; 146 147 if (d == 0) 148 ++np->complex; 149 else if (d < 0) 150 np->complex = rp->complex; 151 } 152 if (np->complex == 0) 153 ++np->complex; 154 155 return np; 156 } 157 158 Node * 159 sethi(Node *np) 160 { 161 Node *lp, *rp; 162 163 if (!np) 164 return np; 165 166 np->complex = 0; 167 np->address = 0; 168 lp = np->left; 169 rp = np->right; 170 171 switch (np->op) { 172 case OAUTO: 173 case OREG: 174 case OMEM: 175 case OCONST: 176 np->address = 11; 177 break; 178 case OASSIG: 179 assert(lp->op != OCAST); 180 goto binary; 181 case OCPL: 182 assert(np->type.flags & INTF); 183 np->op = OBXOR; 184 rp = constnode(NULL, ~(TUINT) 0, &np->type); 185 goto binary; 186 case OSNEG: 187 np->op = OSUB; 188 rp = lp; 189 lp = constnode(NULL, 0, &np->type); 190 if ((np->type.flags & INTF) == 0) 191 lp->u.f = 0.0; 192 default: 193 binary: 194 lp = sethi(lp); 195 rp = sethi(rp); 196 break; 197 } 198 np->left = lp; 199 np->right = rp; 200 201 return complex(np); 202 } 203 204 static int 205 bytes2idx(int nbytes) 206 { 207 if (nbytes== 1) 208 return I1BYTES; 209 else if (nbytes == 2) 210 return I2BYTES; 211 else if (nbytes == 4) 212 return I4BYTES; 213 else if (nbytes == 8) 214 return I8BYTES; 215 else 216 abort(); 217 } 218 219 static Node * 220 load(Type *tp, Node *np) 221 { 222 int op; 223 Node *new; 224 int flags = tp->flags; 225 226 if (flags & (AGGRF|FUNF|ARRF|PTRF)) 227 return np; 228 229 switch (tp->size) { 230 case 1: 231 op = ASLDSB; 232 break; 233 case 2: 234 op = ASLDSH; 235 break; 236 case 4: 237 op = (flags & FLOATF) ? ASLDS : ASLDSW; 238 break; 239 case 8: 240 op = (flags & FLOATF) ? ASLDD : ASLDL; 241 break; 242 default: 243 abort(); 244 } 245 /* 246 * unsigned version of operations are always +1 the 247 * signed version 248 */ 249 if ((flags & (INTF|SIGNF)) == INTF && tp->size < 8) 250 ++op; 251 252 new = tmpnode(tp); 253 code(op, new, np, NULL); 254 255 return new; 256 } 257 258 static Node *rhs(Node *np); 259 260 static Node * 261 cast(Type *td, Node *np) 262 { 263 Type *ts; 264 Node *tmp; 265 int op, d_isint, s_isint, sidx, didx, sign; 266 267 ts = &np->type; 268 d_isint = (td->flags & INTF) != 0; 269 s_isint = (ts->flags & INTF) != 0; 270 271 sidx = bytes2idx(ts->size); 272 didx = bytes2idx(td->size); 273 274 sign = (ts->flags & SIGNF) == 0; 275 276 if (d_isint && s_isint) { 277 /* conversion from int to int */ 278 if (didx < I4BYTES) 279 didx = bytes2idx(4); 280 281 if (didx <= sidx) { 282 np->type = *td; 283 return np; 284 } 285 286 op = i2i_conv[sidx][didx][sign]; 287 } else if (d_isint) { 288 /* conversion from float to int */ 289 if (didx < I4BYTES) 290 didx = bytes2idx(4); 291 292 op = f2i_conv[sidx][didx][sign]; 293 } else if (s_isint) { 294 /* conversion from int to float */ 295 if (sidx == I1BYTES || sidx == I2BYTES) { 296 ts = (ts->flags&SIGNF) ? &int32type : &uint32type; 297 np = cast(ts, np); 298 } 299 op = i2f_conv[sidx][didx][sign]; 300 } else { 301 /* conversion from float to float */ 302 op = (didx == I4BYTES) ? ASEXTS : ASTRUNCD; 303 } 304 305 assert(op != 0); 306 tmp = tmpnode(td); 307 code(op, tmp, np, NULL); 308 309 return tmp; 310 } 311 312 static Node * 313 call(Node *np, Node *fun) 314 { 315 int n, op; 316 Type *tp; 317 Node **q, *tmp, *p, *pars[NR_FUNPARAM]; 318 319 for (n = 0, p = np->right; p; p = p->right) 320 pars[n++] = rhs(p->left); 321 322 tp = &np->type; 323 tmp = tmpnode(tp); 324 code(ASCALL, tmp, fun, NULL); 325 326 for (q = pars; q < &pars[n]; ++q) { 327 op = (q == &pars[n-1]) ? ASPARE : ASPAR; 328 code(op, NULL, *q, tmpnode(&(*q)->type)); 329 } 330 code((np->op == OCALL) ? ASCALLE : ASCALLEX, NULL, NULL, NULL); 331 332 return tmp; 333 } 334 335 static Node * 336 copy(Type *tp, Node *to, Node *from) 337 { 338 int op; 339 340 switch (tp->size) { 341 case 0: 342 return from; 343 case 1: 344 op = ASCOPYB; 345 break; 346 case 2: 347 op = ASCOPYH; 348 break; 349 case 4: 350 op = (tp->flags & FLOATF) ? ASCOPYS : ASCOPYW; 351 break; 352 case 8: 353 op = (tp->flags & FLOATF) ? ASCOPYD : ASCOPYL; 354 break; 355 default: 356 abort(); 357 } 358 code(op, to, from, NULL); 359 return from; 360 } 361 362 static Node * 363 field(Node *np, int islhs) 364 { 365 Node *tmp, *addr; 366 TUINT offset = np->right->u.sym->u.off; 367 368 addr = rhs(np->left); 369 tmp = node(OADD); 370 tmp->type = ptrtype; 371 tmp->left = addr; 372 tmp->right = constnode(NULL, offset, &ptrtype); 373 addr = rhs(tmp); 374 375 if (!islhs) 376 addr = load(&np->type, addr); 377 return addr; 378 } 379 380 static Node * 381 lhs(Node *np) 382 { 383 switch (np->op) { 384 case OREG: 385 case OMEM: 386 case OAUTO: 387 return np; 388 case OPTR: 389 return rhs(np->left); 390 case OFIELD: 391 return field(np, 1); 392 default: 393 abort(); 394 } 395 } 396 397 static void 398 bool(Node *np, Symbol *true, Symbol *false) 399 { 400 Node *l = np->left, *r = np->right; 401 Node ret, ifyes, ifno; 402 Symbol *label; 403 404 switch (np->op) { 405 case ONEG: 406 bool(l, false, true); 407 break; 408 case OAND: 409 label = newlabel(); 410 bool(l, label, false); 411 setlabel(label); 412 bool(r, true, false); 413 break; 414 case OOR: 415 label = newlabel(); 416 bool(l, true, label); 417 setlabel(label); 418 bool(r, true, false); 419 break; 420 default: 421 label2node(&ifyes, true); 422 label2node(&ifno, false); 423 code(ASBRANCH, rhs(np), &ifyes, &ifno); 424 break; 425 } 426 } 427 428 static Node * 429 ternary(Node *np) 430 { 431 Node ifyes, ifno, phi, *colon, *tmp; 432 433 tmp = tmpnode(&np->type); 434 label2node(&ifyes, NULL); 435 label2node(&ifno, NULL); 436 label2node(&phi, NULL); 437 438 colon = np->right; 439 code(ASBRANCH, rhs(np->left), &ifyes, &ifno); 440 441 setlabel(ifyes.u.sym); 442 copy(&tmp->type, tmp, rhs(colon->left)); 443 code(ASJMP, NULL, &phi, NULL); 444 445 setlabel(ifno.u.sym); 446 copy(&tmp->type, tmp, rhs(colon->right)); 447 setlabel(phi.u.sym); 448 449 return tmp; 450 } 451 452 static Node * 453 function(void) 454 { 455 Node aux; 456 Symbol *p; 457 458 /* allocate stack space for parameters */ 459 for (p = locals; p; p = p->next) { 460 if ((p->type.flags & PARF) == 0) 461 continue; 462 if ((p->type.flags & AGGRF) != 0) 463 continue; 464 code(ASALLOC, label2node(&aux, p), NULL, NULL); 465 } 466 467 /* allocate stack space for local variables) */ 468 for (p = locals; p; p = p->next) { 469 if ((p->type.flags & PARF) != 0) 470 continue; 471 if (p->kind != SAUTO || p->id == TMPSYM) 472 continue; 473 code(ASALLOC, label2node(&aux, p), NULL, NULL); 474 } 475 476 /* store formal parameters in parameters */ 477 for (p = locals; p; p = p->next) { 478 if ((p->type.flags & PARF) == 0) 479 continue; 480 if ((p->type.flags & AGGRF) != 0) 481 continue; 482 if ((p->type.flags & (ARRF|AGGRF)) == 0) 483 code(ASFORM, label2node(&aux, p), NULL, NULL); 484 } 485 return NULL; 486 } 487 488 static void 489 swtch_if(Node *idx) 490 { 491 Node aux1, aux2, *np; 492 Symbol *deflabel = NULL; 493 494 for (;;) { 495 np = delstmt(); 496 setlabel(np->label); 497 498 switch (np->op) { 499 case OESWITCH: 500 if (!deflabel) 501 deflabel = np->u.sym; 502 aux1.op = OJMP; 503 aux1.label = NULL; 504 aux1.u.sym = deflabel; 505 cgen(&aux1); 506 return; 507 case OCASE: 508 aux1 = *np; 509 aux1.op = OBRANCH; 510 aux1.label = NULL; 511 aux1.left = &aux2; 512 513 aux2.op = OEQ; 514 aux2.type = idx->type; 515 aux2.left = np->left; 516 aux2.right = idx; 517 518 cgen(&aux1); 519 break; 520 case ODEFAULT: 521 deflabel = np->u.sym; 522 break; 523 default: 524 abort(); 525 } 526 } 527 } 528 529 static int 530 assignop(Type *tp) 531 { 532 int flags = tp->flags; 533 534 if (flags & (AGGRF|FUNF|ARRF)) 535 return ASSTM; 536 537 switch (tp->size) { 538 case 1: 539 return ASSTB; 540 case 2: 541 return ASSTH; 542 case 4: 543 return (tp->flags & FLOATF) ? ASSTS : ASSTW; 544 case 8: 545 return (tp->flags & FLOATF) ? ASSTD : ASSTL; 546 default: 547 abort(); 548 } 549 } 550 551 static void 552 rhs_rhs(Node **lp, Node **rp) 553 { 554 Node *l = *lp, *r = *rp; 555 556 if (l->complex >= r->complex) { 557 l = rhs(l); 558 r = rhs(r); 559 } else { 560 r = rhs(r); 561 l = rhs(l); 562 } 563 564 *lp = l, *rp = r; 565 } 566 567 static void 568 lhs_rhs(Node **lp, Node **rp) 569 { 570 Node *l = *lp, *r = *rp; 571 572 if (l->complex >= r->complex) { 573 l = lhs(l); 574 r = rhs(r); 575 } else { 576 r = rhs(r); 577 l = lhs(l); 578 } 579 580 *lp = l, *rp = r; 581 } 582 583 static Node * 584 assign(Node *np) 585 { 586 Node *ret, aux; 587 Node *l = np->left, *r = np->right; 588 int op; 589 590 switch (np->u.subop) { 591 break; 592 case OINC: 593 op = OADD; 594 goto post_oper; 595 case ODEC: 596 op = OSUB; 597 post_oper: 598 lhs_rhs(&l, &r); 599 ret = load(&l->type, l); 600 aux.op = op; 601 aux.left = ret; 602 aux.right = r; 603 aux.type = np->type; 604 r = rhs(sethi(&aux)); 605 break; 606 default: 607 /* assign abbreviation */ 608 assert(l->type.size == r->type.size); 609 if (r->type.size < 4) { 610 lhs_rhs(&l, &r); 611 aux.op = np->u.subop; 612 aux.left = load(&r->type, l); 613 aux.right = r; 614 aux.type = int32type; 615 aux.address = np->address; 616 ret = r = sethi(rhs(&aux)); 617 break; 618 } 619 620 aux.op = np->u.subop; 621 aux.left = l; 622 aux.right = r; 623 aux.type = np->type; 624 aux.address = np->address; 625 r = sethi(&aux); 626 case 0: 627 lhs_rhs(&l, &r); 628 ret = r; 629 break; 630 } 631 632 code(assignop(&np->type), l, r, NULL); 633 return ret; 634 } 635 636 static Node * 637 rhs(Node *np) 638 { 639 Node *tmp, aux1, aux2; 640 Node *phi, *l = np->left, *r = np->right; 641 Type *tp; 642 int sign, size, isfloat, op; 643 Symbol *true, *false; 644 645 tp = &np->type; 646 647 switch (np->op) { 648 case OBFUN: 649 return function(); 650 case ONOP: 651 case OBLOOP: 652 case OELOOP: 653 case OEFUN: 654 return NULL; 655 case OTMP: 656 case OCONST: 657 return np; 658 case OMEM: 659 case OREG: 660 case OAUTO: 661 return load(tp, np); 662 case ONEG: 663 case OAND: 664 case OOR: 665 true = newlabel(); 666 false = newlabel(); 667 phi = label2node(&aux1, NULL); 668 tmp = tmpnode(&int32type); 669 670 bool(np, true, false); 671 672 setlabel(true); 673 code(ASCOPYW, tmp, constnode(&aux2, 1, &int32type), NULL); 674 code(ASJMP, NULL, phi, NULL); 675 676 setlabel(false); 677 code(ASCOPYW, tmp, constnode(&aux2, 0, &int32type), NULL); 678 679 setlabel(phi->u.sym); 680 return tmp; 681 case OMOD: 682 case OSHL: 683 case OBAND: 684 case OBOR: 685 case OBXOR: 686 case OSHR: 687 assert(tp->flags & INTF); 688 case ODIV: 689 case OLT: 690 case OGT: 691 case OLE: 692 case OGE: 693 case OADD: 694 case OSUB: 695 case OMUL: 696 case OEQ: 697 case ONE: 698 assert(tp->size == 4 || tp->size == 8); 699 700 sign = (tp->flags & SIGNF) == 0; 701 size = tp->size == 8; 702 isfloat = (tp->flags & FLOATF) != 0; 703 op = opbin[isfloat][size][np->op][sign]; 704 rhs_rhs(&l, &r); 705 tmp = tmpnode(tp); 706 code(op, tmp, l, r); 707 return tmp; 708 case OCALL: 709 case OCALLE: 710 if (l->op == OPTR) 711 l = rhs(l); 712 return call(np, l); 713 case OCAST: 714 return cast(tp, rhs(l)); 715 case OASSIG: 716 return assign(np); 717 case OASK: 718 return ternary(np); 719 case OCOMMA: 720 rhs(l); 721 return rhs(r); 722 case OPTR: 723 return load(tp, rhs(l)); 724 case OADDR: 725 l = lhs(l); 726 l->type = *tp; 727 l->type.flags |= PTRF; 728 return l; 729 case OFIELD: 730 return field(np, 0); 731 case OBUILTIN: 732 switch (np->u.subop) { 733 case BVA_START: 734 l = rhs(l); 735 code(ASVSTAR, NULL, l, NULL); 736 case BVA_END: 737 return NULL; 738 case BVA_ARG: 739 l = rhs(l); 740 tmp = tmpnode(tp); 741 code(ASVARG, tmp, l, NULL); 742 return tmp; 743 default: 744 abort(); 745 } 746 default: 747 abort(); 748 } 749 abort(); 750 } 751 752 Node * 753 cgen(Node *np) 754 { 755 Node aux, *p, *next; 756 757 setlabel(np->label); 758 switch (np->op) { 759 case OJMP: 760 label2node(&aux, np->u.sym); 761 code(ASJMP, NULL, &aux, NULL); 762 break; 763 case OBRANCH: 764 next = np->next; 765 if (!next->label) 766 next->label = newlabel(); 767 bool(np->left, np->u.sym, next->label); 768 break; 769 case ORET: 770 p = (np->left) ? rhs(np->left) : NULL; 771 code(ASRET, NULL, p, NULL); 772 break; 773 case OBSWITCH: 774 p = rhs(np->left); 775 swtch_if(p); 776 break; 777 default: 778 rhs(np); 779 break; 780 } 781 return NULL; 782 }