From cad13d0dce46dbbb42140a40f32245f73672dc39 Mon Sep 17 00:00:00 2001 From: Quentin Carbonneaux Date: Tue, 16 Aug 2016 13:26:16 -0700 Subject: add support for unions in sysv abi --- all.h | 5 ++-- parse.c | 3 +-- sysv.c | 86 ++++++++++++++++++++++++++++++++++------------------------- test/abi5.ssa | 13 +++++++++ 4 files changed, 67 insertions(+), 40 deletions(-) diff --git a/all.h b/all.h index b6392e5..39c85f1 100644 --- 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 index 7afa977..31a6d09 100644 --- 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 index 7e5b819..5a82f8e 100644 --- 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; nnunion; 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; iop != Oparc || a->inmem) diff --git a/test/abi5.ssa b/test/abi5.ssa index 7899035..c3d9046 100644 --- 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 # <<< -- cgit 1.4.1