summaryrefslogtreecommitdiff
path: root/src/cmd/6g/gsubr.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/6g/gsubr.c')
-rw-r--r--src/cmd/6g/gsubr.c51
1 files changed, 51 insertions, 0 deletions
diff --git a/src/cmd/6g/gsubr.c b/src/cmd/6g/gsubr.c
index ae6ae5765..211915f54 100644
--- a/src/cmd/6g/gsubr.c
+++ b/src/cmd/6g/gsubr.c
@@ -98,6 +98,19 @@ patch(Prog *p, Prog *to)
p->to.offset = to->loc;
}
+Prog*
+unpatch(Prog *p)
+{
+ Prog *q;
+
+ if(p->to.type != D_BRANCH)
+ fatal("unpatch: not a branch");
+ q = p->to.branch;
+ p->to.branch = P;
+ p->to.offset = 0;
+ return q;
+}
+
/*
* start a new Prog list.
*/
@@ -121,6 +134,44 @@ newplist(void)
}
void
+clearstk(void)
+{
+ Plist *pl;
+ Prog *p1, *p2;
+ Node sp, di, cx, con, ax;
+
+ if((uint32)plast->firstpc->to.offset <= 0)
+ return;
+
+ // reestablish context for inserting code
+ // at beginning of function.
+ pl = plast;
+ p1 = pl->firstpc;
+ p2 = p1->link;
+ pc = mal(sizeof(*pc));
+ clearp(pc);
+ p1->link = pc;
+
+ // zero stack frame
+ nodreg(&sp, types[tptr], D_SP);
+ nodreg(&di, types[tptr], D_DI);
+ nodreg(&cx, types[TUINT64], D_CX);
+ nodconst(&con, types[TUINT64], (uint32)p1->to.offset / widthptr);
+ gins(ACLD, N, N);
+ gins(AMOVQ, &sp, &di);
+ gins(AMOVQ, &con, &cx);
+ nodconst(&con, types[TUINT64], 0);
+ nodreg(&ax, types[TUINT64], D_AX);
+ gins(AMOVQ, &con, &ax);
+ gins(AREP, N, N);
+ gins(ASTOSQ, N, N);
+
+ // continue with original code.
+ gins(ANOP, N, N)->link = p2;
+ pc = P;
+}
+
+void
gused(Node *n)
{
gins(ANOP, n, N); // used