From: Ulya Trofimovich Date: Fri, 7 Apr 2017 15:19:00 +0000 (+0100) Subject: 'save' commands for tags with history may need fallback copies. X-Git-Tag: 1.0~39^2~77 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=a50862bb606268ab0174a7ad6822b2cd68f04985;p=re2c 'save' commands for tags with history may need fallback copies. For simple tags without history 'save' command is self-sufficient: it does not depend on anything. However, for tags with history 'save' commands depend on history, which may be overwritten on the way from accepting state to fallback transition. We must take care and backup such overwritten histories when leaving the accepting state. If history is not overwritten, we don't need a copy, but we still have to propagate its liveness forward on all fallthrough paths outgoing from accepting state. --- diff --git a/re2c/src/dfa/cfg/liveanal.cc b/re2c/src/dfa/cfg/liveanal.cc index f03b3783..0a22391a 100644 --- a/re2c/src/dfa/cfg/liveanal.cc +++ b/re2c/src/dfa/cfg/liveanal.cc @@ -145,6 +145,10 @@ void cfg_t::liveness_analysis(const cfg_t &cfg, bool *live) // not the same as backward propagation of liveness through bblock for (const tcmd_t *p = b->cmd; p; p = p->next) { buf1[p->lhs] = false; + const tagver_t h = p->pred; + if (h != TAGVER_ZERO) { + buf1[h] = true; + } } for (const tcmd_t *p = b->cmd; p; p = p->next) { const tagver_t v = p->rhs; diff --git a/re2c/src/dfa/fallback_tags.cc b/re2c/src/dfa/fallback_tags.cc index de36641d..a5c4fd0d 100644 --- a/re2c/src/dfa/fallback_tags.cc +++ b/re2c/src/dfa/fallback_tags.cc @@ -49,6 +49,19 @@ void find_overwritten_tags(const dfa_t &dfa, size_t state, } } +// overwritten tags need 'copy' on all outgoing non-accepting paths +// ('copy' commands must go first, before potential overwrites) +static void backup(dfa_t &dfa, dfa_state_t *s, tagver_t l, tagver_t r) +{ + for (size_t c = 0; c < dfa.nchars; ++c) { + size_t i = s->arcs[c]; + if (i != dfa_t::NIL && dfa.states[i]->fallthru) { + tcmd_t *&p = s->tcmd[c]; + p = dfa.tcpool.make_tcmd(p, l, r, TAGVER_ZERO); + } + } +} + // WARNING: this function assumes that falthrough and fallback // attributes of DFA states have already been calculated, see // note [fallback states] @@ -74,28 +87,25 @@ void insert_fallback_tags(dfa_t &dfa) for (; p; p = p->next) { const tagver_t l = p->lhs, r = p->rhs, v = p->pred; - // 'save' commands are the same as for final transition - if (!tcmd_t::iscopy(r)) { - t = pool.make_tcmd(t, l, r, v); - continue; - } - - // non-overwritten tags need 'copy' on fallback transition - if (!owrt[r]) { - f = pool.make_tcmd(f, l, r, v); - continue; - } + // 'copy' commands + if (tcmd_t::iscopy(r)) { + if (!owrt[r]) { + f = pool.make_tcmd(f, l, r, v); + } else { + backup(dfa, s, l, r); + } - // overwritten tags need 'copy' on all outgoing non-accepting paths - // ('copy' commands must go first, before potential overwrites) - for (size_t c = 0; c < nsym; ++c) { - size_t j = s->arcs[c]; - if (j != dfa_t::NIL && dfa.states[j]->fallthru) { - tcmd_t *&q = s->tcmd[c]; - q = pool.make_tcmd(q, l, r, v); + // 'save' commands + } else { + if (v == TAGVER_ZERO || !owrt[v]) { + t = pool.make_tcmd(t, l, r, v); + } else { + t = pool.make_tcmd(t, l, r, l); + backup(dfa, s, l, v); } } } + // join 'copy' (fallback) and 'save' commands for (pf = &f; *pf; pf = &(*pf)->next); *pf = t;