aboutsummaryrefslogtreecommitdiff
path: root/emit.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <[email protected]>2017-02-07 23:01:24 -0500
committerQuentin Carbonneaux <[email protected]>2017-02-10 11:05:54 -0500
commitb99a8b0d07d43b89d5e27883ee5a9a67c2645809 (patch)
tree9a3f4ebcc0bb971a7e361115b8d9b19529902cb7 /emit.c
parent8799dc30ac472545bc93957c22f070590ff44cb3 (diff)
support variable argument lists
This change is backward compatible, calls to "variadic" functions (like printf) must now be annotated (with ...).
Diffstat (limited to 'emit.c')
-rw-r--r--emit.c22
1 files changed, 15 insertions, 7 deletions
diff --git a/emit.c b/emit.c
index 2c0b3cc..ccbd516 100644
--- a/emit.c
+++ b/emit.c
@@ -137,13 +137,14 @@ slot(int s, Fn *fn)
/* sign extend s using a bitfield */
x.i = s;
+ assert(x.i <= fn->slot);
/* specific to NAlign == 3 */
if (x.i < 0)
return -4 * x.i;
- else {
- assert(fn->slot >= x.i);
+ else if (fn->vararg)
+ return -176 + -4 * (fn->slot - x.i);
+ else
return -4 * (fn->slot - x.i);
- }
}
static void
@@ -481,7 +482,7 @@ framesz(Fn *fn)
o ^= 1 & (fn->reg >> rclob[i]);
f = fn->slot;
f = (f + 3) & -4;
- return 4*f + 8*o;
+ return 4*f + 8*o + 176*fn->vararg;
}
void
@@ -504,20 +505,27 @@ emitfn(Fn *fn, FILE *f)
static int id0;
Blk *b, *s;
Ins *i, itmp;
- int *r, c, fs;
+ int *r, c, fs, o, n;
fprintf(f, ".text\n");
if (fn->export)
fprintf(f, ".globl %s%s\n", symprefix, fn->name);
fprintf(f,
"%s%s:\n"
- "\tpush %%rbp\n"
- "\tmov %%rsp, %%rbp\n",
+ "\tpushq %%rbp\n"
+ "\tmovq %%rsp, %%rbp\n",
symprefix, fn->name
);
fs = framesz(fn);
if (fs)
fprintf(f, "\tsub $%d, %%rsp\n", fs);
+ if (fn->vararg) {
+ o = -176;
+ for (r=rsave; r-rsave<6; ++r, o+=8)
+ fprintf(f, "\tmovq %%%s, %d(%%rbp)\n", rname[*r][0], o);
+ for (n=0; n<8; ++n, o+=16)
+ fprintf(f, "\tmovaps %%xmm%d, %d(%%rbp)\n", n, o);
+ }
for (r=rclob; r-rclob < NRClob; r++)
if (fn->reg & BIT(*r)) {
itmp.arg[0] = TMP(*r);