aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/gc/pgen.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/gc/pgen.c')
-rw-r--r--src/cmd/gc/pgen.c114
1 files changed, 111 insertions, 3 deletions
diff --git a/src/cmd/gc/pgen.c b/src/cmd/gc/pgen.c
index 7917ea29cc..d04587e74c 100644
--- a/src/cmd/gc/pgen.c
+++ b/src/cmd/gc/pgen.c
@@ -2,8 +2,12 @@
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
-#include "gg.h"
-#include "opt.h"
+#undef EXTERN
+#define EXTERN
+#include "gg.h"
+#include "opt.h"
+
+static void compactframe(Prog* p);
void
compile(Node *fn)
@@ -14,6 +18,7 @@ compile(Node *fn)
int32 lno;
Type *t;
Iter save;
+ vlong oldstksize;
if(newproc == N) {
newproc = sysfunc("newproc");
@@ -107,11 +112,114 @@ compile(Node *fn)
regopt(ptxt);
}
+ oldstksize = stksize;
+ compactframe(ptxt);
+ if(0)
+ print("compactframe: %ld to %ld\n", oldstksize, stksize);
+
defframe(ptxt);
- if(debug['f'])
+ if(0)
frame(0);
ret:
lineno = lno;
}
+
+
+// Sort the list of stack variables. autos after anything else,
+// within autos, unused after used, and within used on reverse alignment.
+// non-autos sort on offset.
+static int
+cmpstackvar(Node *a, Node *b)
+{
+ if (a->class != b->class)
+ return (a->class == PAUTO) ? 1 : -1;
+ if (a->class != PAUTO)
+ return a->xoffset - b->xoffset;
+ if ((a->used == 0) != (b->used == 0))
+ return b->used - a->used;
+ return b->type->align - a->type->align;
+
+}
+
+static void
+compactframe(Prog* ptxt)
+{
+ NodeList *ll;
+ Node* n;
+ Prog *p;
+ uint32 w;
+
+ if (stksize == 0)
+ return;
+
+ // Mark the PAUTO's unused.
+ for(ll=curfn->dcl; ll != nil; ll=ll->next)
+ if (ll->n->class == PAUTO && ll->n->op == ONAME)
+ ll->n->used = 0;
+
+ // Sweep the prog list to mark any used nodes.
+ for (p = ptxt; p; p = p->link) {
+ if (p->from.type == D_AUTO && p->from.node)
+ p->from.node->used++;
+
+ if (p->to.type == D_AUTO && p->to.node)
+ p->to.node->used++;
+ }
+
+ listsort(&curfn->dcl, cmpstackvar);
+
+ // Unused autos are at the end, chop 'em off.
+ ll = curfn->dcl;
+ n = ll->n;
+ if (n->class == PAUTO && n->op == ONAME && !n->used) {
+ curfn->dcl = nil;
+ stksize = 0;
+ return;
+ }
+
+ for(ll = curfn->dcl; ll->next != nil; ll=ll->next) {
+ n = ll->next->n;
+ if (n->class == PAUTO && n->op == ONAME && !n->used) {
+ ll->next = nil;
+ curfn->dcl->end = ll;
+ break;
+ }
+ }
+
+ // Reassign stack offsets of the locals that are still there.
+ stksize = 0;
+ for(ll = curfn->dcl; ll != nil; ll=ll->next) {
+ n = ll->n;
+ // TODO find out where the literal autos come from
+ if (n->class != PAUTO || n->op != ONAME)
+ continue;
+
+ w = n->type->width;
+ if((w >= MAXWIDTH) || (w < 1))
+ fatal("bad width");
+ stksize += w;
+ stksize = rnd(stksize, n->type->align);
+ if(thechar == '5')
+ stksize = rnd(stksize, widthptr);
+ n->stkdelta = -stksize - n->xoffset;
+ }
+
+ // Fixup instructions.
+ for (p = ptxt; p; p = p->link) {
+ if (p->from.type == D_AUTO && p->from.node)
+ p->from.offset += p->from.node->stkdelta;
+
+ if (p->to.type == D_AUTO && p->to.node)
+ p->to.offset += p->to.node->stkdelta;
+ }
+
+ // The debug information needs accurate offsets on the symbols.
+ for(ll = curfn->dcl ;ll != nil; ll=ll->next) {
+ if (ll->n->class != PAUTO || ll->n->op != ONAME)
+ continue;
+ ll->n->xoffset += ll->n->stkdelta;
+ ll->n->stkdelta = 0;
+ }
+}