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