58 typedef boost::adjacency_list<
59 boost::vecS, boost::vecS, boost::bidirectionalS,
60 boost::property<boost::vertex_state_t, const IR::BFN::ParserState *>,
61 boost::property<boost::edge_transition_t, const IR::BFN::Transition *>>
65 const IR::BFN::Parser *parser =
nullptr;
66 std::optional<gress_t> gress;
68 typename Graph::vertex_descriptor get_entry_point() {
69 if (entry_point)
return *entry_point;
71 BUG_CHECK(parser,
"Cannot get entry point, as provided parser is a nullptr.");
72 if (state_to_vertex.count(parser->start))
return state_to_vertex.at(parser->start);
74 BUG(
"Cannot get entry point of parser.");
78 std::optional<typename Graph::vertex_descriptor> entry_point;
81 std::optional<typename Graph::vertex_descriptor> end;
87 auto all_vertices = boost::vertices(graph);
88 if (++all_vertices.first == all_vertices.second) {
94 bool contains(
const IR::BFN::ParserState *state) {
return state_to_vertex.count(state); }
96 typename Graph::vertex_descriptor add_vertex(
const IR::BFN::ParserState *state) {
97 if (state !=
nullptr && !gress) gress = state->gress;
99 if (contains(state)) {
100 LOG1(
"State " << ((state) ? state->name :
"END") <<
" already exists");
101 return state_to_vertex.at(state);
104 auto vertex = boost::add_vertex(state, graph);
106 LOG1(
"Added vertex " << vertex <<
" for state " << state->name);
108 LOG1(
"Added vertex " << vertex <<
" for state END");
110 if (state && state->name.find(
"$entry_point")) entry_point = vertex;
111 if (state ==
nullptr) end = vertex;
113 state_to_vertex[state] = vertex;
114 vertex_to_state[vertex] = state;
119 std::pair<typename Graph::edge_descriptor, bool> add_edge(
120 const IR::BFN::ParserState *source,
const IR::BFN::ParserState *destination,
121 const IR::BFN::Transition *transition) {
122 typename Graph::vertex_descriptor source_vertex, destination_vertex;
123 source_vertex = add_vertex(source);
124 destination_vertex = add_vertex(destination);
127 typename Graph::out_edge_iterator out, end;
128 for (boost::tie(out, end) = boost::out_edges(source_vertex, graph); out != end; ++out) {
129 if (boost::target(*out, graph) == destination_vertex)
return {*out,
false};
132 auto edge = boost::add_edge(source_vertex, destination_vertex, graph);
136 BUG(
"Boost Graph Library failed to add edge.");
137 boost::get(boost::edge_transition, graph)[edge.first] = transition;
138 return {edge.first,
true};
144 boost::copy_graph(other.graph, graph);
188 template <
class P,
class S,
class T>
191 explicit ParserGraphImpl(
const Parser *parser) : root(parser->start) {}
193 const State *
const root;
206 auto it = _transitions.find({src, dst});
207 if (it != _transitions.end())
return it->second;
214 auto has_dst = [dst](
const auto &kv) {
return kv.first.second == dst; };
215 auto it = std::find_if(_transitions.begin(), _transitions.end(), has_dst);
216 while (it != _transitions.end()) {
218 transitions.insert(value.begin(), value.end());
219 it = std::find_if(++it, _transitions.end(), has_dst);
225 if (_to_pipe.count(src))
return _to_pipe.at(src);
235 bool is_loopback_state(
cstring state)
const {
236 for (
auto &kv : _loopbacks) {
237 if (stripThreadPrefix(state) == stripThreadPrefix(kv.first.second))
return true;
243 const State *get_state(
cstring name)
const {
244 for (
auto s : states()) {
245 if (name == s->name)
return s;
258 if (src == dst)
return false;
260 if (!predecessors().count(dst))
return false;
262 if (predecessors().at(dst).count(src))
return true;
264 if (is_ancestor_.count(src) && is_ancestor_.at(src).count(dst))
265 return is_ancestor_.at(src).at(dst);
268 for (
auto p : predecessors().at(dst))
270 is_ancestor_[dst][src] =
false;
271 return is_ancestor_[src][dst] =
true;
274 return is_ancestor_[src][dst] =
false;
277 bool is_descendant(
const State *src,
const State *dst)
const {
return is_ancestor(dst, src); }
279 bool is_loop_reachable(
const State *src,
const State *dst)
const {
280 for (
auto &kv : _loopbacks) {
281 if (kv.first.first == src) {
282 auto loop_state = get_state(kv.first.second);
283 if (loop_state == dst ||
is_ancestor(loop_state, dst))
return true;
339 for (
auto &kv : _loopbacks) {
340 auto loop_from = kv.first.first;
341 auto loop_to = get_state(kv.first.second);
343 if (src == loop_from ||
is_ancestor(src, loop_from)) {
345 if (loop_to == dst)
return true;
363 if (!predecessors().count(s) || predecessors().at(s).empty())
return false;
366 for (
auto ns : predecessors().at(s)) {
379 if (!successors().count(s) || successors().at(s).empty())
return false;
382 for (
auto ns : successors().at(s)) {
411 for (
auto &kv : _loopbacks) {
412 auto le = kv.first.first;
413 auto ls = get_state(kv.first.second);
419 if (_is_loopback_postdominated_by_set_impl(ls, le, set) &&
421 return std::make_pair(ls, le);
426 return std::make_pair(
nullptr,
nullptr);
431 bool is_mutex(
const State *a,
const State *b)
const {
433 !is_loop_reachable(b, a);
439 for (
auto it1 = states.begin(); it1 != states.end(); ++it1) {
440 for (
auto it2 = it1; it2 != states.end(); ++it2) {
441 if (it1 == it2)
continue;
442 if (!
is_mutex(*it1, *it2))
return false;
449 bool is_mutex(
const Transition *a,
const Transition *b)
const {
450 if (a == b)
return false;
452 auto a_dst = get_dst(a);
453 auto a_src = get_src(a);
455 auto b_dst = get_dst(b);
456 auto b_src = get_src(b);
458 if (a_dst == b_src)
return false;
459 if (b_dst == a_src)
return false;
464 if (is_loop_reachable(a_dst, b_src))
return false;
465 if (is_loop_reachable(b_dst, a_src))
return false;
472 get_all_descendants_impl(src, rv);
476 std::vector<const State *> topological_sort()
const {
477 std::vector<int> result = DirectedGraph::topological_sort();
478 std::vector<const State *> mapped_result;
479 for (
auto id : result) mapped_result.push_back(get_state(
id));
480 return mapped_result;
484 std::vector<const State *> longest_path_states(
const State *src)
const {
486 return min_max_path_impl(src, path_map,
true,
true,
true).second;
490 std::vector<const State *> longest_path_states_to(
const State *dest)
const {
492 return min_max_path_impl(dest, path_map,
true,
false,
true).second;
496 std::vector<const State *> shortest_path_states(
const State *src)
const {
498 return min_max_path_impl(src, path_map,
false,
true,
true).second;
502 std::pair<unsigned, std::vector<const State *>> longest_path_bytes(
const State *src)
const {
504 return min_max_path_impl(src, path_map,
true,
true,
false);
508 std::pair<unsigned, std::vector<const State *>> shortest_path_bytes(
const State *src)
const {
510 return min_max_path_impl(src, path_map,
false,
true,
false);
514 std::pair<unsigned, std::vector<const State *>> shortest_path_thru_bytes(
515 const State *src)
const {
519 auto from = min_max_path_impl(src, path_map_from,
false,
true,
false);
520 auto to = min_max_path_impl(src, path_map_to,
false,
false,
false);
522 std::vector<const State *> ret = to.second;
523 ret.insert(ret.end(), ++from.second.begin(), from.second.end());
525 return std::make_pair(from.first + to.first, ret);
528 const State *get_src(
const Transition *t)
const {
529 for (
auto &kv : _transitions) {
530 if (kv.second.count(t))
return kv.first.first;
533 for (
auto &kv : _to_pipe) {
534 if (kv.second.count(t))
return kv.first;
537 for (
auto &kv : _loopbacks) {
538 if (kv.second.count(t))
return kv.first.first;
544 const State *get_dst(
const Transition *t)
const {
545 for (
auto &kv : _transitions) {
546 if (kv.second.count(t))
return kv.first.second;
556 bool _is_loopback_postdominated_by_set_impl(
const State *s,
const State *loop_exit,
559 if (s == loop_exit) {
560 if (set.count(loop_exit)) {
567 if (!successors().count(s) || successors().at(s).empty())
return false;
570 for (
auto ns : successors().at(s)) {
571 if (!set.count(ns) && !_is_loopback_postdominated_by_set_impl(ns, loop_exit, set)) {
578 std::vector<const State *> longest_or_shortest_path_states_impl(
579 const State *src,
assoc::map<
const State *, std::vector<const State *>> &path_map,
580 bool longest)
const {
581 if (path_map.count(src))
return path_map.at(src);
583 const State *best_succ =
nullptr;
584 std::vector<const State *> best_succ_path;
586 if ((longest || to_pipe(src).size() == 0) && successors().count(src)) {
587 for (
auto succ : successors().at(src)) {
588 auto succ_path = longest_or_shortest_path_states_impl(succ, path_map, longest);
590 bool gt = succ_path.size() > best_succ_path.size();
591 bool lt = succ_path.size() < best_succ_path.size();
592 if (!best_succ || (longest ? gt : lt)) {
593 best_succ_path = succ_path;
599 best_succ_path.insert(best_succ_path.begin(), src);
601 path_map[src] = best_succ_path;
603 return best_succ_path;
615 std::pair<unsigned, std::vector<const State *>> min_max_path_impl(
617 assoc::map<
const State *, std::pair<
unsigned, std::vector<const State *>>> &path_map,
618 bool longest,
bool origin,
bool states)
const {
619 if (path_map.count(state))
return path_map.at(state);
621 const State *best =
nullptr;
622 std::vector<const State *> best_path;
623 unsigned best_len = 0;
625 auto max = [](
unsigned v,
const Transition *t) {
return v > t->shift ? v : t->shift; };
626 auto min = [](
unsigned v,
const Transition *t) {
return v < t->shift ? v : t->shift; };
628 auto next_map = origin ? successors() : predecessors();
629 auto exit_trans = origin ? to_pipe(state) :
ordered_set<const Transition *>();
631 if ((longest || exit_trans.size() == 0) && next_map.count(state)) {
632 for (auto next : next_map.at(state)) {
633 auto next_path = min_max_path_impl(next, path_map, longest, origin, states);
634 auto next_trans = origin ? transitions(state, next) : transitions(next, state);
637 : std::accumulate(next_trans.begin(), next_trans.end(),
638 longest ? 0u : SIZE_MAX, longest ? max : min);
640 unsigned path_len = next_inc + next_path.first;
641 bool better = longest ? path_len > best_len : path_len < best_len;
642 if (!best || better) {
643 best_path = next_path.second;
648 }
else if (exit_trans.size()) {
649 best_len = states ? 1
650 : std::accumulate(exit_trans.begin(), exit_trans.end(),
651 longest ? 0u : SIZE_MAX, longest ? max : min);
654 best_path.insert(origin ? best_path.begin() : best_path.end(), state);
656 path_map[state] = std::make_pair(best_len, best_path);
658 return path_map[state];
662 if (!successors().count(src))
return;
664 for (
auto succ : successors().at(src)) {
665 if (!rv.count(succ)) {
667 get_all_descendants_impl(succ, rv);
672 void add_state(
const State *s) { _states.insert(s); }
674 void add_transition(
const State *state,
const Transition *t) {
679 _succs[state].insert(t->next);
680 _preds[t->next].insert(state);
681 _transitions[{state, t->next}].insert(t);
682 }
else if (t->loop) {
683 _loopbacks[{state, t->loop}].insert(t);
685 _to_pipe[state].insert(t);
689 void map_to_boost_graph() {
690 for (
auto s : _states) {
691 int id = DirectedGraph::add_vertex();
692 _state_to_id[s] = id;
693 _id_to_state[id] = s;
696 for (
auto t : _succs)
697 for (
auto dst : t.second) DirectedGraph::add_edge(get_id(t.first), get_id(dst));
700 int get_id(
const State *s) {
701 if (_state_to_id.count(s) == 0) add_state(s);
702 return _state_to_id.at(s);
705 const State *get_state(
int id)
const {
return _id_to_state.at(
id); }
744 const GraphType &graph(
const Parser *p)
const {
return *(_graphs.at(p)); }
745 const GraphType &graph(
const State *s)
const {
return graph(parser(s)); }
747 const Parser *parser(
const State *state)
const {
return _state_to_parser.at(state); }
751 auto rv = Inspector::init_apply(root);
755 _state_to_parser.clear();
760 bool preorder(
const Parser *parser)
override {
766 bool preorder(
const State *state)
override {
767 auto parser = findContext<Parser>();
768 _state_to_parser[state] = parser;
770 auto g = _graphs.at(parser);
774 for (
auto t : state->transitions) g->add_transition(state, t);
780 void clear_cache() { all_shift_amounts_.clear(); }
819 bool reverse_path = graphs().at(parser(src))->is_ancestor(dst, src);
820 if (reverse_path) std::swap(src, dst);
822 auto result = get_all_forward_path_shift_amounts(src, dst);
826 auto negated =
new std::set<int>();
827 for (
auto shift : *result) negated->insert(-shift);
835 const std::set<int> *get_all_forward_path_shift_amounts(
const State *src,
836 const State *dst)
const {
837 if (src == dst)
return new std::set<int>({0});
839 if (all_shift_amounts_.count(src) && all_shift_amounts_.at(src).count(dst))
840 return all_shift_amounts_.at(src).at(dst);
842 auto graph = graphs().at(parser(src));
843 auto result =
new std::set<int>();
846 return all_shift_amounts_[src][dst] = all_shift_amounts_[dst][src] = result;
850 return all_shift_amounts_[src][dst] = result;
854 BUG_CHECK(graph->successors().count(src),
"State %s has a descendant %s, but no successors",
855 src->name, dst->name);
856 for (
auto succ : graph->successors().at(src)) {
857 auto amounts = get_all_forward_path_shift_amounts(succ, dst);
858 if (!amounts->size())
continue;
860 auto transitions = graph->transitions(src, succ);
861 BUG_CHECK(!transitions.empty(),
"Missing parser transition from %s to %s", src->name,
864 auto t = *(transitions.begin());
866 for (
auto amount : *amounts) result->insert(amount + t->shift * 8);
869 return all_shift_amounts_[src][dst] = result;
872 void end_apply()
override {
874 for (
auto g : _graphs) g.second->map_to_boost_graph();