src/ir/dfa/dfa.h \
src/ir/dfa/find_state.h \
src/ir/dfa/tag_optimize.h \
+ src/ir/dfa/tagpool.h \
src/ir/nfa/nfa.h \
src/ir/regexp/encoding/case.h \
src/ir/regexp/encoding/enc.h \
src/ir/dfa/tag_liveness.cc \
src/ir/dfa/tag_optimize.cc \
src/ir/dfa/tag_renaming.cc \
+ src/ir/dfa/tagpool.cc \
src/ir/regexp/encoding/enc.cc \
src/ir/regexp/encoding/range_suffix.cc \
src/ir/regexp/encoding/utf8/utf8_regexp.cc \
{
const bool generic = opts->input_api.type() == InputAPI::CUSTOM;
const std::valarray<Tag> &tags = dfa.tags;
- const tagver_t *vers = dfa.tagpool[rule.tags];
+ const tagver_t *vers = rule.tags;
// trailing context
if (rule.trail != Tag::NONE) {
, head(NULL)
, rules(dfa.rules)
, tags(dfa.tags)
- , tagpool(dfa.tagpool)
, max_fill (0)
, need_backup (false)
, need_accept (false)
delete skeleton;
delete &rules;
delete &tags;
- delete &tagpool;
}
/* note [reordering DFA states]
State * head;
std::valarray<Rule> &rules;
std::valarray<Tag> &tags;
- Tagpool &tagpool;
size_t max_fill;
bool need_backup;
bool need_accept;
, nchars(charset.size() - 1) // (n + 1) bounds for n ranges
, rules(nfa.rules)
, tags(*nfa.tags)
- , tagpool(*nfa.tagpool)
, maxtagver(0)
{
const size_t ntag = tags.size();
+ Tagpool tagpool(ntag);
clospool_t clospool;
closure_t clos1, clos2;
bool *badtags = new bool[ntag]();
#include "src/ir/regexp/regexp.h"
#include "src/ir/rule.h"
#include "src/ir/tag.h"
+#include "src/ir/dfa/tagpool.h"
#include "src/util/forbid_copy.h"
namespace re2c
const size_t nchars;
std::valarray<Rule> &rules;
std::valarray<Tag> &tags;
- Tagpool &tagpool;
tagver_t maxtagver;
dfa_t(const nfa_t &nfa, const charset_t &charset,
std::fill(owrt, owrt + nver, false);
find_overwritten_tags(dfa, i, been, owrt);
- const tagver_t *fin = dfa.tagpool[dfa.rules[s->rule].tags];
+ const tagver_t *fin = dfa.rules[s->rule].tags;
for (const tagsave_t *p = s->rule_tags.save; p; p = p->next) {
owrt[p->ver] = false;
}
void tag_liveness(const cfg_t &cfg, bool *live)
{
- const Tagpool &tagpool = cfg.dfa.tagpool;
const size_t
nbb = cfg.nbblock,
nver = static_cast<size_t>(cfg.dfa.maxtagver) + 1,
- ntag = tagpool.ntags;
+ ntag = cfg.dfa.tags.size();
bool *buf1 = new bool[nver];
bool *buf2 = new bool[nver];
const cfg_bb_t *b = cfg.bblocks + i;
memset(buf1, 0, nver * sizeof(bool));
- if (b->use != TAGVER_ZERO) {
+ if (b->use) {
// final bblock, no successors
- const tagver_t *use = tagpool[b->use];
for (size_t t = 0; t < ntag; ++t) {
- const tagver_t u = use[t];
+ const tagver_t u = b->use[t];
if (u != TAGVER_ZERO) {
buf1[u] = true;
}
for (cfg_ix_t i = 0; i < nbb; ++i) {
const cfg_bb_t *b = cfg.bblocks + i;
- if (b->use == TAGVER_ZERO) continue;
+ if (!b->use) continue;
- const tagver_t *use = tagpool[b->use];
memset(buf1, 0, nver * sizeof(bool));
for (size_t t = 0; t < ntag; ++t) {
- const tagver_t u = use[t];
+ const tagver_t u = b->use[t];
if (u != TAGVER_ZERO) {
buf1[u] = true;
}
static cfg_ix_t map_arcs_to_bblocks(const dfa_t &dfa, cfg_ix_t *arc2bb);
static cfg_bb_t *create_bblocks(const dfa_t &dfa, const cfg_ix_t *arc2bb, cfg_ix_t nbblock);
-static void basic_block(cfg_bb_t *bb, const cfg_ix_t *succb, const cfg_ix_t *succe, const tagcmd_t *cmd, size_t use);
+static void basic_block(cfg_bb_t *bb, const cfg_ix_t *succb, const cfg_ix_t *succe, const tagcmd_t *cmd, tagver_t *use);
static void successors(const dfa_t &dfa, const cfg_ix_t *arc2bb, bool *been, cfg_ix_t *&succ, size_t x);
static void fallback(const dfa_t &dfa, const cfg_ix_t *arc2bb, bool *been, cfg_ix_t *&succ, size_t x);
}
void basic_block(cfg_bb_t *bb, const cfg_ix_t *succb,
- const cfg_ix_t *succe, const tagcmd_t *cmd, size_t use)
+ const cfg_ix_t *succe, const tagcmd_t *cmd, tagver_t *use)
{
const size_t n = static_cast<size_t>(succe - succb);
cfg_ix_t *s = new cfg_ix_t[n];
cfg_ix_t *succb;
cfg_ix_t *succe;
tagcmd_t *cmd;
- size_t use;
+ tagver_t *use;
};
// control flow graph
namespace re2c
{
-static void rename_rule(Tagpool &tagpool, size_t &tags, const tagver_t *ver2new);
-static void rename_save(tagsave_t **psave, const tagver_t *ver2new);
-static void rename_copy(tagcopy_t **pcopy, const tagver_t *ver2new);
-
void tag_renaming(cfg_t &cfg, const tagver_t *ver2new, tagver_t maxver)
{
tagver_t &oldmax = cfg.dfa.maxtagver;
- if (maxver >= oldmax) {
- assert(maxver == oldmax);
- return;
- }
+ if (oldmax == maxver) return;
oldmax = maxver;
cfg_bb_t *b = cfg.bblocks, *e = b + cfg.nbblock;
for (; b < e; ++b) {
- rename_save(&b->cmd->save, ver2new);
- rename_copy(&b->cmd->copy, ver2new);
- }
-
- std::valarray<Rule> &rules = cfg.dfa.rules;
- Tagpool &tagpool = cfg.dfa.tagpool;
- for (size_t i = 0; i < rules.size(); ++i) {
- rename_rule(tagpool, rules[i].tags, ver2new);
- }
-}
-
-void rename_rule(Tagpool &tagpool, size_t &tags, const tagver_t *ver2new)
-{
- if (tags == ZERO_TAGS) return;
-
- const tagver_t *oldver = tagpool[tags];
- tagver_t *newver = tagpool.buffer1;
- const size_t ntag = tagpool.ntags;
- for (size_t t = 0; t < ntag; ++t) {
- const tagver_t v = oldver[t];
- newver[t] = v != TAGVER_ZERO
- ? ver2new[v]
- : v;
- }
-
- tags = tagpool.insert(newver);
-}
+ // tag versions in save commands
+ for (tagsave_t *p = b->cmd->save; p; p = p->next) {
+ p->ver = ver2new[p->ver];
+ }
-void rename_save(tagsave_t **psave, const tagver_t *ver2new)
-{
- for (tagsave_t *p = *psave; p; p = p->next) {
- p->ver = ver2new[p->ver];
+ // tag versions in copy commands
+ for (tagcopy_t *c, **pc = &b->cmd->copy; (c = *pc);) {
+ c->lhs = ver2new[c->lhs];
+ c->rhs = ver2new[c->rhs];
+ if (c->lhs == c->rhs) {
+ *pc = c->next;
+ } else {
+ pc = &c->next;
+ }
+ }
}
-}
-void rename_copy(tagcopy_t **pcopy, const tagver_t *ver2new)
-{
- for (tagcopy_t *c, **pc = pcopy; (c = *pc);) {
- c->lhs = ver2new[c->lhs];
- c->rhs = ver2new[c->rhs];
- if (c->lhs == c->rhs) {
- *pc = c->next;
- } else {
- pc = &c->next;
+ // final tag versions in rules
+ std::valarray<Rule> &rules = cfg.dfa.rules;
+ for (size_t r = 0, t = 0; r < rules.size(); ++r) {
+ Rule &rule = rules[r];
+ for (; t < rule.htag; ++t) {
+ tagver_t &v = rule.tags[t];
+ if (v != TAGVER_ZERO) {
+ v = ver2new[v];
+ }
}
}
}
--- /dev/null
+#include <assert.h>
+#include <stdlib.h> // malloc
+#include <string.h> // memcpy, memcmp
+
+#include "src/ir/dfa/tagpool.h"
+#include "src/util/hash32.h"
+
+namespace re2c
+{
+
+struct eqtag_t
+{
+ size_t ntags;
+
+ explicit eqtag_t(size_t n): ntags(n) {}
+ inline tagver_t operator()(const tagver_t *x, const tagver_t *y) const
+ {
+ return memcmp(x, y, ntags * sizeof(tagver_t)) == 0;
+ }
+};
+
+Tagpool::Tagpool(size_t n)
+ : lookup()
+ , buffer(new tagver_t[n * 3])
+ , ntags(n)
+ , buffer1(&buffer[n * 1])
+ , buffer2(&buffer[n * 2])
+{
+ // all-zero tag configuration must have static number zero
+ std::fill(buffer, buffer + ntags, TAGVER_ZERO);
+ assert(ZERO_TAGS == insert(buffer));
+}
+
+Tagpool::~Tagpool()
+{
+ delete[] buffer;
+ const size_t n = lookup.size();
+ for (size_t i = 0; i < n; ++i) {
+ free(const_cast<tagver_t*>(lookup[i]));
+ }
+}
+
+size_t Tagpool::insert(const tagver_t *tags)
+{
+ const size_t size = ntags * sizeof(tagver_t);
+ const uint32_t hash = hash32(0, tags, size);
+
+ const size_t idx = lookup.find_with(hash, tags, eqtag_t(ntags));
+ if (idx != taglookup_t::NIL) {
+ return idx;
+ }
+
+ tagver_t *copy = static_cast<tagver_t*>(malloc(size));
+ memcpy(copy, tags, size);
+ return lookup.push(hash, copy);
+}
+
+const tagver_t *Tagpool::operator[](size_t idx) const
+{
+ return lookup[idx];
+}
+
+} // namespace re2c
--- /dev/null
+#ifndef _RE2C_IR_DFA_TAGPOOL_
+#define _RE2C_IR_DFA_TAGPOOL_
+
+#include "src/ir/tag.h"
+#include "src/util/lookup.h"
+#include "src/util/forbid_copy.h"
+
+namespace re2c
+{
+
+static const size_t ZERO_TAGS = 0;
+
+struct Tagpool
+{
+private:
+ typedef lookup_t<const tagver_t*> taglookup_t;
+ taglookup_t lookup;
+ tagver_t *buffer;
+
+public:
+ const size_t ntags;
+ tagver_t *buffer1;
+ tagver_t *buffer2;
+
+ explicit Tagpool(size_t n);
+ ~Tagpool();
+ size_t insert(const tagver_t *tags);
+ const tagver_t *operator[](size_t idx) const;
+ FORBID_COPY(Tagpool);
+};
+
+} // namespace re2c
+
+#endif // _RE2C_IR_DFA_TAGPOOL_
void init_rules(const std::vector<const RegExpRule*> ®exps,
std::valarray<Rule> &rules,
- const std::valarray<Tag> &tags,
- Tagpool &tagpool)
+ const std::valarray<Tag> &tags)
{
const size_t nr = rules.size();
const size_t nt = tags.size();
rule.htag = t;
// mark *all* variable tags, including trailing context
- tagver_t *vers = tagpool.buffer1;
+ tagver_t *vers = new tagver_t[nt];
std::fill(vers, vers + nt, TAGVER_ZERO);
for (size_t i = rule.ltag; i < rule.htag; ++i) {
if (tags[i].type == Tag::VAR) {
vers[i] = static_cast<tagver_t>(i + 1);
}
}
- rule.tags = tagpool.insert(vers);
+ rule.tags = vers;
// tags in trailing context are forbidden (they make no sense),
// and since tags are constructed in reversed order, this implies
, states(NULL)
, rules(*new std::valarray<Rule>(regexps.size()))
, tags(NULL)
- , tagpool(NULL)
, root(NULL)
{
size_t ntags = 0;
max_size = counters(regexps, ntags);
- tagpool = new Tagpool(ntags);
tags = new std::valarray<Tag>(ntags);
make_tags(regexps, *tags);
states = new nfa_state_t[max_size];
regexps2nfa(regexps, *this);
- init_rules(regexps, rules, *tags, *tagpool);
+ init_rules(regexps, rules, *tags);
}
nfa_t::~nfa_t()
nfa_state_t *states;
std::valarray<Rule> &rules;
std::valarray<Tag> *tags;
- Tagpool *tagpool;
nfa_state_t *root;
nfa_t(const std::vector<const RegExpRule*> &rs);
void make_tags(const std::vector<const RegExpRule*> ®exps, std::valarray<Tag> &tags);
void regexps2nfa(const std::vector<const RegExpRule*> ®exps, nfa_t &nfa);
bool nullable_rule(const RegExpRule *rule);
-void init_rules(const std::vector<const RegExpRule*> ®exps,
- std::valarray<Rule> &rules,
- const std::valarray<Tag> &tags,
- Tagpool &tagpool);
+void init_rules(const std::vector<const RegExpRule*> ®exps, std::valarray<Rule> &rules, const std::valarray<Tag> &tags);
} // namespace re2c
size_t ltag;
size_t htag;
size_t trail;
- size_t tags;
+ tagver_t *tags;
std::set<uint32_t> shadow;
Rule()
, ltag(0)
, htag(0)
, trail(Tag::NONE)
- , tags(ZERO_TAGS)
+ , tags(NULL)
, shadow()
{}
+ ~Rule()
+ {
+ delete[] tags;
+ }
FORBID_COPY(Rule);
};
if (s->rule != Rule::NONE) {
trail = dfa.rules[s->rule].trail;
if (trail != Tag::NONE) {
- trver = dfa.tagpool[dfa.rules[s->rule].tags][trail];
+ trver = dfa.rules[s->rule].tags[trail];
}
}
-#include <assert.h>
#include <limits>
-#include <stdlib.h> // malloc
-#include <string.h> // memcpy, memcmp
#include "src/ir/rule.h"
#include "src/ir/tag.h"
-#include "src/util/hash32.h"
namespace re2c
{
-struct eqtag_t
-{
- size_t ntags;
-
- explicit eqtag_t(size_t n): ntags(n) {}
- inline tagver_t operator()(const tagver_t *x, const tagver_t *y) const
- {
- return memcmp(x, y, ntags * sizeof(tagver_t)) == 0;
- }
-};
-
const size_t Tag::NONE = std::numeric_limits<size_t>::max();
Tag::Tag()
tag.fix.dist = d;
}
-Tagpool::Tagpool(size_t n)
- : lookup()
- , buffer(new tagver_t[n * 3])
- , ntags(n)
- , buffer1(&buffer[n * 1])
- , buffer2(&buffer[n * 2])
-{
- // all-zero tag configuration must have static number zero
- std::fill(buffer, buffer + ntags, TAGVER_ZERO);
- assert(ZERO_TAGS == insert(buffer));
-}
-
-Tagpool::~Tagpool()
-{
- delete[] buffer;
- const size_t n = lookup.size();
- for (size_t i = 0; i < n; ++i) {
- free(const_cast<tagver_t*>(lookup[i]));
- }
-}
-
-size_t Tagpool::insert(const tagver_t *tags)
-{
- const size_t size = ntags * sizeof(tagver_t);
- const uint32_t hash = hash32(0, tags, size);
-
- const size_t idx = lookup.find_with(hash, tags, eqtag_t(ntags));
- if (idx != taglookup_t::NIL) {
- return idx;
- }
-
- tagver_t *copy = static_cast<tagver_t*>(malloc(size));
- memcpy(copy, tags, size);
- return lookup.push(hash, copy);
-}
-
-const tagver_t *Tagpool::operator[](size_t idx) const
-{
- return lookup[idx];
-}
-
free_list<tagsave_t*> tagsave_t::freelist;
tagsave_t::tagsave_t(tagsave_t *n, tagver_t v)
#include <string>
-#include "src/util/lookup.h"
+#include "src/util/c99_stdint.h"
#include "src/util/forbid_copy.h"
#include "src/util/free_list.h"
void init_var_tag(Tag &tag, size_t r, const std::string *n);
void init_fix_tag(Tag &tag, size_t r, const std::string *n, size_t b, size_t d);
-static const size_t ZERO_TAGS = 0;
-
-struct Tagpool
-{
-private:
- typedef lookup_t<const tagver_t*> taglookup_t;
- taglookup_t lookup;
- tagver_t *buffer;
-
-public:
- const size_t ntags;
- tagver_t *buffer1;
- tagver_t *buffer2;
-
- explicit Tagpool(size_t n);
- ~Tagpool();
- size_t insert(const tagver_t *tags);
- const tagver_t *operator[](size_t idx) const;
- FORBID_COPY(Tagpool);
-};
-
struct tagsave_t
{
static free_list<tagsave_t*> freelist;