1 #include "limbo.h" 2 3 static Inst **breaks; 4 static Inst **conts; 5 static Decl **labels; 6 static Node **bcscps; 7 static int labdep; 8 static Inst nocont; 9 10 static int scp; 11 static Node *scps[MaxScope]; 12 13 static int trcom(Node*, Node*, int); 14 15 static void 16 pushscp(Node *n) 17 { 18 if (scp >= MaxScope) 19 fatal("scope too deep"); 20 scps[scp++] = n; 21 } 22 23 static void 24 popscp(void) 25 { 26 scp--; 27 } 28 29 static Node * 30 curscp(void) 31 { 32 if (scp == 0) 33 return nil; 34 return scps[scp-1]; 35 } 36 37 static void 38 zeroscopes(Node *stop) 39 { 40 int i; 41 Node *cs; 42 43 for (i = scp-1; i >= 0; i--) { 44 cs = scps[i]; 45 if (cs == stop) 46 break; 47 zcom(cs->left, nil); 48 } 49 } 50 51 static void 52 zeroallscopes(Node *n, Node **nn) 53 { 54 if(n == nil) 55 return; 56 for(; n != nil; n = n->right){ 57 switch(n->op){ 58 case Oscope: 59 zeroallscopes(n->right, nn); 60 zcom(n->left, nn); 61 return; 62 case Olabel: 63 case Odo: 64 zeroallscopes(n->right, nn); 65 return; 66 case Oif: 67 case Ofor: 68 zeroallscopes(n->right->left, nn); 69 zeroallscopes(n->right->right, nn); 70 return; 71 case Oalt: 72 case Ocase: 73 case Opick: 74 case Oexcept: 75 for(n = n->right; n != nil; n = n->right) 76 zeroallscopes(n->left->right, nn); 77 return; 78 case Oseq: 79 zeroallscopes(n->left, nn); 80 break; 81 case Oexstmt: 82 zeroallscopes(n->left, nn); 83 zeroallscopes(n->right, nn); 84 return; 85 default: 86 return; 87 } 88 } 89 } 90 91 static Except *excs; 92 93 static void 94 installexc(Node *en, Inst *p1, Inst *p2, Node *zn) 95 { 96 int i, ne; 97 Except *e; 98 Case *c; 99 Label *lab; 100 101 e = allocmem(sizeof(Except)); 102 e->p1 = p1; 103 e->p2 = p2; 104 e->c = en->ty->cse; 105 e->d = en->left->decl; 106 e->zn = zn; 107 e->desc = nil; 108 e->next = excs; 109 excs = e; 110 111 ne = 0; 112 c = e->c; 113 for(i = 0; i < c->nlab; i++){ 114 lab = &c->labs[i]; 115 if(lab->start->ty->kind == Texception) 116 ne++; 117 } 118 e->ne = ne; 119 } 120 121 static int 122 inlist(Decl *d, Decl *dd) 123 { 124 for( ; dd != nil; dd = dd->next) 125 if(d == dd) 126 return 1; 127 return 0; 128 } 129 130 static void 131 excdesc(void) 132 { 133 ulong o, maxo; 134 Except *e; 135 Node *n; 136 Decl *d, *dd, *nd; 137 138 for(e = excs; e != nil; e = e->next){ 139 if(e->zn != nil){ 140 /* set up a decl list for gendesc */ 141 dd = nil; 142 maxo = 0; 143 for(n = e->zn ; n != nil; n = n->right){ 144 d = n->decl; 145 d->locals = d->next; 146 if(!inlist(d, dd)){ 147 d->next = dd; 148 dd = d; 149 o = d->offset+d->ty->size; 150 if(o > maxo) 151 maxo = o; 152 } 153 } 154 e->desc = gendesc(e->d, align(maxo, MaxAlign), dd); 155 for(d = dd; d != nil; d = nd){ 156 nd = d->next; 157 d->next = d->locals; 158 d->locals = nil; 159 } 160 e->zn = nil; 161 } 162 } 163 } 164 165 static Except* 166 reve(Except *e) 167 { 168 Except *l, *n; 169 170 l = nil; 171 for( ; e != nil; e = n){ 172 n = e->next; 173 e->next = l; 174 l = e; 175 } 176 return l; 177 } 178 179 static int 180 ckinline0(Node *n, Decl *d) 181 { 182 Decl *dd; 183 184 if(n == nil) 185 return 1; 186 if(n->op == Oname){ 187 dd = n->decl; 188 if(d == dd) 189 return 0; 190 if(dd->caninline == 1) 191 return ckinline0(dd->init->right, d); 192 return 1; 193 } 194 return ckinline0(n->left, d) && ckinline0(n->right, d); 195 } 196 197 static void 198 ckinline(Decl *d) 199 { 200 d->caninline = ckinline0(d->init->right, d); 201 } 202 203 void 204 modcom(Decl *entry) 205 { 206 Decl *globals, *m, *nils, *d, *ldts; 207 long ninst, ndata, ndesc, nlink, offset, ldtoff; 208 int ok, i, hints; 209 Dlist *dl; 210 211 if(errors) 212 return; 213 214 if(emitcode || emitstub || emittab != nil){ 215 emit(curscope()); 216 popscope(); 217 return; 218 } 219 220 /* 221 * scom introduces global variables for case statements 222 * and unaddressable constants, so it must be done before 223 * popping the global scope 224 */ 225 nlabel = 0; 226 maxstack = MaxTemp; 227 genstart(); 228 229 for(i = 0; i < nfns; i++) 230 if(fns[i]->caninline == 1) 231 ckinline(fns[i]); 232 233 ok = 0; 234 for(i = 0; i < nfns; i++){ 235 d = fns[i]; 236 if(debug['v']) print("fncom: %s %d %p\n", d->sym->name, d->refs, d); 237 if(d->refs > 1 && !(d->caninline == 1 && local(d) && d->iface == nil)){ 238 fns[ok++] = d; 239 fncom(d); 240 } 241 } 242 nfns = ok; 243 if(blocks != -1) 244 fatal("blocks not nested correctly"); 245 firstinst = firstinst->next; 246 if(errors) 247 return; 248 249 globals = popscope(); 250 checkrefs(globals); 251 if(errors) 252 return; 253 globals = vars(globals); 254 moddataref(); 255 256 nils = popscope(); 257 m = nil; 258 for(d = nils; d != nil; d = d->next){ 259 if(debug['n']) 260 print("nil '%s' ref %d\n", d->sym->name, d->refs); 261 if(d->refs && m == nil) 262 m = dupdecl(d); 263 d->offset = 0; 264 } 265 globals = appdecls(m, globals); 266 globals = namesort(globals); 267 globals = modglobals(impdecls->d, globals); 268 vcom(globals); 269 narrowmods(); 270 ldts = nil; 271 if(LDT) 272 globals = resolveldts(globals, &ldts); 273 offset = idoffsets(globals, 0, IBY2WD); 274 if(LDT) 275 ldtoff = idindices(ldts); /* ldtoff = idoffsets(ldts, 0, IBY2WD); */ 276 for(d = nils; d != nil; d = d->next){ 277 if(debug['n']) 278 print("nil '%s' ref %d\n", d->sym->name, d->refs); 279 if(d->refs) 280 d->offset = m->offset; 281 } 282 283 if(debug['g']){ 284 print("globals:\n"); 285 printdecls(globals); 286 } 287 288 ndata = 0; 289 for(d = globals; d != nil; d = d->next) 290 ndata++; 291 ndesc = resolvedesc(impdecls->d, offset, globals); 292 ninst = resolvepcs(firstinst); 293 modresolve(); 294 if(impdecls->next != nil) 295 for(dl = impdecls; dl != nil; dl = dl->next) 296 resolvemod(dl->d); 297 nlink = resolvemod(impdecl); 298 299 maxstack *= 10; 300 if(fixss != 0) 301 maxstack = fixss; 302 303 if(debug['s']) 304 print("%ld instructions\n%ld data elements\n%ld type descriptors\n%ld functions exported\n%ld stack size\n", 305 ninst, ndata, ndesc, nlink, maxstack); 306 307 excs = reve(excs); 308 309 if(gendis){ 310 discon(XMAGIC); 311 hints = 0; 312 if(mustcompile) 313 hints |= MUSTCOMPILE; 314 if(dontcompile) 315 hints |= DONTCOMPILE; 316 if(LDT) 317 hints |= HASLDT; 318 if(excs != nil) 319 hints |= HASEXCEPT; 320 discon(hints); /* runtime hints */ 321 discon(maxstack); /* minimum stack extent size */ 322 discon(ninst); 323 discon(offset); 324 discon(ndesc); 325 discon(nlink); 326 disentry(entry); 327 disinst(firstinst); 328 disdesc(descriptors); 329 disvar(offset, globals); 330 dismod(impdecl); 331 if(LDT) 332 disldt(ldtoff, ldts); 333 if(excs != nil) 334 disexc(excs); 335 dispath(); 336 }else{ 337 asminst(firstinst); 338 asmentry(entry); 339 asmdesc(descriptors); 340 asmvar(offset, globals); 341 asmmod(impdecl); 342 if(LDT) 343 asmldt(ldtoff, ldts); 344 if(excs != nil) 345 asmexc(excs); 346 asmpath(); 347 } 348 if(bsym != nil){ 349 sblmod(impdecl); 350 351 sblfiles(); 352 sblinst(firstinst, ninst); 353 sblty(adts, nadts); 354 sblfn(fns, nfns); 355 sblvar(globals); 356 } 357 358 firstinst = nil; 359 lastinst = nil; 360 361 excs = nil; 362 } 363 364 void 365 fncom(Decl *decl) 366 { 367 Src src; 368 Node *n; 369 Decl *loc, *last; 370 Inst *in; 371 int valued; 372 373 curfn = decl; 374 if(ispoly(decl)) 375 addfnptrs(decl, 1); 376 377 /* 378 * pick up the function body and compile it 379 * this code tries to clean up the parse nodes as fast as possible 380 * function is Ofunc(name, body) 381 */ 382 decl->pc = nextinst(); 383 tinit(); 384 labdep = 0; 385 scp = 0; 386 breaks = allocmem(maxlabdep * sizeof breaks[0]); 387 conts = allocmem(maxlabdep * sizeof conts[0]); 388 labels = allocmem(maxlabdep * sizeof labels[0]); 389 bcscps = allocmem(maxlabdep * sizeof bcscps[0]); 390 n = decl->init; 391 if(decl->caninline == 1) 392 decl->init = dupn(0, nil, n); 393 else 394 decl->init = n->left; 395 src = n->right->src; 396 src.start.line = src.stop.line; 397 src.start.pos = src.stop.pos - 1; 398 for(n = n->right; n != nil; n = n->right){ 399 if(n->op != Oseq){ 400 if(n->op == Ocall && trcom(n, nil, 1)) 401 break; 402 scom(n); 403 break; 404 } 405 if(n->left->op == Ocall && trcom(n->left, n->right, 1)){ 406 n = n->right; 407 if(n == nil || n->op != Oseq) 408 break; 409 } 410 else 411 scom(n->left); 412 } 413 pushblock(); 414 valued = decl->ty->tof != tnone; 415 in = genrawop(&src, valued? IRAISE: IRET, nil, nil, nil); 416 popblock(); 417 reach(decl->pc); 418 if(valued && in->reach) 419 error(src.start, "no return at end of function %D", decl); 420 /* decl->endpc = lastinst; */ 421 if(labdep != 0) 422 fatal("unbalanced label stack"); 423 free(breaks); 424 free(conts); 425 free(labels); 426 free(bcscps); 427 428 loc = declsort(appdecls(vars(decl->locals), tdecls())); 429 decl->offset = idoffsets(loc, decl->offset, MaxAlign); 430 for(last = decl->ty->ids; last != nil && last->next != nil; last = last->next) 431 ; 432 if(last != nil) 433 last->next = loc; 434 else 435 decl->ty->ids = loc; 436 437 if(debug['f']){ 438 print("fn: %s\n", decl->sym->name); 439 printdecls(decl->ty->ids); 440 } 441 442 decl->desc = gendesc(decl, decl->offset, decl->ty->ids); 443 decl->locals = loc; 444 excdesc(); 445 if(decl->offset > maxstack) 446 maxstack = decl->offset; 447 if(optims) 448 optim(decl->pc, decl); 449 if(last != nil) 450 last->next = nil; 451 else 452 decl->ty->ids = nil; 453 } 454 455 /* 456 * statement compiler 457 */ 458 void 459 scom(Node *n) 460 { 461 Inst *p, *pp, *p1, *p2, *p3; 462 Node tret, *left, *zn; 463 464 for(; n != nil; n = n->right){ 465 switch(n->op){ 466 case Ocondecl: 467 case Otypedecl: 468 case Ovardecl: 469 case Oimport: 470 case Oexdecl: 471 return; 472 case Ovardecli: 473 break; 474 case Oscope: 475 pushscp(n); 476 scom(n->right); 477 popscp(); 478 zcom(n->left, nil); 479 return; 480 case Olabel: 481 scom(n->right); 482 return; 483 case Oif: 484 pushblock(); 485 left = simplify(n->left); 486 if(left->op == Oconst && left->ty == tint){ 487 if(left->val != 0) 488 scom(n->right->left); 489 else 490 scom(n->right->right); 491 popblock(); 492 return; 493 } 494 sumark(left); 495 pushblock(); 496 p = bcom(left, 1, nil); 497 tfreenow(); 498 popblock(); 499 scom(n->right->left); 500 if(n->right->right != nil){ 501 pp = p; 502 p = genrawop(&lastinst->src, IJMP, nil, nil, nil); 503 patch(pp, nextinst()); 504 scom(n->right->right); 505 } 506 patch(p, nextinst()); 507 popblock(); 508 return; 509 case Ofor: 510 n->left = left = simplify(n->left); 511 if(left->op == Oconst && left->ty == tint){ 512 if(left->val == 0) 513 return; 514 left->op = Onothing; 515 left->ty = tnone; 516 left->decl = nil; 517 } 518 pp = nextinst(); 519 pushblock(); 520 /* b = pushblock(); */ 521 sumark(left); 522 p = bcom(left, 1, nil); 523 tfreenow(); 524 popblock(); 525 526 if(labdep >= maxlabdep) 527 fatal("label stack overflow"); 528 breaks[labdep] = nil; 529 conts[labdep] = nil; 530 labels[labdep] = n->decl; 531 bcscps[labdep] = curscp(); 532 labdep++; 533 scom(n->right->left); 534 labdep--; 535 536 patch(conts[labdep], nextinst()); 537 if(n->right->right != nil){ 538 pushblock(); 539 scom(n->right->right); 540 popblock(); 541 } 542 repushblock(lastinst->block); /* was b */ 543 patch(genrawop(&lastinst->src, IJMP, nil, nil, nil), pp); /* for cprof: was &left->src */ 544 popblock(); 545 patch(p, nextinst()); 546 patch(breaks[labdep], nextinst()); 547 return; 548 case Odo: 549 pp = nextinst(); 550 551 if(labdep >= maxlabdep) 552 fatal("label stack overflow"); 553 breaks[labdep] = nil; 554 conts[labdep] = nil; 555 labels[labdep] = n->decl; 556 bcscps[labdep] = curscp(); 557 labdep++; 558 scom(n->right); 559 labdep--; 560 561 patch(conts[labdep], nextinst()); 562 563 left = simplify(n->left); 564 if(left->op == Onothing 565 || left->op == Oconst && left->ty == tint){ 566 if(left->op == Onothing || left->val != 0){ 567 pushblock(); 568 p = genrawop(&left->src, IJMP, nil, nil, nil); 569 popblock(); 570 }else 571 p = nil; 572 }else{ 573 pushblock(); 574 p = bcom(sumark(left), 0, nil); 575 tfreenow(); 576 popblock(); 577 } 578 patch(p, pp); 579 patch(breaks[labdep], nextinst()); 580 return; 581 case Oalt: 582 case Ocase: 583 case Opick: 584 case Oexcept: 585 /* need push/pop blocks for alt guards */ 586 pushblock(); 587 if(labdep >= maxlabdep) 588 fatal("label stack overflow"); 589 breaks[labdep] = nil; 590 conts[labdep] = &nocont; 591 labels[labdep] = n->decl; 592 bcscps[labdep] = curscp(); 593 labdep++; 594 switch(n->op){ 595 case Oalt: 596 altcom(n); 597 break; 598 case Ocase: 599 case Opick: 600 casecom(n); 601 break; 602 case Oexcept: 603 excom(n); 604 break; 605 } 606 labdep--; 607 patch(breaks[labdep], nextinst()); 608 popblock(); 609 return; 610 case Obreak: 611 pushblock(); 612 bccom(n, breaks); 613 popblock(); 614 break; 615 case Ocont: 616 pushblock(); 617 bccom(n, conts); 618 popblock(); 619 break; 620 case Oseq: 621 if(n->left->op == Ocall && trcom(n->left, n->right, 0)){ 622 n = n->right; 623 if(n == nil || n->op != Oseq) 624 return; 625 } 626 else 627 scom(n->left); 628 break; 629 case Oret: 630 if(n->left != nil && n->left->op == Ocall && trcom(n->left, nil, 1)) 631 return; 632 pushblock(); 633 if(n->left != nil){ 634 n->left = simplify(n->left); 635 sumark(n->left); 636 ecom(&n->left->src, retalloc(&tret, n->left), n->left); 637 tfreenow(); 638 } 639 genrawop(&n->src, IRET, nil, nil, nil); 640 popblock(); 641 return; 642 case Oexit: 643 pushblock(); 644 genrawop(&n->src, IEXIT, nil, nil, nil); 645 popblock(); 646 return; 647 case Onothing: 648 return; 649 case Ofunc: 650 fatal("Ofunc"); 651 return; 652 case Oexstmt: 653 pushblock(); 654 pp = genrawop(&n->right->src, IEXC0, nil, nil, nil); /* marker */ 655 p1 = nextinst(); 656 scom(n->left); 657 p2 = nextinst(); 658 p3 = genrawop(&n->right->src, IJMP, nil, nil, nil); 659 p = genrawop(&n->right->src, IEXC, nil, nil, nil); /* marker */ 660 p->d.decl = mkdecl(&n->src, 0, n->right->ty); 661 zn = nil; 662 zeroallscopes(n->left, &zn); 663 scom(n->right); 664 patch(p3, nextinst()); 665 installexc(n->right, p1, p2, zn); 666 patch(pp, p); 667 popblock(); 668 return; 669 default: 670 pushblock(); 671 n = simplify(n); 672 sumark(n); 673 ecom(&n->src, nil, n); 674 tfreenow(); 675 popblock(); 676 return; 677 } 678 } 679 } 680 681 /* 682 * compile a break, continue 683 */ 684 void 685 bccom(Node *n, Inst **bs) 686 { 687 Sym *s; 688 Inst *p; 689 int i, ok; 690 691 s = nil; 692 if(n->decl != nil) 693 s = n->decl->sym; 694 ok = -1; 695 for(i = 0; i < labdep; i++){ 696 if(bs[i] == &nocont) 697 continue; 698 if(s == nil || labels[i] != nil && labels[i]->sym == s) 699 ok = i; 700 } 701 if(ok < 0){ 702 nerror(n, "no appropriate target for %V", n); 703 return; 704 } 705 zeroscopes(bcscps[ok]); 706 p = genrawop(&n->src, IJMP, nil, nil, nil); 707 p->branch = bs[ok]; 708 bs[ok] = p; 709 } 710 711 static int 712 dogoto(Case *c) 713 { 714 int i, j, k, n, r, q, v; 715 Label *l, *nl; 716 Src *src; 717 718 l = c->labs; 719 n = c->nlab; 720 if(n == 0) 721 return 0; 722 r = l[n-1].stop->val - l[0].start->val+1; 723 if(r >= 3 && r <= 3*n){ 724 if(r != n){ 725 /* remove ranges, fill in gaps */ 726 c->nlab = r; 727 nl = c->labs = allocmem(r*sizeof(*nl)); 728 k = 0; 729 v = l[0].start->val-1; 730 for(i = 0; i < n; i++){ 731 /* p = l[i].start->val; */ 732 q = l[i].stop->val; 733 src = &l[i].start->src; 734 for(j = v+1; j <= q; j++){ 735 nl[k] = l[i]; 736 nl[k].start = nl[k].stop = mkconst(src, j); 737 k++; 738 } 739 v = q; 740 } 741 if(k != r) 742 fatal("bad case expansion"); 743 } 744 l = c->labs; 745 for(i = 0; i < r; i++) 746 l[i].inst = nil; 747 return 1; 748 } 749 return 0; 750 } 751 752 static void 753 fillrange(Case *c, Node *nn, Inst *in) 754 { 755 int i, j, n, p, q; 756 Label *l; 757 758 l = c->labs; 759 n = c->nlab; 760 p = nn->left->val; 761 q = nn->right->val; 762 for(i = 0; i < n; i++) 763 if(l[i].start->val == p) 764 break; 765 if(i == n) 766 fatal("fillrange fails"); 767 for(j = p; j <= q; j++) 768 l[i++].inst = in; 769 } 770 771 static int 772 nconstqual(Node *s1) 773 { 774 Node *s2; 775 int n; 776 777 n = 0; 778 for(; s1 != nil; s1 = s1->right){ 779 for(s2 = s1->left->left; s2 != nil; s2 = s2->right) 780 if(s2->left->op == Oconst) 781 n++; 782 } 783 return n; 784 } 785 786 void 787 casecom(Node *cn) 788 { 789 Src *src; 790 Case *c; 791 Decl *d; 792 Type *ctype; 793 Inst *j, *jmps, *wild, *k, *j1, *j2; 794 Node *n, *p, *left, tmp, nto, tmpc; 795 Label *labs; 796 char buf[32]; 797 int i, nlab, op, needwild, igoto; 798 799 c = cn->ty->cse; 800 801 needwild = cn->op != Opick || nconstqual(cn->right) != cn->left->right->ty->tof->decl->tag; 802 igoto = cn->left->ty == tint && dogoto(c); 803 j1 = j2 = nil; 804 805 /* 806 * generate global which has case labels 807 */ 808 if(igoto){ 809 seprint(buf, buf+sizeof(buf), ".g%d", nlabel++); 810 cn->ty->kind = Tgoto; 811 } 812 else 813 seprint(buf, buf+sizeof(buf), ".c%d", nlabel++); 814 d = mkids(&cn->src, enter(buf, 0), cn->ty, nil); 815 d->init = mkdeclname(&cn->src, d); 816 817 nto.addable = Rmreg; 818 nto.left = nil; 819 nto.right = nil; 820 nto.op = Oname; 821 nto.ty = d->ty; 822 nto.decl = d; 823 824 tmp.decl = tmpc.decl = nil; 825 left = cn->left; 826 left = simplify(left); 827 cn->left = left; 828 sumark(left); 829 if(debug['c']) 830 print("case %n\n", left); 831 ctype = cn->left->ty; 832 if(left->addable >= Rcant){ 833 if(cn->op == Opick){ 834 ecom(&left->src, nil, left); 835 tfreenow(); 836 left = mkunary(Oind, dupn(1, &left->src, left->left)); 837 left->ty = tint; 838 sumark(left); 839 ctype = tint; 840 }else{ 841 left = eacom(left, &tmp, nil); 842 tfreenow(); 843 } 844 } 845 846 labs = c->labs; 847 nlab = c->nlab; 848 849 if(igoto){ 850 if(labs[0].start->val != 0){ 851 talloc(&tmpc, left->ty, nil); 852 if(left->addable == Radr || left->addable == Rmadr){ 853 genrawop(&left->src, IMOVW, left, nil, &tmpc); 854 left = &tmpc; 855 } 856 genrawop(&left->src, ISUBW, sumark(labs[0].start), left, &tmpc); 857 left = &tmpc; 858 } 859 if(needwild){ 860 j1 = genrawop(&left->src, IBLTW, left, sumark(mkconst(&left->src, 0)), nil); 861 j2 = genrawop(&left->src, IBGTW, left, sumark(mkconst(&left->src, labs[nlab-1].start->val-labs[0].start->val)), nil); 862 } 863 j = nextinst(); 864 genrawop(&left->src, IGOTO, left, nil, &nto); 865 j->d.reg = IBY2WD; 866 } 867 else{ 868 op = ICASE; 869 if(ctype == tbig) 870 op = ICASEL; 871 else if(ctype == tstring) 872 op = ICASEC; 873 genrawop(&left->src, op, left, nil, &nto); 874 } 875 tfree(&tmp); 876 tfree(&tmpc); 877 878 jmps = nil; 879 wild = nil; 880 for(n = cn->right; n != nil; n = n->right){ 881 j = nextinst(); 882 for(p = n->left->left; p != nil; p = p->right){ 883 if(debug['c']) 884 print("case qualifier %n\n", p->left); 885 switch(p->left->op){ 886 case Oconst: 887 labs[findlab(ctype, p->left, labs, nlab)].inst = j; 888 break; 889 case Orange: 890 labs[findlab(ctype, p->left->left, labs, nlab)].inst = j; 891 if(igoto) 892 fillrange(c, p->left, j); 893 break; 894 case Owild: 895 if(needwild) 896 wild = j; 897 /* 898 else 899 nwarn(p->left, "default case redundant"); 900 */ 901 break; 902 } 903 } 904 905 if(debug['c']) 906 print("case body for %V: %n\n", n->left->left, n->left->right); 907 908 k = nextinst(); 909 scom(n->left->right); 910 911 src = &lastinst->src; 912 // if(n->left->right == nil || n->left->right->op == Onothing) 913 if(k == nextinst()) 914 src = &n->left->left->src; 915 j = genrawop(src, IJMP, nil, nil, nil); 916 j->branch = jmps; 917 jmps = j; 918 } 919 patch(jmps, nextinst()); 920 if(wild == nil && needwild) 921 wild = nextinst(); 922 923 if(igoto){ 924 if(needwild){ 925 patch(j1, wild); 926 patch(j2, wild); 927 } 928 for(i = 0; i < nlab; i++) 929 if(labs[i].inst == nil) 930 labs[i].inst = wild; 931 } 932 933 c->iwild = wild; 934 935 d->ty->cse = c; 936 usetype(d->ty); 937 installids(Dglobal, d); 938 } 939 940 void 941 altcom(Node *nalt) 942 { 943 Src altsrc; 944 Case *c; 945 Decl *d; 946 Type *talt; 947 Node *n, *p, *left, tab, slot, off, add, which, nto, adr; 948 Node **comm, *op, *tmps; 949 Inst *j, *tj, *jmps, *me, *wild; 950 Label *labs; 951 char buf[32]; 952 int i, is, ir, nlab, nsnd, altop, isptr; 953 Inst *pp; 954 955 talt = nalt->ty; 956 c = talt->cse; 957 nlab = c->nlab; 958 nsnd = c->nsnd; 959 comm = allocmem(nlab * sizeof *comm); 960 labs = allocmem(nlab * sizeof *labs); 961 tmps = allocmem(nlab * sizeof *tmps); 962 c->labs = labs; 963 964 /* 965 * built the type of the alt channel table 966 * note that we lie to the garbage collector 967 * if we know that another reference exists for the channel 968 */ 969 is = 0; 970 ir = nsnd; 971 i = 0; 972 for(n = nalt->left; n != nil; n = n->right){ 973 for(p = n->left->right->left; p != nil; p = p->right){ 974 left = simplify(p->left); 975 p->left = left; 976 if(left->op == Owild) 977 continue; 978 comm[i] = hascomm(left); 979 left = comm[i]->left; 980 sumark(left); 981 isptr = left->addable >= Rcant; 982 if(comm[i]->op == Osnd) 983 labs[is++].isptr = isptr; 984 else 985 labs[ir++].isptr = isptr; 986 i++; 987 } 988 } 989 990 talloc(&which, tint, nil); 991 talloc(&tab, talt, nil); 992 993 /* 994 * build the node for the address of each channel, 995 * the values to send, and the storage fro values received 996 */ 997 off = znode; 998 off.op = Oconst; 999 off.ty = tint; 1000 off.addable = Rconst; 1001 adr = znode; 1002 adr.op = Oadr; 1003 adr.left = &tab; 1004 adr.ty = tint; 1005 add = znode; 1006 add.op = Oadd; 1007 add.left = &adr; 1008 add.right = &off; 1009 add.ty = tint; 1010 slot = znode; 1011 slot.op = Oind; 1012 slot.left = &add; 1013 sumark(&slot); 1014 1015 /* 1016 * compile the sending and receiving channels and values 1017 */ 1018 is = 2*IBY2WD; 1019 ir = is + nsnd*2*IBY2WD; 1020 i = 0; 1021 for(n = nalt->left; n != nil; n = n->right){ 1022 for(p = n->left->right->left; p != nil; p = p->right){ 1023 if(p->left->op == Owild) 1024 continue; 1025 1026 /* 1027 * gen channel 1028 */ 1029 op = comm[i]; 1030 if(op->op == Osnd){ 1031 off.val = is; 1032 is += 2*IBY2WD; 1033 }else{ 1034 off.val = ir; 1035 ir += 2*IBY2WD; 1036 } 1037 left = op->left; 1038 1039 /* 1040 * this sleaze is lying to the garbage collector 1041 */ 1042 if(left->addable < Rcant) 1043 genmove(&left->src, Mas, tint, left, &slot); 1044 else{ 1045 slot.ty = left->ty; 1046 ecom(&left->src, &slot, left); 1047 tfreenow(); 1048 slot.ty = nil; 1049 } 1050 1051 /* 1052 * gen value 1053 */ 1054 off.val += IBY2WD; 1055 tmps[i].decl = nil; 1056 p->left = rewritecomm(p->left, comm[i], &tmps[i], &slot); 1057 1058 i++; 1059 } 1060 } 1061 1062 /* 1063 * stuff the number of send & receive channels into the table 1064 */ 1065 altsrc = nalt->src; 1066 altsrc.stop.pos += 3; 1067 off.val = 0; 1068 genmove(&altsrc, Mas, tint, sumark(mkconst(&altsrc, nsnd)), &slot); 1069 off.val += IBY2WD; 1070 genmove(&altsrc, Mas, tint, sumark(mkconst(&altsrc, nlab-nsnd)), &slot); 1071 off.val += IBY2WD; 1072 1073 altop = IALT; 1074 if(c->wild != nil) 1075 altop = INBALT; 1076 pp = genrawop(&altsrc, altop, &tab, nil, &which); 1077 pp->m.offset = talt->size; /* for optimizer */ 1078 1079 seprint(buf, buf+sizeof(buf), ".g%d", nlabel++); 1080 d = mkids(&nalt->src, enter(buf, 0), mktype(&nalt->src.start, &nalt->src.stop, Tgoto, nil, nil), nil); 1081 d->ty->cse = c; 1082 d->init = mkdeclname(&nalt->src, d); 1083 1084 nto.addable = Rmreg; 1085 nto.left = nil; 1086 nto.right = nil; 1087 nto.op = Oname; 1088 nto.decl = d; 1089 nto.ty = d->ty; 1090 1091 me = nextinst(); 1092 genrawop(&altsrc, IGOTO, &which, nil, &nto); 1093 me->d.reg = IBY2WD; /* skip the number of cases field */ 1094 tfree(&tab); 1095 tfree(&which); 1096 1097 /* 1098 * compile the guard expressions and bodies 1099 */ 1100 i = 0; 1101 is = 0; 1102 ir = nsnd; 1103 jmps = nil; 1104 wild = nil; 1105 for(n = nalt->left; n != nil; n = n->right){ 1106 j = nil; 1107 for(p = n->left->right->left; p != nil; p = p->right){ 1108 tj = nextinst(); 1109 if(p->left->op == Owild){ 1110 wild = nextinst(); 1111 }else{ 1112 if(comm[i]->op == Osnd) 1113 labs[is++].inst = tj; 1114 else{ 1115 labs[ir++].inst = tj; 1116 tacquire(&tmps[i]); 1117 } 1118 sumark(p->left); 1119 if(debug['a']) 1120 print("alt guard %n\n", p->left); 1121 ecom(&p->left->src, nil, p->left); 1122 tfree(&tmps[i]); 1123 tfreenow(); 1124 i++; 1125 } 1126 if(p->right != nil){ 1127 tj = genrawop(&lastinst->src, IJMP, nil, nil, nil); 1128 tj->branch = j; 1129 j = tj; 1130 } 1131 } 1132 1133 patch(j, nextinst()); 1134 if(debug['a']) 1135 print("alt body %n\n", n->left->right); 1136 scom(n->left); 1137 1138 j = genrawop(&lastinst->src, IJMP, nil, nil, nil); 1139 j->branch = jmps; 1140 jmps = j; 1141 } 1142 patch(jmps, nextinst()); 1143 free(comm); 1144 1145 c->iwild = wild; 1146 1147 usetype(d->ty); 1148 installids(Dglobal, d); 1149 } 1150 1151 void 1152 excom(Node *en) 1153 { 1154 Src *src; 1155 Decl *ed; 1156 Type *qt; 1157 Case *c; 1158 Inst *j, *jmps, *wild, *k; 1159 Node *n, *p; 1160 Label *labs; 1161 int nlab; 1162 1163 ed = en->left->decl; 1164 ed->ty = rtexception; 1165 c = en->ty->cse; 1166 labs = c->labs; 1167 nlab = c->nlab; 1168 jmps = nil; 1169 wild = nil; 1170 for(n = en->right; n != nil; n = n->right){ 1171 qt = nil; 1172 j = nextinst(); 1173 for(p = n->left->left; p != nil; p = p->right){ 1174 switch(p->left->op){ 1175 case Oconst: 1176 labs[findlab(texception, p->left, labs, nlab)].inst = j; 1177 break; 1178 case Owild: 1179 wild = j; 1180 break; 1181 } 1182 if(qt == nil) 1183 qt = p->left->ty; 1184 else if(!tequal(qt, p->left->ty)) 1185 qt = texception; 1186 } 1187 if(qt != nil) 1188 ed->ty = qt; 1189 k = nextinst(); 1190 scom(n->left->right); 1191 src = &lastinst->src; 1192 if(k == nextinst()) 1193 src = &n->left->left->src; 1194 j = genrawop(src, IJMP, nil, nil, nil); 1195 j->branch = jmps; 1196 jmps = j; 1197 } 1198 ed->ty = rtexception; 1199 patch(jmps, nextinst()); 1200 c->iwild = wild; 1201 } 1202 1203 /* 1204 * rewrite the communication operand 1205 * allocate any temps needed for holding value to send or receive 1206 */ 1207 Node* 1208 rewritecomm(Node *n, Node *comm, Node *tmp, Node *slot) 1209 { 1210 Node *adr; 1211 Inst *p; 1212 1213 if(n == nil) 1214 return nil; 1215 adr = nil; 1216 if(n == comm){ 1217 if(comm->op == Osnd && sumark(n->right)->addable < Rcant) 1218 adr = n->right; 1219 else{ 1220 adr = talloc(tmp, n->ty, nil); 1221 tmp->src = n->src; 1222 if(comm->op == Osnd){ 1223 ecom(&n->right->src, tmp, n->right); 1224 tfreenow(); 1225 } 1226 else 1227 trelease(tmp); 1228 } 1229 } 1230 if(n->right == comm && n->op == Oas && comm->op == Orcv 1231 && sumark(n->left)->addable < Rcant && (n->left->op != Oname || n->left->decl != nildecl)) 1232 adr = n->left; 1233 if(adr != nil){ 1234 p = genrawop(&comm->left->src, ILEA, adr, nil, slot); 1235 p->m.offset = adr->ty->size; /* for optimizer */ 1236 if(comm->op == Osnd) 1237 p->m.reg = 1; /* for optimizer */ 1238 return adr; 1239 } 1240 n->left = rewritecomm(n->left, comm, tmp, slot); 1241 n->right = rewritecomm(n->right, comm, tmp, slot); 1242 return n; 1243 } 1244 1245 /* 1246 * merge together two sorted lists, yielding a sorted list 1247 */ 1248 static Decl* 1249 declmerge(Decl *e, Decl *f) 1250 { 1251 Decl rock, *d; 1252 int es, fs, v; 1253 1254 d = &rock; 1255 while(e != nil && f != nil){ 1256 fs = f->ty->size; 1257 es = e->ty->size; 1258 /* v = 0; */ 1259 v = (e->link == nil) - (f->link == nil); 1260 if(v == 0 && (es <= IBY2WD || fs <= IBY2WD)) 1261 v = fs - es; 1262 if(v == 0) 1263 v = e->refs - f->refs; 1264 if(v == 0) 1265 v = fs - es; 1266 if(v == 0) 1267 v = -strcmp(e->sym->name, f->sym->name); 1268 if(v >= 0){ 1269 d->next = e; 1270 d = e; 1271 e = e->next; 1272 while(e != nil && e->nid == 0){ 1273 d = e; 1274 e = e->next; 1275 } 1276 }else{ 1277 d->next = f; 1278 d = f; 1279 f = f->next; 1280 while(f != nil && f->nid == 0){ 1281 d = f; 1282 f = f->next; 1283 } 1284 } 1285 /* d = d->next; */ 1286 } 1287 if(e != nil) 1288 d->next = e; 1289 else 1290 d->next = f; 1291 return rock.next; 1292 } 1293 1294 /* 1295 * recursively split lists and remerge them after they are sorted 1296 */ 1297 static Decl* 1298 recdeclsort(Decl *d, int n) 1299 { 1300 Decl *r, *dd; 1301 int i, m; 1302 1303 if(n <= 1) 1304 return d; 1305 m = n / 2 - 1; 1306 dd = d; 1307 for(i = 0; i < m; i++){ 1308 dd = dd->next; 1309 while(dd->nid == 0) 1310 dd = dd->next; 1311 } 1312 r = dd->next; 1313 while(r->nid == 0){ 1314 dd = r; 1315 r = r->next; 1316 } 1317 dd->next = nil; 1318 return declmerge(recdeclsort(d, n / 2), 1319 recdeclsort(r, (n + 1) / 2)); 1320 } 1321 1322 /* 1323 * sort the ids by size and number of references 1324 */ 1325 Decl* 1326 declsort(Decl *d) 1327 { 1328 Decl *dd; 1329 int n; 1330 1331 n = 0; 1332 for(dd = d; dd != nil; dd = dd->next) 1333 if(dd->nid > 0) 1334 n++; 1335 return recdeclsort(d, n); 1336 } 1337 1338 Src nilsrc; 1339 1340 /* Do we finally 1341 * (a) pick off pointers as in the code below 1342 * (b) generate a block move from zeroed memory as in tfree() in gen.b in limbo version 1343 * (c) add a new block zero instruction to dis 1344 * (d) reorganize the locals/temps in a frame 1345 */ 1346 void 1347 zcom1(Node *n, Node **nn) 1348 { 1349 Type *ty; 1350 Decl *d; 1351 Node *e, *dn; 1352 Src src; 1353 1354 ty = n->ty; 1355 if (!tmustzero(ty)) 1356 return; 1357 if (n->op == Oname && n->decl->refs == 0) 1358 return; 1359 if (nn) { 1360 if(n->op != Oname) 1361 nerror(n, "fatal: bad op in zcom1 map"); 1362 n->right = *nn; 1363 *nn = n; 1364 return; 1365 } 1366 if (debug['Z']) 1367 print("zcom1 : %n\n", n); 1368 if (ty->kind == Tadtpick) 1369 ty = ty->tof; 1370 if (ty->kind == Ttuple || ty->kind == Tadt) { 1371 for (d = ty->ids; d != nil; d = d->next) { 1372 if (tmustzero(d->ty)) { 1373 if (d->next != nil) 1374 dn = dupn(0, nil, n); 1375 else 1376 dn = n; 1377 e = mkbin(Odot, dn, mkname(&nilsrc, d->sym)); 1378 e->right->decl = d; 1379 e->ty = e->right->ty = d->ty; 1380 zcom1(e, nn); 1381 } 1382 } 1383 } 1384 else { 1385 src = n->src; 1386 n->src = nilsrc; 1387 e = mkbin(Oas, n, mknil(&nilsrc)); 1388 e->ty = e->right->ty = ty; 1389 /* 1390 if (debug['Z']) 1391 print("ecom %n\n", e); 1392 */ 1393 pushblock(); 1394 e = simplify(e); 1395 sumark(e); 1396 ecom(&e->src, nil, e); 1397 popblock(); 1398 n->src = src; 1399 } 1400 } 1401 1402 void 1403 zcom0(Decl *id, Node **nn) 1404 { 1405 Node *e; 1406 1407 e = mkname(&nilsrc, id->sym); 1408 e->decl = id; 1409 e->ty = id->ty; 1410 zcom1(e, nn); 1411 } 1412 1413 /* end of scope */ 1414 void 1415 zcom(Node *n, Node **nn) 1416 { 1417 Decl *ids, *last; 1418 Node *r, *nt; 1419 1420 for ( ; n != nil; n = r) { 1421 r = n->right; 1422 n->right = nil; 1423 switch (n->op) { 1424 case Ovardecl : 1425 last = n->left->decl; 1426 for (ids = n->decl; ids != last->next; ids = ids->next) 1427 zcom0(ids, nn); 1428 break; 1429 case Oname : 1430 if (n->decl != nildecl) 1431 zcom1(dupn(0, nil, n), nn); 1432 break; 1433 case Otuple : 1434 for (nt = n->left; nt != nil; nt = nt->right) 1435 zcom(nt->left, nn); 1436 break; 1437 default : 1438 fatal("bad node in zcom()"); 1439 break; 1440 } 1441 n->right = r; 1442 } 1443 } 1444 1445 static int 1446 ret(Node *n, int nilret) 1447 { 1448 if(n == nil) 1449 return nilret; 1450 if(n->op == Oseq) 1451 n = n->left; 1452 return n->op == Oret && n->left == nil; 1453 } 1454 1455 /* 1456 * tail-recursive call 1457 */ 1458 static int 1459 trcom(Node *e, Node *ne, int nilret) 1460 { 1461 Decl *d, *id; 1462 Node *as, *a, *f, *n; 1463 Inst *p; 1464 1465 if(1) 1466 return 0; /* TO DO: should we enable this? */ 1467 if(e->op != Ocall || e->left->op != Oname) 1468 return 0; 1469 d = e->left->decl; 1470 if(d != curfn || d->handler || ispoly(d)) 1471 return 0; 1472 if(!ret(ne, nilret)) 1473 return 0; 1474 pushblock(); 1475 id = d->ty->ids; 1476 /* evaluate args in same order as normal calls */ 1477 for(as = e->right; as != nil; as = as->right){ 1478 a = as->left; 1479 if(!(a->op == Oname && id == a->decl)){ 1480 if(occurs(id, as->right)){ 1481 f = talloc(mkn(0, nil, nil), id->ty, nil); 1482 f->flags |= TEMP; 1483 } 1484 else 1485 f = mkdeclname(&as->src, id); 1486 n = mkbin(Oas, f, a); 1487 n->ty = id->ty; 1488 scom(n); 1489 if(f->flags&TEMP) 1490 as->left = f; 1491 } 1492 id = id->next; 1493 } 1494 id = d->ty->ids; 1495 for(as = e->right; as != nil; as = as->right){ 1496 a = as->left; 1497 if(a->flags&TEMP){ 1498 f = mkdeclname(&as->src, id); 1499 n = mkbin(Oas, f, a); 1500 n->ty = id->ty; 1501 scom(n); 1502 tfree(a); 1503 } 1504 id = id->next; 1505 } 1506 p = genrawop(&e->src, IJMP, nil, nil, nil); 1507 patch(p, d->pc); 1508 popblock(); 1509 return 1; 1510 } 1511