summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFinxx2024-03-17 16:29:32 -0500
committerQuentin Carbonneaux2024-03-20 17:07:15 +0100
commitc071bf04f2883226116e09983850acb71f83f421 (patch)
tree70dfb85ad9fa47c6203c7fad74926c2058b6a5fb
parentffee30ec25b5c19815e7df08f74d806e7f9bdf88 (diff)
WinABI patch, part 2winabi
This is an addendum to the previous patch sent. It fixes many things, primarily fixing a segfault when a function has more than 4 arguments.
-rw-r--r--amd64/all.h38
-rw-r--r--amd64/targ.c4
-rw-r--r--amd64/winabi.c61
3 files changed, 53 insertions, 50 deletions
diff --git a/amd64/all.h b/amd64/all.h
index d1a28c2..b0b3771 100644
--- a/amd64/all.h
+++ b/amd64/all.h
@@ -3,24 +3,26 @@
typedef struct Amd64Op Amd64Op;
enum Amd64Reg {
- RAX = RXX+1, /* caller-save */
- RCX,
- RDX,
- RSI,
- RDI,
- R8,
- R9,
- R10,
- R11,
-
- RBX, /* callee-save */
- R12,
- R13,
- R14,
- R15,
-
- RBP, /* globally live */
- RSP,
+ /* |Register | SysV | WinABI | */
+ /* +------------+------------------+------------------+ */
+ RAX = RXX+1, /* | caller-save (v) | caller-save (v) | */
+ RCX, /* | caller-save (v) | caller-save (v) | */
+ RDX, /* | caller-save (v) | caller-save (v) | */
+ RSI, /* | caller-save (v) | callee-save (nv) | */
+ RDI, /* | caller-save (v) | callee-save (nv) | */
+ R8, /* | caller-save (v) | caller-save (v) | */
+ R9, /* | caller-save (v) | caller-save (v) | */
+ R10, /* | caller-save (v) | caller-save (v) | */
+ R11, /* | caller-save (v) | caller-save (v) | */
+ /* +------------------+------------------+ */
+ RBX, /* | callee-save (nv) | callee-save (nv) | */
+ R12, /* | callee-save (nv) | callee-save (nv) | */
+ R13, /* | callee-save (nv) | callee-save (nv) | */
+ R14, /* | callee-save (nv) | callee-save (nv) | */
+ R15, /* | callee-save (nv) | callee-save (nv) | */
+ /* +------------------+------------------+ */
+ RBP, /* | globally live | callee-save (nv) | */
+ RSP, /* | globally live | callee-save (nv) | */
XMM0, /* sse */
XMM1,
diff --git a/amd64/targ.c b/amd64/targ.c
index a3b4b85..0637d98 100644
--- a/amd64/targ.c
+++ b/amd64/targ.c
@@ -19,7 +19,6 @@ amd64_memargs(int op)
.nfpr = NFPR, \
.rglob = BIT(RBP) | BIT(RSP), \
.nrglob = 2, \
- .nrsave = {NGPS, NFPS}, \
.memargs = amd64_memargs, \
.abi0 = elimsb, \
.isel = amd64_isel, \
@@ -33,6 +32,7 @@ Target T_amd64_sysv = {
.retregs = amd64_sysv_retregs,
.argregs = amd64_sysv_argregs,
.rsave = amd64_sysv_rsave,
+ .nrsave = {NGPS, NFPS},
AMD64_COMMON
};
@@ -46,6 +46,7 @@ Target T_amd64_apple = {
.retregs = amd64_sysv_retregs,
.argregs = amd64_sysv_argregs,
.rsave = amd64_sysv_rsave,
+ .nrsave = {NGPS, NFPS},
AMD64_COMMON
};
@@ -58,5 +59,6 @@ Target T_amd64_win = {
.retregs = amd64_winabi_retregs,
.argregs = amd64_winabi_argregs,
.rsave = amd64_winabi_rsave,
+ .nrsave = {NGPS - 2, XMM3 - XMM0 + 1},
AMD64_COMMON
};
diff --git a/amd64/winabi.c b/amd64/winabi.c
index f6a0c98..553bf4b 100644
--- a/amd64/winabi.c
+++ b/amd64/winabi.c
@@ -92,26 +92,21 @@ typclass(AClass *a, Typ *t)
}
static int
-retr(Ref reg[2], AClass *aret)
+retr(Ref *reg, AClass *aret)
{
- static int retreg[2][2] = {{RAX, RDX}, {XMM0, XMM0+1}};
- int n, k, ca, nr[2];
-
- nr[0] = nr[1] = 0;
- ca = 0;
- for (n=0; (uint)n*8<aret->size; n++) {
- k = KBASE(aret->cls[n]);
- reg[n] = TMP(retreg[k][nr[k]++]);
- ca += 1 << (2 * k);
- }
- return ca;
+ int k;
+
+ assert(aret->size <= 8);
+ k = KBASE(aret->cls[0]);
+ *reg = (k == 0 ? TMP(RAX) : TMP(XMM0));
+ return 1 << (2 * k);
}
static void
selret(Blk *b, Fn *fn)
{
int j, k, ca;
- Ref r, r0, reg[2];
+ Ref r0, reg;
AClass aret;
j = b->jmp.type;
@@ -131,13 +126,9 @@ selret(Blk *b, Fn *fn)
emit(Oblit0, 0, R, r0, fn->retr);
ca = 1;
} else {
- ca = retr(reg, &aret);
- if (aret.size > 8) {
- r = newtmp("abi", Kl, fn);
- emit(Oload, Kl, reg[1], r, R);
- emit(Oadd, Kl, r, r0, getcon(8, fn));
- }
- emit(Oload, Kl, reg[0], r0, R);
+ ca = retr(&reg, &aret);
+ assert(aret.size <= 8);
+ emit(Oload, Kl, reg, r0, R);
}
} else {
k = j - Jretw;
@@ -161,9 +152,9 @@ argsclass(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret, Ref *env)
Ins *i;
if (aret && aret->inmem)
- nint = 5; /* hidden argument */
+ nint = 3; /* hidden argument */
else
- nint = 6;
+ nint = 4;
nsse = 8;
varc = 0;
envc = 0;
@@ -215,15 +206,22 @@ argsclass(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret, Ref *env)
}
if (varc && envc)
- err("winabi does not support variadic env calls");
+ err("winabi abi does not support variadic env calls");
- return ((varc|envc) << 12) | ((6-nint) << 4) | ((8-nsse) << 8);
+ return ((varc|envc) << 12) | ((4-nint) << 4) | ((8-nsse) << 8);
}
int amd64_winabi_rsave[] = {
- RCX, RDX, R8, R9, -1
+ RCX, RDX, R8, R9, R10, R11, RAX,
+ XMM0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
+ XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, -1
};
-int amd64_winabi_rclob[] = {RBX, R12, R13, R14, R15, -1};
+int amd64_winabi_rclob[] = {RBX, R12, R13, R14, R15, RSI, RDI, -1};
+
+MAKESURE(winabi_arrays_ok,
+ sizeof amd64_winabi_rsave == (NGPS+NFPS+1-2) * sizeof(int) &&
+ sizeof amd64_winabi_rclob == (NCLR+2+1) * sizeof(int)
+);
bits
amd64_winabi_retregs(Ref r, int p[2])
@@ -235,10 +233,12 @@ amd64_winabi_retregs(Ref r, int p[2])
b = 0;
ni = r.val & 3;
nf = (r.val >> 2) & 3;
+ assert(ni <= 1);
+ assert(nf <= 1);
if (ni == 1)
b |= BIT(RAX);
else
- b |= BIT(XMM0);
+ b |= BIT(XMM1);
if (p) {
p[0] = ni;
p[1] = nf;
@@ -300,7 +300,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap)
for (stk=0, a=&ac[i1-i0]; a>ac;)
if ((--a)->inmem) {
if (a->align > 4)
- err("win abi requires alignments of 16 or less");
+ err("winabi abi requires alignments of 16 or less");
stk += a->size;
if (a->align == 4)
stk += stk & 15;
@@ -364,8 +364,7 @@ selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap)
ni = ns = 0;
if (ra && aret.inmem)
- emit(Ocopy, Kl, rarg(Kl, &ni, &ns), ra->i.to, R); /* pass
-hidden argument */
+ emit(Ocopy, Kl, rarg(Kl, &ni, &ns), ra->i.to, R); /* pass hidden argument */
for (i=i0, a=ac; i<i1; i++, a++) {
if (i->op >= Oarge || a->inmem)
@@ -450,7 +449,7 @@ selpar(Fn *fn, Ins *i0, Ins *i1)
switch (a->inmem) {
case 1:
if (a->align > 4)
- err("win abi requires alignments of 16 or less");
+ err("winabi abi requires alignments of 16 or less");
if (a->align == 4)
s = (s+3) & -4;
fn->tmp[i->to.val].slot = -s;