aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Forney <mforney@mforney.org>2019-04-24 22:28:52 -0700
committerMichael Forney <mforney@mforney.org>2019-04-24 22:32:22 -0700
commita71a7975c95b794983c4b83a26981c7b4d7f7c82 (patch)
treee8412ab368a931c8df30faab09c64e6283aae14f
parent0e9f74cb67f2227f888e9a127624f77d83aee270 (diff)
Use a common member for expression base
-rw-r--r--cc.h17
-rw-r--r--decl.c2
-rw-r--r--eval.c10
-rw-r--r--expr.c54
-rw-r--r--init.c4
-rw-r--r--qbe.c34
6 files changed, 52 insertions, 69 deletions
diff --git a/cc.h b/cc.h
index a1dabd6..e3aebeb 100644
--- a/cc.h
+++ b/cc.h
@@ -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;
};
diff --git a/decl.c b/decl.c
index 6355689..3ebf51a 100644
--- a/decl.c
+++ b/decl.c
@@ -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);
diff --git a/eval.c b/eval.c
index 0473f4c..1d19180 100644
--- a/eval.c
+++ b/eval.c
@@ -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);
diff --git a/expr.c b/expr.c
index ee498d0..49e01c0 100644
--- a/expr.c
+++ b/expr.c
@@ -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;
}
diff --git a/init.c b/init.c
index 2eee141..edecfa0 100644
--- a/init.c
+++ b/init.c
@@ -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))
diff --git a/qbe.c b/qbe.c
index 750fb75..379d6d4 100644
--- a/qbe.c
+++ b/qbe.c
@@ -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;