|
|
1.1 ! root 1: #include <u.h> ! 2: #include <libc.h> ! 3: #include <bio.h> ! 4: #include <ctype.h> ! 5: #define Extern extern ! 6: #include "parl.h" ! 7: #include "globl.h" ! 8: ! 9: static Glab *gotos; ! 10: static Glab *labels; ! 11: static Jmps *contstack; ! 12: static Jmps *brkstack; ! 13: static Jmps *retstack; ! 14: static Jmps *rescues; ! 15: static Node *lstmnt; ! 16: ! 17: /* Compile a function */ ! 18: void ! 19: fungen(Node *code, Node *args) ! 20: { ! 21: int l; ! 22: Type *t; ! 23: Node n1; ! 24: ulong rpc; ! 25: Inst *fcode; ! 26: ! 27: l = line; ! 28: fcode = ipc; ! 29: ! 30: iter(code, 1); ! 31: typechk(code, 0); ! 32: rewrite(code); ! 33: ! 34: args->left->right = code; ! 35: ! 36: if(code) ! 37: sucalc(code); ! 38: ! 39: if(opt('t')) { ! 40: print("\nTree:\n"); ! 41: ptree(code, 0); ! 42: } ! 43: ! 44: /* Clear the label stack */ ! 45: labels = 0; ! 46: gotos = 0; ! 47: rescues = 0; ! 48: ! 49: if(opt('q') == 0 && nerr == 0) { ! 50: t = curfunc->t->next; ! 51: switch(t->type) { ! 52: case TPOLY: ! 53: curfunc = dupn(curfunc); ! 54: curfunc->t = at(TFUNC, polyshape); ! 55: /* No Break */ ! 56: case TADT: ! 57: case TUNION: ! 58: case TAGGREGATE: ! 59: t = at(TIND, t); ! 60: regret(&n1, t); ! 61: rnode = stknode(n1.t); ! 62: assign(&n1, rnode); ! 63: regfree(&n1); ! 64: becomentry = ipc; ! 65: } ! 66: ! 67: lstmnt = nil; ! 68: if(code) ! 69: stmnt(code); ! 70: ! 71: if(t->type != TVOID) ! 72: if(lstmnt == 0 || ! 73: (lstmnt->type != ORET && lstmnt->type != OBECOME)) ! 74: diag(lstmnt, "typed function has no return"); ! 75: ! 76: rpc = ipc->pc+1; ! 77: /* Improve optimiser by using non return register */ ! 78: switch(t->type) { ! 79: case TVOID: ! 80: instruction(ANOP, ZeroN, ZeroN, regn(Freg)); ! 81: instruction(ANOP, ZeroN, ZeroN, regn(Retireg)); ! 82: break; ! 83: case TFLOAT: ! 84: instruction(ANOP, ZeroN, ZeroN, regn(Retireg)); ! 85: break; ! 86: default: ! 87: instruction(ANOP, ZeroN, ZeroN, regn(Freg)); ! 88: break; ! 89: } ! 90: ! 91: instruction(ARETURN, ZeroN, ZeroN, ZeroN); ! 92: ! 93: /* Patch in all the returns */ ! 94: while(retstack) { ! 95: label(retstack->i, rpc); ! 96: popjmp(&retstack); ! 97: } ! 98: ! 99: /* Back patch the entry */ ! 100: resolvegoto(); ! 101: ! 102: /* Patch in the frame size */ ! 103: funentry->dst.ival = maxframe + frame; ! 104: } ! 105: ! 106: leaveblock(); ! 107: ! 108: regcheck(); ! 109: ! 110: if(opt('N') || opt('R') || opt('P')) ! 111: regopt(fcode); ! 112: ! 113: line = l; ! 114: } ! 115: ! 116: void ! 117: bstmnt(Node *n) ! 118: { ! 119: Node *tmp; ! 120: ! 121: tmp = lstmnt; ! 122: stmnt(n); ! 123: lstmnt = tmp; ! 124: } ! 125: ! 126: /* Compile code for a statement */ ! 127: void ! 128: stmnt(Node *n) ! 129: { ! 130: Jmps *p; ! 131: Node *l, *r, n1, com; ! 132: Inst *false, *truedone, *loop, *enter; ! 133: ! 134: if(n == ZeroN) ! 135: return; ! 136: ! 137: l = n->left; ! 138: r = n->right; ! 139: iline = n->srcline; ! 140: lstmnt = n; ! 141: ! 142: switch(n->type) { ! 143: default: ! 144: genexp(n, ZeroN); ! 145: break; ! 146: ! 147: case OLIST: ! 148: stmnt(l); ! 149: stmnt(r); ! 150: break; ! 151: ! 152: case OBLOCK: ! 153: stmnt(l); ! 154: break; ! 155: ! 156: case OLBLOCK: ! 157: if(l == ZeroN) { ! 158: warn(n, "empty guarded block"); ! 159: break; ! 160: } ! 161: lblock(l); ! 162: break; ! 163: ! 164: case OPAR: ! 165: parcode(l->left); ! 166: break; ! 167: ! 168: case OSWITCH: ! 169: switchcode(n); ! 170: break; ! 171: ! 172: case OSELECT: ! 173: selcode(n); ! 174: break; ! 175: ! 176: case OGOTO: ! 177: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 178: setgoto(n, ipc); ! 179: break; ! 180: ! 181: case OLABEL: ! 182: setlabel(n, ipc->pc+1); ! 183: break; ! 184: ! 185: case OCASE: ! 186: case ODEFAULT: ! 187: n->pc = ipc->pc+1; ! 188: ! 189: if(l && l->type != OCONST) ! 190: stmnt(l); ! 191: ! 192: if(r) ! 193: stmnt(r); ! 194: break; ! 195: ! 196: case OIF: ! 197: gencond(l, ZeroN, True); ! 198: false = ipc; ! 199: if(r && r->type == OELSE) { ! 200: stmnt(r->left); ! 201: truedone = instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 202: label(false, ipc->pc+1); ! 203: stmnt(r->right); ! 204: label(truedone, ipc->pc+1); ! 205: break; ! 206: } ! 207: ! 208: if(r) ! 209: stmnt(r); ! 210: ! 211: label(false, ipc->pc+1); ! 212: break; ! 213: ! 214: case ORET: ! 215: if(l) { ! 216: switch(l->t->type) { ! 217: default: ! 218: regret(&n1, l->t); ! 219: genexp(l, &n1); ! 220: regfree(&n1); ! 221: break; ! 222: ! 223: case TADT: ! 224: case TUNION: ! 225: case TAGGREGATE: ! 226: com.type = OASGN; ! 227: com.t = l->t; ! 228: com.left = an(OIND, rnode, ZeroN); ! 229: com.left->t = rnode->t->next; ! 230: com.right = l; ! 231: sucalc(&com); ! 232: genexp(&com, ZeroN); ! 233: break; ! 234: } ! 235: } ! 236: ! 237: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 238: pushjmp(&retstack); ! 239: break; ! 240: ! 241: case ODWHILE: ! 242: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 243: enter = ipc; ! 244: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Continue */ ! 245: pushjmp(&contstack); ! 246: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */ ! 247: pushjmp(&brkstack); ! 248: ! 249: label(enter, ipc->pc+1); ! 250: loop = ipc; ! 251: if(r) ! 252: stmnt(r); ! 253: ! 254: label(contstack->i, ipc->pc+1); ! 255: if(l) { ! 256: gencond(l, ZeroN, True); ! 257: label(ipc, brkstack->i->pc); ! 258: } ! 259: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Loop */ ! 260: label(ipc, loop->pc+1); ! 261: ! 262: label(brkstack->i, ipc->pc+1); ! 263: popjmp(&contstack); ! 264: popjmp(&brkstack); ! 265: break; ! 266: ! 267: case OWHILE: ! 268: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Continue */ ! 269: pushjmp(&contstack); ! 270: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */ ! 271: pushjmp(&brkstack); ! 272: ! 273: label(contstack->i, ipc->pc+1); ! 274: loop = ipc; ! 275: if(l) { /* Cond */ ! 276: gencond(l, ZeroN, True); ! 277: label(ipc, brkstack->i->pc); ! 278: } ! 279: ! 280: if(r) ! 281: stmnt(r); ! 282: ! 283: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Loop */ ! 284: label(ipc, loop->pc+1); ! 285: ! 286: label(brkstack->i, ipc->pc+1); ! 287: popjmp(&contstack); ! 288: popjmp(&brkstack); ! 289: break; ! 290: ! 291: case OFOR: ! 292: if(l->left) /* Assign */ ! 293: genexp(l->left, ZeroN); ! 294: ! 295: l = l->right; ! 296: ! 297: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 298: enter = ipc; ! 299: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Continue */ ! 300: pushjmp(&contstack); ! 301: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */ ! 302: pushjmp(&brkstack); ! 303: label(enter, ipc->pc+1); ! 304: ! 305: if(l->left) { /* Cond */ ! 306: gencond(l->left, ZeroN, True); ! 307: label(ipc, brkstack->i->pc); ! 308: } ! 309: if(r) ! 310: stmnt(r); ! 311: label(contstack->i, ipc->pc+1); ! 312: if(l->right) /* Action */ ! 313: genexp(l->right, ZeroN); ! 314: ! 315: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 316: label(ipc, enter->pc); ! 317: ! 318: label(brkstack->i, ipc->pc+1); ! 319: popjmp(&contstack); ! 320: popjmp(&brkstack); ! 321: break; ! 322: ! 323: case ORAISE: ! 324: if(l) { ! 325: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 326: setgoto(l, ipc); ! 327: break; ! 328: } ! 329: if(rescues == 0) { ! 330: diag(n, "raise without rescue"); ! 331: break; ! 332: } ! 333: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 334: label(ipc, rescues->i->pc+1); ! 335: if(rescues->par != inpar) ! 336: diag(n, "raise breaks join in par"); ! 337: if(rescues->crit != incrit) ! 338: diag(n, "raise breaks critical section"); ! 339: break; ! 340: ! 341: case ORESCUE: ! 342: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 343: enter = ipc; ! 344: if(l->type == OLABEL) { ! 345: setlabel(l, ipc->pc+1); ! 346: l = l->left; ! 347: } ! 348: stmnt(l); ! 349: label(enter, ipc->pc+1); ! 350: pushlab(&rescues, enter); ! 351: break; ! 352: ! 353: case OBREAK: ! 354: p = brkstack; ! 355: while(p) { ! 356: n->ival--; ! 357: if(n->ival == 0) ! 358: break; ! 359: p = p->next; ! 360: } ! 361: if(p) { ! 362: if(p->par != inpar) ! 363: diag(n, "break breaks join in par"); ! 364: if(p->crit != incrit) ! 365: diag(n, "break breaks critical section"); ! 366: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 367: label(ipc, p->i->pc); ! 368: break; ! 369: } ! 370: diag(n, "break not in loop/switch/select"); ! 371: break; ! 372: ! 373: case OCONT: ! 374: p = contstack; ! 375: while(p) { ! 376: n->ival--; ! 377: if(n->ival == 0) ! 378: break; ! 379: p = p->next; ! 380: } ! 381: if(p) { ! 382: if(p->par != inpar) ! 383: diag(n, "continue breaks join in par"); ! 384: if(p->crit != incrit) ! 385: diag(n, "continue breaks critical section"); ! 386: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 387: label(ipc, p->i->pc); ! 388: break; ! 389: } ! 390: diag(n, "continue not in loop"); ! 391: break; ! 392: } ! 393: } ! 394: ! 395: int ! 396: cascmp(Node **a, Node **b) ! 397: { ! 398: int av, bv; ! 399: ! 400: av = (*a)->left->ival; ! 401: bv = (*b)->left->ival; ! 402: if(av < bv) ! 403: return -1; ! 404: return av > bv; ! 405: } ! 406: ! 407: void ! 408: casecount(Node *n, Node **vec) ! 409: { ! 410: if(n == ZeroN) ! 411: return; ! 412: ! 413: switch(n->type) { ! 414: case ODEFAULT: ! 415: case OCASE: ! 416: if(vec) ! 417: vec[veccnt] = n; ! 418: veccnt++; ! 419: break; ! 420: ! 421: default: ! 422: casecount(n->left, vec); ! 423: casecount(n->right, vec); ! 424: break; ! 425: } ! 426: } ! 427: ! 428: void ! 429: switchcode(Node *n) ! 430: { ! 431: Node val; ! 432: long defpc; ! 433: Inst *enter; ! 434: int i, r, safe; ! 435: Node **cases, *defl, *c, *il, com; ! 436: ! 437: c = n->right; ! 438: if(c == ZeroN) { ! 439: warn(n, "empty switch statement"); ! 440: return; ! 441: } ! 442: ! 443: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Entry */ ! 444: enter = ipc; ! 445: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */ ! 446: pushjmp(&brkstack); ! 447: ! 448: safe = 0; ! 449: if(c->type == OLBLOCK) { ! 450: incrit++; ! 451: safe = 1; ! 452: c = c->left; ! 453: } ! 454: /* Generate the code */ ! 455: stmnt(c); ! 456: ! 457: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Done break */ ! 458: label(ipc, brkstack->i->pc); ! 459: ! 460: /* Count */ ! 461: veccnt = 0; ! 462: casecount(c, 0); ! 463: ! 464: /* Save */ ! 465: cases = malloc(sizeof(Node*)*veccnt); ! 466: veccnt = 0; ! 467: casecount(c, cases); ! 468: ! 469: defl = 0; ! 470: for(i = 0; i < veccnt; i++) { ! 471: c = cases[i]; ! 472: switch(c->type) { ! 473: case OCASE: ! 474: if(c->left->type != OCONST) { ! 475: diag(c, "case must be constant"); ! 476: cases[i] = ZeroN; ! 477: } ! 478: break; ! 479: ! 480: case ODEFAULT: ! 481: if(defl) ! 482: diag(c, "switch already has default"); ! 483: defl = c; ! 484: cases[i] = ZeroN; ! 485: break; ! 486: } ! 487: } ! 488: ! 489: /* Close up the table */ ! 490: for(i = 0; i < veccnt; i++) { ! 491: if(cases[i] == ZeroN) { ! 492: veccnt--; ! 493: memmove(cases+i, cases+i+1, (veccnt-i)*sizeof(Node*)); ! 494: } ! 495: } ! 496: ! 497: qsort(cases, veccnt, sizeof(Node*), cascmp); ! 498: ! 499: for(i = 0; i < veccnt-1; i++) { ! 500: r = cases[i]->left->ival; ! 501: if(r == cases[i+1]->left->ival) ! 502: diag(cases[i+1], "duplicate case %d in switch", r); ! 503: } ! 504: ! 505: label(enter, ipc->pc+1); ! 506: SET(il); ! 507: if(safe) { ! 508: il = internnode(builtype[TIND]); ! 509: il = an(OADDR, il, ZeroN); ! 510: il->t = builtype[TIND]; ! 511: ! 512: com.type = OCALL; ! 513: com.t = builtype[TVOID]; ! 514: com.left = ginode; ! 515: com.right = il; ! 516: ! 517: sucalc(&com); ! 518: stmnt(&com); ! 519: } ! 520: ! 521: reg(&val, builtype[TINT], ZeroN); ! 522: genexp(n->left, &val); ! 523: ! 524: defpc = brkstack->i->pc; ! 525: if(defl) ! 526: defpc = defl->pc; ! 527: ! 528: gencmps(cases, veccnt, defpc, &val); ! 529: ! 530: regfree(&val); ! 531: label(brkstack->i, ipc->pc+1); ! 532: ! 533: if(safe) { ! 534: com.type = OCALL; ! 535: com.t = builtype[TVOID]; ! 536: com.left = gonode; ! 537: com.right = il; ! 538: ! 539: sucalc(&com); ! 540: stmnt(&com); ! 541: incrit--; ! 542: } ! 543: popjmp(&brkstack); ! 544: } ! 545: ! 546: Node* ! 547: gcom(Node *n) ! 548: { ! 549: Node *l; ! 550: ! 551: if(n == 0) ! 552: return ZeroN; ! 553: ! 554: switch(n->type) { ! 555: case ORECV: ! 556: return n; ! 557: case OCALL: ! 558: if(issend(n->left)) ! 559: return n; ! 560: /* Fall through */ ! 561: default: ! 562: l = gcom(n->left); ! 563: if(l == 0) ! 564: l = gcom(n->right); ! 565: return l; ! 566: } ! 567: } ! 568: ! 569: int ! 570: regcode(Node **cases, int cnt) ! 571: { ! 572: int i, var; ! 573: Node *l, *c; ! 574: ! 575: var = 0; ! 576: for(i = 0; i < cnt; i++) { ! 577: c = cases[i]; ! 578: switch(c->type) { ! 579: case OCASE: ! 580: l = gcom(c->left); ! 581: if(l == 0) { ! 582: diag(c, "case expr needs send/receive"); ! 583: cases[i] = ZeroN; ! 584: break; ! 585: } ! 586: if(l->t->variant) ! 587: var++; ! 588: switch(l->type) { ! 589: default: /* Catch the send rewrites */ ! 590: l->left = selsend; ! 591: c->t = l->t; ! 592: l->t = builtype[TVOID]; ! 593: break; ! 594: case ORECV: ! 595: case OCRCV: ! 596: c->left = l; ! 597: l->type = OCALL; ! 598: c->t = l->t; ! 599: l->t = builtype[TVOID]; ! 600: l->left = selrecv; ! 601: break; ! 602: } ! 603: /* Only the channel argument */ ! 604: while(l->right->type == OLIST) ! 605: l->right = l->right->left; ! 606: break; ! 607: case ODEFAULT: ! 608: diag(c, "alt already has default"); ! 609: cases[i] = ZeroN; ! 610: break; ! 611: } ! 612: } ! 613: return var; ! 614: } ! 615: ! 616: void ! 617: selcode(Node *n) ! 618: { ! 619: Inst *enter; ! 620: Node val, com; ! 621: int i, x, safe, var; ! 622: Node **cases, *c, *il; ! 623: ! 624: safe = 0; ! 625: ! 626: val.srcline = n->srcline; ! 627: com.srcline = n->srcline; ! 628: ! 629: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Entry */ ! 630: enter = ipc; ! 631: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Break */ ! 632: pushjmp(&brkstack); ! 633: ! 634: c = n->left; ! 635: if(c == nil) ! 636: return; ! 637: if(c->type == OLBLOCK) { ! 638: incrit++; ! 639: safe = 1; ! 640: c = c->left; ! 641: } ! 642: stmnt(c); ! 643: ! 644: instruction(AJMP, ZeroN, ZeroN, ZeroN); /* Done break */ ! 645: label(ipc, brkstack->i->pc); ! 646: ! 647: veccnt = 0; ! 648: casecount(n->left, 0); ! 649: cases = malloc(sizeof(Node*)*veccnt); ! 650: veccnt = 0; ! 651: casecount(n->left, cases); ! 652: ! 653: /* Convert expression to register channels for select */ ! 654: var = regcode(cases, veccnt); ! 655: ! 656: for(i = 0; i < veccnt; i++) { ! 657: if(cases[i] == ZeroN) { ! 658: veccnt--; ! 659: memmove(cases+i, cases+i+1, (veccnt-i)*sizeof(Node*)); ! 660: } ! 661: } ! 662: if(veccnt == 0) ! 663: return; ! 664: ! 665: label(enter, ipc->pc+1); ! 666: SET(il); ! 667: if(safe) { ! 668: il = internnode(builtype[TIND]); ! 669: il = an(OADDR, il, ZeroN); ! 670: il->t = builtype[TIND]; ! 671: ! 672: com.type = OCALL; ! 673: com.t = builtype[TVOID]; ! 674: com.left = ginode; ! 675: com.right = il; ! 676: ! 677: sucalc(&com); ! 678: stmnt(&com); ! 679: } ! 680: ! 681: /* Assign values */ ! 682: for(i = 0; i < veccnt; i++) { ! 683: c = cases[i]; ! 684: x = i; ! 685: if(var) ! 686: x = typesig(c->t); ! 687: c->left->ival = x; ! 688: } ! 689: ! 690: /* Sort if type match */ ! 691: if(var) ! 692: qsort(cases, veccnt, sizeof(Node*), cascmp); ! 693: ! 694: /* Detect type clashes */ ! 695: for(i = 0; i < veccnt-1; i++) { ! 696: c = cases[i]; ! 697: if(c->left->ival == cases[i+1]->left->ival) ! 698: diag(c, "duplicate variant type %V", c->t); ! 699: } ! 700: ! 701: /* Code the selsend/selrecv expressions */ ! 702: for(i = 0; i < veccnt; i++) ! 703: genexp(cases[i]->left, ZeroN); ! 704: ! 705: com.type = OCALL; ! 706: com.t = builtype[TVOID]; ! 707: com.left = doselect; ! 708: if(var) ! 709: com.left = varselect; ! 710: com.right = ZeroN; ! 711: sucalc(&com); ! 712: stmnt(&com); ! 713: ! 714: regret(&val, builtype[TINT]); ! 715: gencmps(cases, veccnt, -1, &val); ! 716: regfree(&val); ! 717: ! 718: label(brkstack->i, ipc->pc+1); ! 719: if(safe) { ! 720: com.type = OCALL; ! 721: com.t = builtype[TVOID]; ! 722: com.left = gonode; ! 723: com.right = il; ! 724: sucalc(&com); ! 725: stmnt(&com); ! 726: incrit--; ! 727: } ! 728: popjmp(&brkstack); ! 729: } ! 730: ! 731: void ! 732: gencmps(Node **c, int cnt, long defpc, Node *val) ! 733: { ! 734: Node n, con, **r; ! 735: int i; ! 736: Inst *patch; ! 737: ! 738: con.type = OCONST; ! 739: con.t = builtype[TINT]; ! 740: ! 741: if(cnt < 4) { ! 742: for(i = 0; i < cnt; i++) { ! 743: con.ival = (*c)->left->ival; ! 744: reg(&n, builtype[TINT], ZeroN); ! 745: assign(&con, &n); ! 746: codcond(OEQ, &n, val); ! 747: label(ipc, (*c)->pc); ! 748: regfree(&n); ! 749: c++; ! 750: } ! 751: if(defpc != -1) { ! 752: instruction(AJMP, ZeroN, ZeroN, ZeroN); ! 753: label(ipc, defpc); ! 754: } ! 755: return; ! 756: } ! 757: i = cnt/2; ! 758: r = c+i; ! 759: ! 760: con.ival = (*r)->left->ival; ! 761: reg(&n, builtype[TINT], ZeroN); ! 762: assign(&con, &n); ! 763: codcond(OLT, &n, val); ! 764: patch = ipc; ! 765: codcond(OEQ, &n, val); ! 766: label(ipc, (*r)->pc); ! 767: regfree(&n); ! 768: gencmps(c, i, defpc, val); ! 769: ! 770: label(patch, ipc->pc+1); ! 771: gencmps(r+1, cnt-i-1, defpc, val); ! 772: } ! 773: ! 774: ulong ! 775: framefind(Node *n) ! 776: { ! 777: ulong l, r; ! 778: ! 779: if(n == ZeroN) ! 780: return 0; ! 781: ! 782: switch(n->type) { ! 783: default: ! 784: l = framefind(n->left); ! 785: r = framefind(n->right); ! 786: if(r > l) ! 787: l = r; ! 788: break; ! 789: case OCALL: ! 790: frsize = 0; ! 791: framesize(n->right); ! 792: l = frsize; ! 793: } ! 794: return l; ! 795: } ! 796: ! 797: void ! 798: parcode(Node *n) ! 799: { ! 800: Type *t; ! 801: ulong frs; ! 802: int i, cnt; ! 803: Inst *loop; ! 804: Node *barrier, **slist, com, retr; ! 805: Node *stv, *stvp, *oatv, *p; ! 806: ! 807: veccnt = 0; ! 808: listcount(n, 0); ! 809: slist = malloc(sizeof(Node*)*veccnt); ! 810: veccnt = 0; ! 811: listcount(n, slist); ! 812: ! 813: if(opt('O')) { ! 814: for(i = 0; i < veccnt; i++) { ! 815: ptree(slist[i], 0); ! 816: print("*\n"); ! 817: } ! 818: } ! 819: ! 820: if(veccnt < 2) { ! 821: warn(n, "only one statement in par"); ! 822: stmnt(slist[0]); ! 823: return; ! 824: } ! 825: ! 826: inpar++; ! 827: oatv = atv; ! 828: cnt = veccnt; ! 829: ! 830: /* ! 831: * This slime is Parrend in the runtime ! 832: */ ! 833: t = at(TAGGREGATE, 0); ! 834: t->size = SZPAREND*builtype[TINT]->size; ! 835: barrier = an(OADDR, stknode(t), ZeroN); ! 836: barrier->t = at(TIND, t); ! 837: ! 838: /* ! 839: * Build activation vector ! 840: */ ! 841: t = at(TIND, builtype[TIND]); ! 842: t->size = t->next->size * cnt; ! 843: stv = stknode(t); ! 844: stv->ti->t = at(TARRAY, 0); ! 845: ! 846: /* ! 847: * craft: pid = pfork(cnt, stv) ! 848: */ ! 849: com.type = OCALL; ! 850: com.t = builtype[TINT]; ! 851: com.left = pforknode; ! 852: stvp = an(OADDR, stv, ZeroN); ! 853: stvp->t = builtype[TIND]; ! 854: com.right = an(OLIST, con(veccnt-1), an(OLIST, stvp, barrier)); ! 855: ! 856: sucalc(&com); ! 857: genexp(&com, ZeroN); ! 858: ! 859: for(i = 0; i < cnt-1; i++) { ! 860: regret(&retr, builtype[TINT]); ! 861: instruction(ACMP, con(i), ZeroN, &retr); ! 862: instruction(ABNE, ZeroN, ZeroN, ZeroN); ! 863: loop = ipc; ! 864: regfree(&retr); ! 865: ! 866: /* ! 867: * find the largest frame in this activation ! 868: */ ! 869: frs = framefind(slist[i]); ! 870: /* ensure enough space for ALEF_pexit args */ ! 871: if(frs < 2*builtype[TIND]->size) { ! 872: frs = 2*builtype[TIND]->size; ! 873: frs = align(frs, builtype[TIND]); ! 874: } ! 875: if(opt('O')) ! 876: print("%d: frame %d\n", i, frs); ! 877: ! 878: /* ! 879: * Compute my activation from stack vector: atv = stv[pid] ! 880: */ ! 881: t = builtype[TIND]; ! 882: atv = stknode(t); ! 883: p = an(OADD, stvp, con(i*builtype[TIND]->size)); ! 884: p->t = t; ! 885: p = an(OIND, p, ZeroN); ! 886: p->t = t; ! 887: /* ! 888: * 2*sizeof(*) is enough for save SP at activation top plus hole ! 889: * for the saved activation pc ! 890: */ ! 891: p = an(OSUB, p, con(frs+2*builtype[TIND]->size)); ! 892: p->t = t; ! 893: /* ! 894: * word used for activation link ! 895: */ ! 896: atv->atvsafe = frs+builtype[TIND]->size; ! 897: p = an(OASGN, atv, p); ! 898: p->t = t; ! 899: ! 900: sucalc(p); ! 901: genexp(p, ZeroN); ! 902: ! 903: stmnt(slist[i]); ! 904: ! 905: com.type = OCALL; ! 906: com.t = builtype[TVOID]; ! 907: com.left = pexitnode; ! 908: com.right = barrier; ! 909: ! 910: sucalc(&com); ! 911: stmnt(&com); ! 912: ! 913: label(loop, ipc->pc+1); ! 914: } ! 915: atv = oatv; ! 916: ! 917: stmnt(slist[i]); ! 918: ! 919: /* ! 920: * craft terminator: ALEF_pdone(&barrier, stv); ! 921: */ ! 922: com.type = OCALL; ! 923: com.t = builtype[TINT]; ! 924: com.left = pdonenode; ! 925: stvp = an(OADDR, stv, ZeroN); ! 926: stvp->t = builtype[TIND]; ! 927: com.right = an(OLIST, barrier, stvp); ! 928: ! 929: sucalc(&com); ! 930: stmnt(&com); ! 931: ! 932: inpar--; ! 933: } ! 934: ! 935: void ! 936: lblock(Node *n) ! 937: { ! 938: Node com, *i; ! 939: ! 940: i = internnode(builtype[TIND]); ! 941: i = an(OADDR, i, ZeroN); ! 942: i->t = builtype[TIND]; ! 943: ! 944: com.type = OCALL; ! 945: com.t = builtype[TVOID]; ! 946: com.left = ginode; ! 947: com.right = i; ! 948: sucalc(&com); ! 949: stmnt(&com); ! 950: ! 951: incrit++; ! 952: stmnt(n); ! 953: incrit--; ! 954: ! 955: com.type = OCALL; ! 956: com.t = builtype[TVOID]; ! 957: com.left = gonode; ! 958: com.right = i; ! 959: sucalc(&com); ! 960: stmnt(&com); ! 961: } ! 962: ! 963: /* determine addressablility and number of registers */ ! 964: void ! 965: sucalc(Node *n) ! 966: { ! 967: Node *l, *r; ! 968: ! 969: if(n == 0) ! 970: return; ! 971: ! 972: l = n->left; ! 973: r = n->right; ! 974: n->sun = 0; ! 975: n->islval = 0; ! 976: ! 977: /* Addressability */ ! 978: switch(n->type) { ! 979: case OBECOME: ! 980: sucalc(l); ! 981: if(l->type == OCALL) ! 982: n->right = paramdep(l->right); ! 983: return; ! 984: ! 985: case OCONST: ! 986: n->islval = 20; ! 987: return; ! 988: ! 989: case OREGISTER: ! 990: n->islval = 11; ! 991: return; ! 992: ! 993: case OINDREG: ! 994: n->islval = 12; ! 995: return; ! 996: ! 997: case ONAME: ! 998: n->islval = 10; ! 999: return; ! 1000: ! 1001: case OADDR: ! 1002: sucalc(l); ! 1003: if(l->islval == 10) ! 1004: n->islval = 2; ! 1005: if(l->islval == 12) ! 1006: n->islval = 3; ! 1007: break; ! 1008: ! 1009: case OIND: ! 1010: sucalc(l); ! 1011: if(l->islval == 11) ! 1012: n->islval = 12; ! 1013: if(l->islval == 3) ! 1014: n->islval = 12; ! 1015: if(l->islval == 2) ! 1016: n->islval = 10; ! 1017: break; ! 1018: ! 1019: case OADD: ! 1020: sucalc(l); ! 1021: sucalc(r); ! 1022: if(l->islval == 20) { ! 1023: if(r->islval == 2) ! 1024: n->islval = 2; ! 1025: if(r->islval == 3) ! 1026: n->islval = 3; ! 1027: } ! 1028: if(r->islval == 20) { ! 1029: if(l->islval == 2) ! 1030: n->islval = 2; ! 1031: if(l->islval == 3) ! 1032: n->islval = 3; ! 1033: } ! 1034: break; ! 1035: ! 1036: default: ! 1037: sucalc(l); ! 1038: sucalc(r); ! 1039: break; ! 1040: } ! 1041: ! 1042: /* Number of registers */ ! 1043: switch(n->type) { ! 1044: default: ! 1045: if(l != ZeroN) ! 1046: n->sun = l->sun; ! 1047: if(r != ZeroN) { ! 1048: if(n->sun == r->sun) ! 1049: n->sun = n->sun + 1; ! 1050: else if(r->sun > n->sun) ! 1051: n->sun = r->sun; ! 1052: } ! 1053: if(n->sun == 0) ! 1054: n->sun = 1; ! 1055: break; ! 1056: ! 1057: case OCALL: ! 1058: case OSEND: ! 1059: case ORECV: ! 1060: n->sun = Sucall; ! 1061: break; ! 1062: } ! 1063: } ! 1064: ! 1065: void ! 1066: setlabel(Node *n, ulong pc) ! 1067: { ! 1068: Glab *i; ! 1069: ! 1070: for(i = labels; i; i = i->next) { ! 1071: if(i->n->sym == n->sym) { ! 1072: diag(n, "label %s used twice", n->sym->name); ! 1073: return; ! 1074: } ! 1075: } ! 1076: i = malloc(sizeof(Glab)); ! 1077: i->n = n; ! 1078: i->par = inpar; ! 1079: i->crit = incrit; ! 1080: i->pc = pc; ! 1081: i->next = labels; ! 1082: labels = i; ! 1083: } ! 1084: ! 1085: void ! 1086: setgoto(Node *n, Inst *i) ! 1087: { ! 1088: Glab *g; ! 1089: ! 1090: g = malloc(sizeof(Glab)); ! 1091: g->n = n; ! 1092: g->i = i; ! 1093: g->par = inpar; ! 1094: g->crit = incrit; ! 1095: g->next = gotos; ! 1096: gotos = g; ! 1097: } ! 1098: ! 1099: Glab* ! 1100: findlab(Node *n) ! 1101: { ! 1102: Glab *i; ! 1103: ! 1104: for(i = labels; i; i = i->next) ! 1105: if(i->n->sym == n->sym) ! 1106: return i; ! 1107: ! 1108: return 0; ! 1109: } ! 1110: ! 1111: void ! 1112: resolvegoto(void) ! 1113: { ! 1114: Glab *g, *l; ! 1115: ! 1116: for(g = gotos; g; g = g->next) { ! 1117: l = findlab(g->n); ! 1118: if(l == 0) { ! 1119: diag(g->n, "no label called %s", g->n->sym->name); ! 1120: continue; ! 1121: } ! 1122: ! 1123: if(g->par != l->par) ! 1124: diag(g->n, "raise/goto breaks join from par"); ! 1125: if(g->crit != l->crit) ! 1126: diag(g->n, "raise/goto breaks critical section"); ! 1127: ! 1128: label(g->i, l->pc); ! 1129: } ! 1130: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.