github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/src/cmd/5c/swt.c (about) 1 // Inferno utils/5c/swt.c 2 // http://code.google.com/p/inferno-os/source/browse/utils/5c/swt.c 3 // 4 // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved. 5 // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net) 6 // Portions Copyright © 1997-1999 Vita Nuova Limited 7 // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com) 8 // Portions Copyright © 2004,2006 Bruce Ellis 9 // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net) 10 // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others 11 // Portions Copyright © 2009 The Go Authors. All rights reserved. 12 // 13 // Permission is hereby granted, free of charge, to any person obtaining a copy 14 // of this software and associated documentation files (the "Software"), to deal 15 // in the Software without restriction, including without limitation the rights 16 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 17 // copies of the Software, and to permit persons to whom the Software is 18 // furnished to do so, subject to the following conditions: 19 // 20 // The above copyright notice and this permission notice shall be included in 21 // all copies or substantial portions of the Software. 22 // 23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 24 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 25 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 26 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 27 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 28 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 29 // THE SOFTWARE. 30 31 #include "gc.h" 32 33 void 34 swit1(C1 *q, int nc, int32 def, Node *n) 35 { 36 Node nreg; 37 38 if(typev[n->type->etype]) { 39 regsalloc(&nreg, n); 40 nreg.type = types[TVLONG]; 41 cgen(n, &nreg); 42 swit2(q, nc, def, &nreg); 43 return; 44 } 45 46 regalloc(&nreg, n, Z); 47 nreg.type = types[TLONG]; 48 cgen(n, &nreg); 49 swit2(q, nc, def, &nreg); 50 regfree(&nreg); 51 } 52 53 void 54 swit2(C1 *q, int nc, int32 def, Node *n) 55 { 56 C1 *r; 57 int i; 58 int32 v; 59 Prog *sp; 60 61 if(nc >= 3) { 62 i = (q+nc-1)->val - (q+0)->val; 63 if(i > 0 && i < nc*2) 64 goto direct; 65 } 66 if(nc < 5) { 67 for(i=0; i<nc; i++) { 68 if(debug['W']) 69 print("case = %.8ux\n", q->val); 70 gopcode(OEQ, nodconst(q->val), n, Z); 71 patch(p, q->label); 72 q++; 73 } 74 gbranch(OGOTO); 75 patch(p, def); 76 return; 77 } 78 79 i = nc / 2; 80 r = q+i; 81 if(debug['W']) 82 print("case > %.8ux\n", r->val); 83 gopcode(OGT, nodconst(r->val), n, Z); 84 sp = p; 85 gopcode(OEQ, nodconst(r->val), n, Z); /* just gen the B.EQ */ 86 patch(p, r->label); 87 swit2(q, i, def, n); 88 89 if(debug['W']) 90 print("case < %.8ux\n", r->val); 91 patch(sp, pc); 92 swit2(r+1, nc-i-1, def, n); 93 return; 94 95 direct: 96 v = q->val; 97 if(v != 0) 98 gopcode(OSUB, nodconst(v), Z, n); 99 gopcode(OCASE, nodconst((q+nc-1)->val - v), n, Z); 100 patch(p, def); 101 for(i=0; i<nc; i++) { 102 if(debug['W']) 103 print("case = %.8ux\n", q->val); 104 while(q->val != v) { 105 nextpc(); 106 p->as = ABCASE; 107 patch(p, def); 108 v++; 109 } 110 nextpc(); 111 p->as = ABCASE; 112 patch(p, q->label); 113 q++; 114 v++; 115 } 116 gbranch(OGOTO); /* so that regopt() won't be confused */ 117 patch(p, def); 118 } 119 120 void 121 bitload(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 122 { 123 int sh; 124 int32 v; 125 Node *l; 126 127 /* 128 * n1 gets adjusted/masked value 129 * n2 gets address of cell 130 * n3 gets contents of cell 131 */ 132 l = b->left; 133 if(n2 != Z) { 134 regalloc(n1, l, nn); 135 reglcgen(n2, l, Z); 136 regalloc(n3, l, Z); 137 gopcode(OAS, n2, Z, n3); 138 gopcode(OAS, n3, Z, n1); 139 } else { 140 regalloc(n1, l, nn); 141 cgen(l, n1); 142 } 143 if(b->type->shift == 0 && typeu[b->type->etype]) { 144 v = ~0 + (1L << b->type->nbits); 145 gopcode(OAND, nodconst(v), Z, n1); 146 } else { 147 sh = 32 - b->type->shift - b->type->nbits; 148 if(sh > 0) 149 gopcode(OASHL, nodconst(sh), Z, n1); 150 sh += b->type->shift; 151 if(sh > 0) 152 if(typeu[b->type->etype]) 153 gopcode(OLSHR, nodconst(sh), Z, n1); 154 else 155 gopcode(OASHR, nodconst(sh), Z, n1); 156 } 157 } 158 159 void 160 bitstore(Node *b, Node *n1, Node *n2, Node *n3, Node *nn) 161 { 162 int32 v; 163 Node nod, *l; 164 int sh; 165 166 /* 167 * n1 has adjusted/masked value 168 * n2 has address of cell 169 * n3 has contents of cell 170 */ 171 l = b->left; 172 regalloc(&nod, l, Z); 173 v = ~0 + (1L << b->type->nbits); 174 gopcode(OAND, nodconst(v), Z, n1); 175 gopcode(OAS, n1, Z, &nod); 176 if(nn != Z) 177 gopcode(OAS, n1, Z, nn); 178 sh = b->type->shift; 179 if(sh > 0) 180 gopcode(OASHL, nodconst(sh), Z, &nod); 181 v <<= sh; 182 gopcode(OAND, nodconst(~v), Z, n3); 183 gopcode(OOR, n3, Z, &nod); 184 gopcode(OAS, &nod, Z, n2); 185 186 regfree(&nod); 187 regfree(n1); 188 regfree(n2); 189 regfree(n3); 190 } 191 192 int32 193 outstring(char *s, int32 n) 194 { 195 int32 r; 196 197 if(suppress) 198 return nstring; 199 r = nstring; 200 while(n) { 201 string[mnstring] = *s++; 202 mnstring++; 203 nstring++; 204 if(mnstring >= NSNAME) { 205 gpseudo(ADATA, symstring, nodconst(0L)); 206 p->from.offset += nstring - NSNAME; 207 p->reg = NSNAME; 208 p->to.type = D_SCONST; 209 memmove(p->to.sval, string, NSNAME); 210 mnstring = 0; 211 } 212 n--; 213 } 214 return r; 215 } 216 217 int 218 mulcon(Node *n, Node *nn) 219 { 220 Node *l, *r, nod1, nod2; 221 Multab *m; 222 int32 v, vs; 223 int o; 224 char code[sizeof(m->code)+2], *p; 225 226 if(typefd[n->type->etype]) 227 return 0; 228 l = n->left; 229 r = n->right; 230 if(l->op == OCONST) { 231 l = r; 232 r = n->left; 233 } 234 if(r->op != OCONST) 235 return 0; 236 v = convvtox(r->vconst, n->type->etype); 237 if(v != r->vconst) { 238 if(debug['M']) 239 print("%L multiply conv: %lld\n", n->lineno, r->vconst); 240 return 0; 241 } 242 m = mulcon0(v); 243 if(!m) { 244 if(debug['M']) 245 print("%L multiply table: %lld\n", n->lineno, r->vconst); 246 return 0; 247 } 248 if(debug['M'] && debug['v']) 249 print("%L multiply: %d\n", n->lineno, v); 250 251 memmove(code, m->code, sizeof(m->code)); 252 code[sizeof(m->code)] = 0; 253 254 p = code; 255 if(p[1] == 'i') 256 p += 2; 257 regalloc(&nod1, n, nn); 258 cgen(l, &nod1); 259 vs = v; 260 regalloc(&nod2, n, Z); 261 262 loop: 263 switch(*p) { 264 case 0: 265 regfree(&nod2); 266 if(vs < 0) { 267 gopcode(OAS, &nod1, Z, &nod1); 268 gopcode(OSUB, &nod1, nodconst(0), nn); 269 } else 270 gopcode(OAS, &nod1, Z, nn); 271 regfree(&nod1); 272 return 1; 273 case '+': 274 o = OADD; 275 goto addsub; 276 case '-': 277 o = OSUB; 278 addsub: /* number is r,n,l */ 279 v = p[1] - '0'; 280 r = &nod1; 281 if(v&4) 282 r = &nod2; 283 n = &nod1; 284 if(v&2) 285 n = &nod2; 286 l = &nod1; 287 if(v&1) 288 l = &nod2; 289 gopcode(o, l, n, r); 290 break; 291 default: /* op is shiftcount, number is r,l */ 292 v = p[1] - '0'; 293 r = &nod1; 294 if(v&2) 295 r = &nod2; 296 l = &nod1; 297 if(v&1) 298 l = &nod2; 299 v = *p - 'a'; 300 if(v < 0 || v >= 32) { 301 diag(n, "mulcon unknown op: %c%c", p[0], p[1]); 302 break; 303 } 304 gopcode(OASHL, nodconst(v), l, r); 305 break; 306 } 307 p += 2; 308 goto loop; 309 } 310 311 void 312 sextern(Sym *s, Node *a, int32 o, int32 w) 313 { 314 int32 e, lw; 315 316 for(e=0; e<w; e+=NSNAME) { 317 lw = NSNAME; 318 if(w-e < lw) 319 lw = w-e; 320 gpseudo(ADATA, s, nodconst(0)); 321 p->from.offset += o+e; 322 p->reg = lw; 323 p->to.type = D_SCONST; 324 memmove(p->to.sval, a->cstring+e, lw); 325 } 326 } 327 328 void 329 gextern(Sym *s, Node *a, int32 o, int32 w) 330 { 331 332 if(a->op == OCONST && typev[a->type->etype]) { 333 if(isbigendian) 334 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 335 else 336 gpseudo(ADATA, s, nod32const(a->vconst)); 337 p->from.offset += o; 338 p->reg = 4; 339 if(isbigendian) 340 gpseudo(ADATA, s, nod32const(a->vconst)); 341 else 342 gpseudo(ADATA, s, nod32const(a->vconst>>32)); 343 p->from.offset += o + 4; 344 p->reg = 4; 345 return; 346 } 347 gpseudo(ADATA, s, a); 348 p->from.offset += o; 349 p->reg = w; 350 if(p->to.type == D_OREG) 351 p->to.type = D_CONST; 352 } 353 354 void zname(Biobuf*, Sym*, int); 355 char* zaddr(char*, Adr*, int); 356 void zwrite(Biobuf*, Prog*, int, int); 357 void outhist(Biobuf*); 358 359 void 360 zwrite(Biobuf *b, Prog *p, int sf, int st) 361 { 362 char bf[100], *bp; 363 364 bf[0] = p->as; 365 bf[1] = p->scond; 366 bf[2] = p->reg; 367 bf[3] = p->lineno; 368 bf[4] = p->lineno>>8; 369 bf[5] = p->lineno>>16; 370 bf[6] = p->lineno>>24; 371 bp = zaddr(bf+7, &p->from, sf); 372 bp = zaddr(bp, &p->to, st); 373 Bwrite(b, bf, bp-bf); 374 } 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 395 Bprint(&outbuf, "go object %s %s %s\n", getgoos(), thestring, getgoversion()); 396 if(pragcgobuf.to > pragcgobuf.start) { 397 Bprint(&outbuf, "\n"); 398 Bprint(&outbuf, "$$ // exports\n\n"); 399 Bprint(&outbuf, "$$ // local types\n\n"); 400 Bprint(&outbuf, "$$ // cgo\n"); 401 Bprint(&outbuf, "%s", fmtstrflush(&pragcgobuf)); 402 Bprint(&outbuf, "\n$$\n\n"); 403 } 404 Bprint(&outbuf, "!\n"); 405 406 outhist(&outbuf); 407 for(sym=0; sym<NSYM; sym++) { 408 h[sym].sym = S; 409 h[sym].type = 0; 410 } 411 sym = 1; 412 for(p = firstp; p != P; p = p->link) { 413 jackpot: 414 sf = 0; 415 s = p->from.sym; 416 while(s != S) { 417 sf = s->sym; 418 if(sf < 0 || sf >= NSYM) 419 sf = 0; 420 t = p->from.name; 421 if(h[sf].type == t) 422 if(h[sf].sym == s) 423 break; 424 s->sym = sym; 425 zname(&outbuf, s, t); 426 h[sym].sym = s; 427 h[sym].type = t; 428 sf = sym; 429 sym++; 430 if(sym >= NSYM) 431 sym = 1; 432 break; 433 } 434 st = 0; 435 s = p->to.sym; 436 while(s != S) { 437 st = s->sym; 438 if(st < 0 || st >= NSYM) 439 st = 0; 440 t = p->to.name; 441 if(h[st].type == t) 442 if(h[st].sym == s) 443 break; 444 s->sym = sym; 445 zname(&outbuf, s, t); 446 h[sym].sym = s; 447 h[sym].type = t; 448 st = sym; 449 sym++; 450 if(sym >= NSYM) 451 sym = 1; 452 if(st == sf) 453 goto jackpot; 454 break; 455 } 456 zwrite(&outbuf, p, sf, st); 457 } 458 firstp = P; 459 lastp = P; 460 } 461 462 void 463 outhist(Biobuf *b) 464 { 465 Hist *h; 466 char *p, *q, *op, c; 467 Prog pg; 468 int n; 469 char *tofree; 470 static int first = 1; 471 static char *goroot, *goroot_final; 472 473 if(first) { 474 // Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL. 475 first = 0; 476 goroot = getenv("GOROOT"); 477 goroot_final = getenv("GOROOT_FINAL"); 478 if(goroot == nil) 479 goroot = ""; 480 if(goroot_final == nil) 481 goroot_final = goroot; 482 if(strcmp(goroot, goroot_final) == 0) { 483 goroot = nil; 484 goroot_final = nil; 485 } 486 } 487 488 tofree = nil; 489 pg = zprog; 490 pg.as = AHISTORY; 491 c = pathchar(); 492 for(h = hist; h != H; h = h->link) { 493 p = h->name; 494 if(p != nil && goroot != nil) { 495 n = strlen(goroot); 496 if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') { 497 tofree = smprint("%s%s", goroot_final, p+n); 498 p = tofree; 499 } 500 } 501 op = 0; 502 if(systemtype(Windows) && p && p[1] == ':'){ 503 c = p[2]; 504 } else if(p && p[0] != c && h->offset == 0 && pathname){ 505 if(systemtype(Windows) && pathname[1] == ':') { 506 op = p; 507 p = pathname; 508 c = p[2]; 509 } else if(pathname[0] == c){ 510 op = p; 511 p = pathname; 512 } 513 } 514 while(p) { 515 q = utfrune(p, c); 516 if(q) { 517 n = q-p; 518 if(n == 0){ 519 n = 1; /* leading "/" */ 520 *p = '/'; /* don't emit "\" on windows */ 521 } 522 q++; 523 } else { 524 n = strlen(p); 525 q = 0; 526 } 527 if(n) { 528 BPUTC(b, ANAME); 529 BPUTC(b, D_FILE); 530 BPUTC(b, 1); 531 BPUTC(b, '<'); 532 Bwrite(b, p, n); 533 BPUTC(b, 0); 534 } 535 p = q; 536 if(p == 0 && op) { 537 p = op; 538 op = 0; 539 } 540 } 541 pg.lineno = h->line; 542 pg.to.type = zprog.to.type; 543 pg.to.offset = h->offset; 544 if(h->offset) 545 pg.to.type = D_CONST; 546 547 zwrite(b, &pg, 0, 0); 548 549 if(tofree) { 550 free(tofree); 551 tofree = nil; 552 } 553 } 554 } 555 556 void 557 zname(Biobuf *b, Sym *s, int t) 558 { 559 char *n, bf[7]; 560 uint32 sig; 561 562 n = s->name; 563 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ 564 sig = sign(s); 565 bf[0] = ASIGNAME; 566 bf[1] = sig; 567 bf[2] = sig>>8; 568 bf[3] = sig>>16; 569 bf[4] = sig>>24; 570 bf[5] = t; 571 bf[6] = s->sym; 572 Bwrite(b, bf, 7); 573 s->sig = SIGDONE; 574 } 575 else{ 576 bf[0] = ANAME; 577 bf[1] = t; /* type */ 578 bf[2] = s->sym; /* sym */ 579 Bwrite(b, bf, 3); 580 } 581 Bwrite(b, n, strlen(n)+1); 582 } 583 584 char* 585 zaddr(char *bp, Adr *a, int s) 586 { 587 int32 l; 588 Ieee e; 589 590 bp[0] = a->type; 591 bp[1] = a->reg; 592 bp[2] = s; 593 bp[3] = a->name; 594 bp[4] = 0; 595 bp += 5; 596 switch(a->type) { 597 default: 598 diag(Z, "unknown type %d in zaddr", a->type); 599 600 case D_NONE: 601 case D_REG: 602 case D_FREG: 603 case D_PSR: 604 break; 605 606 case D_CONST2: 607 l = a->offset2; 608 bp[0] = l; 609 bp[1] = l>>8; 610 bp[2] = l>>16; 611 bp[3] = l>>24; 612 bp += 4; // fall through 613 case D_OREG: 614 case D_CONST: 615 case D_BRANCH: 616 case D_SHIFT: 617 l = a->offset; 618 bp[0] = l; 619 bp[1] = l>>8; 620 bp[2] = l>>16; 621 bp[3] = l>>24; 622 bp += 4; 623 break; 624 625 case D_SCONST: 626 memmove(bp, a->sval, NSNAME); 627 bp += NSNAME; 628 break; 629 630 case D_FCONST: 631 ieeedtod(&e, a->dval); 632 l = e.l; 633 bp[0] = l; 634 bp[1] = l>>8; 635 bp[2] = l>>16; 636 bp[3] = l>>24; 637 bp += 4; 638 l = e.h; 639 bp[0] = l; 640 bp[1] = l>>8; 641 bp[2] = l>>16; 642 bp[3] = l>>24; 643 bp += 4; 644 break; 645 } 646 return bp; 647 } 648 649 int32 650 align(int32 i, Type *t, int op, int32 *maxalign) 651 { 652 int32 o; 653 Type *v; 654 int w; 655 656 o = i; 657 w = 1; 658 switch(op) { 659 default: 660 diag(Z, "unknown align opcode %d", op); 661 break; 662 663 case Asu2: /* padding at end of a struct */ 664 w = *maxalign; 665 if(w < 1) 666 w = 1; 667 if(packflg) 668 w = packflg; 669 break; 670 671 case Ael1: /* initial align of struct element */ 672 for(v=t; v->etype==TARRAY; v=v->link) 673 ; 674 if(v->etype == TSTRUCT || v->etype == TUNION) 675 w = v->align; 676 else { 677 w = ewidth[v->etype]; 678 if(w == 8) 679 w = 4; 680 } 681 if(w < 1 || w > SZ_LONG) 682 fatal(Z, "align"); 683 if(packflg) 684 w = packflg; 685 break; 686 687 case Ael2: /* width of a struct element */ 688 o += t->width; 689 break; 690 691 case Aarg0: /* initial passbyptr argument in arg list */ 692 if(typesuv[t->etype]) { 693 o = align(o, types[TIND], Aarg1, nil); 694 o = align(o, types[TIND], Aarg2, nil); 695 } 696 break; 697 698 case Aarg1: /* initial align of parameter */ 699 w = ewidth[t->etype]; 700 if(w <= 0 || w >= SZ_LONG) { 701 w = SZ_LONG; 702 break; 703 } 704 w = 1; /* little endian no adjustment */ 705 break; 706 707 case Aarg2: /* width of a parameter */ 708 o += t->width; 709 w = t->width; 710 if(w > SZ_LONG) 711 w = SZ_LONG; 712 break; 713 714 case Aaut3: /* total align of automatic */ 715 o = align(o, t, Ael2, nil); 716 o = align(o, t, Ael1, nil); 717 w = SZ_LONG; /* because of a pun in cc/dcl.c:contig() */ 718 break; 719 } 720 o = xround(o, w); 721 if(maxalign != nil && *maxalign < w) 722 *maxalign = w; 723 if(debug['A']) 724 print("align %s %d %T = %d\n", bnames[op], i, t, o); 725 return o; 726 } 727 728 int32 729 maxround(int32 max, int32 v) 730 { 731 v = xround(v, SZ_LONG); 732 if(v > max) 733 return v; 734 return max; 735 }