summary refs log tree commit diff
path: root/emit.c
diff options
context:
space:
mode:
authorQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2017-02-07 23:01:24 -0500
committerQuentin Carbonneaux <quentin.carbonneaux@yale.edu>2017-02-10 11:05:54 -0500
commitb99a8b0d07d43b89d5e27883ee5a9a67c2645809 (patch)
tree9a3f4ebcc0bb971a7e361115b8d9b19529902cb7 /emit.c
parent8799dc30ac472545bc93957c22f070590ff44cb3 (diff)
downloadroux-b99a8b0d07d43b89d5e27883ee5a9a67c2645809.tar.gz
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);