LEFT | RIGHT |
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 |
(...skipping 318 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
329 static void | 329 static void |
330 dumpgclocals(Node* fn, Sym *sym) | 330 dumpgclocals(Node* fn, Sym *sym) |
331 { | 331 { |
332 Bvec *bv; | 332 Bvec *bv; |
333 NodeList *ll; | 333 NodeList *ll; |
334 Node *node; | 334 Node *node; |
335 vlong xoffset; | 335 vlong xoffset; |
336 int32 i; | 336 int32 i; |
337 int off; | 337 int off; |
338 | 338 |
339 » bv = bvalloc(rnd(stksize, widthptr) / widthptr); | 339 » bv = bvalloc(stkptrsize / widthptr); |
340 for(ll = fn->dcl; ll != nil; ll = ll->next) { | 340 for(ll = fn->dcl; ll != nil; ll = ll->next) { |
341 node = ll->n; | 341 node = ll->n; |
342 if(node->class == PAUTO && node->op == ONAME) { | 342 if(node->class == PAUTO && node->op == ONAME) { |
343 if(haspointers(node->type)) { | 343 if(haspointers(node->type)) { |
344 » » » » xoffset = node->xoffset + rnd(stksize,widthptr); | 344 » » » » xoffset = node->xoffset + stksize; |
345 walktype1(node->type, &xoffset, bv); | 345 walktype1(node->type, &xoffset, bv); |
346 } | 346 } |
347 } | 347 } |
348 } | 348 } |
349 off = duint32(sym, 0, bv->n); | 349 off = duint32(sym, 0, bv->n); |
350 for(i = 0; i < bv->n; i += 32) { | 350 for(i = 0; i < bv->n; i += 32) { |
351 off = duint32(sym, off, bv->b[i/32]); | 351 off = duint32(sym, off, bv->b[i/32]); |
352 } | 352 } |
353 free(bv); | 353 free(bv); |
354 ggloblsym(sym, off, 0, 1); | 354 ggloblsym(sym, off, 0, 1); |
355 } | 355 } |
356 | 356 |
357 // Sort the list of stack variables. autos after anything else, | 357 // Sort the list of stack variables. Autos after anything else, |
358 // within autos, unused after used, within used, things with | 358 // within autos, unused after used, within used, things with |
359 // pointers first, and then increasing size. | 359 // pointers first, and then decreasing size. |
360 // non-autos sort on offset. | 360 // Because autos are laid out in decreasing addresses |
| 361 // on the stack, pointers first and decreasing size |
| 362 // really means, in memory, pointers near the top of the· |
| 363 // stack and increasing in size. |
| 364 // Non-autos sort on offset. |
361 static int | 365 static int |
362 cmpstackvar(Node *a, Node *b) | 366 cmpstackvar(Node *a, Node *b) |
363 { | 367 { |
364 int ap, bp; | 368 int ap, bp; |
365 | 369 |
366 if (a->class != b->class) | 370 if (a->class != b->class) |
367 » » return (a->class == PAUTO) ? 1 : -1; | 371 » » return (a->class == PAUTO) ? +1 : -1; |
368 if (a->class != PAUTO) { | 372 if (a->class != PAUTO) { |
369 if (a->xoffset < b->xoffset) | 373 if (a->xoffset < b->xoffset) |
370 return -1; | 374 return -1; |
371 if (a->xoffset > b->xoffset) | 375 if (a->xoffset > b->xoffset) |
372 » » » return 1; | 376 » » » return +1; |
373 return 0; | 377 return 0; |
374 } | 378 } |
375 if ((a->used == 0) != (b->used == 0)) | 379 if ((a->used == 0) != (b->used == 0)) |
376 return b->used - a->used; | 380 return b->used - a->used; |
| 381 |
377 ap = haspointers(a->type); | 382 ap = haspointers(a->type); |
378 bp = haspointers(b->type); | 383 bp = haspointers(b->type); |
379 if(ap != bp) | 384 if(ap != bp) |
380 return bp - ap; | 385 return bp - ap; |
381 if(a->type->width < b->type->width) | 386 if(a->type->width < b->type->width) |
| 387 return +1; |
| 388 if(a->type->width > b->type->width) |
382 return -1; | 389 return -1; |
383 if(a->type->width > b->type->width) | |
384 return 1; | |
385 return 0; | 390 return 0; |
386 } | 391 } |
387 | 392 |
388 // TODO(lvd) find out where the PAUTO/OLITERAL nodes come from. | 393 // TODO(lvd) find out where the PAUTO/OLITERAL nodes come from. |
389 static void | 394 static void |
390 allocauto(Prog* ptxt) | 395 allocauto(Prog* ptxt) |
391 { | 396 { |
392 NodeList *ll; | 397 NodeList *ll; |
393 Node* n; | 398 Node* n; |
394 vlong w; | 399 vlong w; |
395 | 400 » vlong ptrlimit; |
396 » if(curfn->dcl == nil) | 401 |
| 402 » if(curfn->dcl == nil) { |
| 403 » » stksize = 0; |
| 404 » » stkptrsize = 0; |
397 return; | 405 return; |
| 406 } |
398 | 407 |
399 // Mark the PAUTO's unused. | 408 // Mark the PAUTO's unused. |
400 for(ll=curfn->dcl; ll != nil; ll=ll->next) | 409 for(ll=curfn->dcl; ll != nil; ll=ll->next) |
401 if (ll->n->class == PAUTO) | 410 if (ll->n->class == PAUTO) |
402 ll->n->used = 0; | 411 ll->n->used = 0; |
403 | 412 |
404 markautoused(ptxt); | 413 markautoused(ptxt); |
405 | 414 |
406 listsort(&curfn->dcl, cmpstackvar); | 415 listsort(&curfn->dcl, cmpstackvar); |
407 | 416 |
408 // Unused autos are at the end, chop 'em off. | 417 // Unused autos are at the end, chop 'em off. |
409 ll = curfn->dcl; | 418 ll = curfn->dcl; |
410 n = ll->n; | 419 n = ll->n; |
411 if (n->class == PAUTO && n->op == ONAME && !n->used) { | 420 if (n->class == PAUTO && n->op == ONAME && !n->used) { |
412 // No locals used at all | 421 // No locals used at all |
413 curfn->dcl = nil; | 422 curfn->dcl = nil; |
414 stksize = 0; | 423 stksize = 0; |
| 424 stkptrsize = 0; |
415 fixautoused(ptxt); | 425 fixautoused(ptxt); |
416 return; | 426 return; |
417 } | 427 } |
418 | 428 |
419 for(ll = curfn->dcl; ll->next != nil; ll=ll->next) { | 429 for(ll = curfn->dcl; ll->next != nil; ll=ll->next) { |
420 n = ll->next->n; | 430 n = ll->next->n; |
421 if (n->class == PAUTO && n->op == ONAME && !n->used) { | 431 if (n->class == PAUTO && n->op == ONAME && !n->used) { |
422 ll->next = nil; | 432 ll->next = nil; |
423 curfn->dcl->end = ll; | 433 curfn->dcl->end = ll; |
424 break; | 434 break; |
425 } | 435 } |
426 } | 436 } |
427 | 437 |
428 // Reassign stack offsets of the locals that are still there. | 438 // Reassign stack offsets of the locals that are still there. |
429 stksize = 0; | 439 stksize = 0; |
| 440 ptrlimit = -1; |
430 for(ll = curfn->dcl; ll != nil; ll=ll->next) { | 441 for(ll = curfn->dcl; ll != nil; ll=ll->next) { |
431 n = ll->n; | 442 n = ll->n; |
432 if (n->class != PAUTO || n->op != ONAME) | 443 if (n->class != PAUTO || n->op != ONAME) |
433 continue; | 444 continue; |
434 | 445 |
435 dowidth(n->type); | 446 dowidth(n->type); |
436 w = n->type->width; | 447 w = n->type->width; |
437 if(w >= MAXWIDTH || w < 0) | 448 if(w >= MAXWIDTH || w < 0) |
438 fatal("bad width"); | 449 fatal("bad width"); |
439 stksize += w; | 450 stksize += w; |
440 stksize = rnd(stksize, n->type->align); | 451 stksize = rnd(stksize, n->type->align); |
| 452 if(ptrlimit < 0 && haspointers(n->type)) |
| 453 ptrlimit = stksize - w; |
441 if(thechar == '5') | 454 if(thechar == '5') |
442 stksize = rnd(stksize, widthptr); | 455 stksize = rnd(stksize, widthptr); |
443 if(stksize >= (1ULL<<31)) { | 456 if(stksize >= (1ULL<<31)) { |
444 setlineno(curfn); | 457 setlineno(curfn); |
445 yyerror("stack frame too large (>2GB)"); | 458 yyerror("stack frame too large (>2GB)"); |
446 } | 459 } |
447 n->stkdelta = -stksize - n->xoffset; | 460 n->stkdelta = -stksize - n->xoffset; |
448 } | 461 } |
| 462 stksize = rnd(stksize, widthptr); |
| 463 |
| 464 if(ptrlimit < 0) |
| 465 stkptrsize = 0; |
| 466 else |
| 467 stkptrsize = stksize - ptrlimit; |
| 468 stkptrsize = rnd(stkptrsize, widthptr); |
449 | 469 |
450 fixautoused(ptxt); | 470 fixautoused(ptxt); |
451 | 471 |
452 // The debug information needs accurate offsets on the symbols. | 472 // The debug information needs accurate offsets on the symbols. |
453 » for(ll = curfn->dcl ;ll != nil; ll=ll->next) { | 473 » for(ll = curfn->dcl; ll != nil; ll=ll->next) { |
454 if (ll->n->class != PAUTO || ll->n->op != ONAME) | 474 if (ll->n->class != PAUTO || ll->n->op != ONAME) |
455 continue; | 475 continue; |
456 ll->n->xoffset += ll->n->stkdelta; | 476 ll->n->xoffset += ll->n->stkdelta; |
457 ll->n->stkdelta = 0; | 477 ll->n->stkdelta = 0; |
458 } | 478 } |
459 } | 479 } |
460 | 480 |
461 static void movelargefn(Node*); | 481 static void movelargefn(Node*); |
462 | 482 |
463 void | 483 void |
464 movelarge(NodeList *l) | 484 movelarge(NodeList *l) |
465 { | 485 { |
466 for(; l; l=l->next) | 486 for(; l; l=l->next) |
467 if(l->n->op == ODCLFUNC) | 487 if(l->n->op == ODCLFUNC) |
468 movelargefn(l->n); | 488 movelargefn(l->n); |
469 } | 489 } |
470 | 490 |
471 static void | 491 static void |
472 movelargefn(Node *fn) | 492 movelargefn(Node *fn) |
473 { | 493 { |
474 NodeList *l; | 494 NodeList *l; |
475 Node *n; | 495 Node *n; |
476 | 496 |
477 for(l=fn->dcl; l != nil; l=l->next) { | 497 for(l=fn->dcl; l != nil; l=l->next) { |
478 n = l->n; | 498 n = l->n; |
479 if(n->class == PAUTO && n->type != T && n->type->width > MaxStac
kVarSize) | 499 if(n->class == PAUTO && n->type != T && n->type->width > MaxStac
kVarSize) |
480 addrescapes(n); | 500 addrescapes(n); |
481 } | 501 } |
482 } | 502 } |
LEFT | RIGHT |