From 0beaca9548a524557d33d3c618e5ec586cf489d3 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sun, 17 Feb 2019 13:01:51 -0800 Subject: Allow computing address of non-lvalue structs/unions We currently compile '.' member access as taking the address of the struct, adding the offset, and then dereferencing as the member type. However, the '.' operator is allowed on non-lvalues, even though the '&' operator is not. So, we need to handle arbitrary struct/union expressions in objectaddr by just compiling them normally, then converting them to regular pointers (since struct/union values are just pointers with additional type information). --- qbe.c | 9 +++++++-- tests/struct-return-2.c | 6 +++--- tests/struct-return-2.qbe | 14 ++++++++++---- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/qbe.c b/qbe.c index 2080e7c..29f005b 100644 --- a/qbe.c +++ b/qbe.c @@ -463,8 +463,13 @@ objectaddr(struct function *f, struct expression *e) funcinit(f, d, e->compound.init); return d->value; case EXPRUNARY: - if (e->unary.op == TMUL) - return funcexpr(f, e->unary.base); + if (e->unary.op != TMUL) + break; + return funcexpr(f, e->unary.base); + default: + if (e->type->kind != TYPESTRUCT && e->type->kind != TYPEUNION) + break; + return funcinst(f, ICOPY, &iptr, (struct value *[]){funcexpr(f, e)}); } error(&tok.loc, "expression is not an object"); } diff --git a/tests/struct-return-2.c b/tests/struct-return-2.c index 9fa50f5..726e667 100644 --- a/tests/struct-return-2.c +++ b/tests/struct-return-2.c @@ -1,4 +1,4 @@ -struct s {int x;} g(void); -void f(void) { - g(); +struct {int x, y;} g(void); +int f(void) { + return g().y; } diff --git a/tests/struct-return-2.qbe b/tests/struct-return-2.qbe index 2f1d3da..415ec2f 100644 --- a/tests/struct-return-2.qbe +++ b/tests/struct-return-2.qbe @@ -1,8 +1,14 @@ -type :s.1 = { w, } +type :.1 = { w, w, } export -function $f() { +function w $f() { @start.1 @body.2 - %.1 =:s.1 call $g() - ret + %.1 =:.1 call $g() + %.2 =l copy %.1 + %.3 =l copy %.2 + %.4 =l mul 4, 1 + %.5 =l add %.3, %.4 + %.6 =l copy %.5 + %.7 =w loadsw %.6 + ret %.7 } -- cgit v1.2.3