From f453b313f62ba42d748f00628be7b3750c797c86 Mon Sep 17 00:00:00 2001 From: lemon Date: Thu, 29 Jun 2023 09:59:30 +0200 Subject: add initializers (only static for initialier list rn) and other fixes --- eval.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) (limited to 'eval.c') diff --git a/eval.c b/eval.c index 71be890..2a2de6d 100644 --- a/eval.c +++ b/eval.c @@ -77,6 +77,30 @@ unop(struct expr *ex, enum evalmode mode) { struct expr *sub = ex->sub; + if (mode >= EVSTATICINI && ex->t == EDEREF) { + uvlong off; + struct bytes s; + if (sub->t == ESTRLIT) { + /* *"s" */ + off = 0; + s = sub->s; + } else if (sub->t == EADD && sub->sub[0].t == ESTRLIT && eval(&sub->sub[1], EVINTCONST)) { + /* "s"[0] */ + assert(sub->sub[1].t == ENUMLIT && isint(sub->sub[1].ty)); + off = sub->sub[1].u; + s = sub->sub[0].s; + } else if (sub->t == EADD && sub->sub[1].t == ESTRLIT && eval(&sub->sub[0], EVINTCONST)) { + /* 0["s"] */ + assert(sub->sub[0].t == ENUMLIT && isint(sub->sub[0].ty)); + off = sub->sub[0].u; + s = sub->sub[1].s; + } else return 0; + if (off > s.n) return 0; + ex->t = ENUMLIT; + ex->ty = mktype(TYINT); + ex->u = off == s.n ? 0 : s.p[off]; + return 1; + } if (sub->t != ENUMLIT && !eval(sub, mode)) return 0; switch (ex->t) { case ECAST: @@ -101,6 +125,30 @@ unop(struct expr *ex, enum evalmode mode) return 1; } +/* link time constants */ +static bool +isglobsym(const struct expr *ex) +{ + return ex->t == ESTRLIT || (ex->t == ESYM && ex->sym && (ex->sym->scls & (SCSTATIC | SCEXTERN))); +} + +static bool +isaddrconst(struct expr *ex) +{ + if (ex->t == EADDROF && isglobsym(ex->sub)) + return 1; + if (isglobsym(ex) && in_range(ex->ty.t, TYARRAY, TYFUNC)) + return 1; + if (ex->t == ESUB) + return isglobsym(&ex->sub[0]) && isint(ex->sub[1].ty) && eval(&ex->sub[1], EVSTATICINI); + if (ex->t == EADD) { + for (int swp = 0; swp < 2; ++swp) + if (isglobsym(&ex->sub[swp]) && isint(ex->sub[swp^1].ty) && eval(&ex->sub[swp^1], EVSTATICINI)) + return 1; + } + return 0; +} + static bool binop(struct expr *ex, enum evalmode mode) { @@ -205,6 +253,8 @@ eval(struct expr *ex, enum evalmode mode) if (mode <= EVINTCONST) return isint(ex->ty); return 1; } + if (mode == EVSTATICINI && isaddrconst(ex)) + return 1; if (isunop(ex->t)) return unop(ex, mode) && eval(ex, mode); if (isbinop(ex->t)) return binop(ex, mode) && eval(ex, mode); if (ex->t == ESEQ) { -- cgit v1.2.3