aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorlemon <lsof@mailbox.org>2023-06-20 20:47:32 +0200
committerlemon <lsof@mailbox.org>2023-06-20 20:47:32 +0200
commit7fa68005dde6d1468ac7611c513a492292c48992 (patch)
tree26334ededa3580d43d9a8ae9085426636010fae5
parentfdf047b7d1f737ce8b892b08370ac9a1bedcda73 (diff)
amd64: conform to ABI for varargs func calls
-rw-r--r--amd64/emit.c9
-rw-r--r--amd64/isel.c1
2 files changed, 9 insertions, 1 deletions
diff --git a/amd64/emit.c b/amd64/emit.c
index 7e9bbd3..d3dad9c 100644
--- a/amd64/emit.c
+++ b/amd64/emit.c
@@ -765,6 +765,15 @@ emitinstr(uchar **pcode, struct function *fn, struct block *blk, int curi, struc
gencopy(pcode, cls, blk, curi, dst, ins->l);
break;
case Ocall:
+ if (calltab.p[ins->r.i].vararg >= 0) {
+ struct call *call = &calltab.p[ins->r.i];
+ /* variadic functions need the caller to write num of args in sse regs to %al */
+ int n = 0;
+ for (int i = 0; i < call->narg; ++i)
+ n += call->abiarg[i].reg >= XMM0;
+ if (!n) DS("\x31\xC0"); /* XOR EAX, EAX */
+ else B(0xB0), B(n); /* MOV AL, n */
+ }
Xcall(pcode, KPTR, ref2oper(ins->l));
break;
}
diff --git a/amd64/isel.c b/amd64/isel.c
index b0cacea..e5aa281 100644
--- a/amd64/isel.c
+++ b/amd64/isel.c
@@ -73,7 +73,6 @@ fixarg(union ref *r, struct instr *ins, struct block *blk, int *curi)
/* float immediates & >32b immediates are loaded from memory */
uchar data[8];
uint siz = cls2siz[con->cls];
- if (ins) assert(ins->cls == con->cls);
if (con->cls == KI4) wr32le(data, con->i);
else if (con->cls != KF4) wr64le(data, con->i);
else {