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