1 #include "gc.h" 2 3 void 4 codgen(Node *n, Node *nn) 5 { 6 Prog *sp; 7 Node *n1, nod, nod1; 8 9 cursafe = 0; 10 curarg = 0; 11 maxargsafe = 0; 12 13 /* 14 * isolate name 15 */ 16 for(n1 = nn;; n1 = n1->left) { 17 if(n1 == Z) { 18 diag(nn, "cant find function name"); 19 return; 20 } 21 if(n1->op == ONAME) 22 break; 23 } 24 nearln = nn->lineno; 25 gpseudo(ATEXT, n1->sym, nodconst(stkoff)); 26 sp = p; 27 sp->reg |= ALLTHUMBS; /* denotes thumb code */ 28 29 /* 30 * isolate first argument 31 */ 32 if(REGARG >= 0) { 33 if(typesuv[thisfn->link->etype]) { 34 nod1 = *nodret->left; 35 nodreg(&nod, &nod1, REGARG); 36 gopcode(OAS, &nod, Z, &nod1); 37 } else 38 if(firstarg && typechlp[firstargtype->etype]) { 39 nod1 = *nodret->left; 40 nod1.sym = firstarg; 41 nod1.type = firstargtype; 42 nod1.xoffset = align(0, firstargtype, Aarg1); 43 nod1.etype = firstargtype->etype; 44 nodreg(&nod, &nod1, REGARG); 45 gopcode(OAS, &nod, Z, &nod1); 46 } 47 } 48 49 retok = 0; 50 gen(n); 51 if(!retok) 52 if(thisfn->link->etype != TVOID) 53 warn(Z, "no return at end of function: %s", n1->sym->name); 54 noretval(3); 55 gbranch(ORETURN); 56 57 if(!debug['N'] || debug['R'] || debug['P']) 58 regopt(sp); 59 60 sp->to.offset += maxargsafe; 61 } 62 63 void 64 supgen(Node *n) 65 { 66 long spc; 67 Prog *sp; 68 69 if(n == Z) 70 return; 71 suppress++; 72 spc = pc; 73 sp = lastp; 74 gen(n); 75 lastp = sp; 76 pc = spc; 77 sp->link = nil; 78 suppress--; 79 } 80 81 void 82 gen(Node *n) 83 { 84 Node *l, nod; 85 Prog *sp, *spc, *spb; 86 Case *cn; 87 long sbc, scc; 88 int o, f; 89 90 loop: 91 if(n == Z) 92 return; 93 nearln = n->lineno; 94 o = n->op; 95 if(debug['G']) 96 if(o != OLIST) 97 print("%L %O\n", nearln, o); 98 99 retok = 0; 100 switch(o) { 101 102 default: 103 complex(n); 104 cgen(n, Z); 105 break; 106 107 case OLIST: 108 gen(n->left); 109 110 rloop: 111 n = n->right; 112 goto loop; 113 114 case ORETURN: 115 retok = 1; 116 complex(n); 117 if(n->type == T) 118 break; 119 l = n->left; 120 if(l == Z) { 121 noretval(3); 122 gbranch(ORETURN); 123 break; 124 } 125 if(typesuv[n->type->etype]) { 126 sugen(l, nodret, n->type->width); 127 noretval(3); 128 gbranch(ORETURN); 129 break; 130 } 131 regret(&nod, n); 132 cgen(l, &nod); 133 regfree(&nod); 134 if(typefd[n->type->etype]) 135 noretval(1); 136 else 137 noretval(2); 138 gbranch(ORETURN); 139 break; 140 141 case OLABEL: 142 l = n->left; 143 if(l) { 144 l->pc = pc; 145 if(l->label) 146 patch(l->label, pc); 147 } 148 gbranch(OGOTO); /* prevent self reference in reg */ 149 patch(p, pc); 150 goto rloop; 151 152 case OGOTO: 153 retok = 1; 154 n = n->left; 155 if(n == Z) 156 return; 157 if(n->complex == 0) { 158 diag(Z, "label undefined: %s", n->sym->name); 159 return; 160 } 161 if(suppress) 162 return; 163 gbranch(OGOTO); 164 if(n->pc) { 165 patch(p, n->pc); 166 return; 167 } 168 if(n->label) 169 patch(n->label, pc-1); 170 n->label = p; 171 return; 172 173 case OCASE: 174 l = n->left; 175 if(cases == C) 176 diag(n, "case/default outside a switch"); 177 if(l == Z) { 178 cas(); 179 cases->val = 0; 180 cases->def = 1; 181 cases->label = pc; 182 goto rloop; 183 } 184 complex(l); 185 if(l->type == T) 186 goto rloop; 187 if(l->op == OCONST) 188 if(typechl[l->type->etype]) { 189 cas(); 190 cases->val = l->vconst; 191 cases->def = 0; 192 cases->label = pc; 193 goto rloop; 194 } 195 diag(n, "case expression must be integer constant"); 196 goto rloop; 197 198 case OSWITCH: 199 l = n->left; 200 complex(l); 201 if(l->type == T) 202 break; 203 if(!typechl[l->type->etype]) { 204 diag(n, "switch expression must be integer"); 205 break; 206 } 207 208 gbranch(OGOTO); /* entry */ 209 sp = p; 210 211 cn = cases; 212 cases = C; 213 cas(); 214 215 sbc = breakpc; 216 breakpc = pc; 217 gbranch(OGOTO); 218 spb = p; 219 220 gen(n->right); 221 gbranch(OGOTO); 222 patch(p, breakpc); 223 224 patch(sp, pc); 225 regalloc(&nod, l, Z); 226 nod.type = types[TLONG]; 227 cgen(l, &nod); 228 doswit(&nod); 229 regfree(&nod); 230 patch(spb, pc); 231 232 cases = cn; 233 breakpc = sbc; 234 break; 235 236 case OWHILE: 237 case ODWHILE: 238 l = n->left; 239 gbranch(OGOTO); /* entry */ 240 sp = p; 241 242 scc = continpc; 243 continpc = pc; 244 gbranch(OGOTO); 245 spc = p; 246 247 sbc = breakpc; 248 breakpc = pc; 249 gbranch(OGOTO); 250 spb = p; 251 252 patch(spc, pc); 253 if(n->op == OWHILE) 254 patch(sp, pc); 255 bcomplex(l, Z); /* test */ 256 patch(p, breakpc); 257 258 if(n->op == ODWHILE) 259 patch(sp, pc); 260 gen(n->right); /* body */ 261 gbranch(OGOTO); 262 patch(p, continpc); 263 264 patch(spb, pc); 265 continpc = scc; 266 breakpc = sbc; 267 break; 268 269 case OFOR: 270 l = n->left; 271 gen(l->right->left); /* init */ 272 gbranch(OGOTO); /* entry */ 273 sp = p; 274 275 scc = continpc; 276 continpc = pc; 277 gbranch(OGOTO); 278 spc = p; 279 280 sbc = breakpc; 281 breakpc = pc; 282 gbranch(OGOTO); 283 spb = p; 284 285 patch(spc, pc); 286 gen(l->right->right); /* inc */ 287 patch(sp, pc); 288 if(l->left != Z) { /* test */ 289 bcomplex(l->left, Z); 290 patch(p, breakpc); 291 } 292 gen(n->right); /* body */ 293 gbranch(OGOTO); 294 patch(p, continpc); 295 296 patch(spb, pc); 297 continpc = scc; 298 breakpc = sbc; 299 break; 300 301 case OCONTINUE: 302 if(continpc < 0) { 303 diag(n, "continue not in a loop"); 304 break; 305 } 306 gbranch(OGOTO); 307 patch(p, continpc); 308 break; 309 310 case OBREAK: 311 if(breakpc < 0) { 312 diag(n, "break not in a loop"); 313 break; 314 } 315 gbranch(OGOTO); 316 patch(p, breakpc); 317 break; 318 319 case OIF: 320 l = n->left; 321 if(bcomplex(l, n->right)) { 322 if(typefd[l->type->etype]) 323 f = !l->fconst; 324 else 325 f = !l->vconst; 326 if(debug['c']) 327 print("%L const if %s\n", nearln, f ? "false" : "true"); 328 if(f) { 329 supgen(n->right->left); 330 gen(n->right->right); 331 } 332 else { 333 gen(n->right->left); 334 supgen(n->right->right); 335 } 336 } 337 else { 338 sp = p; 339 if(n->right->left != Z) 340 gen(n->right->left); 341 if(n->right->right != Z) { 342 gbranch(OGOTO); 343 patch(sp, pc); 344 sp = p; 345 gen(n->right->right); 346 } 347 patch(sp, pc); 348 } 349 break; 350 351 case OSET: 352 case OUSED: 353 usedset(n->left, o); 354 break; 355 } 356 } 357 358 void 359 usedset(Node *n, int o) 360 { 361 if(n->op == OLIST) { 362 usedset(n->left, o); 363 usedset(n->right, o); 364 return; 365 } 366 complex(n); 367 switch(n->op) { 368 case OADDR: /* volatile */ 369 gins(ANOP, n, Z); 370 break; 371 case ONAME: 372 if(o == OSET) 373 gins(ANOP, Z, n); 374 else 375 gins(ANOP, n, Z); 376 break; 377 } 378 } 379 380 void 381 noretval(int n) 382 { 383 384 if(n & 1) { 385 gins(ANOP, Z, Z); 386 p->to.type = D_REG; 387 p->to.reg = REGRET; 388 } 389 if(n & 2) { 390 gins(ANOP, Z, Z); 391 p->to.type = D_FREG; 392 p->to.reg = FREGRET; 393 } 394 } 395 396 /* 397 * calculate addressability as follows 398 * CONST ==> 20 $value 399 * NAME ==> 10 name 400 * REGISTER ==> 11 register 401 * INDREG ==> 12 *[(reg)+offset] 402 * &10 ==> 2 $name 403 * ADD(2, 20) ==> 2 $name+offset 404 * ADD(3, 20) ==> 3 $(reg)+offset 405 * &12 ==> 3 $(reg)+offset 406 * *11 ==> 11 ?? 407 * *2 ==> 10 name 408 * *3 ==> 12 *(reg)+offset 409 * calculate complexity (number of registers) 410 */ 411 void 412 xcom(Node *n) 413 { 414 Node *l, *r; 415 int t; 416 417 if(n == Z) 418 return; 419 l = n->left; 420 r = n->right; 421 n->addable = 0; 422 n->complex = 0; 423 switch(n->op) { 424 case OCONST: 425 n->addable = 20; 426 return; 427 428 case OREGISTER: 429 n->addable = 11; 430 return; 431 432 case OINDREG: 433 n->addable = 12; 434 return; 435 436 case ONAME: 437 n->addable = 10; 438 return; 439 440 case OADDR: 441 xcom(l); 442 if(l->addable == 10) 443 n->addable = 2; 444 if(l->addable == 12) 445 n->addable = 3; 446 break; 447 448 case OIND: 449 xcom(l); 450 if(l->addable == 11) 451 n->addable = 12; 452 if(l->addable == 3) 453 n->addable = 12; 454 if(l->addable == 2) 455 n->addable = 10; 456 break; 457 458 case OADD: 459 xcom(l); 460 xcom(r); 461 if(l->addable == 20) { 462 if(r->addable == 2) 463 n->addable = 2; 464 if(r->addable == 3) 465 n->addable = 3; 466 } 467 if(r->addable == 20) { 468 if(l->addable == 2) 469 n->addable = 2; 470 if(l->addable == 3) 471 n->addable = 3; 472 } 473 break; 474 475 /* 476 case OSUB: 477 xcom(l); 478 xcom(r); 479 if(typefd[n->type->etype] || typev[n->type->etype]) 480 break; 481 if(vconst(l) == 0) 482 n->op = ONEG; 483 n->left = l; 484 n->right = Z; 485 } 486 break; 487 */ 488 489 case OASHL: 490 case OASHR: 491 case OLSHR: 492 case OASASHL: 493 case OASASHR: 494 case OASLSHR: 495 xcom(l); 496 xcom(r); 497 if(sconst(r) && r->vconst < 0){ 498 r->vconst = -r->vconst; 499 switch(n->op){ 500 case OASHL: n->op = OASHR; break; 501 case OASHR: n->op = OASHL; break; 502 case OLSHR: n->op = OASHL; break; 503 case OASASHL: n->op = OASASHR; break; 504 case OASASHR: n->op = OASASHL; break; 505 case OASLSHR: n->op = OASASHL; break; 506 } 507 } 508 break; 509 510 case OASLMUL: 511 case OASMUL: 512 xcom(l); 513 xcom(r); 514 t = vlog(r); 515 if(t >= 0) { 516 n->op = OASASHL; 517 r->vconst = t; 518 r->type = types[TINT]; 519 } 520 break; 521 522 case OMUL: 523 case OLMUL: 524 xcom(l); 525 xcom(r); 526 t = vlog(r); 527 if(t >= 0) { 528 n->op = OASHL; 529 r->vconst = t; 530 r->type = types[TINT]; 531 } 532 t = vlog(l); 533 if(t >= 0) { 534 n->op = OASHL; 535 n->left = r; 536 n->right = l; 537 r = l; 538 l = n->left; 539 r->vconst = t; 540 r->type = types[TINT]; 541 } 542 break; 543 544 case OASLDIV: 545 xcom(l); 546 xcom(r); 547 t = vlog(r); 548 if(t >= 0) { 549 n->op = OASLSHR; 550 r->vconst = t; 551 r->type = types[TINT]; 552 } 553 break; 554 555 case OLDIV: 556 xcom(l); 557 xcom(r); 558 t = vlog(r); 559 if(t >= 0) { 560 n->op = OLSHR; 561 r->vconst = t; 562 r->type = types[TINT]; 563 } 564 break; 565 566 case OASLMOD: 567 xcom(l); 568 xcom(r); 569 t = vlog(r); 570 if(t >= 0) { 571 n->op = OASAND; 572 r->vconst--; 573 } 574 break; 575 576 case OLMOD: 577 xcom(l); 578 xcom(r); 579 t = vlog(r); 580 if(t >= 0) { 581 n->op = OAND; 582 r->vconst--; 583 } 584 break; 585 586 default: 587 if(l != Z) 588 xcom(l); 589 if(r != Z) 590 xcom(r); 591 break; 592 } 593 if(n->addable >= 10) 594 return; 595 596 if(l != Z) 597 n->complex = l->complex; 598 if(r != Z) { 599 if(r->complex == n->complex) 600 n->complex = r->complex+1; 601 else 602 if(r->complex > n->complex) 603 n->complex = r->complex; 604 } 605 if(n->complex == 0) 606 n->complex++; 607 608 if(com64(n)) 609 return; 610 611 switch(n->op) { 612 case OFUNC: 613 n->complex = FNX; 614 break; 615 616 case OLE: 617 case OLT: 618 case OGE: 619 case OGT: 620 case OHI: 621 case OHS: 622 case OLO: 623 case OLS: 624 /* 625 * immediate operators, make const on right 626 */ 627 if(l->op == OCONST) { 628 n->left = r; 629 n->right = l; 630 n->op = invrel[relindex(n->op)]; 631 } 632 break; 633 634 case OADD: 635 case OXOR: 636 case OAND: 637 case OOR: 638 case OEQ: 639 case ONE: 640 /* 641 * immediate operators, make const on right 642 */ 643 if(l->op == OCONST) { 644 n->left = r; 645 n->right = l; 646 } 647 break; 648 } 649 } 650 651 int 652 bcomplex(Node *n, Node *c) 653 { 654 655 complex(n); 656 if(n->type != T) 657 if(tcompat(n, T, n->type, tnot)) 658 n->type = T; 659 if(n->type != T) { 660 if(c != Z && n->op == OCONST && deadheads(c)) 661 return 1; 662 bool64(n); 663 boolgen(n, 1, Z); 664 } else 665 gbranch(OGOTO); 666 return 0; 667 } 668