20 #include <boost/graph/adjacency_list.hpp>
21 #include <boost/iterator/filter_iterator.hpp>
22 #include <boost/iterator/indirect_iterator.hpp>
23 #include <boost/iterator/iterator_facade.hpp>
24 #include <boost/iterator/transform_iterator.hpp>
25 #include <boost/range/iterator_range.hpp>
72 std::optional<std::tuple<ConditionalEdge, DirectEdge, EdgeType>>;
82 template <
class OutEdgeListS = boost::vecS,
class VertexListS = boost::vecS,
83 class DirectedS = boost::directedS,
class EdgeListS = boost::listS>
85 using vertex_descriptor =
typename boost::adjacency_list_traits<
86 OutEdgeListS, VertexListS, DirectedS, EdgeListS>::vertex_descriptor;
87 using type = boost::adjacency_list<
88 OutEdgeListS, VertexListS, DirectedS,
95 std::unordered_map<const CfgNode*, vertex_descriptor>, EdgeListS>;
102 using CFG = CfgBuilder<boost::listS,
104 boost::bidirectionalS
107 class cfg_node_iter_base
108 :
public boost::iterator_facade<cfg_node_iter_base,
109 const boost::vertex_bundle_type<CFG>::type,
110 CFG::vertex_iterator::iterator_category> {
112 cfg_node_iter_base() =
default;
113 cfg_node_iter_base(
const CFG& cfg_, CFG::vertex_iterator& it_)
114 : cfg(&cfg_), it(it_) {}
117 cfg_node_iter_base(
const cfg_node_iter_base&) =
default;
118 cfg_node_iter_base(cfg_node_iter_base&&) =
default;
119 cfg_node_iter_base& operator=(
const cfg_node_iter_base&) =
default;
120 cfg_node_iter_base& operator=(cfg_node_iter_base&&) =
default;
123 friend class boost::iterator_core_access;
125 void increment() { ++it; }
126 void decrement() { --it; }
128 std::ptrdiff_t distance_to(
const cfg_node_iter_base& other)
const {
129 return std::distance(it, other.it);
132 bool equal(
const cfg_node_iter_base& other)
const {
return it == other.it; }
134 const boost::vertex_bundle_type<CFG>::type& dereference()
const {
138 const CFG* cfg{
nullptr};
139 CFG::vertex_iterator it;
142 template <
typename ToTy>
struct downcast {
143 template <
typename FromTy>
auto operator()(FromTy& Val)
const {
144 return dyn_cast_or_null<ToTy>(Val);
149 template <
typename T>
bool operator()(
const T* t) {
return t !=
nullptr; }
152 template <
typename T>
153 using cfg_node_downcast_iter =
154 boost::transform_iterator<downcast<std::remove_const_t<T>>,
157 template <
typename T>
158 using cfg_node_downcast_not_null_iter =
159 boost::filter_iterator<not_null, cfg_node_downcast_iter<T>>;
161 template <
typename T>
162 class cfg_node_cast_iter
163 :
public boost::indirect_iterator<cfg_node_downcast_not_null_iter<T>, T> {
165 using xform_iterator = cfg_node_downcast_iter<T>;
166 using filter_iterator = cfg_node_downcast_not_null_iter<T>;
167 using parent = boost::indirect_iterator<filter_iterator, T>;
170 cfg_node_cast_iter() : parent() {}
172 cfg_node_cast_iter(
const CFG& g, CFG::vertex_iterator& first,
173 CFG::vertex_iterator& last)
174 : parent(filter_iterator(xform_iterator(cfg_node_iter_base(g, first)),
175 xform_iterator(cfg_node_iter_base(g, last)))) {}
177 template <
typename OtherT>
178 cfg_node_cast_iter(
const cfg_node_cast_iter<OtherT>& other) : parent(other) {}
190 boost::indirect_iterator<cfg_node_iter_base, const CfgNode>;
320 struct CfgPredecessorTraits {
321 using edge_iterator = boost::graph_traits<CFG>::in_edge_iterator;
322 static CfgNode* getNode(
const CFG::edge_descriptor& EDesc,
const CFG& Cfg) {
323 return Cfg[source(EDesc, Cfg)];
325 static std::pair<edge_iterator, edge_iterator>
326 getEdges(
const CFG::vertex_descriptor& VtxDescr,
const CFG& Cfg) {
327 return in_edges(VtxDescr, Cfg);
334 struct CfgSuccessorTraits {
335 using edge_iterator = boost::graph_traits<CFG>::out_edge_iterator;
336 static CfgNode* getNode(
const CFG::edge_descriptor& EDesc,
const CFG& Cfg) {
337 return Cfg[target(EDesc, Cfg)];
339 static std::pair<edge_iterator, edge_iterator>
340 getEdges(
const CFG::vertex_descriptor& VtxDescr,
const CFG& Cfg) {
341 return out_edges(VtxDescr, Cfg);
351 template <
class Traits,
typename CfgNodePtr>
struct EdgeDescrToNodeLabel {
357 const CFG* Cfg =
nullptr;
359 EdgeDescrToNodeLabel() =
default;
360 EdgeDescrToNodeLabel(
const CFG* G) : Cfg(G) {}
363 EdgeDescrToNodeLabel(
const EdgeDescrToNodeLabel<Traits, CfgNode*>& Rhs)
366 std::pair<CfgNodePtr, EdgeLabel>
367 operator()(
const CFG::edge_descriptor& EDesc)
const {
368 return {Traits::getNode(EDesc, *Cfg), (*Cfg)[EDesc]};
387 template <
class Traits,
typename CfgNodePtr>
388 auto cfgEdgeIters(
const CFG& G,
const CfgNode* N) {
389 const std::optional<CFG::vertex_descriptor> OptVtxDescr =
getVertex(N, G);
390 if (OptVtxDescr == std::nullopt) {
392 return boost::iterator_range<
393 boost::transform_iterator<EdgeDescrToNodeLabel<Traits, CfgNodePtr>,
394 typename Traits::edge_iterator>>();
396 const auto [Begin, End] = Traits::getEdges(OptVtxDescr.value(), G);
397 return boost::make_iterator_range(
398 boost::make_transform_iterator(
399 Begin, EdgeDescrToNodeLabel<Traits, CfgNodePtr>{&G}),
400 boost::make_transform_iterator(
401 End, EdgeDescrToNodeLabel<Traits, CfgNodePtr>{&G}));
408 EdgeDescrToNodeLabel<CfgPredecessorTraits, CfgNode*>,
409 CfgPredecessorTraits::edge_iterator>>;
412 boost::iterator_range<boost::transform_iterator<
413 EdgeDescrToNodeLabel<CfgPredecessorTraits, const CfgNode*>,
414 CfgPredecessorTraits::edge_iterator>>;
417 EdgeDescrToNodeLabel<CfgSuccessorTraits, CfgNode*>,
418 CfgSuccessorTraits::edge_iterator>>;
421 boost::iterator_range<boost::transform_iterator<
422 EdgeDescrToNodeLabel<CfgSuccessorTraits, const CfgNode*>,
423 CfgSuccessorTraits::edge_iterator>>;
438 return cfgEdgeIters<CfgPredecessorTraits, CfgNode*>(G, N);
442 return cfgEdgeIters<CfgPredecessorTraits, const CfgNode*>(G, N);
458 return cfgEdgeIters<CfgSuccessorTraits, CfgNode*>(G, N);
462 return cfgEdgeIters<CfgSuccessorTraits, const CfgNode*>(G, N);
466 #endif // GTIRB_CFG_H