github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/cmd/6g/gobj.c (about) 1 // Derived from 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 <u.h> 32 #include <libc.h> 33 #include "gg.h" 34 35 void 36 zname(Biobuf *b, Sym *s, int t) 37 { 38 Bputc(b, ANAME); /* as */ 39 Bputc(b, ANAME>>8); /* as */ 40 Bputc(b, t); /* type */ 41 Bputc(b, s->sym); /* sym */ 42 43 Bputname(b, s); 44 } 45 46 void 47 zfile(Biobuf *b, char *p, int n) 48 { 49 Bputc(b, ANAME); 50 Bputc(b, ANAME>>8); 51 Bputc(b, D_FILE); 52 Bputc(b, 1); 53 Bputc(b, '<'); 54 Bwrite(b, p, n); 55 Bputc(b, 0); 56 } 57 58 void 59 zhist(Biobuf *b, int line, vlong offset) 60 { 61 Addr a; 62 63 Bputc(b, AHISTORY); 64 Bputc(b, AHISTORY>>8); 65 Bputc(b, line); 66 Bputc(b, line>>8); 67 Bputc(b, line>>16); 68 Bputc(b, line>>24); 69 zaddr(b, &zprog.from, 0, 0); 70 a = zprog.to; 71 if(offset != 0) { 72 a.offset = offset; 73 a.type = D_CONST; 74 } 75 zaddr(b, &a, 0, 0); 76 } 77 78 void 79 zaddr(Biobuf *b, Addr *a, int s, int gotype) 80 { 81 int32 l; 82 uint64 e; 83 int i, t; 84 char *n; 85 86 t = 0; 87 if(a->index != D_NONE || a->scale != 0) 88 t |= T_INDEX; 89 if(s != 0) 90 t |= T_SYM; 91 if(gotype != 0) 92 t |= T_GOTYPE; 93 94 switch(a->type) { 95 96 case D_BRANCH: 97 if(a->u.branch == nil) 98 fatal("unpatched branch"); 99 a->offset = a->u.branch->loc; 100 101 default: 102 t |= T_TYPE; 103 104 case D_NONE: 105 if(a->offset != 0) { 106 t |= T_OFFSET; 107 l = a->offset; 108 if((vlong)l != a->offset) 109 t |= T_64; 110 } 111 break; 112 case D_FCONST: 113 t |= T_FCONST; 114 break; 115 case D_SCONST: 116 t |= T_SCONST; 117 break; 118 } 119 Bputc(b, t); 120 121 if(t & T_INDEX) { /* implies index, scale */ 122 Bputc(b, a->index); 123 Bputc(b, a->scale); 124 } 125 if(t & T_OFFSET) { /* implies offset */ 126 l = a->offset; 127 Bputc(b, l); 128 Bputc(b, l>>8); 129 Bputc(b, l>>16); 130 Bputc(b, l>>24); 131 if(t & T_64) { 132 l = a->offset>>32; 133 Bputc(b, l); 134 Bputc(b, l>>8); 135 Bputc(b, l>>16); 136 Bputc(b, l>>24); 137 } 138 } 139 if(t & T_SYM) /* implies sym */ 140 Bputc(b, s); 141 if(t & T_FCONST) { 142 ieeedtod(&e, a->u.dval); 143 l = e; 144 Bputc(b, l); 145 Bputc(b, l>>8); 146 Bputc(b, l>>16); 147 Bputc(b, l>>24); 148 l = e >> 32; 149 Bputc(b, l); 150 Bputc(b, l>>8); 151 Bputc(b, l>>16); 152 Bputc(b, l>>24); 153 return; 154 } 155 if(t & T_SCONST) { 156 n = a->u.sval; 157 for(i=0; i<NSNAME; i++) { 158 Bputc(b, *n); 159 n++; 160 } 161 return; 162 } 163 if(t & T_TYPE) 164 Bputc(b, a->type); 165 if(t & T_GOTYPE) 166 Bputc(b, gotype); 167 } 168 169 static struct { 170 struct { Sym *sym; short type; } h[NSYM]; 171 int sym; 172 } z; 173 174 static void 175 zsymreset(void) 176 { 177 for(z.sym=0; z.sym<NSYM; z.sym++) { 178 z.h[z.sym].sym = S; 179 z.h[z.sym].type = 0; 180 } 181 z.sym = 1; 182 } 183 184 static int 185 zsym(Sym *s, int t, int *new) 186 { 187 int i; 188 189 *new = 0; 190 if(s == S) 191 return 0; 192 193 i = s->sym; 194 if(i < 0 || i >= NSYM) 195 i = 0; 196 if(z.h[i].type == t && z.h[i].sym == s) 197 return i; 198 i = z.sym; 199 s->sym = i; 200 zname(bout, s, t); 201 z.h[i].sym = s; 202 z.h[i].type = t; 203 if(++z.sym >= NSYM) 204 z.sym = 1; 205 *new = 1; 206 return i; 207 } 208 209 static int 210 zsymaddr(Addr *a, int *new) 211 { 212 int t; 213 214 t = a->type; 215 if(t == D_ADDR) 216 t = a->index; 217 return zsym(a->sym, t, new); 218 } 219 220 void 221 dumpfuncs(void) 222 { 223 Plist *pl; 224 int sf, st, gf, gt, new; 225 Sym *s; 226 Prog *p; 227 228 zsymreset(); 229 230 // fix up pc 231 pcloc = 0; 232 for(pl=plist; pl!=nil; pl=pl->link) { 233 if(isblank(pl->name)) 234 continue; 235 for(p=pl->firstpc; p!=P; p=p->link) { 236 p->loc = pcloc; 237 if(p->as != ADATA && p->as != AGLOBL) 238 pcloc++; 239 } 240 } 241 242 // put out functions 243 for(pl=plist; pl!=nil; pl=pl->link) { 244 if(isblank(pl->name)) 245 continue; 246 247 // -S prints code; -SS prints code and data 248 if(debug['S'] && (pl->name || debug['S']>1)) { 249 s = S; 250 if(pl->name != N) 251 s = pl->name->sym; 252 print("\n--- prog list \"%S\" ---\n", s); 253 for(p=pl->firstpc; p!=P; p=p->link) 254 print("%P\n", p); 255 } 256 257 for(p=pl->firstpc; p!=P; p=p->link) { 258 for(;;) { 259 sf = zsymaddr(&p->from, &new); 260 gf = zsym(p->from.gotype, D_EXTERN, &new); 261 if(new && sf == gf) 262 continue; 263 st = zsymaddr(&p->to, &new); 264 if(new && (st == sf || st == gf)) 265 continue; 266 gt = zsym(p->to.gotype, D_EXTERN, &new); 267 if(new && (gt == sf || gt == gf || gt == st)) 268 continue; 269 break; 270 } 271 272 Bputc(bout, p->as); 273 Bputc(bout, p->as>>8); 274 Bputc(bout, p->lineno); 275 Bputc(bout, p->lineno>>8); 276 Bputc(bout, p->lineno>>16); 277 Bputc(bout, p->lineno>>24); 278 zaddr(bout, &p->from, sf, gf); 279 zaddr(bout, &p->to, st, gt); 280 } 281 } 282 } 283 284 int 285 dsname(Sym *s, int off, char *t, int n) 286 { 287 Prog *p; 288 289 p = gins(ADATA, N, N); 290 p->from.type = D_EXTERN; 291 p->from.index = D_NONE; 292 p->from.offset = off; 293 p->from.scale = n; 294 p->from.sym = s; 295 296 p->to.type = D_SCONST; 297 p->to.index = D_NONE; 298 memmove(p->to.u.sval, t, n); 299 return off + n; 300 } 301 302 /* 303 * make a refer to the data s, s+len 304 * emitting DATA if needed. 305 */ 306 void 307 datastring(char *s, int len, Addr *a) 308 { 309 Sym *sym; 310 311 sym = stringsym(s, len); 312 a->type = D_EXTERN; 313 a->sym = sym; 314 a->node = sym->def; 315 a->offset = widthptr+widthint; // skip header 316 a->etype = simtype[TINT]; 317 } 318 319 /* 320 * make a refer to the string sval, 321 * emitting DATA if needed. 322 */ 323 void 324 datagostring(Strlit *sval, Addr *a) 325 { 326 Sym *sym; 327 328 sym = stringsym(sval->s, sval->len); 329 a->type = D_EXTERN; 330 a->sym = sym; 331 a->node = sym->def; 332 a->offset = 0; // header 333 a->etype = TINT32; 334 } 335 336 void 337 gdata(Node *nam, Node *nr, int wid) 338 { 339 Prog *p; 340 341 if(nr->op == OLITERAL) { 342 switch(nr->val.ctype) { 343 case CTCPLX: 344 gdatacomplex(nam, nr->val.u.cval); 345 return; 346 case CTSTR: 347 gdatastring(nam, nr->val.u.sval); 348 return; 349 } 350 } 351 p = gins(ADATA, nam, nr); 352 p->from.scale = wid; 353 } 354 355 void 356 gdatacomplex(Node *nam, Mpcplx *cval) 357 { 358 Prog *p; 359 int w; 360 361 w = cplxsubtype(nam->type->etype); 362 w = types[w]->width; 363 364 p = gins(ADATA, nam, N); 365 p->from.scale = w; 366 p->to.type = D_FCONST; 367 p->to.u.dval = mpgetflt(&cval->real); 368 369 p = gins(ADATA, nam, N); 370 p->from.scale = w; 371 p->from.offset += w; 372 p->to.type = D_FCONST; 373 p->to.u.dval = mpgetflt(&cval->imag); 374 } 375 376 void 377 gdatastring(Node *nam, Strlit *sval) 378 { 379 Prog *p; 380 Node nod1; 381 382 p = gins(ADATA, nam, N); 383 datastring(sval->s, sval->len, &p->to); 384 p->from.scale = types[tptr]->width; 385 p->to.index = p->to.type; 386 p->to.type = D_ADDR; 387 //print("%P\n", p); 388 389 nodconst(&nod1, types[TINT], sval->len); 390 p = gins(ADATA, nam, &nod1); 391 p->from.scale = widthint; 392 p->from.offset += widthptr; 393 } 394 395 int 396 dstringptr(Sym *s, int off, char *str) 397 { 398 Prog *p; 399 400 off = rnd(off, widthptr); 401 p = gins(ADATA, N, N); 402 p->from.type = D_EXTERN; 403 p->from.index = D_NONE; 404 p->from.sym = s; 405 p->from.offset = off; 406 p->from.scale = widthptr; 407 408 datastring(str, strlen(str)+1, &p->to); 409 p->to.index = p->to.type; 410 p->to.type = D_ADDR; 411 p->to.etype = simtype[TINT]; 412 off += widthptr; 413 414 return off; 415 } 416 417 int 418 dgostrlitptr(Sym *s, int off, Strlit *lit) 419 { 420 Prog *p; 421 422 if(lit == nil) 423 return duintptr(s, off, 0); 424 425 off = rnd(off, widthptr); 426 p = gins(ADATA, N, N); 427 p->from.type = D_EXTERN; 428 p->from.index = D_NONE; 429 p->from.sym = s; 430 p->from.offset = off; 431 p->from.scale = widthptr; 432 datagostring(lit, &p->to); 433 p->to.index = p->to.type; 434 p->to.type = D_ADDR; 435 p->to.etype = simtype[TINT]; 436 off += widthptr; 437 438 return off; 439 } 440 441 int 442 dgostringptr(Sym *s, int off, char *str) 443 { 444 int n; 445 Strlit *lit; 446 447 if(str == nil) 448 return duintptr(s, off, 0); 449 450 n = strlen(str); 451 lit = mal(sizeof *lit + n); 452 strcpy(lit->s, str); 453 lit->len = n; 454 return dgostrlitptr(s, off, lit); 455 } 456 457 int 458 duintxx(Sym *s, int off, uint64 v, int wid) 459 { 460 Prog *p; 461 462 off = rnd(off, wid); 463 464 p = gins(ADATA, N, N); 465 p->from.type = D_EXTERN; 466 p->from.index = D_NONE; 467 p->from.sym = s; 468 p->from.offset = off; 469 p->from.scale = wid; 470 p->to.type = D_CONST; 471 p->to.index = D_NONE; 472 p->to.offset = v; 473 off += wid; 474 475 return off; 476 } 477 478 int 479 dsymptr(Sym *s, int off, Sym *x, int xoff) 480 { 481 Prog *p; 482 483 off = rnd(off, widthptr); 484 485 p = gins(ADATA, N, N); 486 p->from.type = D_EXTERN; 487 p->from.index = D_NONE; 488 p->from.sym = s; 489 p->from.offset = off; 490 p->from.scale = widthptr; 491 p->to.type = D_ADDR; 492 p->to.index = D_EXTERN; 493 p->to.sym = x; 494 p->to.offset = xoff; 495 off += widthptr; 496 497 return off; 498 } 499 500 void 501 genembedtramp(Type *rcvr, Type *method, Sym *newnam, int iface) 502 { 503 Sym *e; 504 int c, d, mov, add, loaded; 505 int64 o; 506 Prog *p; 507 Type *f; 508 509 USED(iface); 510 511 if(0 && debug['r']) 512 print("genembedtramp %T %T %S\n", rcvr, method, newnam); 513 514 e = method->sym; 515 for(d=0; d<nelem(dotlist); d++) { 516 c = adddot1(e, rcvr, d, nil, 0); 517 if(c == 1) 518 goto out; 519 } 520 fatal("genembedtramp %T.%S", rcvr, method->sym); 521 522 out: 523 newplist()->name = newname(newnam); 524 525 //TEXT main·S_test2(SB),7,$0 526 p = pc; 527 gins(ATEXT, N, N); 528 p->from.type = D_EXTERN; 529 p->from.sym = newnam; 530 p->to.type = D_CONST; 531 p->to.offset = 0; 532 p->from.scale = 7; 533 //print("1. %P\n", p); 534 535 mov = AMOVQ; 536 add = AADDQ; 537 loaded = 0; 538 o = 0; 539 for(c=d-1; c>=0; c--) { 540 f = dotlist[c].field; 541 o += f->width; 542 if(!isptr[f->type->etype]) 543 continue; 544 if(!loaded) { 545 loaded = 1; 546 //MOVQ 8(SP), AX 547 p = pc; 548 gins(mov, N, N); 549 p->from.type = D_INDIR+D_SP; 550 p->from.offset = widthptr; 551 p->to.type = D_AX; 552 //print("2. %P\n", p); 553 } 554 555 //MOVQ o(AX), AX 556 p = pc; 557 gins(mov, N, N); 558 p->from.type = D_INDIR+D_AX; 559 p->from.offset = o; 560 p->to.type = D_AX; 561 //print("3. %P\n", p); 562 o = 0; 563 } 564 if(o != 0) { 565 //ADDQ $XX, AX 566 p = pc; 567 gins(add, N, N); 568 p->from.type = D_CONST; 569 p->from.offset = o; 570 if(loaded) 571 p->to.type = D_AX; 572 else { 573 p->to.type = D_INDIR+D_SP; 574 p->to.offset = widthptr; 575 } 576 //print("4. %P\n", p); 577 } 578 579 //MOVQ AX, 8(SP) 580 if(loaded) { 581 p = pc; 582 gins(mov, N, N); 583 p->from.type = D_AX; 584 p->to.type = D_INDIR+D_SP; 585 p->to.offset = widthptr; 586 //print("5. %P\n", p); 587 } else { 588 // TODO(rsc): obviously this is unnecessary, 589 // but 6l has a bug, and it can't handle 590 // JMP instructions too close to the top of 591 // a new function. 592 gins(ANOP, N, N); 593 } 594 595 f = dotlist[0].field; 596 //JMP main·*Sub_test2(SB) 597 if(isptr[f->type->etype]) 598 f = f->type; 599 p = pc; 600 gins(AJMP, N, N); 601 p->to.type = D_EXTERN; 602 p->to.sym = methodsym(method->sym, ptrto(f->type), 0); 603 //print("6. %P\n", p); 604 605 pc->as = ARET; // overwrite AEND 606 } 607 608 void 609 nopout(Prog *p) 610 { 611 p->as = ANOP; 612 } 613