From 2e3ecc7000138622a528eef7681bfdd8ca0bc3c5 Mon Sep 17 00:00:00 2001 From: Michael Forney Date: Sat, 23 Mar 2024 14:15:00 -0700 Subject: expr: Keep track of storage duration of compound literals --- cc.h | 14 ++++++++------ decl.c | 2 +- eval.c | 16 +++++++--------- expr.c | 15 ++++++++------- qbe.c | 2 +- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/cc.h b/cc.h index bd05deb..b75d511 100644 --- a/cc.h +++ b/cc.h @@ -247,6 +247,12 @@ enum linkage { LINKEXTERN, }; +enum storageduration { + SDSTATIC, + SDTHREAD, + SDAUTO, +}; + enum builtinkind { BUILTINALLOCA, BUILTINCONSTANTP, @@ -360,6 +366,7 @@ struct expr { struct bitfield bits; } bitfield; struct { + enum storageduration storage; struct init *init; } compound; struct { @@ -502,12 +509,7 @@ struct expr *exprpromote(struct expr *); /* eval */ -enum evalkind { - EVALARITH, /* arithmetic constant expression */ - EVALINIT, /* initializer constant expression */ -}; - -struct expr *eval(struct expr *, enum evalkind); +struct expr *eval(struct expr *); /* init */ diff --git a/decl.c b/decl.c index fc48dc9..34e61f4 100644 --- a/decl.c +++ b/decl.c @@ -625,7 +625,7 @@ declaratortypes(struct scope *s, struct list *result, char **name, bool allowabs error(&tok.loc, "VLAs are not yet supported"); t = mkarraytype(NULL, tq, 0); if (tok.kind != TRBRACK) { - e = eval(assignexpr(s), EVALARITH); + e = eval(assignexpr(s)); if (e->kind != EXPRCONST || !(e->type->prop & PROPINT)) error(&tok.loc, "VLAs are not yet supported"); i = e->u.constant.u; diff --git a/eval.c b/eval.c index 9b6b33c..e1be25e 100644 --- a/eval.c +++ b/eval.c @@ -101,7 +101,7 @@ binary(struct expr *expr, enum tokenkind op, struct expr *l, struct expr *r) #undef S struct expr * -eval(struct expr *expr, enum evalkind kind) +eval(struct expr *expr) { struct expr *l, *r, *c; struct decl *d; @@ -116,7 +116,7 @@ eval(struct expr *expr, enum evalkind kind) expr->u.constant.u = intconstvalue(expr->u.ident.decl->value); break; case EXPRCOMPOUND: - if (kind != EVALINIT) + if (expr->u.compound.storage != SDSTATIC) break; d = mkdecl(DECLOBJECT, t, expr->qual, LINKNONE); d->value = mkglobal(NULL, true); @@ -125,17 +125,15 @@ eval(struct expr *expr, enum evalkind kind) expr->u.ident.decl = d; break; case EXPRUNARY: - l = eval(expr->base, kind); + l = eval(expr->base); switch (expr->op) { case TBAND: switch (l->kind) { case EXPRUNARY: if (l->op == TMUL) - expr = eval(l->base, kind); + expr = eval(l->base); break; case EXPRSTRING: - if (kind != EVALINIT) - break; l->u.ident.decl = stringdecl(l); l->kind = EXPRIDENT; expr->base = l; @@ -152,7 +150,7 @@ eval(struct expr *expr, enum evalkind kind) } break; case EXPRCAST: - l = eval(expr->base, kind); + l = eval(expr->base); if (l->kind == EXPRCONST) { expr->kind = EXPRCONST; if (l->type->prop & PROPINT && t->prop & PROPFLOAT) { @@ -186,8 +184,8 @@ eval(struct expr *expr, enum evalkind kind) } break; case EXPRBINARY: - l = eval(expr->u.binary.l, kind); - r = eval(expr->u.binary.r, kind); + l = eval(expr->u.binary.l); + r = eval(expr->u.binary.r); expr->u.binary.l = l; expr->u.binary.r = r; switch (expr->op) { diff --git a/expr.c b/expr.c index 9a168de..d9fb9b6 100644 --- a/expr.c +++ b/expr.c @@ -271,11 +271,11 @@ mkbinaryexpr(struct location *loc, enum tokenkind op, struct expr *l, struct exp e = l, l = r, r = e; if (l->type->kind != TYPEPOINTER) error(loc, "invalid operands to '%s' operator", tokstr[op]); - if (nullpointer(eval(r, EVALARITH))) { + if (nullpointer(eval(r))) { r = exprconvert(r, l->type); break; } - if (nullpointer(eval(l, EVALARITH))) { + if (nullpointer(eval(l))) { l = exprconvert(l, r->type); break; } @@ -781,7 +781,7 @@ builtinfunc(struct scope *s, enum builtinkind kind) e->u.builtin.kind = BUILTINALLOCA; break; case BUILTINCONSTANTP: - e = mkconstexpr(&typeint, eval(condexpr(s), EVALARITH)->kind == EXPRCONST); + e = mkconstexpr(&typeint, eval(condexpr(s))->kind == EXPRCONST); break; case BUILTINEXPECT: /* just a no-op for now */ @@ -1126,6 +1126,7 @@ castexpr(struct scope *s) e->qual = tq; e->lvalue = true; e->u.compound.init = parseinit(s, t); + e->u.compound.storage = s == &filescope ? SDSTATIC : SDAUTO; e = postfixexpr(s, decay(e)); goto done; } @@ -1216,8 +1217,8 @@ condexpr(struct scope *s) } else if (lt == &typevoid && rt == &typevoid) { t = &typevoid; } else { - l = eval(l, EVALARITH); - r = eval(r, EVALARITH); + l = eval(l); + r = eval(r); if (nullpointer(l) && rt->kind == TYPEPOINTER) { t = rt; } else if (nullpointer(r) && lt->kind == TYPEPOINTER) { @@ -1239,7 +1240,7 @@ condexpr(struct scope *s) error(&tok.loc, "invalid operands to conditional operator"); } } - e = eval(e, EVALARITH); + e = eval(e); if (e->kind == EXPRCONST && e->type->prop & PROPINT) return exprconvert(e->u.constant.u ? l : r, t); e = mkexpr(EXPRCOND, t, e); @@ -1251,7 +1252,7 @@ condexpr(struct scope *s) struct expr * evalexpr(struct scope *s) { - return eval(condexpr(s), EVALARITH); + return eval(condexpr(s)); } unsigned long long diff --git a/qbe.c b/qbe.c index 08d10b5..60e911f 100644 --- a/qbe.c +++ b/qbe.c @@ -1323,7 +1323,7 @@ emitdata(struct decl *d, struct init *init) align = d->u.obj.align; for (cur = init; cur; cur = cur->next) - cur->expr = eval(cur->expr, EVALINIT); + cur->expr = eval(cur->expr); if (d->linkage == LINKEXTERN) fputs("export ", stdout); fputs("data ", stdout); -- cgit v1.2.3