diff options
Diffstat (limited to 'src/cmd/6g/gsubr.c')
| -rw-r--r-- | src/cmd/6g/gsubr.c | 51 |
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 |
