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