mirror of
https://github.com/VectorCamp/vectorscan.git
synced 2025-06-28 16:41:01 +03:00
limex: more general CANNOT_DIE analysis
This commit is contained in:
parent
152552423f
commit
9a82689d00
@ -66,6 +66,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <boost/graph/breadth_first_search.hpp>
|
#include <boost/graph/breadth_first_search.hpp>
|
||||||
|
#include <boost/graph/depth_first_search.hpp>
|
||||||
#include <boost/range/adaptor/map.hpp>
|
#include <boost/range/adaptor/map.hpp>
|
||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
@ -1640,6 +1641,84 @@ u32 findBestNumOfVarShifts(const build_info &args,
|
|||||||
return bestNumOfVarShifts;
|
return bestNumOfVarShifts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
bool cannotDie(const build_info &args, const set<NFAVertex> &tops) {
|
||||||
|
const auto &h = args.h;
|
||||||
|
|
||||||
|
// When this top is activated, all of the vertices in 'tops' are switched
|
||||||
|
// on. If any of those lead to a graph that cannot die, then this top
|
||||||
|
// cannot die.
|
||||||
|
|
||||||
|
// For each top, we use a depth-first search to traverse the graph from the
|
||||||
|
// top, looking for a cyclic path consisting of vertices of dot reach. If
|
||||||
|
// one exists, than the NFA cannot die after this top is triggered.
|
||||||
|
|
||||||
|
vector<boost::default_color_type> colours(num_vertices(h));
|
||||||
|
auto colour_map = boost::make_iterator_property_map(colours.begin(),
|
||||||
|
get(vertex_index, h));
|
||||||
|
|
||||||
|
struct CycleFound {};
|
||||||
|
struct CannotDieVisitor : public boost::default_dfs_visitor {
|
||||||
|
void back_edge(const NFAEdge &e, const NGHolder &g) const {
|
||||||
|
DEBUG_PRINTF("back-edge %zu,%zu\n", g[source(e, g)].index,
|
||||||
|
g[target(e, g)].index);
|
||||||
|
if (g[target(e, g)].char_reach.all()) {
|
||||||
|
assert(g[source(e, g)].char_reach.all());
|
||||||
|
throw CycleFound();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
try {
|
||||||
|
for (const auto &top : tops) {
|
||||||
|
DEBUG_PRINTF("checking top vertex %zu\n", h[top].index);
|
||||||
|
|
||||||
|
// Constrain the search to the top vertices and any dot vertices it
|
||||||
|
// can reach.
|
||||||
|
auto term_func = [&](NFAVertex v, const NGHolder &g) {
|
||||||
|
if (v == top) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (!g[v].char_reach.all()) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
if (contains(args.br_cyclic, v) &&
|
||||||
|
args.br_cyclic.at(v).repeatMax != depth::infinity()) {
|
||||||
|
// Bounded repeat vertices without inf max can be turned
|
||||||
|
// off.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
boost::depth_first_visit(h, top, CannotDieVisitor(), colour_map,
|
||||||
|
term_func);
|
||||||
|
}
|
||||||
|
} catch (const CycleFound &) {
|
||||||
|
DEBUG_PRINTF("cycle found\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** \brief True if this NFA cannot ever be in no states at all. */
|
||||||
|
static
|
||||||
|
bool cannotDie(const build_info &args) {
|
||||||
|
const auto &h = args.h;
|
||||||
|
const auto &state_ids = args.state_ids;
|
||||||
|
|
||||||
|
// If we have a startDs we're actually using, we can't die.
|
||||||
|
if (state_ids.at(h.startDs) != NO_STATE) {
|
||||||
|
DEBUG_PRINTF("is using startDs\n");
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return all_of_in(args.tops | map_values, [&](const set<NFAVertex> &verts) {
|
||||||
|
return cannotDie(args, verts);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
template<NFAEngineType dtype>
|
template<NFAEngineType dtype>
|
||||||
struct Factory {
|
struct Factory {
|
||||||
// typedefs for readability, for types derived from traits
|
// typedefs for readability, for types derived from traits
|
||||||
@ -2237,7 +2316,8 @@ struct Factory {
|
|||||||
limex->shiftCount = shiftCount;
|
limex->shiftCount = shiftCount;
|
||||||
writeShiftMasks(args, limex);
|
writeShiftMasks(args, limex);
|
||||||
|
|
||||||
if (hasInitDsStates(args.h, args.state_ids)) {
|
if (cannotDie(args)) {
|
||||||
|
DEBUG_PRINTF("nfa cannot die\n");
|
||||||
setLimexFlag(limex, LIMEX_FLAG_CANNOT_DIE);
|
setLimexFlag(limex, LIMEX_FLAG_CANNOT_DIE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user