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