LEFT | RIGHT |
(no file at all) | |
1 // Copyright 2011 The Go Authors. All rights reserved. | 1 // Copyright 2011 The Go Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style | 2 // Use of this source code is governed by a BSD-style |
3 // license that can be found in the LICENSE file. | 3 // license that can be found in the LICENSE file. |
4 | 4 |
5 #include <u.h> | 5 #include <u.h> |
6 #include <libc.h> | 6 #include <libc.h> |
7 #include "gg.h" | 7 #include "gg.h" |
8 #include "opt.h" | 8 #include "opt.h" |
9 #include "../../pkg/runtime/funcdata.h" | 9 #include "../../pkg/runtime/funcdata.h" |
10 | 10 |
11 static void allocauto(Prog* p); | 11 static void allocauto(Prog* p); |
12 static int pointermap(Sym*, int, Node*); | 12 static void dumpgcargs(Node*, Sym*); |
13 static void gcsymbol(Sym*, Node*); | 13 static void dumpgclocals(Node*, Sym*); |
14 | 14 |
15 void | 15 void |
16 compile(Node *fn) | 16 compile(Node *fn) |
17 { | 17 { |
18 Plist *pl; | 18 Plist *pl; |
19 » Node nod1, *n, *gcnod; | 19 » Node nod1, *n, *gcargsnod, *gclocalsnod; |
20 Prog *ptxt, *p, *p1; | 20 Prog *ptxt, *p, *p1; |
21 int32 lno; | 21 int32 lno; |
22 Type *t; | 22 Type *t; |
23 Iter save; | 23 Iter save; |
24 vlong oldstksize; | 24 vlong oldstksize; |
25 NodeList *l; | 25 NodeList *l; |
26 » Sym *gcsym; | 26 » Sym *gcargssym, *gclocalssym; |
27 » static int ngcsym; | 27 » static int ngcargs, ngclocals; |
28 | 28 |
29 if(newproc == N) { | 29 if(newproc == N) { |
30 newproc = sysfunc("newproc"); | 30 newproc = sysfunc("newproc"); |
31 deferproc = sysfunc("deferproc"); | 31 deferproc = sysfunc("deferproc"); |
32 deferreturn = sysfunc("deferreturn"); | 32 deferreturn = sysfunc("deferreturn"); |
33 panicindex = sysfunc("panicindex"); | 33 panicindex = sysfunc("panicindex"); |
34 panicslice = sysfunc("panicslice"); | 34 panicslice = sysfunc("panicslice"); |
35 throwreturn = sysfunc("throwreturn"); | 35 throwreturn = sysfunc("throwreturn"); |
36 } | 36 } |
37 | 37 |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 setlineno(curfn); | 86 setlineno(curfn); |
87 | 87 |
88 nodconst(&nod1, types[TINT32], 0); | 88 nodconst(&nod1, types[TINT32], 0); |
89 ptxt = gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1); | 89 ptxt = gins(ATEXT, isblank(curfn->nname) ? N : curfn->nname, &nod1); |
90 if(fn->dupok) | 90 if(fn->dupok) |
91 ptxt->TEXTFLAG = DUPOK; | 91 ptxt->TEXTFLAG = DUPOK; |
92 afunclit(&ptxt->from, curfn->nname); | 92 afunclit(&ptxt->from, curfn->nname); |
93 | 93 |
94 ginit(); | 94 ginit(); |
95 | 95 |
96 » snprint(namebuf, sizeof namebuf, "gc·%d", ngcsym++); | 96 » snprint(namebuf, sizeof namebuf, "gcargs·%d", ngcargs++); |
97 » gcsym = lookup(namebuf); | 97 » gcargssym = lookup(namebuf); |
98 » gcnod = newname(gcsym); | 98 » gcargsnod = newname(gcargssym); |
99 » gcnod->class = PEXTERN; | 99 » gcargsnod->class = PEXTERN; |
100 | 100 |
101 » nodconst(&nod1, types[TINT32], FUNCDATA_GC); | 101 » nodconst(&nod1, types[TINT32], FUNCDATA_GCArgs); |
102 » gins(AFUNCDATA, &nod1, gcnod); | 102 » gins(AFUNCDATA, &nod1, gcargsnod); |
| 103 |
| 104 » snprint(namebuf, sizeof(namebuf), "gclocals·%d", ngclocals++); |
| 105 » gclocalssym = lookup(namebuf); |
| 106 » gclocalsnod = newname(gclocalssym); |
| 107 » gclocalsnod->class = PEXTERN; |
| 108 |
| 109 » nodconst(&nod1, types[TINT32], FUNCDATA_GCLocals); |
| 110 » gins(AFUNCDATA, &nod1, gclocalsnod); |
103 | 111 |
104 for(t=curfn->paramfld; t; t=t->down) | 112 for(t=curfn->paramfld; t; t=t->down) |
105 gtrack(tracksym(t->type)); | 113 gtrack(tracksym(t->type)); |
106 | 114 |
107 for(l=fn->dcl; l; l=l->next) { | 115 for(l=fn->dcl; l; l=l->next) { |
108 n = l->n; | 116 n = l->n; |
109 if(n->op != ONAME) // might be OTYPE or OLITERAL | 117 if(n->op != ONAME) // might be OTYPE or OLITERAL |
110 continue; | 118 continue; |
111 switch(n->class) { | 119 switch(n->class) { |
112 case PAUTO: | 120 case PAUTO: |
(...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
152 | 160 |
153 pc->as = ARET; // overwrite AEND | 161 pc->as = ARET; // overwrite AEND |
154 pc->lineno = lineno; | 162 pc->lineno = lineno; |
155 | 163 |
156 if(!debug['N'] || debug['R'] || debug['P']) { | 164 if(!debug['N'] || debug['R'] || debug['P']) { |
157 regopt(ptxt); | 165 regopt(ptxt); |
158 } | 166 } |
159 | 167 |
160 oldstksize = stksize; | 168 oldstksize = stksize; |
161 allocauto(ptxt); | 169 allocauto(ptxt); |
162 ········ | |
163 // Emit garbage collection symbol. | |
164 gcsymbol(gcsym, fn); | |
165 | 170 |
166 if(0) | 171 if(0) |
167 print("allocauto: %lld to %lld\n", oldstksize, (vlong)stksize); | 172 print("allocauto: %lld to %lld\n", oldstksize, (vlong)stksize); |
168 | 173 |
169 setlineno(curfn); | 174 setlineno(curfn); |
170 » if((int64)stksize+maxarg > (1ULL<<31)) | 175 » if((int64)stksize+maxarg > (1ULL<<31)) { |
171 yyerror("stack frame too large (>2GB)"); | 176 yyerror("stack frame too large (>2GB)"); |
| 177 goto ret; |
| 178 } |
172 | 179 |
173 defframe(ptxt); | 180 defframe(ptxt); |
174 | 181 |
175 if(0) | 182 if(0) |
176 frame(0); | 183 frame(0); |
177 | 184 |
| 185 // Emit garbage collection symbols. |
| 186 dumpgcargs(fn, gcargssym); |
| 187 dumpgclocals(curfn, gclocalssym); |
| 188 |
178 ret: | 189 ret: |
179 lineno = lno; | 190 lineno = lno; |
180 } | |
181 | |
182 static void | |
183 gcsymbol(Sym *gcsym, Node *fn) | |
184 { | |
185 int off; | |
186 | |
187 off = 0; | |
188 off = duint32(gcsym, off, stksize); // size of local block | |
189 off = pointermap(gcsym, off, fn); // pointer bitmap for args (must be la
st) | |
190 ggloblsym(gcsym, off, 0, 1); | |
191 } | 191 } |
192 | 192 |
193 static void | 193 static void |
194 walktype1(Type *t, vlong *xoffset, Bvec *bv) | 194 walktype1(Type *t, vlong *xoffset, Bvec *bv) |
195 { | 195 { |
196 vlong fieldoffset, i, o; | 196 vlong fieldoffset, i, o; |
197 Type *t1; | 197 Type *t1; |
198 | 198 |
199 if(t->align > 0 && (*xoffset % t->align) != 0) | 199 if(t->align > 0 && (*xoffset % t->align) != 0) |
200 fatal("walktype1: invalid initial alignment, %T", t); | 200 fatal("walktype1: invalid initial alignment, %T", t); |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
289 { | 289 { |
290 vlong xoffset; | 290 vlong xoffset; |
291 | 291 |
292 // Start the walk at offset 0. The correct offset will be | 292 // Start the walk at offset 0. The correct offset will be |
293 // filled in by the first type encountered during the walk. | 293 // filled in by the first type encountered during the walk. |
294 xoffset = 0; | 294 xoffset = 0; |
295 walktype1(type, &xoffset, bv); | 295 walktype1(type, &xoffset, bv); |
296 } | 296 } |
297 | 297 |
298 // Compute a bit vector to describes the pointer containing locations | 298 // Compute a bit vector to describes the pointer containing locations |
299 // in the argument list. | 299 // in the in and out argument list and dump the bitvector length and |
300 static int | 300 // data to the provided symbol. |
301 pointermap(Sym *gcsym, int off, Node *fn) | 301 static void |
| 302 dumpgcargs(Node *fn, Sym *sym) |
302 { | 303 { |
303 Type *thistype, *inargtype, *outargtype; | 304 Type *thistype, *inargtype, *outargtype; |
304 Bvec *bv; | 305 Bvec *bv; |
305 int32 i; | 306 int32 i; |
| 307 int off; |
306 | 308 |
307 thistype = getthisx(fn->type); | 309 thistype = getthisx(fn->type); |
308 inargtype = getinargx(fn->type); | 310 inargtype = getinargx(fn->type); |
309 outargtype = getoutargx(fn->type); | 311 outargtype = getoutargx(fn->type); |
310 bv = bvalloc(fn->type->argwid / widthptr); | 312 bv = bvalloc(fn->type->argwid / widthptr); |
311 if(thistype != nil) | 313 if(thistype != nil) |
312 walktype(thistype, bv); | 314 walktype(thistype, bv); |
313 if(inargtype != nil) | 315 if(inargtype != nil) |
314 walktype(inargtype, bv); | 316 walktype(inargtype, bv); |
315 if(outargtype != nil) | 317 if(outargtype != nil) |
316 walktype(outargtype, bv); | 318 walktype(outargtype, bv); |
317 » off = duint32(gcsym, off, bv->n); | 319 » off = duint32(sym, 0, bv->n); |
318 for(i = 0; i < bv->n; i += 32) | 320 for(i = 0; i < bv->n; i += 32) |
319 » » off = duint32(gcsym, off, bv->b[i/32]); | 321 » » off = duint32(sym, off, bv->b[i/32]); |
320 free(bv); | 322 free(bv); |
321 » return off; | 323 » ggloblsym(sym, off, 0, 1); |
| 324 } |
| 325 |
| 326 // Compute a bit vector to describes the pointer containing locations |
| 327 // in local variables and dumps the bitvector length and data out to |
| 328 // the provided symbol. |
| 329 static void |
| 330 dumpgclocals(Node* fn, Sym *sym) |
| 331 { |
| 332 » Bvec *bv; |
| 333 » NodeList *ll; |
| 334 » Node *node; |
| 335 » vlong xoffset; |
| 336 » int32 i; |
| 337 » int off; |
| 338 |
| 339 » bv = bvalloc(rnd(stksize, widthptr) / widthptr); |
| 340 » for(ll = fn->dcl; ll != nil; ll = ll->next) { |
| 341 » » node = ll->n; |
| 342 » » if(node->class == PAUTO && node->op == ONAME) { |
| 343 » » » if(haspointers(node->type)) { |
| 344 » » » » xoffset = node->xoffset + rnd(stksize,widthptr); |
| 345 » » » » walktype1(node->type, &xoffset, bv); |
| 346 » » » } |
| 347 » » } |
| 348 » } |
| 349 » off = duint32(sym, 0, bv->n); |
| 350 » for(i = 0; i < bv->n; i += 32) { |
| 351 » » off = duint32(sym, off, bv->b[i/32]); |
| 352 » } |
| 353 » free(bv); |
| 354 » ggloblsym(sym, off, 0, 1); |
322 } | 355 } |
323 | 356 |
324 // Sort the list of stack variables. autos after anything else, | 357 // Sort the list of stack variables. autos after anything else, |
325 // within autos, unused after used, and within used on reverse alignment. | 358 // within autos, unused after used, and within used on reverse alignment. |
326 // non-autos sort on offset. | 359 // non-autos sort on offset. |
327 static int | 360 static int |
328 cmpstackvar(Node *a, Node *b) | 361 cmpstackvar(Node *a, Node *b) |
329 { | 362 { |
330 if (a->class != b->class) | 363 if (a->class != b->class) |
331 return (a->class == PAUTO) ? 1 : -1; | 364 return (a->class == PAUTO) ? 1 : -1; |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
407 fixautoused(ptxt); | 440 fixautoused(ptxt); |
408 | 441 |
409 // The debug information needs accurate offsets on the symbols. | 442 // The debug information needs accurate offsets on the symbols. |
410 for(ll = curfn->dcl ;ll != nil; ll=ll->next) { | 443 for(ll = curfn->dcl ;ll != nil; ll=ll->next) { |
411 if (ll->n->class != PAUTO || ll->n->op != ONAME) | 444 if (ll->n->class != PAUTO || ll->n->op != ONAME) |
412 continue; | 445 continue; |
413 ll->n->xoffset += ll->n->stkdelta; | 446 ll->n->xoffset += ll->n->stkdelta; |
414 ll->n->stkdelta = 0; | 447 ll->n->stkdelta = 0; |
415 } | 448 } |
416 } | 449 } |
LEFT | RIGHT |