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