00001 #ifndef wali_graph_INTER_GRAPH_GUARD
00002 #define wali_graph_INTER_GRAPH_GUARD 1
00003
00004 #include "wali/Countable.hpp"
00005 #include "wali/ref_ptr.hpp"
00006 #include "wali/MergeFn.hpp"
00007
00008 #include "wali/graph/GraphCommon.hpp"
00009
00010 #include <list>
00011 #include <vector>
00012 #include <iostream>
00013 #include <map>
00014 #include <set>
00015
00016 namespace wali {
00017
00018 namespace graph {
00019
00020 class IntraGraph;
00021 class InterGraph;
00022
00023 class UnionFind {
00024 friend class InterGraph;
00025 int *arr;
00026 int n;
00027 public:
00028 UnionFind(int len);
00029 ~UnionFind();
00030 void reset();
00031 int find(int a);
00032 void takeUnion(int a, int b);
00033 };
00034
00035
00036 struct InterGraphStats {
00037 int nnodes;
00038 int nedges;
00039 int nhyperedges;
00040 int ncombine;
00041 int nextend;
00042 int nstar;
00043 int ngraphs;
00044 int nupdatable;
00045 int ncutset;
00046 int nget_weight;
00047 int niter;
00048 int ncomponents;
00049 int ndom_sequence;
00050 int ndom_componentsize;
00051 int ndom_components;
00052 int ndom_componentcutset;
00053
00054 InterGraphStats() {
00055 nnodes = nedges = nhyperedges = 0;
00056 ncombine = nextend = nstar = 0;
00057 ngraphs = nupdatable = ncutset = 0;
00058 niter = 0;
00059 ncomponents = 0;
00060 ndom_sequence = 0;
00061 ndom_componentsize = 0;
00062 ndom_components = 0;
00063 ndom_componentcutset = 0;
00064 nget_weight = 0;
00065
00066
00067 }
00068 };
00069
00070
00071 class ETransHandler {
00072
00073 friend class InterGraph;
00074 friend class SummaryGraph;
00075
00076 private:
00077 typedef std::pair<int, sem_elem_t> Dependency;
00078 typedef std::map<int, Dependency> EdgeMap;
00079
00080 ETransHandler() {}
00081 bool exists(int ret);
00082 void addEdge(int call, int ret, sem_elem_t wtCallRule);
00083 sem_elem_t get_dependency(int ret, int &call);
00084
00085 private:
00086 EdgeMap edgeMap;
00087
00088 };
00089
00090 class HyperEdge {
00091 public:
00092 int src1, src2, tgt;
00093 sem_elem_t weight;
00094 wali::merge_fn_t mf;
00095 HyperEdge(int s1, int s2, int t, sem_elem_t se) : src1(s1), src2(s2), tgt(t), weight(se), mf(0) {}
00096 HyperEdge(int s1, int s2, int t, wali::merge_fn_t f) : src1(s1), src2(s2), tgt(t), weight(0), mf(f) {}
00097 HyperEdge(const HyperEdge &h) : src1(h.src1), src2(h.src2), tgt(h.tgt), weight(h.weight), mf(h.mf) {}
00098 };
00099
00100 class GraphEdge {
00101 public:
00102 int src, tgt;
00103 sem_elem_t weight;
00104 GraphEdge(int s, int t, sem_elem_t w) : src(s), tgt(t), weight(w) {}
00105 GraphEdge(const GraphEdge &e) {
00106 src = e.src;
00107 tgt = e.tgt;
00108 weight = e.weight;
00109 }
00110 };
00111
00112 enum inter_node_t {InterNone = 0, InterSource = 1, InterOutNode = 2, InterSourceOutNode = 3};
00113
00114 class GraphNode {
00115 public:
00116 Transition trans;
00117 int intra_nodeno;
00118 inter_node_t type;
00119 sem_elem_t weight;
00120 IntraGraph *gr;
00121 std::list<int> outgoing;
00122 std::list<int> incoming;
00123 std::list<int> out_hyper_edges;
00124 bool visited;
00125 GraphNode(Transition tr, inter_node_t ty = InterNone) : trans(tr), intra_nodeno(-1), type(ty), weight(0), gr(NULL) {}
00126 GraphNode(const GraphNode &g) : trans(g.trans), intra_nodeno(g.intra_nodeno), type(g.type), weight(g.weight),
00127 gr(g.gr), outgoing(g.outgoing), incoming(g.incoming),
00128 out_hyper_edges(g.out_hyper_edges), visited(g.visited) {}
00129 };
00130
00131 class InterGraph : public Countable {
00132 public:
00133 typedef std::ostream & (*PRINT_OP)(std::ostream &, int);
00134
00135 private:
00136 friend class SummaryGraph;
00137
00138 typedef std::map<Transition, int, TransitionCmp> TransMap;
00139 typedef bool (*WT_CHECK)(SemElem *);
00140 typedef SemElem *(*WT_CORRECT)(SemElem *);
00141 typedef std::pair<int,int> tup;
00142 typedef std::pair<int, int> call_edge_t;
00143
00144 std::vector<GraphNode> nodes;
00145 std::vector<GraphEdge> intra_edges;
00146 std::vector<HyperEdge> inter_edges;
00147 std::vector<call_edge_t> call_edges;
00148 int max_scc_computed;
00149
00150 UnionFind *intra_graph_uf;
00151 std::list<IntraGraph *> gr_list;
00152
00153 ETransHandler eHandler;
00154
00155
00156 TransMap node_number;
00157 sem_elem_t sem;
00158 bool running_ewpds;
00159 bool running_prestar;
00160 InterGraphStats stats;
00161
00162 static std::ostream &defaultPrintOp(std::ostream &out, int a) {
00163 out << a;
00164 return out;
00165 }
00166
00167 public:
00168 InterGraph(wali::sem_elem_t s, bool e, bool pre) {
00169 sem = s;
00170 intra_graph_uf = NULL;
00171 running_ewpds = e;
00172 running_prestar = pre;
00173 max_scc_computed = 0;
00174 count = 0;
00175 }
00176 ~InterGraph();
00177 void addEdge(Transition src, Transition tgt, wali::sem_elem_t se);
00178 void addEdge(Transition src1, Transition src2, Transition tgt, wali::sem_elem_t se);
00179 void addEdge(Transition src1, Transition src2, Transition tgt, wali::merge_fn_t mf);
00180 void addCallRetEdge(Transition src, Transition tgt, wali::sem_elem_t se);
00181
00182 void addCallEdge(Transition src1, Transition src2);
00183
00184 void setSource(Transition t, wali::sem_elem_t se);
00185 void setESource(Transition t, wali::sem_elem_t wtAtCall, wali::sem_elem_t wtAfterCall);
00186
00187 void setupInterSolution(std::list<Transition> *wt_required = NULL);
00188
00189 sem_elem_t get_weight(Transition t);
00190 sem_elem_t get_call_weight(Transition t);
00191
00192 void update_all_weights();
00193
00194 bool exists(int state, int stack, WT_CHECK op);
00195
00196 std::ostream &print(std::ostream &out, PRINT_OP pop = defaultPrintOp);
00197
00198 std::ostream &print_stats(std::ostream &out);
00199
00200 bool path_summary(int state, int stack, int accept, WT_CORRECT correct, WT_CHECK op);
00201
00202 bool exists(Transition &t);
00203
00204 int nGraphs() {
00205 return (int)gr_list.size();
00206 }
00207 private:
00208 int nodeno(Transition &t);
00209
00210 int intra_edgeno(Transition &src, Transition &tgt);
00211
00212 int inter_edgeno(Transition &src1, Transition &src2, Transition &tgt);
00213
00214 void dfsIntraForward(IntraGraph *gr,
00215 std::list<IntraGraph *> &finished,
00216 std::map<IntraGraph *,
00217 std::list<IntraGraph *> > &rev_edges);
00218
00219 void bfsIntra(IntraGraph *start, unsigned int scc_number);
00220
00221 unsigned SCC(std::list<IntraGraph *> &grlist, std::list<IntraGraph *> &grsorted);
00222
00223 void saturate(std::multiset<tup> &worklist, unsigned scc_n);
00224
00225 void setup_worklist(std::list<IntraGraph *> &gr_sorted,
00226 std::list<IntraGraph *>::iterator &gr_it,
00227 unsigned int scc_n,
00228 std::multiset<tup> &worklist);
00229
00230 void resetSCCedges(IntraGraph *gr, unsigned int scc_number);
00231 };
00232
00233 typedef ref_ptr<InterGraph> InterGraphPtr;
00234 }
00235
00236 }
00237
00238
00239 #endif // wali_graph_INTER_GRAPH_GUARD
00240