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