PageRenderTime 59ms CodeModel.GetById 28ms RepoModel.GetById 1ms app.codeStats 0ms

/src/cmd/8g/gobj.c

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