github.com/rohankumardubey/syslog-redirector-golang@v0.0.0-20140320174030-4859f03d829a/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 BPUTLE2(&b, p->as); 315 BPUTLE4(&b, p->lineno); 316 zaddr(&b, &p->from, sf); 317 zaddr(&b, &p->to, st); 318 } 319 Bterm(&b); 320 close(f); 321 firstp = P; 322 lastp = P; 323 } 324 325 void 326 outhist(Biobuf *b) 327 { 328 Hist *h; 329 char *p, *q, *op, c; 330 Prog pg; 331 int n; 332 char *tofree; 333 static int first = 1; 334 static char *goroot, *goroot_final; 335 336 if(first) { 337 // Decide whether we need to rewrite paths from $GOROOT to $GOROOT_FINAL. 338 first = 0; 339 goroot = getenv("GOROOT"); 340 goroot_final = getenv("GOROOT_FINAL"); 341 if(goroot == nil) 342 goroot = ""; 343 if(goroot_final == nil) 344 goroot_final = goroot; 345 if(strcmp(goroot, goroot_final) == 0) { 346 goroot = nil; 347 goroot_final = nil; 348 } 349 } 350 351 tofree = nil; 352 pg = zprog; 353 pg.as = AHISTORY; 354 c = pathchar(); 355 for(h = hist; h != H; h = h->link) { 356 p = h->name; 357 if(p != nil && goroot != nil) { 358 n = strlen(goroot); 359 if(strncmp(p, goroot, strlen(goroot)) == 0 && p[n] == '/') { 360 tofree = smprint("%s%s", goroot_final, p+n); 361 p = tofree; 362 } 363 } 364 op = 0; 365 if(systemtype(Windows) && p && p[1] == ':'){ 366 c = p[2]; 367 } else if(p && p[0] != c && h->offset == 0 && pathname){ 368 if(systemtype(Windows) && pathname[1] == ':') { 369 op = p; 370 p = pathname; 371 c = p[2]; 372 } else if(pathname[0] == c){ 373 op = p; 374 p = pathname; 375 } 376 } 377 while(p) { 378 q = utfrune(p, c); 379 if(q) { 380 n = q-p; 381 if(n == 0){ 382 n = 1; /* leading "/" */ 383 *p = '/'; /* don't emit "\" on windows */ 384 } 385 q++; 386 } else { 387 n = strlen(p); 388 q = 0; 389 } 390 if(n) { 391 BPUTLE2(b, ANAME); 392 BPUTC(b, D_FILE); 393 BPUTC(b, 1); 394 BPUTC(b, '<'); 395 Bwrite(b, p, n); 396 BPUTC(b, 0); 397 } 398 p = q; 399 if(p == 0 && op) { 400 p = op; 401 op = 0; 402 } 403 } 404 pg.lineno = h->line; 405 pg.to.type = zprog.to.type; 406 pg.to.offset = h->offset; 407 if(h->offset) 408 pg.to.type = D_CONST; 409 410 BPUTLE2(b, pg.as); 411 BPUTLE4(b, pg.lineno); 412 zaddr(b, &pg.from, 0); 413 zaddr(b, &pg.to, 0); 414 415 if(tofree) { 416 free(tofree); 417 tofree = nil; 418 } 419 } 420 } 421 422 void 423 zname(Biobuf *b, Sym *s, int t) 424 { 425 char *n; 426 uint32 sig; 427 428 if(debug['T'] && t == D_EXTERN && s->sig != SIGDONE && s->type != types[TENUM] && s != symrathole){ 429 sig = sign(s); 430 BPUTLE2(b, ASIGNAME); 431 BPUTLE4(b, sig); 432 s->sig = SIGDONE; 433 } 434 else{ 435 BPUTLE2(b, ANAME); /* as */ 436 } 437 BPUTC(b, t); /* type */ 438 BPUTC(b, s->sym); /* sym */ 439 n = s->name; 440 while(*n) { 441 BPUTC(b, *n); 442 n++; 443 } 444 BPUTC(b, 0); 445 } 446 447 void 448 zaddr(Biobuf *b, Adr *a, int s) 449 { 450 int32 l; 451 int i, t; 452 char *n; 453 Ieee e; 454 455 t = 0; 456 if(a->index != D_NONE || a->scale != 0) 457 t |= T_INDEX; 458 if(s != 0) 459 t |= T_SYM; 460 461 switch(a->type) { 462 default: 463 t |= T_TYPE; 464 case D_NONE: 465 if(a->offset != 0) { 466 t |= T_OFFSET; 467 l = a->offset; 468 if((vlong)l != a->offset) 469 t |= T_64; 470 } 471 break; 472 case D_FCONST: 473 t |= T_FCONST; 474 break; 475 case D_SCONST: 476 t |= T_SCONST; 477 break; 478 } 479 BPUTC(b, t); 480 481 if(t & T_INDEX) { /* implies index, scale */ 482 BPUTC(b, a->index); 483 BPUTC(b, a->scale); 484 } 485 if(t & T_OFFSET) { /* implies offset */ 486 l = a->offset; 487 BPUTLE4(b, l); 488 if(t & T_64) { 489 l = a->offset>>32; 490 BPUTLE4(b, l); 491 } 492 } 493 if(t & T_SYM) /* implies sym */ 494 BPUTC(b, s); 495 if(t & T_FCONST) { 496 ieeedtod(&e, a->dval); 497 l = e.l; 498 BPUTLE4(b, l); 499 l = e.h; 500 BPUTLE4(b, l); 501 return; 502 } 503 if(t & T_SCONST) { 504 n = a->sval; 505 for(i=0; i<NSNAME; i++) { 506 BPUTC(b, *n); 507 n++; 508 } 509 return; 510 } 511 if(t & T_TYPE) 512 BPUTC(b, a->type); 513 } 514 515 int32 516 align(int32 i, Type *t, int op, int32 *maxalign) 517 { 518 int32 o; 519 Type *v; 520 int w; 521 522 o = i; 523 w = 1; 524 switch(op) { 525 default: 526 diag(Z, "unknown align opcode %d", op); 527 break; 528 529 case Asu2: /* padding at end of a struct */ 530 w = *maxalign; 531 if(w < 1) 532 w = 1; 533 if(packflg) 534 w = packflg; 535 break; 536 537 case Ael1: /* initial align of struct element */ 538 for(v=t; v->etype==TARRAY; v=v->link) 539 ; 540 if(v->etype == TSTRUCT || v->etype == TUNION) 541 w = v->align; 542 else 543 w = ewidth[v->etype]; 544 if(w < 1 || w > SZ_VLONG) 545 fatal(Z, "align"); 546 if(packflg) 547 w = packflg; 548 break; 549 550 case Ael2: /* width of a struct element */ 551 o += t->width; 552 break; 553 554 case Aarg0: /* initial passbyptr argument in arg list */ 555 if(typesu[t->etype]) { 556 o = align(o, types[TIND], Aarg1, nil); 557 o = align(o, types[TIND], Aarg2, nil); 558 } 559 break; 560 561 case Aarg1: /* initial align of parameter */ 562 w = ewidth[t->etype]; 563 if(w <= 0 || w >= SZ_VLONG) { 564 w = SZ_VLONG; 565 break; 566 } 567 w = 1; /* little endian no adjustment */ 568 break; 569 570 case Aarg2: /* width of a parameter */ 571 o += t->width; 572 w = t->width; 573 if(w > SZ_VLONG) 574 w = SZ_VLONG; 575 break; 576 577 case Aaut3: /* total align of automatic */ 578 o = align(o, t, Ael1, nil); 579 o = align(o, t, Ael2, nil); 580 break; 581 } 582 o = xround(o, w); 583 if(maxalign && *maxalign < w) 584 *maxalign = w; 585 if(debug['A']) 586 print("align %s %d %T = %d\n", bnames[op], i, t, o); 587 return o; 588 } 589 590 int32 591 maxround(int32 max, int32 v) 592 { 593 v = xround(v, SZ_VLONG); 594 if(v > max) 595 return v; 596 return max; 597 }