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