cproc

Unnamed repository; edit this file 'description' to name the repository.
git clone git://git.nihaljere.xyz/cproc
Log | Files | Refs | Submodules | README | LICENSE

commit 5b8a2d225ca3777c7b49421182bb5c1faf99ae64
parent b3865e402e426387d4cdccdcd249a02d5ba1bc05
Author: Michael Forney <mforney@mforney.org>
Date:   Wed,  3 Apr 2019 12:36:14 -0700

Revert "Make member access its own expression type"

This reverts commit b3865e402e426387d4cdccdcd249a02d5ba1bc05.

This breaks member address expressions in static initializers. We can
support bit-fields by instead adding a "bit-field" expression that
affects loads and stores to the underlying object.

Diffstat:
Mexpr.c | 24++++++++++++------------
Mexpr.h | 10+++-------
Mqbe.c | 3---
Mtests/struct-return-2.qbe | 9++++++---
4 files changed, 21 insertions(+), 25 deletions(-)

diff --git a/expr.c b/expr.c @@ -483,7 +483,9 @@ postfixexpr(struct scope *s, struct expr *r) struct type *t; enum typequal tq; struct param *p; + uint64_t offset; enum tokenkind op; + bool lvalue; if (!r) r = primaryexpr(s); @@ -564,19 +566,17 @@ postfixexpr(struct scope *s, struct expr *r) next(); if (tok.kind != TIDENT) error(&tok.loc, "expected identifier after '->' operator"); - e = mkexpr(EXPRMEMBER, NULL, 0); - e->member.base = r; - e->member.offset = 0; - e->type = typemember(t, tok.lit, &e->member.offset); - if (!e->type) + lvalue = op == TARROW || r->unary.base->flags & EXPRFLAG_LVAL; + r = exprconvert(r, mkpointertype(&typechar)); + offset = 0; + t = typemember(t, tok.lit, &offset); + if (!t) error(&tok.loc, "struct/union has no member named '%s'", tok.lit); - if (op == TARROW || r->unary.base->flags & EXPRFLAG_LVAL) { - e->type = mkqualifiedtype(e->type, tq); - e->flags |= EXPRFLAG_LVAL; - } else { - e->type = typeunqual(e->type, NULL); - } - e = decay(e); + r = mkbinaryexpr(&tok.loc, TADD, r, mkconstexpr(&typeulong, offset)); + r = exprconvert(r, mkpointertype(mkqualifiedtype(t, tq))); + e = mkunaryexpr(TMUL, r); + if (!lvalue) + e->flags &= ~EXPRFLAG_LVAL; next(); break; case TINC: diff --git a/expr.h b/expr.h @@ -6,7 +6,7 @@ enum exprkind { /* postfix expression */ EXPRCALL, - EXPRMEMBER, + /* member E.M gets transformed to *(typeof(E.M) *)((char *)E + offsetof(typeof(E), M)) */ EXPRINCDEC, EXPRCOMPOUND, /* subscript E1[E2] gets transformed to *((E1)+(E2)) */ @@ -49,18 +49,14 @@ struct expr { size_t nargs; } call; struct { - struct expr *base; - size_t offset; - } member; + struct init *init; + } compound; struct { int op; _Bool post; struct expr *base; } incdec; struct { - struct init *init; - } compound; - struct { int op; struct expr *base; } unary; diff --git a/qbe.c b/qbe.c @@ -479,8 +479,6 @@ objectaddr(struct func *f, struct expr *e) case EXPRSTRING: d = stringdecl(e); return d->value; - case EXPRMEMBER: - return funcinst(f, IADD, &iptr, funcexpr(f, e->member.base), mkintconst(&iptr, e->member.offset)); case EXPRCOMPOUND: d = mkdecl(DECLOBJECT, e->type, LINKNONE); funcinit(f, d, e->compound.init); @@ -601,7 +599,6 @@ funcexpr(struct func *f, struct expr *e) if (typeprop(e->type) & PROPINT || e->type->kind == TYPEPOINTER) return mkintconst(e->type->repr, e->constant.i); return mkfltconst(e->type->repr, e->constant.f); - case EXPRMEMBER: case EXPRCOMPOUND: l = objectaddr(f, e); return funcload(f, e->type, l); diff --git a/tests/struct-return-2.qbe b/tests/struct-return-2.qbe @@ -5,7 +5,10 @@ function w $f() { @body.2 %.1 =:.1 call $g() %.2 =l copy %.1 - %.3 =l add %.2, 4 - %.4 =w loadsw %.3 - ret %.4 + %.3 =l copy %.2 + %.4 =l mul 4, 1 + %.5 =l add %.3, %.4 + %.6 =l copy %.5 + %.7 =w loadsw %.6 + ret %.7 }