From 65ace14e184807df026e985e073b3b5c5aaf576c Mon Sep 17 00:00:00 2001 From: lemon Date: Thu, 1 Jun 2023 23:16:48 +0200 Subject: basic ABI lowering of aggregates --- amd64/all.h | 15 --------- amd64/sysv.c | 103 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 103 insertions(+), 15 deletions(-) (limited to 'amd64') diff --git a/amd64/all.h b/amd64/all.h index fdd759a..915d93a 100644 --- a/amd64/all.h +++ b/amd64/all.h @@ -1,6 +1,5 @@ #include "../ir.h" - #define LIST_REGS(_) \ _(RAX) _(RCX) _(RDX) _(RBX) _(RSP) _(RBP) _(RSI) _(RDI) \ _(R8) _(R9) _(R10) _(R11) _(R12) _(R13) _(R14) _(R15) \ @@ -13,18 +12,4 @@ enum { #undef R }; -const char amd64_rnames[][6] = { -#define R(r) #r, - LIST_REGS(R) -#undef R -}; - -const struct mctarg t_amd64_sysv = { - .gpr0 = RAX, .ngpr = R15 - RAX + 1, - .fpr0 = XMM0, .nfpr = XMM15 - XMM0 + 1, - .rcallee = {{1<siz, 8); + if (siz > 16) /* MEMORY */ + return 0; + for (int i = 0; i < td->nmemb; ++i) { + struct fielddata *fld = &td->fld[i].f; + uint align = typealign(fld->t); + if (alignup(fld->off, align) != fld->off) /* unaligned field */ + return cls[0] = cls[1] = 0; + if (isagg(fld->t)) { + if (!classify(cls, &typedata[fld->t.dat], fld->off)) + return cls[0] = cls[1] = 0; + } else if (isflt(fld->t)) { /* SSE */ + if (!cls[(fld->off + off)/8]) + cls[(fld->off + off)/8] = KF8; + } else { /* INTEGER */ + cls[(fld->off + off)/8] = KI8; + } + } + return !!cls[0] + !!cls[1]; +} + +static int +argabi(short r[2], uchar cls[2], int *ni, int *nf, union irtype typ) +{ + static const uchar intregs[] = { RDI, RSI, RDX, RCX, R8, R9 }; + enum { NINT = arraylength(intregs), NFLT = 8 }; + int ret, ni_save, nf_save; + + if (!typ.isagg) { + if (kisflt(typ.cls) && *nf < NFLT) { + cls[0] = KF8; /* SSE */ + r[0] = XMM0 + (*nf)++; + return 1; + } + if (*ni < NINT) { + cls[0] = KI8; /* INTEGER */ + r[0] = intregs[(*ni)++]; + return 1; + } + return 0; /* MEMORY */ + } + cls[0] = cls[1] = 0; + ret = classify(cls, &typedata[typ.dat], 0); + if (!ret) return 0; + ni_save = *ni, nf_save = *nf; + assert(ret <= 2); + for (int i = 0; i < ret; ++i) { + assert(cls[i]); + if (cls[i] == KF8 && *nf < NFLT) + r[i] = XMM0 + (*nf)++; + else if (cls[i] == KI8 && *ni < NINT) + r[i] = intregs[(*ni)++]; + else { /* MEMORY */ + *ni = ni_save, *nf = nf_save; + return cls[0] = cls[1] = 0; + } + } + return ret; +} + +static int +retabi(short r[2], uchar cls[2], union irtype typ) +{ + int ret; + + if (!typ.isagg) return kisflt(typ.cls) ? XMM0 : RAX; + cls[0] = cls[1] = 0; + ret = classify(cls, &typedata[typ.dat], 0); + if (!ret) { /* MEMORY */ + r[0] = RDI; /* register for caller-owned result location argument */ + return 0; + } + assert(ret <= 2); + for (int i = 0; i < ret; ++i) { + assert(cls[i]); + if (cls[i] == KF8) /* SSE (XMM0, XMM1) */ + r[i] = XMM0 + i; + else if (cls[i] == KI8) /* INTEGER (RAX, RDX) */ + r[i] = i == 0 ? RAX : RDX; + else assert(0); + } + return ret; +} + +const char amd64_rnames[][6] = { +#define R(r) #r, + LIST_REGS(R) +#undef R +}; + +const struct mctarg t_amd64_sysv = { + .gpr0 = RAX, .ngpr = R15 - RAX + 1, + .fpr0 = XMM0, .nfpr = XMM15 - XMM0 + 1, + .rcallee = {{1<