Unified · Split
| @@ -9,7 +9,9 @@ · 8 unmodified lines | |||
| 9 | #define REGRET 0 | 9 | #define REGRET 0 |
| 10 | #define REGARG 0 | 10 | #define REGARG 0 |
| 11 | /* compiler allocates R1 up as temps */ | 11 | /* compiler allocates R1 up as temps */ |
| 12 | /* compiler allocates register variables R3 up */ | 12 | /* compiler allocates register variables R2 up */ |
| 13 | #define REGMIN 2 | ||
| 14 | #define REGMAX 8 | ||
| 13 | #define REGEXT 10 | 15 | #define REGEXT 10 |
| 14 | /* compiler allocates external registers R10 down */ | 16 | /* compiler allocates external registers R10 down */ |
| 15 | #define REGTMP 11 | 17 | #define REGTMP 11 |
| @@ -1,7 +1,13 @@ | |||
| 1 | #include "gc.h" | 1 | #include "gc.h" |
| 2 | 2 | ||
| 3 | void | 3 | void |
| 4 | cgen(Node *n, Node *nn, int inrel) | 4 | cgen(Node *n, Node *nn) |
| 5 | { | ||
| 6 | cgenrel(n, nn, 0); | ||
| 7 | } | ||
| 8 | |||
| 9 | void | ||
| 10 | cgenrel(Node *n, Node *nn, int inrel) | ||
| 5 | { | 11 | { |
| 6 | Node *l, *r; | 12 | Node *l, *r; |
| 7 | Prog *p1; | 13 | Prog *p1; |
| @@ -45,7 +51,7 @@ cgen(Node *n, Node *nn, int inrel) · 37 unmodified lines | |||
| 45 | switch(o) { | 51 | switch(o) { |
| 46 | default: | 52 | default: |
| 47 | regret(&nod, r); | 53 | regret(&nod, r); |
| 48 | cgen(r, &nod, 0); | 54 | cgen(r, &nod); |
| 49 | 55 | ||
| 50 | regsalloc(&nod1, r); | 56 | regsalloc(&nod1, r); |
| 51 | gopcode(OAS, &nod, Z, &nod1); | 57 | gopcode(OAS, &nod, Z, &nod1); |
| @@ -53,7 +59,7 @@ cgen(Node *n, Node *nn, int inrel) · 1 unmodified line | |||
| 53 | regfree(&nod); | 59 | regfree(&nod); |
| 54 | nod = *n; | 60 | nod = *n; |
| 55 | nod.right = &nod1; | 61 | nod.right = &nod1; |
| 56 | cgen(&nod, nn, 0); | 62 | cgen(&nod, nn); |
| 57 | return; | 63 | return; |
| 58 | 64 | ||
| 59 | case OFUNC: | 65 | case OFUNC: |
| @@ -79,7 +85,7 @@ cgen(Node *n, Node *nn, int inrel) · 19 unmodified lines | |||
| 79 | regret(&nod, r); | 85 | regret(&nod, r); |
| 80 | else | 86 | else |
| 81 | regalloc(&nod, r, nn); | 87 | regalloc(&nod, r, nn); |
| 82 | cgen(r, &nod, 0); | 88 | cgen(r, &nod); |
| 83 | gmove(&nod, l); | 89 | gmove(&nod, l); |
| 84 | if(nn != Z) | 90 | if(nn != Z) |
| 85 | gmove(&nod, nn); | 91 | gmove(&nod, nn); |
| @@ -98,10 +104,10 @@ cgen(Node *n, Node *nn, int inrel) · 12 unmodified lines | |||
| 98 | break; | 104 | break; |
| 99 | } | 105 | } |
| 100 | regalloc(&nod, r, nn); | 106 | regalloc(&nod, r, nn); |
| 101 | cgen(r, &nod, 0); | 107 | cgen(r, &nod); |
| 102 | } else { | 108 | } else { |
| 103 | regalloc(&nod, r, nn); | 109 | regalloc(&nod, r, nn); |
| 104 | cgen(r, &nod, 0); | 110 | cgen(r, &nod); |
| 105 | reglcgen(&nod1, l, Z); | 111 | reglcgen(&nod1, l, Z); |
| 106 | } | 112 | } |
| 107 | gmove(&nod, &nod1); | 113 | gmove(&nod, &nod1); |
| @@ -114,9 +120,9 @@ cgen(Node *n, Node *nn, int inrel) · 6 unmodified lines | |||
| 114 | regalloc(&nod, r, nn); | 120 | regalloc(&nod, r, nn); |
| 115 | if(l->complex >= r->complex) { | 121 | if(l->complex >= r->complex) { |
| 116 | reglcgen(&nod1, n, Z); | 122 | reglcgen(&nod1, n, Z); |
| 117 | cgen(r, &nod, 0); | 123 | cgen(r, &nod); |
| 118 | } else { | 124 | } else { |
| 119 | cgen(r, &nod, 0); | 125 | cgen(r, &nod); |
| 120 | reglcgen(&nod1, n, Z); | 126 | reglcgen(&nod1, n, Z); |
| 121 | } | 127 | } |
| 122 | regalloc(&nod2, n, Z); | 128 | regalloc(&nod2, n, Z); |
| @@ -139,7 +145,7 @@ cgen(Node *n, Node *nn, int inrel) · 16 unmodified lines | |||
| 139 | if(nn != Z) | 145 | if(nn != Z) |
| 140 | if((t = vlog(r)) >= 0) { | 146 | if((t = vlog(r)) >= 0) { |
| 141 | /* signed div/mod by constant power of 2 */ | 147 | /* signed div/mod by constant power of 2 */ |
| 142 | cgen(l, nn, 0); | 148 | cgen(l, nn); |
| 143 | gopcode(OGE, nodconst(0), nn, Z); | 149 | gopcode(OGE, nodconst(0), nn, Z); |
| 144 | p1 = p; | 150 | p1 = p; |
| 145 | if(o == ODIV) { | 151 | if(o == ODIV) { |
| @@ -164,7 +170,7 @@ cgen(Node *n, Node *nn, int inrel) · 18 unmodified lines | |||
| 164 | if(nn != Z) | 170 | if(nn != Z) |
| 165 | if(l->op == OCONST) | 171 | if(l->op == OCONST) |
| 166 | if(!typefd[n->type->etype]) { | 172 | if(!typefd[n->type->etype]) { |
| 167 | cgen(r, nn, 0); | 173 | cgen(r, nn); |
| 168 | gopcode(o, Z, l, nn); | 174 | gopcode(o, Z, l, nn); |
| 169 | break; | 175 | break; |
| 170 | } | 176 | } |
| @@ -181,7 +187,7 @@ cgen(Node *n, Node *nn, int inrel) · 10 unmodified lines | |||
| 181 | if(nn != Z) | 187 | if(nn != Z) |
| 182 | if(r->op == OCONST) | 188 | if(r->op == OCONST) |
| 183 | if(!typefd[n->type->etype]) { | 189 | if(!typefd[n->type->etype]) { |
| 184 | cgen(l, nn, 0); | 190 | cgen(l, nn); |
| 185 | if(r->vconst == 0) | 191 | if(r->vconst == 0) |
| 186 | if(o != OAND) | 192 | if(o != OAND) |
| 187 | break; | 193 | break; |
| @@ -205,15 +211,15 @@ cgen(Node *n, Node *nn, int inrel) · 17 unmodified lines | |||
| 205 | } | 211 | } |
| 206 | if(l->complex >= r->complex) { | 212 | if(l->complex >= r->complex) { |
| 207 | regalloc(&nod, l, nn); | 213 | regalloc(&nod, l, nn); |
| 208 | cgen(l, &nod, 0); | 214 | cgen(l, &nod); |
| 209 | regalloc(&nod1, r, Z); | 215 | regalloc(&nod1, r, Z); |
| 210 | cgen(r, &nod1, 0); | 216 | cgen(r, &nod1); |
| 211 | gopcode(o, &nod1, Z, &nod); | 217 | gopcode(o, &nod1, Z, &nod); |
| 212 | } else { | 218 | } else { |
| 213 | regalloc(&nod, r, nn); | 219 | regalloc(&nod, r, nn); |
| 214 | cgen(r, &nod, 0); | 220 | cgen(r, &nod); |
| 215 | regalloc(&nod1, l, Z); | 221 | regalloc(&nod1, l, Z); |
| 216 | cgen(l, &nod1, 0); | 222 | cgen(l, &nod1); |
| 217 | gopcode(o, &nod, &nod1, &nod); | 223 | gopcode(o, &nod, &nod1, &nod); |
| 218 | } | 224 | } |
| 219 | gopcode(OAS, &nod, Z, nn); | 225 | gopcode(OAS, &nod, Z, nn); |
| @@ -263,10 +269,10 @@ cgen(Node *n, Node *nn, int inrel) · 43 unmodified lines | |||
| 263 | else | 269 | else |
| 264 | nod2 = *l; | 270 | nod2 = *l; |
| 265 | regalloc(&nod1, r, Z); | 271 | regalloc(&nod1, r, Z); |
| 266 | cgen(r, &nod1, 0); | 272 | cgen(r, &nod1); |
| 267 | } else { | 273 | } else { |
| 268 | regalloc(&nod1, r, Z); | 274 | regalloc(&nod1, r, Z); |
| 269 | cgen(r, &nod1, 0); | 275 | cgen(r, &nod1); |
| 270 | if(l->addable < INDEXED) | 276 | if(l->addable < INDEXED) |
| 271 | reglcgen(&nod2, l, Z); | 277 | reglcgen(&nod2, l, Z); |
| 272 | else | 278 | else |
| @@ -290,10 +296,10 @@ cgen(Node *n, Node *nn, int inrel) · 17 unmodified lines | |||
| 290 | if(l->complex >= r->complex) { | 296 | if(l->complex >= r->complex) { |
| 291 | bitload(l, &nod, &nod1, &nod2, &nod4); | 297 | bitload(l, &nod, &nod1, &nod2, &nod4); |
| 292 | regalloc(&nod3, r, Z); | 298 | regalloc(&nod3, r, Z); |
| 293 | cgen(r, &nod3, 0); | 299 | cgen(r, &nod3); |
| 294 | } else { | 300 | } else { |
| 295 | regalloc(&nod3, r, Z); | 301 | regalloc(&nod3, r, Z); |
| 296 | cgen(r, &nod3, 0); | 302 | cgen(r, &nod3); |
| 297 | bitload(l, &nod, &nod1, &nod2, &nod4); | 303 | bitload(l, &nod, &nod1, &nod2, &nod4); |
| 298 | } | 304 | } |
| 299 | gmove(&nod, &nod4); | 305 | gmove(&nod, &nod4); |
| @@ -318,7 +324,7 @@ cgen(Node *n, Node *nn, int inrel) · 18 unmodified lines | |||
| 318 | diag(n, "bad function call"); | 324 | diag(n, "bad function call"); |
| 319 | 325 | ||
| 320 | regret(&nod, l->left); | 326 | regret(&nod, l->left); |
| 321 | cgen(l->left, &nod, 0); | 327 | cgen(l->left, &nod); |
| 322 | regsalloc(&nod1, l->left); | 328 | regsalloc(&nod1, l->left); |
| 323 | gopcode(OAS, &nod, Z, &nod1); | 329 | gopcode(OAS, &nod, Z, &nod1); |
| 324 | regfree(&nod); | 330 | regfree(&nod); |
| @@ -328,7 +334,7 @@ cgen(Node *n, Node *nn, int inrel) · 3 unmodified lines | |||
| 328 | nod2 = *l; | 334 | nod2 = *l; |
| 329 | nod2.left = &nod1; | 335 | nod2.left = &nod1; |
| 330 | nod2.complex = 1; | 336 | nod2.complex = 1; |
| 331 | cgen(&nod, nn, 0); | 337 | cgen(&nod, nn); |
| 332 | 338 | ||
| 333 | return; | 339 | return; |
| 334 | } | 340 | } |
| @@ -363,11 +369,11 @@ cgen(Node *n, Node *nn, int inrel) · 28 unmodified lines | |||
| 363 | if(sconst(r) && (v = r->vconst+nod.xoffset) > -4096 && v < 4096) { | 369 | if(sconst(r) && (v = r->vconst+nod.xoffset) > -4096 && v < 4096) { |
| 364 | v = r->vconst; | 370 | v = r->vconst; |
| 365 | r->vconst = 0; | 371 | r->vconst = 0; |
| 366 | cgen(l, &nod, 0); | 372 | cgen(l, &nod); |
| 367 | nod.xoffset += v; | 373 | nod.xoffset += v; |
| 368 | r->vconst = v; | 374 | r->vconst = v; |
| 369 | } else | 375 | } else |
| 370 | cgen(l, &nod, 0); | 376 | cgen(l, &nod); |
| 371 | regind(&nod, n); | 377 | regind(&nod, n); |
| 372 | gopcode(OAS, &nod, Z, nn); | 378 | gopcode(OAS, &nod, Z, nn); |
| 373 | regfree(&nod); | 379 | regfree(&nod); |
| @@ -406,8 +412,8 @@ cgen(Node *n, Node *nn, int inrel) · 32 unmodified lines | |||
| 406 | break; | 412 | break; |
| 407 | 413 | ||
| 408 | case OCOMMA: | 414 | case OCOMMA: |
| 409 | cgen(l, Z, 0); | 415 | cgen(l, Z); |
| 410 | cgen(r, nn, 0); | 416 | cgen(r, nn); |
| 411 | break; | 417 | break; |
| 412 | 418 | ||
| 413 | case OCAST: | 419 | case OCAST: |
| @@ -420,12 +426,12 @@ cgen(Node *n, Node *nn, int inrel) · 6 unmodified lines | |||
| 420 | */ | 426 | */ |
| 421 | if(nocast(l->type, n->type)) { | 427 | if(nocast(l->type, n->type)) { |
| 422 | if(nocast(n->type, nn->type)) { | 428 | if(nocast(n->type, nn->type)) { |
| 423 | cgen(l, nn, 0); | 429 | cgen(l, nn); |
| 424 | break; | 430 | break; |
| 425 | } | 431 | } |
| 426 | } | 432 | } |
| 427 | regalloc(&nod, l, nn); | 433 | regalloc(&nod, l, nn); |
| 428 | cgen(l, &nod, 0); | 434 | cgen(l, &nod); |
| 429 | regalloc(&nod1, n, &nod); | 435 | regalloc(&nod1, n, &nod); |
| 430 | if(inrel) | 436 | if(inrel) |
| 431 | gmover(&nod, &nod1); | 437 | gmover(&nod, &nod1); |
| @@ -447,18 +453,18 @@ cgen(Node *n, Node *nn, int inrel) · 15 unmodified lines | |||
| 447 | } | 453 | } |
| 448 | nod.xoffset += (long)r->vconst; | 454 | nod.xoffset += (long)r->vconst; |
| 449 | nod.type = n->type; | 455 | nod.type = n->type; |
| 450 | cgen(&nod, nn, 0); | 456 | cgen(&nod, nn); |
| 451 | } | 457 | } |
| 452 | break; | 458 | break; |
| 453 | 459 | ||
| 454 | case OCOND: | 460 | case OCOND: |
| 455 | bcgen(l, 1); | 461 | bcgen(l, 1); |
| 456 | p1 = p; | 462 | p1 = p; |
| 457 | cgen(r->left, nn, 0); | 463 | cgen(r->left, nn); |
| 458 | gbranch(OGOTO); | 464 | gbranch(OGOTO); |
| 459 | patch(p1, pc); | 465 | patch(p1, pc); |
| 460 | p1 = p; | 466 | p1 = p; |
| 461 | cgen(r->right, nn, 0); | 467 | cgen(r->right, nn); |
| 462 | patch(p1, pc); | 468 | patch(p1, pc); |
| 463 | break; | 469 | break; |
| 464 | 470 | ||
| @@ -533,6 +539,8 @@ cgen(Node *n, Node *nn, int inrel) · 68 unmodified lines | |||
| 533 | } else | 539 | } else |
| 534 | gopcode(OADD, nodconst(v), Z, &nod); | 540 | gopcode(OADD, nodconst(v), Z, &nod); |
| 535 | gopcode(OAS, &nod, Z, &nod2); | 541 | gopcode(OAS, &nod, Z, &nod2); |
| 542 | if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */ | ||
| 543 | gins(ANOP, l, Z); | ||
| 536 | 544 | ||
| 537 | regfree(&nod); | 545 | regfree(&nod); |
| 538 | if(l->addable < INDEXED) | 546 | if(l->addable < INDEXED) |
| @@ -579,7 +587,7 @@ reglcgen(Node *t, Node *n, Node *nn) · 40 unmodified lines | |||
| 579 | } else if(n->op == OINDREG) { | 587 | } else if(n->op == OINDREG) { |
| 580 | if((v = n->xoffset) > -4096 && v < 4096) { | 588 | if((v = n->xoffset) > -4096 && v < 4096) { |
| 581 | n->op = OREGISTER; | 589 | n->op = OREGISTER; |
| 582 | cgen(n, t, 0); | 590 | cgen(n, t); |
| 583 | t->xoffset += v; | 591 | t->xoffset += v; |
| 584 | n->op = OINDREG; | 592 | n->op = OINDREG; |
| 585 | regind(t, n); | 593 | regind(t, n); |
| @@ -638,12 +646,12 @@ lcgen(Node *n, Node *nn) · 52 unmodified lines | |||
| 638 | break; | 646 | break; |
| 639 | 647 | ||
| 640 | case OCOMMA: | 648 | case OCOMMA: |
| 641 | cgen(n->left, n->left, 0); | 649 | cgen(n->left, n->left); |
| 642 | lcgen(n->right, nn); | 650 | lcgen(n->right, nn); |
| 643 | break; | 651 | break; |
| 644 | 652 | ||
| 645 | case OIND: | 653 | case OIND: |
| 646 | cgen(n->left, nn, 0); | 654 | cgen(n->left, nn); |
| 647 | break; | 655 | break; |
| 648 | 656 | ||
| 649 | case OCOND: | 657 | case OCOND: |
| @@ -688,7 +696,7 @@ boolgen(Node *n, int true, Node *nn) · 38 unmodified lines | |||
| 688 | 696 | ||
| 689 | default: | 697 | default: |
| 690 | regalloc(&nod, n, nn); | 698 | regalloc(&nod, n, nn); |
| 691 | cgen(n, &nod, 0); | 699 | cgen(n, &nod); |
| 692 | o = ONE; | 700 | o = ONE; |
| 693 | if(true) | 701 | if(true) |
| 694 | o = comrel[relindex(o)]; | 702 | o = comrel[relindex(o)]; |
| @@ -712,7 +720,7 @@ boolgen(Node *n, int true, Node *nn) · 17 unmodified lines | |||
| 712 | goto com; | 720 | goto com; |
| 713 | 721 | ||
| 714 | case OCOMMA: | 722 | case OCOMMA: |
| 715 | cgen(l, Z, 0); | 723 | cgen(l, Z); |
| 716 | boolgen(r, true, nn); | 724 | boolgen(r, true, nn); |
| 717 | break; | 725 | break; |
| 718 | 726 | ||
| @@ -779,7 +787,7 @@ boolgen(Node *n, int true, Node *nn) · 60 unmodified lines | |||
| 779 | o = comrel[relindex(o)]; | 787 | o = comrel[relindex(o)]; |
| 780 | if(l->complex >= FNX && r->complex >= FNX) { | 788 | if(l->complex >= FNX && r->complex >= FNX) { |
| 781 | regret(&nod, r); | 789 | regret(&nod, r); |
| 782 | cgen(r, &nod, 1); | 790 | cgenrel(r, &nod, 1); |
| 783 | regsalloc(&nod1, r); | 791 | regsalloc(&nod1, r); |
| 784 | gopcode(OAS, &nod, Z, &nod1); | 792 | gopcode(OAS, &nod, Z, &nod1); |
| 785 | regfree(&nod); | 793 | regfree(&nod); |
| @@ -790,7 +798,7 @@ boolgen(Node *n, int true, Node *nn) · 4 unmodified lines | |||
| 790 | } | 798 | } |
| 791 | if(sconst(l)) { | 799 | if(sconst(l)) { |
| 792 | regalloc(&nod, r, nn); | 800 | regalloc(&nod, r, nn); |
| 793 | cgen(r, &nod, 1); | 801 | cgenrel(r, &nod, 1); |
| 794 | o = invrel[relindex(o)]; | 802 | o = invrel[relindex(o)]; |
| 795 | gopcode(o, l, &nod, Z); | 803 | gopcode(o, l, &nod, Z); |
| 796 | regfree(&nod); | 804 | regfree(&nod); |
| @@ -798,21 +806,21 @@ boolgen(Node *n, int true, Node *nn) · 1 unmodified line | |||
| 798 | } | 806 | } |
| 799 | if(sconst(r)) { | 807 | if(sconst(r)) { |
| 800 | regalloc(&nod, l, nn); | 808 | regalloc(&nod, l, nn); |
| 801 | cgen(l, &nod, 1); | 809 | cgenrel(l, &nod, 1); |
| 802 | gopcode(o, r, &nod, Z); | 810 | gopcode(o, r, &nod, Z); |
| 803 | regfree(&nod); | 811 | regfree(&nod); |
| 804 | goto com; | 812 | goto com; |
| 805 | } | 813 | } |
| 806 | if(l->complex >= r->complex) { | 814 | if(l->complex >= r->complex) { |
| 807 | regalloc(&nod1, l, nn); | 815 | regalloc(&nod1, l, nn); |
| 808 | cgen(l, &nod1, 1); | 816 | cgenrel(l, &nod1, 1); |
| 809 | regalloc(&nod, r, Z); | 817 | regalloc(&nod, r, Z); |
| 810 | cgen(r, &nod, 1); | 818 | cgenrel(r, &nod, 1); |
| 811 | } else { | 819 | } else { |
| 812 | regalloc(&nod, r, nn); | 820 | regalloc(&nod, r, nn); |
| 813 | cgen(r, &nod, 1); | 821 | cgenrel(r, &nod, 1); |
| 814 | regalloc(&nod1, l, Z); | 822 | regalloc(&nod1, l, Z); |
| 815 | cgen(l, &nod1, 1); | 823 | cgenrel(l, &nod1, 1); |
| 816 | } | 824 | } |
| 817 | gopcode(o, &nod, &nod1, Z); | 825 | gopcode(o, &nod, &nod1, Z); |
| 818 | regfree(&nod); | 826 | regfree(&nod); |
| @@ -936,7 +944,7 @@ sugen(Node *n, Node *nn, long w) · 117 unmodified lines | |||
| 936 | r = r->right; | 944 | r = r->right; |
| 937 | } | 945 | } |
| 938 | if(nn == Z) { | 946 | if(nn == Z) { |
| 939 | cgen(l, nn, 0); | 947 | cgen(l, nn); |
| 940 | continue; | 948 | continue; |
| 941 | } | 949 | } |
| 942 | /* | 950 | /* |
| @@ -974,7 +982,7 @@ sugen(Node *n, Node *nn, long w) · 31 unmodified lines | |||
| 974 | xcom(&nod0); | 982 | xcom(&nod0); |
| 975 | nod0.addable = 0; | 983 | nod0.addable = 0; |
| 976 | 984 | ||
| 977 | cgen(&nod0, Z, 0); | 985 | cgen(&nod0, Z); |
| 978 | } | 986 | } |
| 979 | break; | 987 | break; |
| 980 | 988 | ||
| @@ -1004,7 +1012,7 @@ sugen(Node *n, Node *nn, long w) · 23 unmodified lines | |||
| 1004 | n = new(OFUNC, n->left, new(OLIST, nn, n->right)); | 1012 | n = new(OFUNC, n->left, new(OLIST, nn, n->right)); |
| 1005 | n->type = types[TVOID]; | 1013 | n->type = types[TVOID]; |
| 1006 | n->left->type = types[TVOID]; | 1014 | n->left->type = types[TVOID]; |
| 1007 | cgen(n, Z, 0); | 1015 | cgen(n, Z); |
| 1008 | break; | 1016 | break; |
| 1009 | 1017 | ||
| 1010 | case OCOND: | 1018 | case OCOND: |
| @@ -1019,7 +1027,7 @@ sugen(Node *n, Node *nn, long w) · 8 unmodified lines | |||
| 1019 | break; | 1027 | break; |
| 1020 | 1028 | ||
| 1021 | case OCOMMA: | 1029 | case OCOMMA: |
| 1022 | cgen(n->left, Z, 0); | 1030 | cgen(n->left, Z); |
| 1023 | sugen(n->right, nn, w); | 1031 | sugen(n->right, nn, w); |
| 1024 | break; | 1032 | break; |
| 1025 | } | 1033 | } |
| @@ -1063,6 +1071,10 @@ copy: · 37 unmodified lines | |||
| 1063 | } | 1071 | } |
| 1064 | regalloc(&nod3, ®node, Z); | 1072 | regalloc(&nod3, ®node, Z); |
| 1065 | regalloc(&nod4, ®node, Z); | 1073 | regalloc(&nod4, ®node, Z); |
| 1074 | if(nod3.reg > nod4.reg){ | ||
| 1075 | /* code below assumes nod3 loaded first */ | ||
| 1076 | Node t = nod3; nod3 = nod4; nod4 = t; | ||
| 1077 | } | ||
| 1066 | nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg)); | 1078 | nod0 = *nodconst((1<<nod3.reg)|(1<<nod4.reg)); |
| 1067 | if(w == 2 && nod1.xoffset == 0) | 1079 | if(w == 2 && nod1.xoffset == 0) |
| 1068 | gmovm(&nod1, &nod0, 0); | 1080 | gmovm(&nod1, &nod0, 0); |
| @@ -62,6 +62,7 @@ struct Case · 61 unmodified lines | |||
| 62 | long val; | 62 | long val; |
| 63 | long label; | 63 | long label; |
| 64 | char def; | 64 | char def; |
| 65 | char isv; | ||
| 65 | }; | 66 | }; |
| 66 | #define C ((Case*)0) | 67 | #define C ((Case*)0) |
| 67 | 68 | ||
| @@ -134,6 +135,7 @@ struct Rgn · 66 unmodified lines | |||
| 134 | }; | 135 | }; |
| 135 | 136 | ||
| 136 | EXTERN long breakpc; | 137 | EXTERN long breakpc; |
| 138 | EXTERN long nbreak; | ||
| 137 | EXTERN Case* cases; | 139 | EXTERN Case* cases; |
| 138 | EXTERN Node constnode; | 140 | EXTERN Node constnode; |
| 139 | EXTERN Node fconstnode; | 141 | EXTERN Node fconstnode; |
| @@ -145,7 +147,6 @@ EXTERN Prog* lastp; · 5 unmodified lines | |||
| 145 | EXTERN long maxargsafe; | 147 | EXTERN long maxargsafe; |
| 146 | EXTERN int mnstring; | 148 | EXTERN int mnstring; |
| 147 | EXTERN Multab multab[20]; | 149 | EXTERN Multab multab[20]; |
| 148 | EXTERN int retok; | ||
| 149 | EXTERN int hintabsize; | 150 | EXTERN int hintabsize; |
| 150 | EXTERN Node* nodrat; | 151 | EXTERN Node* nodrat; |
| 151 | EXTERN Node* nodret; | 152 | EXTERN Node* nodret; |
| @@ -216,7 +217,8 @@ int bcomplex(Node*, Node*); · 64 unmodified lines | |||
| 216 | /* | 217 | /* |
| 217 | * cgen.c | 218 | * cgen.c |
| 218 | */ | 219 | */ |
| 219 | void cgen(Node*, Node*, int); | 220 | void cgen(Node*, Node*); |
| 221 | void cgenrel(Node*, Node*, int); | ||
| 220 | void reglcgen(Node*, Node*, Node*); | 222 | void reglcgen(Node*, Node*, Node*); |
| 221 | void lcgen(Node*, Node*); | 223 | void lcgen(Node*, Node*); |
| 222 | void bcgen(Node*, int); | 224 | void bcgen(Node*, int); |
| @@ -265,7 +267,8 @@ void gpseudo(int, Sym*, Node*); · 42 unmodified lines | |||
| 265 | */ | 267 | */ |
| 266 | int swcmp(const void*, const void*); | 268 | int swcmp(const void*, const void*); |
| 267 | void doswit(Node*); | 269 | void doswit(Node*); |
| 268 | void swit1(C1*, int, long, Node*, Node*); | 270 | void swit1(C1*, int, long, Node*); |
| 271 | void swit2(C1*, int, long, Node*, Node*); | ||
| 269 | void casf(void); | 272 | void casf(void); |
| 270 | void bitload(Node*, Node*, Node*, Node*, Node*); | 273 | void bitload(Node*, Node*, Node*, Node*, Node*); |
| 271 | void bitstore(Node*, Node*, Node*, Node*, Node*); | 274 | void bitstore(Node*, Node*, Node*, Node*, Node*); |
| @@ -8,6 +8,8 @@ OFILES=\ · 7 unmodified lines | |||
| 8 | list.$O\ | 8 | list.$O\ |
| 9 | mul.$O\ | 9 | mul.$O\ |
| 10 | peep.$O\ | 10 | peep.$O\ |
| 11 | pgen.$O\ | ||
| 12 | pswt.$O\ | ||
| 11 | reg.$O\ | 13 | reg.$O\ |
| 12 | sgen.$O\ | 14 | sgen.$O\ |
| 13 | swt.$O\ | 15 | swt.$O\ |
| @@ -28,3 +30,9 @@ $ROOT/$OBJDIR/lib/libcc.a: · 14 unmodified lines | |||
| 28 | cd ../cc | 30 | cd ../cc |
| 29 | mk $MKFLAGS install | 31 | mk $MKFLAGS install |
| 30 | mk $MKFLAGS clean | 32 | mk $MKFLAGS clean |
| 33 | |||
| 34 | %.$O: ../cc/%.c | ||
| 35 | $CC $CFLAGS -I. ../cc/$stem.c | ||
| 36 | |||
| 37 | #enam.c: 5.out.h | ||
| 38 | # rc mkenam | ||
| @@ -789,6 +789,7 @@ loopit(Reg *r, long nr) · 788 unmodified lines | |||
| 789 | idom = alloc(nr * sizeof(long)); | 789 | idom = alloc(nr * sizeof(long)); |
| 790 | maxnr = nr; | 790 | maxnr = nr; |
| 791 | } | 791 | } |
| 792 | |||
| 792 | d = postorder(r, rpo2r, 0); | 793 | d = postorder(r, rpo2r, 0); |
| 793 | if(d > nr) | 794 | if(d > nr) |
| 794 | fatal(Z, "too many reg nodes"); | 795 | fatal(Z, "too many reg nodes"); |
| @@ -1116,15 +1117,15 @@ long · 321 unmodified lines | |||
| 1116 | RtoB(int r) | 1117 | RtoB(int r) |
| 1117 | { | 1118 | { |
| 1118 | 1119 | ||
| 1119 | if(r < 2 || r >= REGTMP) | 1120 | if(r >= REGMIN && r <= REGMAX) |
| 1120 | return 0; | 1121 | return 1L << r; |
| 1121 | return 1L << r; | 1122 | return 0; |
| 1122 | } | 1123 | } |
| 1123 | 1124 | ||
| 1124 | int | 1125 | int |
| 1125 | BtoR(long b) | 1126 | BtoR(long b) |
| 1126 | { | 1127 | { |
| 1127 | b &= 0x07fcL; | 1128 | b &= 0x01fcL; |
| 1128 | if(b == 0) | 1129 | if(b == 0) |
| 1129 | return 0; | 1130 | return 0; |
| 1130 | return bitno(b); | 1131 | return bitno(b); |
| @@ -1,381 +1,5 @@ | |||
| 1 | #include "gc.h" | 1 | #include "gc.h" |
| 2 | 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 >= 0) { | ||
| 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 | supgen(Node *n) | ||
| 64 | { | ||
| 65 | long spc; | ||
| 66 | Prog *sp; | ||
| 67 | |||
| 68 | if(n == Z) | ||
| 69 | return; | ||
| 70 | suppress++; | ||
| 71 | spc = pc; | ||
| 72 | sp = lastp; | ||
| 73 | gen(n); | ||
| 74 | lastp = sp; | ||
| 75 | pc = spc; | ||
| 76 | sp->link = nil; | ||
| 77 | suppress--; | ||
| 78 | } | ||
| 79 | |||
| 80 | void | ||
| 81 | gen(Node *n) | ||
| 82 | { | ||
| 83 | Node *l, nod; | ||
| 84 | Prog *sp, *spc, *spb; | ||
| 85 | Case *cn; | ||
| 86 | long sbc, scc; | ||
| 87 | int o, f; | ||
| 88 | |||
| 89 | loop: | ||
| 90 | if(n == Z) | ||
| 91 | return; | ||
| 92 | nearln = n->lineno; | ||
| 93 | o = n->op; | ||
| 94 | if(debug['G']) | ||
| 95 | if(o != OLIST) | ||
| 96 | print("%L %O\n", nearln, o); | ||
| 97 | |||
| 98 | retok = 0; | ||
| 99 | switch(o) { | ||
| 100 | |||
| 101 | default: | ||
| 102 | complex(n); | ||
| 103 | cgen(n, Z, 0); | ||
| 104 | break; | ||
| 105 | |||
| 106 | case OLIST: | ||
| 107 | gen(n->left); | ||
| 108 | |||
| 109 | rloop: | ||
| 110 | n = n->right; | ||
| 111 | goto loop; | ||
| 112 | |||
| 113 | case ORETURN: | ||
| 114 | retok = 1; | ||
| 115 | complex(n); | ||
| 116 | if(n->type == T) | ||
| 117 | break; | ||
| 118 | l = n->left; | ||
| 119 | if(l == Z) { | ||
| 120 | noretval(3); | ||
| 121 | gbranch(ORETURN); | ||
| 122 | break; | ||
| 123 | } | ||
| 124 | if(typesuv[n->type->etype]) { | ||
| 125 | sugen(l, nodret, n->type->width); | ||
| 126 | noretval(3); | ||
| 127 | gbranch(ORETURN); | ||
| 128 | break; | ||
| 129 | } | ||
| 130 | regret(&nod, n); | ||
| 131 | cgen(l, &nod, 0); | ||
| 132 | regfree(&nod); | ||
| 133 | if(typefd[n->type->etype]) | ||
| 134 | noretval(1); | ||
| 135 | else | ||
| 136 | noretval(2); | ||
| 137 | gbranch(ORETURN); | ||
| 138 | break; | ||
| 139 | |||
| 140 | case OLABEL: | ||
| 141 | l = n->left; | ||
| 142 | if(l) { | ||
| 143 | l->pc = pc; | ||
| 144 | if(l->label) | ||
| 145 | patch(l->label, pc); | ||
| 146 | } | ||
| 147 | gbranch(OGOTO); /* prevent self reference in reg */ | ||
| 148 | patch(p, pc); | ||
| 149 | goto rloop; | ||
| 150 | |||
| 151 | case OGOTO: | ||
| 152 | retok = 1; | ||
| 153 | n = n->left; | ||
| 154 | if(n == Z) | ||
| 155 | return; | ||
| 156 | if(n->complex == 0) { | ||
| 157 | diag(Z, "label undefined: %s", n->sym->name); | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | if(suppress) | ||
| 161 | return; | ||
| 162 | gbranch(OGOTO); | ||
| 163 | if(n->pc) { | ||
| 164 | patch(p, n->pc); | ||
| 165 | return; | ||
| 166 | } | ||
| 167 | if(n->label) | ||
| 168 | patch(n->label, pc-1); | ||
| 169 | n->label = p; | ||
| 170 | return; | ||
| 171 | |||
| 172 | case OCASE: | ||
| 173 | l = n->left; | ||
| 174 | if(cases == C) | ||
| 175 | diag(n, "case/default outside a switch"); | ||
| 176 | if(l == Z) { | ||
| 177 | casf(); | ||
| 178 | cases->val = 0; | ||
| 179 | cases->def = 1; | ||
| 180 | cases->label = pc; | ||
| 181 | goto rloop; | ||
| 182 | } | ||
| 183 | complex(l); | ||
| 184 | if(l->type == T) | ||
| 185 | goto rloop; | ||
| 186 | if(l->op == OCONST) | ||
| 187 | if(typechl[l->type->etype]) { | ||
| 188 | casf(); | ||
| 189 | cases->val = l->vconst; | ||
| 190 | cases->def = 0; | ||
| 191 | cases->label = pc; | ||
| 192 | goto rloop; | ||
| 193 | } | ||
| 194 | diag(n, "case expression must be integer constant"); | ||
| 195 | goto rloop; | ||
| 196 | |||
| 197 | case OSWITCH: | ||
| 198 | l = n->left; | ||
| 199 | complex(l); | ||
| 200 | if(l->type == T) | ||
| 201 | break; | ||
| 202 | if(!typechl[l->type->etype]) { | ||
| 203 | diag(n, "switch expression must be integer"); | ||
| 204 | break; | ||
| 205 | } | ||
| 206 | |||
| 207 | gbranch(OGOTO); /* entry */ | ||
| 208 | sp = p; | ||
| 209 | |||
| 210 | cn = cases; | ||
| 211 | cases = C; | ||
| 212 | casf(); | ||
| 213 | |||
| 214 | sbc = breakpc; | ||
| 215 | breakpc = pc; | ||
| 216 | gbranch(OGOTO); | ||
| 217 | spb = p; | ||
| 218 | |||
| 219 | gen(n->right); | ||
| 220 | gbranch(OGOTO); | ||
| 221 | patch(p, breakpc); | ||
| 222 | |||
| 223 | patch(sp, pc); | ||
| 224 | regalloc(&nod, l, Z); | ||
| 225 | nod.type = types[TLONG]; | ||
| 226 | cgen(l, &nod, 0); | ||
| 227 | doswit(&nod); | ||
| 228 | regfree(&nod); | ||
| 229 | patch(spb, pc); | ||
| 230 | |||
| 231 | cases = cn; | ||
| 232 | breakpc = sbc; | ||
| 233 | break; | ||
| 234 | |||
| 235 | case OWHILE: | ||
| 236 | case ODWHILE: | ||
| 237 | l = n->left; | ||
| 238 | gbranch(OGOTO); /* entry */ | ||
| 239 | sp = p; | ||
| 240 | |||
| 241 | scc = continpc; | ||
| 242 | continpc = pc; | ||
| 243 | gbranch(OGOTO); | ||
| 244 | spc = p; | ||
| 245 | |||
| 246 | sbc = breakpc; | ||
| 247 | breakpc = pc; | ||
| 248 | gbranch(OGOTO); | ||
| 249 | spb = p; | ||
| 250 | |||
| 251 | patch(spc, pc); | ||
| 252 | if(n->op == OWHILE) | ||
| 253 | patch(sp, pc); | ||
| 254 | bcomplex(l, Z); /* test */ | ||
| 255 | patch(p, breakpc); | ||
| 256 | |||
| 257 | if(n->op == ODWHILE) | ||
| 258 | patch(sp, pc); | ||
| 259 | gen(n->right); /* body */ | ||
| 260 | gbranch(OGOTO); | ||
| 261 | patch(p, continpc); | ||
| 262 | |||
| 263 | patch(spb, pc); | ||
| 264 | continpc = scc; | ||
| 265 | breakpc = sbc; | ||
| 266 | break; | ||
| 267 | |||
| 268 | case OFOR: | ||
| 269 | l = n->left; | ||
| 270 | gen(l->right->left); /* init */ | ||
| 271 | gbranch(OGOTO); /* entry */ | ||
| 272 | sp = p; | ||
| 273 | |||
| 274 | scc = continpc; | ||
| 275 | continpc = pc; | ||
| 276 | gbranch(OGOTO); | ||
| 277 | spc = p; | ||
| 278 | |||
| 279 | sbc = breakpc; | ||
| 280 | breakpc = pc; | ||
| 281 | gbranch(OGOTO); | ||
| 282 | spb = p; | ||
| 283 | |||
| 284 | patch(spc, pc); | ||
| 285 | gen(l->right->right); /* inc */ | ||
| 286 | patch(sp, pc); | ||
| 287 | if(l->left != Z) { /* test */ | ||
| 288 | bcomplex(l->left, Z); | ||
| 289 | patch(p, breakpc); | ||
| 290 | } | ||
| 291 | gen(n->right); /* body */ | ||
| 292 | gbranch(OGOTO); | ||
| 293 | patch(p, continpc); | ||
| 294 | |||
| 295 | patch(spb, pc); | ||
| 296 | continpc = scc; | ||
| 297 | breakpc = sbc; | ||
| 298 | break; | ||
| 299 | |||
| 300 | case OCONTINUE: | ||
| 301 | if(continpc < 0) { | ||
| 302 | diag(n, "continue not in a loop"); | ||
| 303 | break; | ||
| 304 | } | ||
| 305 | gbranch(OGOTO); | ||
| 306 | patch(p, continpc); | ||
| 307 | break; | ||
| 308 | |||
| 309 | case OBREAK: | ||
| 310 | if(breakpc < 0) { | ||
| 311 | diag(n, "break not in a loop"); | ||
| 312 | break; | ||
| 313 | } | ||
| 314 | gbranch(OGOTO); | ||
| 315 | patch(p, breakpc); | ||
| 316 | break; | ||
| 317 | |||
| 318 | case OIF: | ||
| 319 | l = n->left; | ||
| 320 | if(bcomplex(l, n->right)) { | ||
| 321 | if(typefd[l->type->etype]) | ||
| 322 | f = !l->fconst; | ||
| 323 | else | ||
| 324 | f = !l->vconst; | ||
| 325 | if(debug['c']) | ||
| 326 | print("%L const if %s\n", nearln, f ? "false" : "true"); | ||
| 327 | if(f) { | ||
| 328 | supgen(n->right->left); | ||
| 329 | gen(n->right->right); | ||
| 330 | } | ||
| 331 | else { | ||
| 332 | gen(n->right->left); | ||
| 333 | supgen(n->right->right); | ||
| 334 | } | ||
| 335 | } | ||
| 336 | else { | ||
| 337 | sp = p; | ||
| 338 | if(n->right->left != Z) | ||
| 339 | gen(n->right->left); | ||
| 340 | if(n->right->right != Z) { | ||
| 341 | gbranch(OGOTO); | ||
| 342 | patch(sp, pc); | ||
| 343 | sp = p; | ||
| 344 | gen(n->right->right); | ||
| 345 | } | ||
| 346 | patch(sp, pc); | ||
| 347 | } | ||
| 348 | break; | ||
| 349 | |||
| 350 | case OSET: | ||
| 351 | case OUSED: | ||
| 352 | usedset(n->left, o); | ||
| 353 | break; | ||
| 354 | } | ||
| 355 | } | ||
| 356 | |||
| 357 | void | ||
| 358 | usedset(Node *n, int o) | ||
| 359 | { | ||
| 360 | if(n->op == OLIST) { | ||
| 361 | usedset(n->left, o); | ||
| 362 | usedset(n->right, o); | ||
| 363 | return; | ||
| 364 | } | ||
| 365 | complex(n); | ||
| 366 | switch(n->op) { | ||
| 367 | case OADDR: /* volatile */ | ||
| 368 | gins(ANOP, n, Z); | ||
| 369 | break; | ||
| 370 | case ONAME: | ||
| 371 | if(o == OSET) | ||
| 372 | gins(ANOP, Z, n); | ||
| 373 | else | ||
| 374 | gins(ANOP, n, Z); | ||
| 375 | break; | ||
| 376 | } | ||
| 377 | } | ||
| 378 | |||
| 379 | void | 3 | void |
| 380 | noretval(int n) | 4 | noretval(int n) |
| 381 | { | 5 | { |
| @@ -593,21 +217,3 @@ xcom(Node *n) · 211 unmodified lines | |||
| 593 | break; | 217 | break; |
| 594 | } | 218 | } |
| 595 | } | 219 | } |
| 596 | |||
| 597 | int | ||
| 598 | bcomplex(Node *n, Node *c) | ||
| 599 | { | ||
| 600 | |||
| 601 | complex(n); | ||
| 602 | if(n->type != T) | ||
| 603 | if(tcompat(n, T, n->type, tnot)) | ||
| 604 | n->type = T; | ||
| 605 | if(n->type != T) { | ||
| 606 | if(c != Z && n->op == OCONST && deadheads(c)) | ||
| 607 | return 1; | ||
| 608 | bool64(n); | ||
| 609 | boolgen(n, 1, Z); | ||
| 610 | } else | ||
| 611 | gbranch(OGOTO); | ||
| 612 | return 0; | ||
| 613 | } | ||
| @@ -1,62 +1,17 @@ | |||
| 1 | #include "gc.h" | 1 | #include "gc.h" |
| 2 | 2 | ||
| 3 | int | ||
| 4 | swcmp(const void *a1, const void *a2) | ||
| 5 | { | ||
| 6 | C1 *p1, *p2; | ||
| 7 | |||
| 8 | p1 = (C1*)a1; | ||
| 9 | p2 = (C1*)a2; | ||
| 10 | if(p1->val < p2->val) | ||
| 11 | return -1; | ||
| 12 | return p1->val > p2->val; | ||
| 13 | } | ||
| 14 | |||
| 15 | void | 3 | void |
| 16 | doswit(Node *n) | 4 | swit1(C1 *q, int nc, long def, Node *n) |
| 17 | { | 5 | { |
| 18 | Case *c; | ||
| 19 | C1 *q, *iq; | ||
| 20 | long def, nc, i; | ||
| 21 | Node tn; | 6 | Node tn; |
| 22 | 7 | ||
| 23 | def = 0; | ||
| 24 | nc = 0; | ||
| 25 | for(c = cases; c->link != C; c = c->link) { | ||
| 26 | if(c->def) { | ||
| 27 | if(def) | ||
| 28 | diag(n, "more than one default in switch"); | ||
| 29 | def = c->label; | ||
| 30 | continue; | ||
| 31 | } | ||
| 32 | nc++; | ||
| 33 | } | ||
| 34 | |||
| 35 | iq = alloc(nc*sizeof(C1)); | ||
| 36 | q = iq; | ||
| 37 | for(c = cases; c->link != C; c = c->link) { | ||
| 38 | if(c->def) | ||
| 39 | continue; | ||
| 40 | q->label = c->label; | ||
| 41 | q->val = c->val; | ||
| 42 | q++; | ||
| 43 | } | ||
| 44 | qsort(iq, nc, sizeof(C1), swcmp); | ||
| 45 | if(debug['W']) | ||
| 46 | for(i=0; i<nc; i++) | ||
| 47 | print("case %2ld: = %.8lux\n", i, iq[i].val); | ||
| 48 | if(def == 0) | ||
| 49 | def = breakpc; | ||
| 50 | for(i=0; i<nc-1; i++) | ||
| 51 | if(iq[i].val == iq[i+1].val) | ||
| 52 | diag(n, "duplicate cases in switch %ld", iq[i].val); | ||
| 53 | regalloc(&tn, ®node, Z); | 8 | regalloc(&tn, ®node, Z); |
| 54 | swit1(iq, nc, def, n, &tn); | 9 | swit2(q, nc, def, n, &tn); |
| 55 | regfree(&tn); | 10 | regfree(&tn); |
| 56 | } | 11 | } |
| 57 | 12 | ||
| 58 | void | 13 | void |
| 59 | swit1(C1 *q, int nc, long def, Node *n, Node *tn) | 14 | swit2(C1 *q, int nc, long def, Node *n, Node *tn) |
| 60 | { | 15 | { |
| 61 | C1 *r; | 16 | C1 *r; |
| 62 | int i; | 17 | int i; |
| @@ -89,12 +44,12 @@ swit1(C1 *q, int nc, long def, Node *n, Node *tn) · 26 unmodified lines | |||
| 89 | sp = p; | 44 | sp = p; |
| 90 | gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */ | 45 | gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */ |
| 91 | patch(p, r->label); | 46 | patch(p, r->label); |
| 92 | swit1(q, i, def, n, tn); | 47 | swit2(q, i, def, n, tn); |
| 93 | 48 | ||
| 94 | if(debug['W']) | 49 | if(debug['W']) |
| 95 | print("case < %.8lux\n", r->val); | 50 | print("case < %.8lux\n", r->val); |
| 96 | patch(sp, pc); | 51 | patch(sp, pc); |
| 97 | swit1(r+1, nc-i-1, def, n, tn); | 52 | swit2(r+1, nc-i-1, def, n, tn); |
| 98 | return; | 53 | return; |
| 99 | 54 | ||
| 100 | direct: | 55 | direct: |
| @@ -122,16 +77,6 @@ direct: · 21 unmodified lines | |||
| 122 | patch(p, def); | 77 | patch(p, def); |
| 123 | } | 78 | } |
| 124 | 79 | ||
| 125 | void | ||
| 126 | casf(void) | ||
| 127 | { | ||
| 128 | Case *c; | ||
| 129 | |||
| 130 | c = alloc(sizeof(*c)); | ||
| 131 | c->link = cases; | ||
| 132 | cases = c; | ||
| 133 | } | ||
| 134 | |||
| 135 | void | 80 | void |
| 136 | bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) | 81 | bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) |
| 137 | { | 82 | { |
| @@ -153,7 +98,7 @@ bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) · 15 unmodified lines | |||
| 153 | gopcode(OAS, n3, Z, n1); | 98 | gopcode(OAS, n3, Z, n1); |
| 154 | } else { | 99 | } else { |
| 155 | regalloc(n1, l, nn); | 100 | regalloc(n1, l, nn); |
| 156 | cgen(l, n1, 0); | 101 | cgen(l, n1); |
| 157 | } | 102 | } |
| 158 | if(b->type->shift == 0 && typeu[b->type->etype]) { | 103 | if(b->type->shift == 0 && typeu[b->type->etype]) { |
| 159 | v = ~0 + (1L << b->type->nbits); | 104 | v = ~0 + (1L << b->type->nbits); |
| @@ -229,33 +174,6 @@ outstring(char *s, long n) · 69 unmodified lines | |||
| 229 | return r; | 174 | return r; |
| 230 | } | 175 | } |
| 231 | 176 | ||
| 232 | long | ||
| 233 | outlstring(ushort *s, long n) | ||
| 234 | { | ||
| 235 | char buf[2]; | ||
| 236 | int c; | ||
| 237 | long r; | ||
| 238 | |||
| 239 | if(suppress) | ||
| 240 | return nstring; | ||
| 241 | while(nstring & 1) | ||
| 242 | outstring("", 1); | ||
| 243 | r = nstring; | ||
| 244 | while(n > 0) { | ||
| 245 | c = *s++; | ||
| 246 | if(align(0, types[TCHAR], Aarg1)) { | ||
| 247 | buf[0] = c>>8; | ||
| 248 | buf[1] = c; | ||
| 249 | } else { | ||
| 250 | buf[0] = c; | ||
| 251 | buf[1] = c>>8; | ||
| 252 | } | ||
| 253 | outstring(buf, 2); | ||
| 254 | n -= sizeof(ushort); | ||
| 255 | } | ||
| 256 | return r; | ||
| 257 | } | ||
| 258 | |||
| 259 | int | 177 | int |
| 260 | mulcon(Node *n, Node *nn) | 178 | mulcon(Node *n, Node *nn) |
| 261 | { | 179 | { |
| @@ -297,7 +215,7 @@ mulcon(Node *n, Node *nn) · 35 unmodified lines | |||
| 297 | if(p[1] == 'i') | 215 | if(p[1] == 'i') |
| 298 | p += 2; | 216 | p += 2; |
| 299 | regalloc(&nod1, n, nn); | 217 | regalloc(&nod1, n, nn); |
| 300 | cgen(l, &nod1, 0); | 218 | cgen(l, &nod1); |
| 301 | vs = v; | 219 | vs = v; |
| 302 | regalloc(&nod2, n, Z); | 220 | regalloc(&nod2, n, Z); |
| 303 | 221 | ||
| @@ -350,16 +268,6 @@ loop: · 46 unmodified lines | |||
| 350 | goto loop; | 268 | goto loop; |
| 351 | } | 269 | } |
| 352 | 270 | ||
| 353 | void | ||
| 354 | nullwarn(Node *l, Node *r) | ||
| 355 | { | ||
| 356 | warn(Z, "result of operation not used"); | ||
| 357 | if(l != Z) | ||
| 358 | cgen(l, Z, 0); | ||
| 359 | if(r != Z) | ||
| 360 | cgen(r, Z, 0); | ||
| 361 | } | ||
| 362 | |||
| 363 | void | 271 | void |
| 364 | sextern(Sym *s, Node *a, long o, long w) | 272 | sextern(Sym *s, Node *a, long o, long w) |
| 365 | { | 273 | { |
| @@ -651,35 +559,6 @@ zaddr(char *bp, Adr *a, int s) · 285 unmodified lines | |||
| 651 | return bp; | 559 | return bp; |
| 652 | } | 560 | } |
| 653 | 561 | ||
| 654 | void | ||
| 655 | ieeedtod(Ieee *ieee, double native) | ||
| 656 | { | ||
| 657 | double fr, ho, f; | ||
| 658 | int exp; | ||
| 659 | |||
| 660 | if(native < 0) { | ||
| 661 | ieeedtod(ieee, -native); | ||
| 662 | ieee->h |= 0x80000000L; | ||
| 663 | return; | ||
| 664 | } | ||
| 665 | if(native == 0) { | ||
| 666 | ieee->l = 0; | ||
| 667 | ieee->h = 0; | ||
| 668 | return; | ||
| 669 | } | ||
| 670 | fr = frexp(native, &exp); | ||
| 671 | f = 2097152L; /* shouldnt use fp constants here */ | ||
| 672 | fr = modf(fr*f, &ho); | ||
| 673 | ieee->h = ho; | ||
| 674 | ieee->h &= 0xfffffL; | ||
| 675 | ieee->h |= (exp+1022L) << 20; | ||
| 676 | f = 65536L; | ||
| 677 | fr = modf(fr*f, &ho); | ||
| 678 | ieee->l = ho; | ||
| 679 | ieee->l <<= 16; | ||
| 680 | ieee->l |= (long)(fr*f); | ||
| 681 | } | ||
| 682 | |||
| 683 | long | 562 | long |
| 684 | align(long i, Type *t, int op) | 563 | align(long i, Type *t, int op) |
| 685 | { | 564 | { |
| @@ -170,7 +170,7 @@ garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp) · 169 unmodified lines | |||
| 170 | nod.left = *fnxp; | 170 | nod.left = *fnxp; |
| 171 | nod.right = n; | 171 | nod.right = n; |
| 172 | nod.type = n->type; | 172 | nod.type = n->type; |
| 173 | cgen(&nod, Z, 0); | 173 | cgen(&nod, Z); |
| 174 | (*fnxp)++; | 174 | (*fnxp)++; |
| 175 | } | 175 | } |
| 176 | return; | 176 | return; |
| @@ -187,18 +187,18 @@ garg1(Node *n, Node *tn1, Node *tn2, int f, Node **fnxp) · 10 unmodified lines | |||
| 187 | if(REGARG >= 0 && curarg == 0 && typechlp[n->type->etype]) { | 187 | if(REGARG >= 0 && curarg == 0 && typechlp[n->type->etype]) { |
| 188 | regaalloc1(tn1, n); | 188 | regaalloc1(tn1, n); |
| 189 | if(n->complex >= FNX) { | 189 | if(n->complex >= FNX) { |
| 190 | cgen(*fnxp, tn1, 0); | 190 | cgen(*fnxp, tn1); |
| 191 | (*fnxp)++; | 191 | (*fnxp)++; |
| 192 | } else | 192 | } else |
| 193 | cgen(n, tn1, 0); | 193 | cgen(n, tn1); |
| 194 | return; | 194 | return; |
| 195 | } | 195 | } |
| 196 | regalloc(tn1, n, Z); | 196 | regalloc(tn1, n, Z); |
| 197 | if(n->complex >= FNX) { | 197 | if(n->complex >= FNX) { |
| 198 | cgen(*fnxp, tn1, 0); | 198 | cgen(*fnxp, tn1); |
| 199 | (*fnxp)++; | 199 | (*fnxp)++; |
| 200 | } else | 200 | } else |
| 201 | cgen(n, tn1, 0); | 201 | cgen(n, tn1); |
| 202 | regaalloc(tn2, n); | 202 | regaalloc(tn2, n); |
| 203 | gopcode(OAS, tn1, Z, tn2); | 203 | gopcode(OAS, tn1, Z, tn2); |
| 204 | regfree(tn1); | 204 | regfree(tn1); |
| @@ -57,6 +57,7 @@ struct Case · 56 unmodified lines | |||
| 57 | long val; | 57 | long val; |
| 58 | long label; | 58 | long label; |
| 59 | char def; | 59 | char def; |
| 60 | char isv; | ||
| 60 | }; | 61 | }; |
| 61 | #define C ((Case*)0) | 62 | #define C ((Case*)0) |
| 62 | 63 | ||
| @@ -128,6 +129,7 @@ struct Rgn · 65 unmodified lines | |||
| 128 | }; | 129 | }; |
| 129 | 130 | ||
| 130 | EXTERN long breakpc; | 131 | EXTERN long breakpc; |
| 132 | EXTERN long nbreak; | ||
| 131 | EXTERN Case* cases; | 133 | EXTERN Case* cases; |
| 132 | EXTERN Node constnode; | 134 | EXTERN Node constnode; |
| 133 | EXTERN Node fconstnode; | 135 | EXTERN Node fconstnode; |
| @@ -140,7 +142,6 @@ EXTERN int hintabsize; · 6 unmodified lines | |||
| 140 | EXTERN long maxargsafe; | 142 | EXTERN long maxargsafe; |
| 141 | EXTERN Multab multab[20]; | 143 | EXTERN Multab multab[20]; |
| 142 | EXTERN int mnstring; | 144 | EXTERN int mnstring; |
| 143 | EXTERN int retok; | ||
| 144 | EXTERN Node* nodrat; | 145 | EXTERN Node* nodrat; |
| 145 | EXTERN Node* nodret; | 146 | EXTERN Node* nodret; |
| 146 | EXTERN Node* nodsafe; | 147 | EXTERN Node* nodsafe; |
| @@ -183,6 +184,7 @@ EXTERN long regbits; · 36 unmodified lines | |||
| 183 | EXTERN long exregbits; | 184 | EXTERN long exregbits; |
| 184 | 185 | ||
| 185 | EXTERN int change; | 186 | EXTERN int change; |
| 187 | EXTERN int suppress; | ||
| 186 | 188 | ||
| 187 | EXTERN Reg* firstr; | 189 | EXTERN Reg* firstr; |
| 188 | EXTERN Reg* lastr; | 190 | EXTERN Reg* lastr; |
| @@ -204,7 +206,7 @@ void gen(Node*); · 15 unmodified lines | |||
| 204 | void usedset(Node*, int); | 206 | void usedset(Node*, int); |
| 205 | void noretval(int); | 207 | void noretval(int); |
| 206 | void xcom(Node*); | 208 | void xcom(Node*); |
| 207 | void bcomplex(Node*); | 209 | int bcomplex(Node*, Node*); |
| 208 | 210 | ||
| 209 | /* | 211 | /* |
| 210 | * cgen.c | 212 | * cgen.c |
| @@ -255,7 +257,8 @@ void gpseudo(int, Sym*, Node*); · 44 unmodified lines | |||
| 255 | */ | 257 | */ |
| 256 | int swcmp(const void*, const void*); | 258 | int swcmp(const void*, const void*); |
| 257 | void doswit(Node*); | 259 | void doswit(Node*); |
| 258 | void swit1(C1*, int, long, Node*, Node*); | 260 | void swit1(C1*, int, long, Node*); |
| 261 | void swit2(C1*, int, long, Node*, Node*); | ||
| 259 | void casf(void); | 262 | void casf(void); |
| 260 | void bitload(Node*, Node*, Node*, Node*, Node*); | 263 | void bitload(Node*, Node*, Node*, Node*, Node*); |
| 261 | void bitstore(Node*, Node*, Node*, Node*, Node*); | 264 | void bitstore(Node*, Node*, Node*, Node*, Node*); |
| @@ -4,6 +4,8 @@ TARG=kc · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | OFILES=\ | 5 | OFILES=\ |
| 6 | peep.$O\ | 6 | peep.$O\ |
| 7 | pgen.$O\ | ||
| 8 | pswt.$O\ | ||
| 7 | reg.$O\ | 9 | reg.$O\ |
| 8 | cgen.$O\ | 10 | cgen.$O\ |
| 9 | enam.$O\ | 11 | enam.$O\ |
| @@ -30,3 +32,9 @@ $ROOT/$OBJDIR/lib/libcc.a: · 20 unmodified lines | |||
| 30 | cd ../cc | 32 | cd ../cc |
| 31 | mk $MKFLAGS install | 33 | mk $MKFLAGS install |
| 32 | mk $MKFLAGS clean | 34 | mk $MKFLAGS clean |
| 35 | |||
| 36 | %.$O: ../cc/%.c | ||
| 37 | $CC $CFLAGS -I. ../cc/$stem.c | ||
| 38 | |||
| 39 | #enam.c: k.out.h | ||
| 40 | # rc mkenam | ||
| @@ -1,343 +1,5 @@ | |||
| 1 | #include "gc.h" | 1 | #include "gc.h" |
| 2 | 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 | retok = 0; | ||
| 80 | switch(o) { | ||
| 81 | |||
| 82 | default: | ||
| 83 | complex(n); | ||
| 84 | cgen(n, Z); | ||
| 85 | break; | ||
| 86 | |||
| 87 | case OLIST: | ||
| 88 | gen(n->left); | ||
| 89 | |||
| 90 | rloop: | ||
| 91 | n = n->right; | ||
| 92 | goto loop; | ||
| 93 | |||
| 94 | case ORETURN: | ||
| 95 | retok = 1; | ||
| 96 | complex(n); | ||
| 97 | if(n->type == T) | ||
| 98 | break; | ||
| 99 | l = n->left; | ||
| 100 | if(l == Z) { | ||
| 101 | noretval(3); | ||
| 102 | gbranch(ORETURN); | ||
| 103 | break; | ||
| 104 | } | ||
| 105 | if(typesuv[n->type->etype]) { | ||
| 106 | sugen(l, nodret, n->type->width); | ||
| 107 | noretval(3); | ||
| 108 | gbranch(ORETURN); | ||
| 109 | break; | ||
| 110 | } | ||
| 111 | regret(&nod, n); | ||
| 112 | cgen(l, &nod); | ||
| 113 | regfree(&nod); | ||
| 114 | if(typefd[n->type->etype]) | ||
| 115 | noretval(1); | ||
| 116 | else | ||
| 117 | noretval(2); | ||
| 118 | gbranch(ORETURN); | ||
| 119 | break; | ||
| 120 | |||
| 121 | case OLABEL: | ||
| 122 | l = n->left; | ||
| 123 | if(l) { | ||
| 124 | l->xoffset = pc; | ||
| 125 | if(l->label) | ||
| 126 | patch(l->label, pc); | ||
| 127 | } | ||
| 128 | gbranch(OGOTO); /* prevent self reference in reg */ | ||
| 129 | patch(p, pc); | ||
| 130 | goto rloop; | ||
| 131 | |||
| 132 | case OGOTO: | ||
| 133 | retok = 1; | ||
| 134 | n = n->left; | ||
| 135 | if(n == Z) | ||
| 136 | return; | ||
| 137 | if(n->complex == 0) { | ||
| 138 | diag(Z, "label undefined: %s", n->sym->name); | ||
| 139 | return; | ||
| 140 | } | ||
| 141 | gbranch(OGOTO); | ||
| 142 | if(n->xoffset) { | ||
| 143 | patch(p, n->xoffset); | ||
| 144 | return; | ||
| 145 | } | ||
| 146 | if(n->label) | ||
| 147 | patch(n->label, pc-1); | ||
| 148 | n->label = p; | ||
| 149 | return; | ||
| 150 | |||
| 151 | case OCASE: | ||
| 152 | l = n->left; | ||
| 153 | if(cases == C) | ||
| 154 | diag(n, "case/default outside a switch"); | ||
| 155 | if(l == Z) { | ||
| 156 | casf(); | ||
| 157 | cases->val = 0; | ||
| 158 | cases->def = 1; | ||
| 159 | cases->label = pc; | ||
| 160 | goto rloop; | ||
| 161 | } | ||
| 162 | complex(l); | ||
| 163 | if(l->type == T) | ||
| 164 | goto rloop; | ||
| 165 | if(l->op == OCONST) | ||
| 166 | if(typechl[l->type->etype]) { | ||
| 167 | casf(); | ||
| 168 | cases->val = l->vconst; | ||
| 169 | cases->def = 0; | ||
| 170 | cases->label = pc; | ||
| 171 | goto rloop; | ||
| 172 | } | ||
| 173 | diag(n, "case expression must be integer constant"); | ||
| 174 | goto rloop; | ||
| 175 | |||
| 176 | case OSWITCH: | ||
| 177 | l = n->left; | ||
| 178 | complex(l); | ||
| 179 | if(l->type == T) | ||
| 180 | break; | ||
| 181 | if(!typechl[l->type->etype]) { | ||
| 182 | diag(n, "switch expression must be integer"); | ||
| 183 | break; | ||
| 184 | } | ||
| 185 | |||
| 186 | gbranch(OGOTO); /* entry */ | ||
| 187 | sp = p; | ||
| 188 | |||
| 189 | cn = cases; | ||
| 190 | cases = C; | ||
| 191 | casf(); | ||
| 192 | |||
| 193 | sbc = breakpc; | ||
| 194 | breakpc = pc; | ||
| 195 | gbranch(OGOTO); | ||
| 196 | spb = p; | ||
| 197 | |||
| 198 | gen(n->right); | ||
| 199 | gbranch(OGOTO); | ||
| 200 | patch(p, breakpc); | ||
| 201 | |||
| 202 | patch(sp, pc); | ||
| 203 | regalloc(&nod, l, Z); | ||
| 204 | nod.type = types[TLONG]; | ||
| 205 | cgen(l, &nod); | ||
| 206 | doswit(&nod); | ||
| 207 | regfree(&nod); | ||
| 208 | patch(spb, pc); | ||
| 209 | |||
| 210 | cases = cn; | ||
| 211 | breakpc = sbc; | ||
| 212 | break; | ||
| 213 | |||
| 214 | case OWHILE: | ||
| 215 | case ODWHILE: | ||
| 216 | l = n->left; | ||
| 217 | gbranch(OGOTO); /* entry */ | ||
| 218 | sp = p; | ||
| 219 | |||
| 220 | scc = continpc; | ||
| 221 | continpc = pc; | ||
| 222 | gbranch(OGOTO); | ||
| 223 | spc = p; | ||
| 224 | |||
| 225 | sbc = breakpc; | ||
| 226 | breakpc = pc; | ||
| 227 | gbranch(OGOTO); | ||
| 228 | spb = p; | ||
| 229 | |||
| 230 | patch(spc, pc); | ||
| 231 | if(n->op == OWHILE) | ||
| 232 | patch(sp, pc); | ||
| 233 | bcomplex(l); /* test */ | ||
| 234 | patch(p, breakpc); | ||
| 235 | |||
| 236 | if(n->op == ODWHILE) | ||
| 237 | patch(sp, pc); | ||
| 238 | gen(n->right); /* body */ | ||
| 239 | gbranch(OGOTO); | ||
| 240 | patch(p, continpc); | ||
| 241 | |||
| 242 | patch(spb, pc); | ||
| 243 | continpc = scc; | ||
| 244 | breakpc = sbc; | ||
| 245 | break; | ||
| 246 | |||
| 247 | case OFOR: | ||
| 248 | l = n->left; | ||
| 249 | gen(l->right->left); /* init */ | ||
| 250 | gbranch(OGOTO); /* entry */ | ||
| 251 | sp = p; | ||
| 252 | |||
| 253 | scc = continpc; | ||
| 254 | continpc = pc; | ||
| 255 | gbranch(OGOTO); | ||
| 256 | spc = p; | ||
| 257 | |||
| 258 | sbc = breakpc; | ||
| 259 | breakpc = pc; | ||
| 260 | gbranch(OGOTO); | ||
| 261 | spb = p; | ||
| 262 | |||
| 263 | patch(spc, pc); | ||
| 264 | gen(l->right->right); /* inc */ | ||
| 265 | patch(sp, pc); | ||
| 266 | if(l->left != Z) { /* test */ | ||
| 267 | bcomplex(l->left); | ||
| 268 | patch(p, breakpc); | ||
| 269 | } | ||
| 270 | gen(n->right); /* body */ | ||
| 271 | gbranch(OGOTO); | ||
| 272 | patch(p, continpc); | ||
| 273 | |||
| 274 | patch(spb, pc); | ||
| 275 | continpc = scc; | ||
| 276 | breakpc = sbc; | ||
| 277 | break; | ||
| 278 | |||
| 279 | case OCONTINUE: | ||
| 280 | if(continpc < 0) { | ||
| 281 | diag(n, "continue not in a loop"); | ||
| 282 | break; | ||
| 283 | } | ||
| 284 | gbranch(OGOTO); | ||
| 285 | patch(p, continpc); | ||
| 286 | break; | ||
| 287 | |||
| 288 | case OBREAK: | ||
| 289 | if(breakpc < 0) { | ||
| 290 | diag(n, "break not in a loop"); | ||
| 291 | break; | ||
| 292 | } | ||
| 293 | gbranch(OGOTO); | ||
| 294 | patch(p, breakpc); | ||
| 295 | break; | ||
| 296 | |||
| 297 | case OIF: | ||
| 298 | l = n->left; | ||
| 299 | bcomplex(l); | ||
| 300 | sp = p; | ||
| 301 | if(n->right->left != Z) | ||
| 302 | gen(n->right->left); | ||
| 303 | if(n->right->right != Z) { | ||
| 304 | gbranch(OGOTO); | ||
| 305 | patch(sp, pc); | ||
| 306 | sp = p; | ||
| 307 | gen(n->right->right); | ||
| 308 | } | ||
| 309 | patch(sp, pc); | ||
| 310 | break; | ||
| 311 | |||
| 312 | case OSET: | ||
| 313 | case OUSED: | ||
| 314 | usedset(n->left, o); | ||
| 315 | break; | ||
| 316 | } | ||
| 317 | } | ||
| 318 | |||
| 319 | void | ||
| 320 | usedset(Node *n, int o) | ||
| 321 | { | ||
| 322 | if(n->op == OLIST) { | ||
| 323 | usedset(n->left, o); | ||
| 324 | usedset(n->right, o); | ||
| 325 | return; | ||
| 326 | } | ||
| 327 | complex(n); | ||
| 328 | switch(n->op) { | ||
| 329 | case OADDR: /* volatile */ | ||
| 330 | gins(ANOP, n, Z); | ||
| 331 | break; | ||
| 332 | case ONAME: | ||
| 333 | if(o == OSET) | ||
| 334 | gins(ANOP, Z, n); | ||
| 335 | else | ||
| 336 | gins(ANOP, n, Z); | ||
| 337 | break; | ||
| 338 | } | ||
| 339 | } | ||
| 340 | |||
| 341 | void | 3 | void |
| 342 | noretval(int n) | 4 | noretval(int n) |
| 343 | { | 5 | { |
| @@ -574,17 +236,3 @@ xcom(Node *n) · 230 unmodified lines | |||
| 574 | } | 236 | } |
| 575 | } | 237 | } |
| 576 | 238 | ||
| 577 | void | ||
| 578 | bcomplex(Node *n) | ||
| 579 | { | ||
| 580 | |||
| 581 | complex(n); | ||
| 582 | if(n->type != T) | ||
| 583 | if(tcompat(n, T, n->type, tnot)) | ||
| 584 | n->type = T; | ||
| 585 | if(n->type != T) { | ||
| 586 | bool64(n); | ||
| 587 | boolgen(n, 1, Z); | ||
| 588 | } else | ||
| 589 | gbranch(OGOTO); | ||
| 590 | } | ||
| @@ -1,59 +1,17 @@ | |||
| 1 | #include "gc.h" | 1 | #include "gc.h" |
| 2 | 2 | ||
| 3 | int | ||
| 4 | swcmp(const void *a1, const void *a2) | ||
| 5 | { | ||
| 6 | C1 *p1, *p2; | ||
| 7 | |||
| 8 | p1 = (C1*)a1; | ||
| 9 | p2 = (C1*)a2; | ||
| 10 | if(p1->val < p2->val) | ||
| 11 | return -1; | ||
| 12 | return p1->val > p2->val; | ||
| 13 | } | ||
| 14 | |||
| 15 | void | 3 | void |
| 16 | doswit(Node *n) | 4 | swit1(C1 *q, int nc, long def, Node *n) |
| 17 | { | 5 | { |
| 18 | Case *c; | ||
| 19 | C1 *q, *iq; | ||
| 20 | long def, nc, i; | ||
| 21 | Node tn; | 6 | Node tn; |
| 22 | 7 | ||
| 23 | def = 0; | ||
| 24 | nc = 0; | ||
| 25 | for(c = cases; c->link != C; c = c->link) { | ||
| 26 | if(c->def) { | ||
| 27 | if(def) | ||
| 28 | diag(n, "more than one default in switch"); | ||
| 29 | def = c->label; | ||
| 30 | continue; | ||
| 31 | } | ||
| 32 | nc++; | ||
| 33 | } | ||
| 34 | |||
| 35 | iq = alloc(nc*sizeof(C1)); | ||
| 36 | q = iq; | ||
| 37 | for(c = cases; c->link != C; c = c->link) { | ||
| 38 | if(c->def) | ||
| 39 | continue; | ||
| 40 | q->label = c->label; | ||
| 41 | q->val = c->val; | ||
| 42 | q++; | ||
| 43 | } | ||
| 44 | qsort(iq, nc, sizeof(C1), swcmp); | ||
| 45 | if(def == 0) | ||
| 46 | def = breakpc; | ||
| 47 | for(i=0; i<nc-1; i++) | ||
| 48 | if(iq[i].val == iq[i+1].val) | ||
| 49 | diag(n, "duplicate cases in switch %ld", iq[i].val); | ||
| 50 | regalloc(&tn, ®node, Z); | 8 | regalloc(&tn, ®node, Z); |
| 51 | swit1(iq, nc, def, n, &tn); | 9 | swit2(q, nc, def, n, &tn); |
| 52 | regfree(&tn); | 10 | regfree(&tn); |
| 53 | } | 11 | } |
| 54 | 12 | ||
| 55 | void | 13 | void |
| 56 | swit1(C1 *q, int nc, long def, Node *n, Node *tn) | 14 | swit2(C1 *q, int nc, long def, Node *n, Node *tn) |
| 57 | { | 15 | { |
| 58 | C1 *r; | 16 | C1 *r; |
| 59 | int i; | 17 | int i; |
| @@ -87,20 +45,10 @@ swit1(C1 *q, int nc, long def, Node *n, Node *tn) · 27 unmodified lines | |||
| 87 | gbranch(OGOTO); | 45 | gbranch(OGOTO); |
| 88 | p->as = ABE; | 46 | p->as = ABE; |
| 89 | patch(p, r->label); | 47 | patch(p, r->label); |
| 90 | swit1(q, i, def, n, tn); | 48 | swit2(q, i, def, n, tn); |
| 91 | 49 | ||
| 92 | patch(sp, pc); | 50 | patch(sp, pc); |
| 93 | swit1(r+1, nc-i-1, def, n, tn); | 51 | swit2(r+1, nc-i-1, def, n, tn); |
| 94 | } | ||
| 95 | |||
| 96 | void | ||
| 97 | casf(void) | ||
| 98 | { | ||
| 99 | Case *c; | ||
| 100 | |||
| 101 | c = alloc(sizeof(*c)); | ||
| 102 | c->link = cases; | ||
| 103 | cases = c; | ||
| 104 | } | 52 | } |
| 105 | 53 | ||
| 106 | void | 54 | void |
| @@ -198,31 +146,6 @@ outstring(char *s, long n) · 91 unmodified lines | |||
| 198 | return r; | 146 | return r; |
| 199 | } | 147 | } |
| 200 | 148 | ||
| 201 | long | ||
| 202 | outlstring(ushort *s, long n) | ||
| 203 | { | ||
| 204 | char buf[2]; | ||
| 205 | int c; | ||
| 206 | long r; | ||
| 207 | |||
| 208 | while(nstring & 1) | ||
| 209 | outstring("", 1); | ||
| 210 | r = nstring; | ||
| 211 | while(n > 0) { | ||
| 212 | c = *s++; | ||
| 213 | if(align(0, types[TCHAR], Aarg1)) { | ||
| 214 | buf[0] = c>>8; | ||
| 215 | buf[1] = c; | ||
| 216 | } else { | ||
| 217 | buf[0] = c; | ||
| 218 | buf[1] = c>>8; | ||
| 219 | } | ||
| 220 | outstring(buf, 2); | ||
| 221 | n -= sizeof(ushort); | ||
| 222 | } | ||
| 223 | return r; | ||
| 224 | } | ||
| 225 | |||
| 226 | int | 149 | int |
| 227 | mulcon(Node *n, Node *nn) | 150 | mulcon(Node *n, Node *nn) |
| 228 | { | 151 | { |
| @@ -312,16 +235,6 @@ loop: · 83 unmodified lines | |||
| 312 | goto loop; | 235 | goto loop; |
| 313 | } | 236 | } |
| 314 | 237 | ||
| 315 | void | ||
| 316 | nullwarn(Node *l, Node *r) | ||
| 317 | { | ||
| 318 | warn(Z, "result of operation not used"); | ||
| 319 | if(l != Z) | ||
| 320 | cgen(l, Z); | ||
| 321 | if(r != Z) | ||
| 322 | cgen(r, Z); | ||
| 323 | } | ||
| 324 | |||
| 325 | void | 238 | void |
| 326 | sextern(Sym *s, Node *a, long o, long w) | 239 | sextern(Sym *s, Node *a, long o, long w) |
| 327 | { | 240 | { |
| @@ -609,35 +522,6 @@ zaddr(Biobuf *b, Adr *a, int s) · 281 unmodified lines | |||
| 609 | } | 522 | } |
| 610 | } | 523 | } |
| 611 | 524 | ||
| 612 | void | ||
| 613 | ieeedtod(Ieee *ieee, double native) | ||
| 614 | { | ||
| 615 | double fr, ho, f; | ||
| 616 | int exp; | ||
| 617 | |||
| 618 | if(native < 0) { | ||
| 619 | ieeedtod(ieee, -native); | ||
| 620 | ieee->h |= 0x80000000L; | ||
| 621 | return; | ||
| 622 | } | ||
| 623 | if(native == 0) { | ||
| 624 | ieee->l = 0; | ||
| 625 | ieee->h = 0; | ||
| 626 | return; | ||
| 627 | } | ||
| 628 | fr = frexp(native, &exp); | ||
| 629 | f = 2097152L; /* shouldnt use fp constants here */ | ||
| 630 | fr = modf(fr*f, &ho); | ||
| 631 | ieee->h = ho; | ||
| 632 | ieee->h &= 0xfffffL; | ||
| 633 | ieee->h |= (exp+1022L) << 20; | ||
| 634 | f = 65536L; | ||
| 635 | fr = modf(fr*f, &ho); | ||
| 636 | ieee->l = ho; | ||
| 637 | ieee->l <<= 16; | ||
| 638 | ieee->l |= (long)(fr*f); | ||
| 639 | } | ||
| 640 | |||
| 641 | long | 525 | long |
| 642 | align(long i, Type *t, int op) | 526 | align(long i, Type *t, int op) |
| 643 | { | 527 | { |
| @@ -497,6 +497,8 @@ cgen(Node *n, Node *nn) · 496 unmodified lines | |||
| 497 | } else | 497 | } else |
| 498 | gopcode(OADD, nodconst(v), Z, &nod); | 498 | gopcode(OADD, nodconst(v), Z, &nod); |
| 499 | gopcode(OAS, &nod, Z, &nod2); | 499 | gopcode(OAS, &nod, Z, &nod2); |
| 500 | if(nn && l->op == ONAME) /* in x=++i, emit USED(i) */ | ||
| 501 | gins(ANOP, l, Z); | ||
| 500 | 502 | ||
| 501 | regfree(&nod); | 503 | regfree(&nod); |
| 502 | if(l->addable < INDEXED) | 504 | if(l->addable < INDEXED) |
| @@ -58,6 +58,7 @@ struct Case · 57 unmodified lines | |||
| 58 | long val; | 58 | long val; |
| 59 | long label; | 59 | long label; |
| 60 | char def; | 60 | char def; |
| 61 | char isv; | ||
| 61 | }; | 62 | }; |
| 62 | #define C ((Case*)0) | 63 | #define C ((Case*)0) |
| 63 | 64 | ||
| @@ -129,6 +130,7 @@ struct Rgn · 65 unmodified lines | |||
| 129 | }; | 130 | }; |
| 130 | 131 | ||
| 131 | EXTERN long breakpc; | 132 | EXTERN long breakpc; |
| 133 | EXTERN long nbreak; | ||
| 132 | EXTERN Case* cases; | 134 | EXTERN Case* cases; |
| 133 | EXTERN Node constnode; | 135 | EXTERN Node constnode; |
| 134 | EXTERN Node fconstnode; | 136 | EXTERN Node fconstnode; |
| @@ -140,7 +142,6 @@ EXTERN Prog* lastp; · 5 unmodified lines | |||
| 140 | EXTERN long maxargsafe; | 142 | EXTERN long maxargsafe; |
| 141 | EXTERN int mnstring; | 143 | EXTERN int mnstring; |
| 142 | EXTERN Multab multab[20]; | 144 | EXTERN Multab multab[20]; |
| 143 | EXTERN int retok; | ||
| 144 | EXTERN int hintabsize; | 145 | EXTERN int hintabsize; |
| 145 | EXTERN Node* nodrat; | 146 | EXTERN Node* nodrat; |
| 146 | EXTERN Node* nodret; | 147 | EXTERN Node* nodret; |
| @@ -184,6 +185,7 @@ EXTERN long regbits; · 37 unmodified lines | |||
| 184 | EXTERN long exregbits; | 185 | EXTERN long exregbits; |
| 185 | 186 | ||
| 186 | EXTERN int change; | 187 | EXTERN int change; |
| 188 | EXTERN int suppress; | ||
| 187 | 189 | ||
| 188 | EXTERN Reg* firstr; | 190 | EXTERN Reg* firstr; |
| 189 | EXTERN Reg* lastr; | 191 | EXTERN Reg* lastr; |
| @@ -204,7 +206,7 @@ void codgen(Node*, Node*); · 14 unmodified lines | |||
| 204 | void gen(Node*); | 206 | void gen(Node*); |
| 205 | void noretval(int); | 207 | void noretval(int); |
| 206 | void xcom(Node*); | 208 | void xcom(Node*); |
| 207 | void bcomplex(Node*); | 209 | int bcomplex(Node*, Node*); |
| 208 | void usedset(Node*, int); | 210 | void usedset(Node*, int); |
| 209 | 211 | ||
| 210 | /* | 212 | /* |
| @@ -256,7 +258,8 @@ void gpseudo(int, Sym*, Node*); · 45 unmodified lines | |||
| 256 | */ | 258 | */ |
| 257 | int swcmp(const void*, const void*); | 259 | int swcmp(const void*, const void*); |
| 258 | void doswit(Node*); | 260 | void doswit(Node*); |
| 259 | void swit1(C1*, int, long, Node*, Node*); | 261 | void swit1(C1*, int, long, Node*); |
| 262 | void swit2(C1*, int, long, Node*, Node*); | ||
| 260 | void casf(void); | 263 | void casf(void); |
| 261 | void bitload(Node*, Node*, Node*, Node*, Node*); | 264 | void bitload(Node*, Node*, Node*, Node*, Node*); |
| 262 | void bitstore(Node*, Node*, Node*, Node*, Node*); | 265 | void bitstore(Node*, Node*, Node*, Node*, Node*); |
| @@ -7,6 +7,8 @@ OFILES=\ · 6 unmodified lines | |||
| 7 | enam.$O\ | 7 | enam.$O\ |
| 8 | list.$O\ | 8 | list.$O\ |
| 9 | peep.$O\ | 9 | peep.$O\ |
| 10 | pgen.$O\ | ||
| 11 | pswt.$O\ | ||
| 10 | reg.$O\ | 12 | reg.$O\ |
| 11 | sgen.$O\ | 13 | sgen.$O\ |
| 12 | swt.$O\ | 14 | swt.$O\ |
| @@ -30,3 +32,9 @@ $ROOT/$OBJDIR/lib/libcc.a: · 17 unmodified lines | |||
| 30 | cd ../cc | 32 | cd ../cc |
| 31 | mk $MKFLAGS install | 33 | mk $MKFLAGS install |
| 32 | mk $MKFLAGS clean | 34 | mk $MKFLAGS clean |
| 35 | |||
| 36 | %.$O: ../cc/%.c | ||
| 37 | $CC $CFLAGS -I. ../cc/$stem.c | ||
| 38 | |||
| 39 | #enam.c: v.out.h | ||
| 40 | # rc mkenam | ||
| @@ -569,7 +569,7 @@ copyu(Prog *p, Adr *v, Adr *s) · 568 unmodified lines | |||
| 569 | return 3; | 569 | return 3; |
| 570 | return 0; | 570 | return 0; |
| 571 | } | 571 | } |
| 572 | return 0; | 572 | /* not reached */ |
| 573 | } | 573 | } |
| 574 | 574 | ||
| 575 | int | 575 | int |
| @@ -1,344 +1,5 @@ | |||
| 1 | #include "gc.h" | 1 | #include "gc.h" |
| 2 | 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 | casf(); | ||
| 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 | casf(); | ||
| 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 | casf(); | ||
| 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 | 3 | void |
| 343 | noretval(int n) | 4 | noretval(int n) |
| 344 | { | 5 | { |
| @@ -564,17 +225,3 @@ xcom(Node *n) · 219 unmodified lines | |||
| 564 | } | 225 | } |
| 565 | } | 226 | } |
| 566 | 227 | ||
| 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 | } | ||
| @@ -1,62 +1,17 @@ | |||
| 1 | #include "gc.h" | 1 | #include "gc.h" |
| 2 | 2 | ||
| 3 | int | ||
| 4 | swcmp(const void *a1, const void *a2) | ||
| 5 | { | ||
| 6 | C1 *p1, *p2; | ||
| 7 | |||
| 8 | p1 = (C1*)a1; | ||
| 9 | p2 = (C1*)a2; | ||
| 10 | if(p1->val < p2->val) | ||
| 11 | return -1; | ||
| 12 | return p1->val > p2->val; | ||
| 13 | } | ||
| 14 | |||
| 15 | void | 3 | void |
| 16 | doswit(Node *n) | 4 | swit1(C1 *q, int nc, long def, Node *n) |
| 17 | { | 5 | { |
| 18 | Case *c; | ||
| 19 | C1 *q, *iq; | ||
| 20 | long def, nc, i; | ||
| 21 | Node tn; | 6 | Node tn; |
| 22 | 7 | ||
| 23 | def = 0; | ||
| 24 | nc = 0; | ||
| 25 | for(c = cases; c->link != C; c = c->link) { | ||
| 26 | if(c->def) { | ||
| 27 | if(def) | ||
| 28 | diag(n, "more than one default in switch"); | ||
| 29 | def = c->label; | ||
| 30 | continue; | ||
| 31 | } | ||
| 32 | nc++; | ||
| 33 | } | ||
| 34 | |||
| 35 | iq = alloc(nc*sizeof(C1)); | ||
| 36 | q = iq; | ||
| 37 | for(c = cases; c->link != C; c = c->link) { | ||
| 38 | if(c->def) | ||
| 39 | continue; | ||
| 40 | q->label = c->label; | ||
| 41 | q->val = c->val; | ||
| 42 | q++; | ||
| 43 | } | ||
| 44 | qsort(iq, nc, sizeof(C1), swcmp); | ||
| 45 | if(debug['W']) | ||
| 46 | for(i=0; i<nc; i++) | ||
| 47 | print("case %2ld: = %.8lux\n", i, iq[i].val); | ||
| 48 | if(def == 0) | ||
| 49 | def = breakpc; | ||
| 50 | for(i=0; i<nc-1; i++) | ||
| 51 | if(iq[i].val == iq[i+1].val) | ||
| 52 | diag(n, "duplicate cases in switch %ld", iq[i].val); | ||
| 53 | regalloc(&tn, ®node, Z); | 8 | regalloc(&tn, ®node, Z); |
| 54 | swit1(iq, nc, def, n, &tn); | 9 | swit2(q, nc, def, n, &tn); |
| 55 | regfree(&tn); | 10 | regfree(&tn); |
| 56 | } | 11 | } |
| 57 | 12 | ||
| 58 | void | 13 | void |
| 59 | swit1(C1 *q, int nc, long def, Node *n, Node *tn) | 14 | swit2(C1 *q, int nc, long def, Node *n, Node *tn) |
| 60 | { | 15 | { |
| 61 | C1 *r; | 16 | C1 *r; |
| 62 | int i; | 17 | int i; |
| @@ -84,22 +39,12 @@ swit1(C1 *q, int nc, long def, Node *n, Node *tn) · 21 unmodified lines | |||
| 84 | sp = p; | 39 | sp = p; |
| 85 | gopcode(OEQ, n, tn, Z); | 40 | gopcode(OEQ, n, tn, Z); |
| 86 | patch(p, r->label); | 41 | patch(p, r->label); |
| 87 | swit1(q, i, def, n, tn); | 42 | swit2(q, i, def, n, tn); |
| 88 | 43 | ||
| 89 | if(debug['W']) | 44 | if(debug['W']) |
| 90 | print("case < %.8lux\n", r->val); | 45 | print("case < %.8lux\n", r->val); |
| 91 | patch(sp, pc); | 46 | patch(sp, pc); |
| 92 | swit1(r+1, nc-i-1, def, n, tn); | 47 | swit2(r+1, nc-i-1, def, n, tn); |
| 93 | } | ||
| 94 | |||
| 95 | void | ||
| 96 | casf(void) | ||
| 97 | { | ||
| 98 | Case *c; | ||
| 99 | |||
| 100 | c = alloc(sizeof(*c)); | ||
| 101 | c->link = cases; | ||
| 102 | cases = c; | ||
| 103 | } | 48 | } |
| 104 | 49 | ||
| 105 | void | 50 | void |
| @@ -197,31 +142,6 @@ outstring(char *s, long n) · 91 unmodified lines | |||
| 197 | return r; | 142 | return r; |
| 198 | } | 143 | } |
| 199 | 144 | ||
| 200 | long | ||
| 201 | outlstring(ushort *s, long n) | ||
| 202 | { | ||
| 203 | char buf[2]; | ||
| 204 | int c; | ||
| 205 | long r; | ||
| 206 | |||
| 207 | while(nstring & 1) | ||
| 208 | outstring("", 1); | ||
| 209 | r = nstring; | ||
| 210 | while(n > 0) { | ||
| 211 | c = *s++; | ||
| 212 | if(align(0, types[TCHAR], Aarg1)) { | ||
| 213 | buf[0] = c>>8; | ||
| 214 | buf[1] = c; | ||
| 215 | } else { | ||
| 216 | buf[0] = c; | ||
| 217 | buf[1] = c>>8; | ||
| 218 | } | ||
| 219 | outstring(buf, 2); | ||
| 220 | n -= sizeof(ushort); | ||
| 221 | } | ||
| 222 | return r; | ||
| 223 | } | ||
| 224 | |||
| 225 | int | 145 | int |
| 226 | mulcon(Node *n, Node *nn) | 146 | mulcon(Node *n, Node *nn) |
| 227 | { | 147 | { |
| @@ -313,16 +233,6 @@ loop: · 85 unmodified lines | |||
| 313 | goto loop; | 233 | goto loop; |
| 314 | } | 234 | } |
| 315 | 235 | ||
| 316 | void | ||
| 317 | nullwarn(Node *l, Node *r) | ||
| 318 | { | ||
| 319 | warn(Z, "result of operation not used"); | ||
| 320 | if(l != Z) | ||
| 321 | cgen(l, Z); | ||
| 322 | if(r != Z) | ||
| 323 | cgen(r, Z); | ||
| 324 | } | ||
| 325 | |||
| 326 | void | 236 | void |
| 327 | sextern(Sym *s, Node *a, long o, long w) | 237 | sextern(Sym *s, Node *a, long o, long w) |
| 328 | { | 238 | { |
| @@ -615,35 +525,6 @@ zaddr(char *bp, Adr *a, int s) · 286 unmodified lines | |||
| 615 | return bp; | 525 | return bp; |
| 616 | } | 526 | } |
| 617 | 527 | ||
| 618 | void | ||
| 619 | ieeedtod(Ieee *ieee, double native) | ||
| 620 | { | ||
| 621 | double fr, ho, f; | ||
| 622 | int exp; | ||
| 623 | |||
| 624 | if(native < 0) { | ||
| 625 | ieeedtod(ieee, -native); | ||
| 626 | ieee->h |= 0x80000000L; | ||
| 627 | return; | ||
| 628 | } | ||
| 629 | if(native == 0) { | ||
| 630 | ieee->l = 0; | ||
| 631 | ieee->h = 0; | ||
| 632 | return; | ||
| 633 | } | ||
| 634 | fr = frexp(native, &exp); | ||
| 635 | f = 2097152L; /* shouldnt use fp constants here */ | ||
| 636 | fr = modf(fr*f, &ho); | ||
| 637 | ieee->h = ho; | ||
| 638 | ieee->h &= 0xfffffL; | ||
| 639 | ieee->h |= (exp+1022L) << 20; | ||
| 640 | f = 65536L; | ||
| 641 | fr = modf(fr*f, &ho); | ||
| 642 | ieee->l = ho; | ||
| 643 | ieee->l <<= 16; | ||
| 644 | ieee->l |= (long)(fr*f); | ||
| 645 | } | ||
| 646 | |||
| 647 | long | 528 | long |
| 648 | align(long i, Type *t, int op) | 529 | align(long i, Type *t, int op) |
| 649 | { | 530 | { |
| @@ -660,6 +541,8 @@ align(long i, Type *t, int op) · 10 unmodified lines | |||
| 660 | 541 | ||
| 661 | case Asu2: /* padding at end of a struct */ | 542 | case Asu2: /* padding at end of a struct */ |
| 662 | w = SZ_LONG; | 543 | w = SZ_LONG; |
| 544 | if(packflg) | ||
| 545 | w = packflg; | ||
| 663 | break; | 546 | break; |
| 664 | 547 | ||
| 665 | case Ael1: /* initial allign of struct element */ | 548 | case Ael1: /* initial allign of struct element */ |
| @@ -668,6 +551,8 @@ align(long i, Type *t, int op) · 2 unmodified lines | |||
| 668 | w = ewidth[v->etype]; | 551 | w = ewidth[v->etype]; |
| 669 | if(w <= 0 || w >= SZ_LONG) | 552 | if(w <= 0 || w >= SZ_LONG) |
| 670 | w = SZ_LONG; | 553 | w = SZ_LONG; |
| 554 | if(packflg) | ||
| 555 | w = packflg; | ||
| 671 | break; | 556 | break; |
| 672 | 557 | ||
| 673 | case Ael2: /* width of a struct element */ | 558 | case Ael2: /* width of a struct element */ |
| @@ -687,7 +572,8 @@ align(long i, Type *t, int op) · 13 unmodified lines | |||
| 687 | w = SZ_LONG; | 572 | w = SZ_LONG; |
| 688 | break; | 573 | break; |
| 689 | } | 574 | } |
| 690 | o += SZ_LONG - w; /* big endian adjustment */ | 575 | if(thechar == 'v') |
| 576 | o += SZ_LONG - w; /* big endian adjustment */ | ||
| 691 | w = 1; | 577 | w = 1; |
| 692 | break; | 578 | break; |
| 693 | 579 | ||