1 #include "gc.h" 2 3 int 4 swcmp(void *a1, void *a2) 5 { 6 C1 *p1, *p2; 7 8 p1 = a1; 9 p2 = a2; 10 if(p1->val < p2->val) 11 return -1; 12 return p1->val > p2->val; 13 } 14 15 void 16 doswit(Node *n) 17 { 18 Case *c; 19 C1 *q, *iq; 20 long def, nc, i; 21 Node tn; 22 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); 51 swit1(iq, nc, def, n, &tn); 52 regfree(&tn); 53 } 54 55 void 56 swit1(C1 *q, int nc, long def, Node *n, Node *tn) 57 { 58 C1 *r; 59 int i; 60 Prog *sp; 61 62 if(nc < 5) { 63 for(i=0; i<nc; i++) { 64 if(sval(q->val)) { 65 gopcode(OEQ, n, Z, nodconst(q->val)); 66 } else { 67 gopcode(OSUB, nodconst(q->val), n, tn); 68 gopcode(OEQ, tn, Z, nodconst(0)); 69 } 70 patch(p, q->label); 71 q++; 72 } 73 gbranch(OGOTO); 74 patch(p, def); 75 return; 76 } 77 i = nc / 2; 78 r = q+i; 79 if(sval(r->val)) { 80 gopcode(OGT, n, Z, nodconst(r->val)); 81 sp = p; 82 } else { 83 gopcode(OSUB, nodconst(r->val), n, tn); 84 gopcode(OGT, tn, Z, nodconst(0)); 85 sp = p; 86 } 87 gbranch(OGOTO); 88 p->as = ABEQ; 89 patch(p, r->label); 90 swit1(q, i, def, n, tn); 91 92 patch(sp, pc); 93 swit1(r+1, nc-i-1, def, n, tn); 94 } 95 96 void 97 cas(void) 98 { 99 Case *c; 100 101 c = alloc(sizeof(*c)); 102 c->link = cases; 103 cases = c; 104 } 105 106 void 107 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 108 { 109 int sh; 110 long v; 111 Node *l; 112 113 /* 114 * n1 gets adjusted/masked value 115 * n2 gets address of cell 116 * n3 gets contents of cell 117 */ 118 l = b->left; 119 if(n2 != Z) { 120 regalloc(n1, l, nn); 121 reglcgen(n2, l, Z); 122 regalloc(n3, l, Z); 123 gopcode(OAS, n2, Z, n3); 124 gopcode(OAS, n3, Z, n1); 125 } else { 126 regalloc(n1, l, nn); 127 cgen(l, n1); 128 } 129 if(b->type->shift == 0 && typeu[b->type->etype]) { 130 v = ~0 + (1L << b->type->nbits); 131 gopcode(OAND, nodconst(v), Z, n1); 132 } else { 133 sh = 32 - b->type->shift - b->type->nbits; 134 if(sh > 0) 135 gopcode(OASHL, nodconst(sh), Z, n1); 136 sh += b->type->shift; 137 if(sh > 0) 138 if(typeu[b->type->etype]) 139 gopcode(OLSHR, nodconst(sh), Z, n1); 140 else 141 gopcode(OASHR, nodconst(sh), Z, n1); 142 } 143 } 144 145 void 146 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 147 { 148 long v; 149 Node nod, *l; 150 int sh; 151 152 /* 153 * n1 has adjusted/masked value 154 * n2 has address of cell 155 * n3 has contents of cell 156 */ 157 l = b->left; 158 regalloc(&nod, l, Z); 159 v = ~0 + (1L << b->type->nbits); 160 gopcode(OAND, nodconst(v), Z, n1); 161 gopcode(OAS, n1, Z, &nod); 162 if(nn != Z) 163 gopcode(OAS, n1, Z, nn); 164 sh = b->type->shift; 165 if(sh > 0) 166 gopcode(OASHL, nodconst(sh), Z, &nod); 167 v <<= sh; 168 gopcode(OAND, nodconst(~v), Z, n3); 169 gopcode(OOR, n3, Z, &nod); 170 gopcode(OAS, &nod, Z, n2); 171 172 regfree(&nod); 173 regfree(n1); 174 regfree(n2); 175 regfree(n3); 176 } 177 178 long 179 outstring(char *s, long n) 180 { 181 long r; 182 183 if(suppress) 184 return nstring; 185 r = nstring; 186 while(n) { 187 string[mnstring] = *s++; 188 mnstring++; 189 nstring++; 190 if(mnstring >= NSNAME) { 191 gpseudo(ADATA, symstring, nodconst(0L)); 192 p->from.offset += nstring - NSNAME; 193 p->reg = NSNAME; 194 p->to.type = D_SCONST; 195 memmove(p->to.sval, string, NSNAME); 196 mnstring = 0; 197 } 198 n--; 199 } 200 return r; 201 } 202 203 long 204 outlstring(ushort *s, long n) 205 { 206 char buf[2]; 207 int c; 208 long r; 209 210 if(suppress) 211 return nstring; 212 while(nstring & 1) 213 outstring("", 1); 214 r = nstring; 215 while(n > 0) { 216 c = *s++; 217 if(align(0, types[TCHAR], Aarg1)) { 218 buf[0] = c>>8; 219 buf[1] = c; 220 } else { 221 buf[0] = c; 222 buf[1] = c>>8; 223 } 224 outstring(buf, 2); 225 n -= sizeof(ushort); 226 } 227 return r; 228 } 229 230 int 231 mulcon(Node *n, Node *nn) 232 { 233 Node *l, *r, nod1, nod2; 234 Multab *m; 235 long v; 236 int o; 237 char code[sizeof(m->code)+2], *p; 238 239 if(typefd[n->type->etype]) 240 return 0; 241 l = n->left; 242 r = n->right; 243 if(l->op == OCONST) { 244 l = r; 245 r = n->left; 246 } 247 if(r->op != OCONST) 248 return 0; 249 v = convvtox(r->vconst, n->type->etype); 250 if(v != r->vconst) { 251 if(debug['M']) 252 print("%L multiply conv: %lld\n", n->lineno, r->vconst); 253 return 0; 254 } 255 m = mulcon0(n, v); 256 if(!m) { 257 if(debug['M']) 258 print("%L multiply table: %lld\n", n->lineno, r->vconst); 259 return 0; 260 } 261 262 memmove(code, m->code, sizeof(m->code)); 263 code[sizeof(m->code)] = 0; 264 265 p = code; 266 if(p[1] == 'i') 267 p += 2; 268 regalloc(&nod1, n, nn); 269 cgen(l, &nod1); 270 if(v < 0) 271 gopcode(ONEG, &nod1, Z, &nod1); 272 regalloc(&nod2, n, Z); 273 274 loop: 275 switch(*p) { 276 case 0: 277 regfree(&nod2); 278 gopcode(OAS, &nod1, Z, nn); 279 regfree(&nod1); 280 return 1; 281 case '+': 282 o = OADD; 283 goto addsub; 284 case '-': 285 o = OSUB; 286 addsub: /* number is r,n,l */ 287 v = p[1] - '0'; 288 r = &nod1; 289 if(v&4) 290 r = &nod2; 291 n = &nod1; 292 if(v&2) 293 n = &nod2; 294 l = &nod1; 295 if(v&1) 296 l = &nod2; 297 gopcode(o, l, n, r); 298 break; 299 default: /* op is shiftcount, number is r,l */ 300 v = p[1] - '0'; 301 r = &nod1; 302 if(v&2) 303 r = &nod2; 304 l = &nod1; 305 if(v&1) 306 l = &nod2; 307 v = *p - 'a'; 308 if(v < 0 || v >= 32) { 309 diag(n, "mulcon unknown op: %c%c", p[0], p[1]); 310 break; 311 } 312 gopcode(OASHL, nodconst(v), l, r); 313 break; 314 } 315 p += 2; 316 goto loop; 317 } 318 319 void 320 nullwarn(Node *l, Node *r) 321 { 322 warn(Z, "result of operation not used"); 323 if(l != Z) 324 cgen(l, Z); 325 if(r != Z) 326 cgen(r, Z); 327 } 328 329 void 330 sextern(Sym *s, Node *a, long o, long w) 331 { 332 long e, lw; 333 334 for(e=0; e<w; e+=NSNAME) { 335 lw = NSNAME; 336 if(w-e < lw) 337 lw = w-e; 338 gpseudo(ADATA, s, nodconst(0)); 339 p->from.offset += o+e; 340 p->reg = lw; 341 p->to.type = D_SCONST; 342 memmove(p->to.sval, a->cstring+e, lw); 343 } 344 } 345 346 void 347 gextern(Sym *s, Node *a, long o, long w) 348 { 349 if(a->op == OCONST && typev[a->type->etype]) { 350 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 351 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 352 else 353 gpseudo(ADATA, s, nod32const(a->vconst)); 354 p->from.offset += o; 355 p->reg = 4; 356 if(align(0, types[TCHAR], Aarg1)) /* isbigendian */ 357 gpseudo(ADATA, s, nod32const(a->vconst)); 358 else 359 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 360 p->from.offset += o + 4; 361 p->reg = 4; 362 return; 363 } 364 gpseudo(ADATA, s, a); 365 p->from.offset += o; 366 p->reg = w; 367 if(p->to.type == D_OREG) 368 p->to.type = D_CONST; 369 } 370 371 void zname(Biobuf*, Sym*, int); 372 char* zaddr(char*, Adr*, int); 373 void zwrite(Biobuf*, Prog*, int, int); 374 void outhist(Biobuf*); 375 376 void 377 outcode(void) 378 { 379 struct { Sym *sym; short type; } h[NSYM]; 380 Prog *p; 381 Sym *s; 382 int sf, st, t, sym; 383 384 if(debug['S']) { 385 for(p = firstp; p != P; p = p->link) 386 if(p->as != ADATA && p->as != AGLOBL) 387 pc--; 388 for(p = firstp; p != P; p = p->link) { 389 print("%P\n", p); 390 if(p->as != ADATA && p->as != AGLOBL) 391 pc++; 392 } 393 } 394 outhist(&outbuf); 395 for(sym=0; sym<NSYM; sym++) { 396 h[sym].sym = S; 397 h[sym].type = 0; 398 } 399 sym = 1; 400 for(p = firstp; p != P; p = p->link) { 401 jackpot: 402 sf = 0; 403 s = p->from.sym; 404 while(s != S) { 405 sf = s->sym; 406 if(sf < 0 || sf >= NSYM) 407 sf = 0; 408 t = p->from.name; 409 if(h[sf].type == t) 410 if(h[sf].sym == s) 411 break; 412 s->sym = sym; 413 zname(&outbuf, s, t); 414 h[sym].sym = s; 415 h[sym].type = t; 416 sf = sym; 417 sym++; 418 if(sym >= NSYM) 419 sym = 1; 420 break; 421 } 422 st = 0; 423 s = p->to.sym; 424 while(s != S) { 425 st = s->sym; 426 if(st < 0 || st >= NSYM) 427 st = 0; 428 t = p->to.name; 429 if(h[st].type == t) 430 if(h[st].sym == s) 431 break; 432 s->sym = sym; 433 zname(&outbuf, s, t); 434 h[sym].sym = s; 435 h[sym].type = t; 436 st = sym; 437 sym++; 438 if(sym >= NSYM) 439 sym = 1; 440 if(st == sf) 441 goto jackpot; 442 break; 443 } 444 zwrite(&outbuf, p, sf, st); 445 } 446 firstp = P; 447 lastp = P; 448 } 449 450 void 451 zwrite(Biobuf *b, Prog *p, int sf, int st) 452 { 453 char bf[100], *bp; 454 long l; 455 456 bf[0] = p->as; 457 bf[1] = p->reg; 458 l = p->lineno; 459 bf[2] = l; 460 bf[3] = l>>8; 461 bf[4] = l>>16; 462 bf[5] = l>>24; 463 bp = zaddr(bf+6, &p->from, sf); 464 bp = zaddr(bp, &p->to, st); 465 Bwrite(b, bf, bp-bf); 466 } 467 468 void 469 outhist(Biobuf *b) 470 { 471 Hist *h; 472 char *p, *q, *op, c; 473 Prog pg; 474 int n; 475 476 pg = zprog; 477 pg.as = AHISTORY; 478 c = pathchar(); 479 for(h = hist; h != H; h = h->link) { 480 p = h->name; 481 op = 0; 482 /* on windows skip drive specifier in pathname */ 483 if(systemtype(Windows) && p && p[1] == ':'){ 484 p += 2; 485 c = *p; 486 } 487 if(p && p[0] != c && h->offset == 0 && pathname){ 488 /* on windows skip drive specifier in pathname */ 489 if(systemtype(Windows) && pathname[1] == ':') { 490 op = p; 491 p = pathname+2; 492 c = *p; 493 } else if(pathname[0] == c){ 494 op = p; 495 p = pathname; 496 } 497 } 498 while(p) { 499 q = utfrune(p, c); 500 if(q) { 501 n = q-p; 502 if(n == 0){ 503 n = 1; /* leading "/" */ 504 *p = '/'; /* don't emit "\" on windows */ 505 } 506 q++; 507 } else { 508 n = strlen(p); 509 q = 0; 510 } 511 if(n) { 512 Bputc(b, ANAME); 513 Bputc(b, D_FILE); 514 Bputc(b, 1); 515 Bputc(b, '<'); 516 Bwrite(b, p, n); 517 Bputc(b, 0); 518 } 519 p = q; 520 if(p == 0 && op) { 521 p = op; 522 op = 0; 523 } 524 } 525 pg.lineno = h->line; 526 pg.to.type = zprog.to.type; 527 pg.to.offset = h->offset; 528 if(h->offset) 529 pg.to.type = D_CONST; 530 531 zwrite(b, &pg, 0, 0); 532 } 533 } 534 535 void 536 zname(Biobuf *b, Sym *s, int t) 537 { 538 char *n, bf[7]; 539 ulong sig; 540 541 n = s->name; 542 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ 543 sig = sign(s); 544 bf[0] = ASIGNAME; 545 bf[1] = sig; 546 bf[2] = sig>>8; 547 bf[3] = sig>>16; 548 bf[4] = sig>>24; 549 bf[5] = t; 550 bf[6] = s->sym; 551 Bwrite(b, bf, 7); 552 s->sig = SIGDONE; 553 } 554 else{ 555 bf[0] = ANAME; 556 bf[1] = t; /* type */ 557 bf[2] = s->sym; /* sym */ 558 Bwrite(b, bf, 3); 559 } 560 Bwrite(b, n, strlen(n)+1); 561 } 562 563 char* 564 zaddr(char *bp, Adr *a, int s) 565 { 566 long l; 567 Ieee e; 568 569 bp[0] = a->type; 570 bp[1] = a->reg; 571 bp[2] = s; 572 bp[3] = a->name; 573 bp += 4; 574 switch(a->type) { 575 default: 576 diag(Z, "unknown type %d in zaddr", a->type); 577 578 case D_NONE: 579 case D_REG: 580 case D_FREG: 581 case D_CREG: 582 break; 583 584 case D_OREG: 585 case D_CONST: 586 case D_BRANCH: 587 l = a->offset; 588 bp[0] = l; 589 bp[1] = l>>8; 590 bp[2] = l>>16; 591 bp[3] = l>>24; 592 bp += 4; 593 break; 594 595 case D_SCONST: 596 memmove(bp, a->sval, NSNAME); 597 bp += NSNAME; 598 break; 599 600 case D_FCONST: 601 ieeedtod(&e, a->dval); 602 l = e.l; 603 bp[0] = l; 604 bp[1] = l>>8; 605 bp[2] = l>>16; 606 bp[3] = l>>24; 607 bp += 4; 608 l = e.h; 609 bp[0] = l; 610 bp[1] = l>>8; 611 bp[2] = l>>16; 612 bp[3] = l>>24; 613 bp += 4; 614 break; 615 } 616 return bp; 617 } 618 619 void 620 ieeedtod(Ieee *ieee, double native) 621 { 622 double fr, ho, f; 623 int exp; 624 625 if(native < 0) { 626 ieeedtod(ieee, -native); 627 ieee->h |= 0x80000000L; 628 return; 629 } 630 if(native == 0) { 631 ieee->l = 0; 632 ieee->h = 0; 633 return; 634 } 635 fr = frexp(native, &exp); 636 f = 2097152L; /* shouldnt use fp constants here */ 637 fr = modf(fr*f, &ho); 638 ieee->h = ho; 639 ieee->h &= 0xfffffL; 640 ieee->h |= (exp+1022L) << 20; 641 f = 65536L; 642 fr = modf(fr*f, &ho); 643 ieee->l = ho; 644 ieee->l <<= 16; 645 ieee->l |= (long)(fr*f); 646 } 647 648 long 649 align(long i, Type *t, int op) 650 { 651 long o; 652 Type *v; 653 int w; 654 655 o = i; 656 w = 1; 657 switch(op) { 658 default: 659 diag(Z, "unknown align opcode %d", op); 660 break; 661 662 case Asu2: /* padding at end of a struct */ 663 w = SZ_LONG; 664 if(packflg) 665 w = packflg; 666 break; 667 668 case Ael1: /* initial allign of struct element */ 669 for(v=t; v->etype==TARRAY; v=v->link) 670 ; 671 w = ewidth[v->etype]; 672 if(w <= 0 || w >= SZ_LONG) 673 w = SZ_LONG; 674 if(packflg) 675 w = packflg; 676 break; 677 678 case Ael2: /* width of a struct element */ 679 o += t->width; 680 break; 681 682 case Aarg0: /* initial passbyptr argument in arg list */ 683 if(typesuv[t->etype]) { 684 o = align(o, types[TIND], Aarg1); 685 o = align(o, types[TIND], Aarg2); 686 } 687 break; 688 689 case Aarg1: /* initial allign of parameter */ 690 w = ewidth[t->etype]; 691 if(w <= 0 || w >= SZ_LONG) { 692 w = SZ_LONG; 693 break; 694 } 695 o += SZ_LONG - w; /* big endian adjustment */ 696 w = 1; 697 break; 698 699 case Aarg2: /* width of a parameter */ 700 o += t->width; 701 w = SZ_LONG; 702 break; 703 704 case Aaut3: /* total allign of automatic */ 705 o = align(o, t, Ael1); 706 o = align(o, t, Ael2); 707 break; 708 } 709 o = round(o, w); 710 if(debug['A']) 711 print("align %s %ld %T = %ld\n", bnames[op], i, t, o); 712 return o; 713 } 714 715 long 716 maxround(long max, long v) 717 { 718 v += SZ_LONG-1; 719 if(v > max) 720 max = round(v, SZ_LONG); 721 return max; 722 } 723