commit cad13d0dce46dbbb42140a40f32245f73672dc39
parent fbbb8e4d78e8b2e9410699fd27af282cc6ddfc4b
Author: Quentin Carbonneaux <quentin.carbonneaux@yale.edu>
Date: Tue, 16 Aug 2016 13:26:16 -0700
add support for unions in sysv abi
Diffstat:
M | all.h | | | 5 | +++-- |
M | parse.c | | | 3 | +-- |
M | sysv.c | | | 86 | ++++++++++++++++++++++++++++++++++++++++++++++--------------------------------- |
M | test/abi5.ssa | | | 13 | +++++++++++++ |
4 files changed, 67 insertions(+), 40 deletions(-)
diff --git a/all.h b/all.h
@@ -429,13 +429,14 @@ struct Typ {
struct Seg {
enum {
+ Send,
Spad,
Sint,
Sflt,
Styp,
};
- uint type:2;
- uint len:30; /* index in typ[] for Styp */
+ uint type:3;
+ uint len:29; /* index in typ[] for Styp */
} (*seg)[NSeg+1];
};
diff --git a/parse.c b/parse.c
@@ -847,8 +847,7 @@ parseseg(Seg *seg, Typ *ty, int t)
}
if (t != Trbrace)
err(", or } expected");
- seg[n].type = Sint;
- seg[n].len = 0;
+ seg[n].type = Send;
a = 1 << al;
sz = (sz + a - 1) & -a;
if (sz >= ty->size)
diff --git a/sysv.c b/sysv.c
@@ -17,11 +17,44 @@ struct RAlloc {
};
static void
-aclass(AClass *a, Typ *t)
+classify(AClass *a, Typ *t, int *pn, int *pe)
{
- int e, s, n, cls;
- uint sz, al;
Seg *seg;
+ int n, s, *cls;
+
+ for (n=0; n<t->nunion; n++) {
+ seg = t->seg[n];
+ for (s=0; *pe<2; (*pe)++) {
+ cls = &a->cls[*pe];
+ for (; *pn<8 && seg[s].type!=Send; s++) {
+ switch (seg[s].type) {
+ case Spad:
+ /* don't change anything */
+ break;
+ case Sflt:
+ if (*cls == Kx)
+ *cls = Kd;
+ break;
+ case Sint:
+ *cls = Kl;
+ break;
+ case Styp:
+ classify(a, &typ[seg[s].len], pn, pe);
+ continue;
+ }
+ *pn += seg[s].len;
+ }
+ assert(*pn <= 8);
+ *pn = 0;
+ }
+ }
+}
+
+static void
+typclass(AClass *a, Typ *t)
+{
+ int e, n;
+ uint sz, al;
sz = t->size;
al = 1u << t->align;
@@ -46,31 +79,12 @@ aclass(AClass *a, Typ *t)
return;
}
- seg = t->seg[0];
+ a->cls[0] = Kx;
+ a->cls[1] = Kx;
a->inmem = 0;
- for (e=0, s=0; e<2; e++) {
- cls = -1;
- for (n=0; n<8 && seg[s].len; s++) {
- switch (seg[s].type) {
- case Spad:
- /* don't change anything */
- break;
- case Sflt:
- if (cls == -1)
- cls = Kd;
- break;
- case Sint:
- cls = Kl;
- break;
- case Styp:
- assert(!"todo");
- break;
- }
- n += seg[s].len;
- }
- assert(n <= 8);
- a->cls[e] = cls;
- }
+ n = 0;
+ e = 0;
+ classify(a, t, &n, &e);
}
static void
@@ -124,7 +138,7 @@ selret(Blk *b, Fn *fn)
b->jmp.type = Jret0;
if (j == Jretc) {
- aclass(&aret, &typ[fn->retty]);
+ typclass(&aret, &typ[fn->retty]);
if (aret.inmem) {
assert(rtype(fn->retr) == RTmp);
emit(Ocopy, Kl, TMP(RAX), fn->retr, R);
@@ -154,7 +168,7 @@ selret(Blk *b, Fn *fn)
}
static int
-classify(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret)
+argsclass(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret)
{
int nint, ni, nsse, ns, n, *pn;
AClass *a;
@@ -181,7 +195,7 @@ classify(Ins *i0, Ins *i1, AClass *ac, int op, AClass *aret)
a->cls[0] = i->cls;
} else {
n = i->arg[0].val;
- aclass(a, &typ[n]);
+ typclass(a, &typ[n]);
if (a->inmem)
continue;
ni = ns = 0;
@@ -279,10 +293,10 @@ selcall(Fn *fn, Ins *i0, Ins *i1, RAlloc **rap)
ac = alloc((i1-i0) * sizeof ac[0]);
if (!req(i1->arg[1], R)) {
assert(rtype(i1->arg[1]) == RType);
- aclass(&aret, &typ[i1->arg[1].val]);
- ca = classify(i0, i1, ac, Oarg, &aret);
+ typclass(&aret, &typ[i1->arg[1].val]);
+ ca = argsclass(i0, i1, ac, Oarg, &aret);
} else
- ca = classify(i0, i1, ac, Oarg, 0);
+ ca = argsclass(i0, i1, ac, Oarg, 0);
for (stk=0, a=&ac[i1-i0]; a>ac;)
if ((--a)->inmem) {
@@ -393,10 +407,10 @@ selpar(Fn *fn, Ins *i0, Ins *i1)
ni = ns = 0;
if (fn->retty >= 0) {
- aclass(&aret, &typ[fn->retty]);
- classify(i0, i1, ac, Opar, &aret);
+ typclass(&aret, &typ[fn->retty]);
+ argsclass(i0, i1, ac, Opar, &aret);
} else
- classify(i0, i1, ac, Opar, 0);
+ argsclass(i0, i1, ac, Opar, 0);
for (i=i0, a=ac; i<i1; i++, a++) {
if (i->op != Oparc || a->inmem)
diff --git a/test/abi5.ssa b/test/abi5.ssa
@@ -8,6 +8,8 @@ type :st5 = { s, l }
type :st6 = { b 16 }
type :st7 = { s, d }
type :st8 = { w 4 }
+type :un9 = { { b } { s } }
+type :st9 = { w, :un9 }
data $fmt1 = { b "t1: %s\n", b 0 }
data $fmt2 = { b "t2: %d\n", b 0 }
@@ -17,6 +19,7 @@ data $fmt5 = { b "t5: %f %lld\n", b 0 }
data $fmt6 = { b "t6: %s\n", b 0 }
data $fmt7 = { b "t7: %f %f\n", b 0 }
data $fmt8 = { b "t8: %d %d %d %d\n", b 0 }
+data $fmt9 = { b "t9: %d %f\n", b 0 }
export
function $test() {
@@ -68,6 +71,13 @@ function $test() {
%w84 =w loadw %r812
%i8 =w call $printf(l $fmt8, w %w81, w %w82, w %w83, w %w84)
+ %r9 =:st9 call $t9()
+ %r94 =l add 4, %r9
+ %w9 =w loadw %r9
+ %s9 =s loads %r94
+ %d9 =d exts %s9
+ %i9 =w call $printf(l $fmt9, w %w9, d %d9)
+
ret
}
@@ -82,6 +92,7 @@ function $test() {
# typedef struct { char t[16]; } st6;
# typedef struct { float f; double d; } st7;
# typedef struct { int i[4]; } st8;
+# typedef struct { int i; union { char c; float f; } u; } st9;
# extern void test(void);
# st1 t1() { return (st1){"abcdefghijklmnop"}; }
# st2 t2() { return (st2){2}; }
@@ -91,6 +102,7 @@ function $test() {
# st6 t6() { return (st6){"abcdefghijklmno"}; }
# st7 t7() { return (st7){7.77,77.7}; }
# st8 t8() { return (st8){-8,88,-888,8888}; }
+# st9 t9() { return (st9){9,{.f=9.9}}; }
# int main() { test(); return 0; }
# <<<
@@ -103,4 +115,5 @@ function $test() {
# t6: abcdefghijklmno
# t7: 7.770000 77.700000
# t8: -8 88 -888 8888
+# t9: 9 9.900000
# <<<