diff options
author | Michael Forney <mforney@mforney.org> | 2019-04-24 22:28:52 -0700 |
---|---|---|
committer | Michael Forney <mforney@mforney.org> | 2019-04-24 22:32:22 -0700 |
commit | a71a7975c95b794983c4b83a26981c7b4d7f7c82 (patch) | |
tree | e8412ab368a931c8df30faab09c64e6283aae14f | |
parent | 0e9f74cb67f2227f888e9a127624f77d83aee270 (diff) |
Use a common member for expression base
-rw-r--r-- | cc.h | 17 | ||||
-rw-r--r-- | decl.c | 2 | ||||
-rw-r--r-- | eval.c | 10 | ||||
-rw-r--r-- | expr.c | 54 | ||||
-rw-r--r-- | init.c | 4 | ||||
-rw-r--r-- | qbe.c | 34 |
6 files changed, 52 insertions, 69 deletions
@@ -306,6 +306,7 @@ struct expr { /* the type qualifiers of the object this expression refers to (ignored for non-lvalues) */ enum typequal qual; enum tokenkind op; + struct expr *base; struct expr *next; union { struct { @@ -320,11 +321,10 @@ struct expr { size_t size; } string; struct { - struct expr *func, *args; + struct expr *args; size_t nargs; } call; struct { - struct expr *base; struct bitfield bits; } bitfield; struct { @@ -332,29 +332,18 @@ struct expr { } compound; struct { _Bool post; - struct expr *base; } incdec; struct { - struct expr *base; - } unary; - struct { - struct expr *e; - } cast; - struct { struct expr *l, *r; } binary; struct { - struct expr *e, *t, *f; + struct expr *t, *f; } cond; struct { struct expr *l, *r; } assign; struct { - struct expr *exprs; - } comma; - struct { enum builtinkind kind; - struct expr *arg; } builtin; struct value *temp; }; @@ -348,7 +348,7 @@ declspecs(struct scope *s, enum storageclass *sc, enum funcspec *fs, int *align) if (!t) { e = expr(s); if (e->decayed) - e = e->unary.base; + e = e->base; t = e->type; tq |= e->qual; delexpr(e); @@ -107,23 +107,23 @@ eval(struct expr *expr) expr->ident.decl = d; break; case EXPRUNARY: - l = eval(expr->unary.base); + l = eval(expr->base); if (expr->op != TBAND) break; switch (l->kind) { case EXPRUNARY: if (l->op == TMUL) - expr = eval(l->unary.base); + expr = eval(l->base); break; case EXPRSTRING: l->ident.decl = stringdecl(l); l->kind = EXPRIDENT; - expr->unary.base = l; + expr->base = l; break; } break; case EXPRCAST: - l = eval(expr->cast.e); + l = eval(expr->base); if (l->kind == EXPRCONST) { expr->kind = EXPRCONST; if (l->type->prop & PROPINT && expr->type->prop & PROPFLOAT) @@ -176,7 +176,7 @@ eval(struct expr *expr) case EXPRCOND: l = expr->cond.t; r = expr->cond.f; - c = eval(expr->cond.e); + c = eval(expr->base); if (c->kind != EXPRCONST) break; return eval(c->constant.i ? l : r); @@ -33,30 +33,24 @@ delexpr(struct expr *e) switch (e->kind) { case EXPRCALL: - delexpr(e->call.func); + delexpr(e->base); while (sub = e->call.args) { e->call.args = sub->next; delexpr(sub); } break; case EXPRBITFIELD: - delexpr(e->bitfield.base); - break; case EXPRINCDEC: - delexpr(e->incdec.base); - break; case EXPRUNARY: - delexpr(e->unary.base); - break; case EXPRCAST: - delexpr(e->cast.e); + delexpr(e->base); break; case EXPRBINARY: delexpr(e->binary.l); delexpr(e->binary.r); break; case EXPRCOND: - delexpr(e->cond.e); + delexpr(e->base); delexpr(e->cond.t); delexpr(e->cond.f); break; @@ -70,8 +64,8 @@ delexpr(struct expr *e) break; */ case EXPRCOMMA: - while (sub = e->comma.exprs) { - e->comma.exprs = sub->next; + while (sub = e->base) { + e->base = sub->next; delexpr(sub); } break; @@ -138,7 +132,7 @@ mkunaryexpr(enum tokenkind op, struct expr *base) error(&tok.loc, "cannot take address of bit-field"); expr = mkexpr(EXPRUNARY, mkpointertype(base->type, base->qual)); expr->op = op; - expr->unary.base = base; + expr->base = base; return expr; case TMUL: if (base->type->kind != TYPEPOINTER) @@ -147,7 +141,7 @@ mkunaryexpr(enum tokenkind op, struct expr *base) expr->qual = base->type->qual; expr->lvalue = true; expr->op = op; - expr->unary.base = base; + expr->base = base; return decay(expr); } /* other unary operators get compiled as equivalent binary ones */ @@ -560,7 +554,7 @@ builtinfunc(struct scope *s, enum builtinkind kind) case BUILTINALLOCA: e = mkexpr(EXPRBUILTIN, mkpointertype(&typevoid, QUALNONE)); e->builtin.kind = BUILTINALLOCA; - e->builtin.arg = exprconvert(assignexpr(s), &typeulong); + e->base = exprconvert(assignexpr(s), &typeulong); break; case BUILTINCONSTANTP: e = mkconstexpr(&typeint, eval(condexpr(s))->kind == EXPRCONST); @@ -572,7 +566,7 @@ builtinfunc(struct scope *s, enum builtinkind kind) break; case BUILTINNANF: e = assignexpr(s); - if (!e->decayed || e->unary.base->kind != EXPRSTRING || e->unary.base->string.size > 0) + if (!e->decayed || e->base->kind != EXPRSTRING || e->base->string.size > 0) error(&tok.loc, "__builtin_nanf currently only supports empty string literals"); e = mkexpr(EXPRCONST, &typefloat); /* TODO: use NAN here when we can handle musl's math.h */ @@ -600,7 +594,7 @@ builtinfunc(struct scope *s, enum builtinkind kind) case BUILTINVAARG: e = mkexpr(EXPRBUILTIN, NULL); e->builtin.kind = BUILTINVAARG; - e->builtin.arg = exprconvert(assignexpr(s), &typevalistptr); + e->base = exprconvert(assignexpr(s), &typevalistptr); expect(TCOMMA, "after va_list"); e->type = typename(s, &e->qual); break; @@ -619,7 +613,7 @@ builtinfunc(struct scope *s, enum builtinkind kind) case BUILTINVASTART: e = mkexpr(EXPRBUILTIN, &typevoid); e->builtin.kind = BUILTINVASTART; - e->builtin.arg = exprconvert(assignexpr(s), &typevalistptr); + e->base = exprconvert(assignexpr(s), &typevalistptr); expect(TCOMMA, "after va_list"); param = assignexpr(s); if (param->kind != EXPRIDENT) @@ -644,7 +638,7 @@ mkincdecexpr(enum tokenkind op, struct expr *base, bool post) error(&tok.loc, "operand of '%s' operator is const qualified", tokstr[op]); e = mkexpr(EXPRINCDEC, base->type); e->op = op; - e->incdec.base = base; + e->base = base; e->incdec.post = post; return e; } @@ -694,7 +688,7 @@ postfixexpr(struct scope *s, struct expr *r) error(&tok.loc, "called object is not a function"); t = r->type->base; e = mkexpr(EXPRCALL, t->base); - e->call.func = r; + e->base = r; e->call.args = NULL; e->call.nargs = 0; p = t->func.params; @@ -735,7 +729,7 @@ postfixexpr(struct scope *s, struct expr *r) next(); if (tok.kind != TIDENT) error(&tok.loc, "expected identifier after '%s' operator", tokstr[op]); - lvalue = op == TARROW || r->unary.base->lvalue; + lvalue = op == TARROW || r->base->lvalue; r = exprconvert(r, mkpointertype(&typechar, QUALNONE)); offset = 0; m = typemember(t, tok.lit, &offset); @@ -748,7 +742,7 @@ postfixexpr(struct scope *s, struct expr *r) if (m->bits.before || m->bits.after) { e = mkexpr(EXPRBITFIELD, r->type); e->lvalue = lvalue; - e->bitfield.base = r; + e->base = r; e->bitfield.bits = m->bits; } else { e = r; @@ -836,13 +830,13 @@ unaryexpr(struct scope *s) if (op == TSIZEOF) e = postfixexpr(s, e); if (e->decayed) - e = e->unary.base; + e = e->base; t = e->type; } } else if (op == TSIZEOF) { e = unaryexpr(s); if (e->decayed) - e = e->unary.base; + e = e->base; t = e->type; } else { error(&tok.loc, "expected ')' after '_Alignof'"); @@ -886,7 +880,7 @@ castexpr(struct scope *s) e = mkexpr(EXPRCAST, t); // XXX check types 6.5.4 *end = e; - end = &e->cast.e; + end = &e->base; } *end = unaryexpr(s); @@ -962,7 +956,7 @@ condexpr(struct scope *s) if (!consume(TQUESTION)) return r; e = mkexpr(EXPRCOND, NULL); - e->cond.e = exprconvert(r, &typebool); + e->base = exprconvert(r, &typebool); e->cond.t = expr(s); expect(TCOLON, "in conditional expression"); e->cond.f = condexpr(s); @@ -1064,7 +1058,7 @@ assignexpr(struct scope *s) /* rewrite `E1 OP= E2` as `T = &E1, *T = *T OP E2`, where T is a temporary slot */ if (l->kind == EXPRBITFIELD) { bit = l; - l = l->bitfield.base; + l = l->base; } else { bit = NULL; } @@ -1074,13 +1068,13 @@ assignexpr(struct scope *s) e = mkassignexpr(tmp, mkunaryexpr(TBAND, l)); l = mkunaryexpr(TMUL, tmp); if (bit) { - bit->bitfield.base = l; + bit->base = l; l = bit; } r = mkbinaryexpr(&tok.loc, op, l, r); e->next = mkassignexpr(l, r); l = mkexpr(EXPRCOMMA, l->type); - l->comma.exprs = e; + l->base = e; return l; } @@ -1101,7 +1095,7 @@ expr(struct scope *s) if (!r->next) return r; e = mkexpr(EXPRCOMMA, e->type); - e->comma.exprs = r; + e->base = r; return e; } @@ -1114,7 +1108,7 @@ exprconvert(struct expr *e, struct type *t) if (typecompatible(e->type, t)) return e; cast = mkexpr(EXPRCAST, t); - cast->cast.e = e; + cast->base = e; return cast; } @@ -240,8 +240,8 @@ parseinit(struct scope *s, struct type *t) t = p.sub->type; switch (t->kind) { case TYPEARRAY: - if (expr->decayed && expr->unary.base->kind == EXPRSTRING) { - expr = expr->unary.base; + if (expr->decayed && expr->base->kind == EXPRSTRING) { + expr = expr->base; base = t->base; /* XXX: wide string literals */ if (!(base->prop & PROPCHAR)) @@ -493,7 +493,7 @@ funclval(struct func *f, struct expr *e) if (e->kind == EXPRBITFIELD) { lval.bits = e->bitfield.bits; - e = e->bitfield.base; + e = e->base; } switch (e->kind) { case EXPRIDENT: @@ -520,7 +520,7 @@ funclval(struct func *f, struct expr *e) case EXPRUNARY: if (e->op != TMUL) break; - lval.addr = funcexpr(f, e->unary.base); + lval.addr = funcexpr(f, e->base); break; default: if (e->type->kind != TYPESTRUCT && e->type->kind != TYPEUNION) @@ -642,8 +642,8 @@ funcexpr(struct func *f, struct expr *e) lval = funclval(f, e); return funcload(f, e->type, lval); case EXPRINCDEC: - lval = funclval(f, e->incdec.base); - l = funcload(f, e->incdec.base->type, lval); + lval = funclval(f, e->base); + l = funcload(f, e->base->type, lval); if (e->type->kind == TYPEPOINTER) r = mkintconst(e->type->repr, e->type->base->size); else if (e->type->prop & PROPINT) @@ -657,26 +657,26 @@ funcexpr(struct func *f, struct expr *e) return e->incdec.post ? l : v; case EXPRCALL: argvals = xreallocarray(NULL, e->call.nargs + 3, sizeof(argvals[0])); - argvals[0] = funcexpr(f, e->call.func); + argvals[0] = funcexpr(f, e->base); emittype(e->type); for (argval = &argvals[1], arg = e->call.args; arg; ++argval, arg = arg->next) { emittype(arg->type); *argval = funcexpr(f, arg); } *argval = NULL; - op = e->call.func->type->base->func.isvararg ? IVACALL : ICALL; + op = e->base->type->base->func.isvararg ? IVACALL : ICALL; v = funcinstn(f, op, e->type == &typevoid ? NULL : e->type->repr, argvals); free(argvals); - //if (e->call.func->type->base->func.isnoreturn) + //if (e->base->type->base->func.isnoreturn) // funcret(f, NULL); return v; case EXPRUNARY: switch (e->op) { case TBAND: - lval = funclval(f, e->unary.base); + lval = funclval(f, e->base); return lval.addr; case TMUL: - r = funcexpr(f, e->unary.base); + r = funcexpr(f, e->base); return funcload(f, e->type, (struct lvalue){r}); } fatal("internal error; unknown unary expression"); @@ -684,10 +684,10 @@ funcexpr(struct func *f, struct expr *e) case EXPRCAST: { struct type *src, *dst; - l = funcexpr(f, e->cast.e); + l = funcexpr(f, e->base); r = NULL; - src = e->cast.e->type; + src = e->base->type; if (src->kind == TYPEPOINTER) src = &typeulong; dst = e->type; @@ -847,7 +847,7 @@ funcexpr(struct func *f, struct expr *e) label[1] = mkblock("cond_false"); label[2] = mkblock("cond_join"); - v = funcexpr(f, e->cond.e); + v = funcexpr(f, e->base); funcjnz(f, v, label[0], label[1]); funclabel(f, label[0]); @@ -873,23 +873,23 @@ funcexpr(struct func *f, struct expr *e) } return r; case EXPRCOMMA: - for (e = e->comma.exprs; e->next; e = e->next) + for (e = e->base; e->next; e = e->next) funcexpr(f, e); return funcexpr(f, e); case EXPRBUILTIN: switch (e->builtin.kind) { case BUILTINVASTART: - l = funcexpr(f, e->builtin.arg); + l = funcexpr(f, e->base); funcinst(f, IVASTART, NULL, l); break; case BUILTINVAARG: - l = funcexpr(f, e->builtin.arg); + l = funcexpr(f, e->base); return funcinst(f, IVAARG, e->type->repr, l); case BUILTINVAEND: /* no-op */ break; case BUILTINALLOCA: - l = funcexpr(f, e->builtin.arg); + l = funcexpr(f, e->base); return funcinst(f, IALLOC16, &iptr, l); default: fatal("internal error: unimplemented builtin"); @@ -1193,7 +1193,7 @@ dataitem(struct expr *expr, uint64_t size) case EXPRUNARY: if (expr->op != TBAND) fatal("not a address expr"); - expr = expr->unary.base; + expr = expr->base; if (expr->kind != EXPRIDENT) error(&tok.loc, "initializer is not a constant expression"); decl = expr->ident.decl; |