summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--all.h1
-rw-r--r--amd64/emit.c16
-rw-r--r--amd64/isel.c1
-rw-r--r--test/dynalloc.ssa27
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
+}