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