diff options
-rw-r--r-- | all.h | 1 | ||||
-rw-r--r-- | amd64/emit.c | 16 | ||||
-rw-r--r-- | amd64/isel.c | 1 | ||||
-rw-r--r-- | test/dynalloc.ssa | 27 |
4 files changed, 41 insertions, 4 deletions
diff --git a/all.h b/all.h index 629fea3..24a1755 100644 --- a/all.h +++ b/all.h @@ -342,6 +342,7 @@ struct Fn { int slot; char export; char vararg; + char dynalloc; char name[NString]; }; diff --git a/amd64/emit.c b/amd64/emit.c index 51833b4..b8fa655 100644 --- a/amd64/emit.c +++ b/amd64/emit.c @@ -488,10 +488,10 @@ emitins(Ins i, Fn *fn, FILE *f) } } -static int +static uint64_t framesz(Fn *fn) { - int i, o, f; + uint64_t i, o, f; /* specific to NAlign == 3 */ for (i=0, o=0; i<NCLR; i++) @@ -512,7 +512,8 @@ amd64_emitfn(Fn *fn, FILE *f) static int id0; Blk *b, *s; Ins *i, itmp; - int *r, c, fs, o, n, lbl; + int *r, c, o, n, lbl; + uint64_t fs; fprintf(f, ".text\n"); if (fn->export) @@ -525,7 +526,7 @@ amd64_emitfn(Fn *fn, FILE *f) ); fs = framesz(fn); if (fs) - fprintf(f, "\tsub $%d, %%rsp\n", fs); + fprintf(f, "\tsub $%"PRIu64", %%rsp\n", fs); if (fn->vararg) { o = -176; for (r=amd64_sysv_rsave; r<&amd64_sysv_rsave[6]; r++, o+=8) @@ -537,6 +538,7 @@ amd64_emitfn(Fn *fn, FILE *f) if (fn->reg & BIT(*r)) { itmp.arg[0] = TMP(*r); emitf("pushq %L0", &itmp, fn, f); + fs += 8; } for (lbl=0, b=fn->start; b; b=b->link) { @@ -547,6 +549,12 @@ amd64_emitfn(Fn *fn, FILE *f) lbl = 1; switch (b->jmp.type) { case Jret0: + if (fn->dynalloc) + fprintf(f, + "\tmovq %%rbp, %%rsp\n" + "\tsubq $%"PRIu64", %%rsp\n", + fs + ); for (r=&amd64_sysv_rclob[NCLR]; r>amd64_sysv_rclob;) if (fn->reg & BIT(*--r)) { itmp.arg[0] = TMP(*r); diff --git a/amd64/isel.c b/amd64/isel.c index 4202610..46ed259 100644 --- a/amd64/isel.c +++ b/amd64/isel.c @@ -291,6 +291,7 @@ Emit: * the stack remains aligned * (rsp = 0) mod 16 */ + fn->dynalloc = 1; if (rtype(i.arg[0]) == RCon) { sz = fn->con[i.arg[0].val].bits.i; if (sz < 0 || sz >= INT_MAX-15) diff --git a/test/dynalloc.ssa b/test/dynalloc.ssa new file mode 100644 index 0000000..7c54e88 --- /dev/null +++ b/test/dynalloc.ssa @@ -0,0 +1,27 @@ +# make sure dynamic allocations +# and caller-save regs interact +# soundly + +function $g() { +@start + ret +} + +function w $f(w %arg) { +@start + call $g() +@alloc + %r =l alloc8 16 + storel 180388626474, %r + %r8 =l add 8, %r + storel 180388626474, %r8 + ret %arg +} + +export +function w $main() { +@start + %a =w call $f(w 0) + %b =w call $f(w 0) + ret %a +} |