File indexing completed on 2026-05-10 08:44:46
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013 #ifndef LLVM_XRAY_GRAPH_H
0014 #define LLVM_XRAY_GRAPH_H
0015
0016 #include <initializer_list>
0017 #include <stdint.h>
0018 #include <type_traits>
0019 #include <utility>
0020
0021 #include "llvm/ADT/DenseMap.h"
0022 #include "llvm/ADT/DenseSet.h"
0023 #include "llvm/ADT/iterator.h"
0024 #include "llvm/Support/Error.h"
0025
0026 namespace llvm {
0027 namespace xray {
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072 template <typename VertexAttribute, typename EdgeAttribute,
0073 typename VI = int32_t>
0074 class Graph {
0075 public:
0076
0077 typedef VI VertexIdentifier;
0078 typedef std::pair<VI, VI> EdgeIdentifier;
0079
0080
0081
0082 using VertexValueType =
0083 detail::DenseMapPair<VertexIdentifier, VertexAttribute>;
0084
0085
0086
0087 using EdgeValueType = detail::DenseMapPair<EdgeIdentifier, EdgeAttribute>;
0088
0089 using size_type = std::size_t;
0090
0091 private:
0092
0093 using EdgeMapT = DenseMap<EdgeIdentifier, EdgeAttribute>;
0094
0095
0096
0097 using VertexMapT = DenseMap<VertexIdentifier, VertexAttribute>;
0098
0099
0100
0101
0102
0103 using NeighborSetT = DenseSet<VertexIdentifier>;
0104
0105
0106
0107 using NeighborLookupT = DenseMap<VertexIdentifier, NeighborSetT>;
0108
0109 private:
0110
0111
0112 EdgeMapT Edges;
0113
0114
0115 VertexMapT Vertices;
0116
0117
0118 NeighborLookupT InNeighbors;
0119
0120
0121 NeighborLookupT OutNeighbors;
0122
0123
0124
0125
0126
0127 template <bool IsConst, bool IsOut,
0128 typename BaseIt = typename NeighborSetT::const_iterator,
0129 typename T =
0130 std::conditional_t<IsConst, const EdgeValueType, EdgeValueType>>
0131 class NeighborEdgeIteratorT
0132 : public iterator_adaptor_base<
0133 NeighborEdgeIteratorT<IsConst, IsOut>, BaseIt,
0134 typename std::iterator_traits<BaseIt>::iterator_category, T> {
0135 using InternalEdgeMapT =
0136 std::conditional_t<IsConst, const EdgeMapT, EdgeMapT>;
0137
0138 friend class NeighborEdgeIteratorT<false, IsOut, BaseIt, EdgeValueType>;
0139 friend class NeighborEdgeIteratorT<true, IsOut, BaseIt,
0140 const EdgeValueType>;
0141
0142 InternalEdgeMapT *MP;
0143 VertexIdentifier SI;
0144
0145 public:
0146 template <bool IsConstDest,
0147 typename = std::enable_if_t<IsConstDest && !IsConst>>
0148 operator NeighborEdgeIteratorT<IsConstDest, IsOut, BaseIt,
0149 const EdgeValueType>() const {
0150 return NeighborEdgeIteratorT<IsConstDest, IsOut, BaseIt,
0151 const EdgeValueType>(this->I, MP, SI);
0152 }
0153
0154 NeighborEdgeIteratorT() = default;
0155 NeighborEdgeIteratorT(BaseIt _I, InternalEdgeMapT *_MP,
0156 VertexIdentifier _SI)
0157 : iterator_adaptor_base<
0158 NeighborEdgeIteratorT<IsConst, IsOut>, BaseIt,
0159 typename std::iterator_traits<BaseIt>::iterator_category, T>(_I),
0160 MP(_MP), SI(_SI) {}
0161
0162 T &operator*() const {
0163 if (!IsOut)
0164 return *(MP->find({*(this->I), SI}));
0165 else
0166 return *(MP->find({SI, *(this->I)}));
0167 }
0168 };
0169
0170 public:
0171
0172
0173
0174
0175 using ConstInEdgeIterator = NeighborEdgeIteratorT<true, false>;
0176
0177
0178
0179
0180 using InEdgeIterator = NeighborEdgeIteratorT<false, false>;
0181
0182
0183
0184
0185
0186 using ConstOutEdgeIterator = NeighborEdgeIteratorT<true, true>;
0187
0188
0189
0190
0191 using OutEdgeIterator = NeighborEdgeIteratorT<false, true>;
0192
0193
0194
0195
0196
0197
0198 template <bool isConst, bool isOut> class InOutEdgeView {
0199 public:
0200 using iterator = NeighborEdgeIteratorT<isConst, isOut>;
0201 using const_iterator = NeighborEdgeIteratorT<true, isOut>;
0202 using GraphT = std::conditional_t<isConst, const Graph, Graph>;
0203 using InternalEdgeMapT =
0204 std::conditional_t<isConst, const EdgeMapT, EdgeMapT>;
0205
0206 private:
0207 InternalEdgeMapT &M;
0208 const VertexIdentifier A;
0209 const NeighborLookupT &NL;
0210
0211 public:
0212 iterator begin() {
0213 auto It = NL.find(A);
0214 if (It == NL.end())
0215 return iterator();
0216 return iterator(It->second.begin(), &M, A);
0217 }
0218
0219 const_iterator cbegin() const {
0220 auto It = NL.find(A);
0221 if (It == NL.end())
0222 return const_iterator();
0223 return const_iterator(It->second.begin(), &M, A);
0224 }
0225
0226 const_iterator begin() const { return cbegin(); }
0227
0228 iterator end() {
0229 auto It = NL.find(A);
0230 if (It == NL.end())
0231 return iterator();
0232 return iterator(It->second.end(), &M, A);
0233 }
0234 const_iterator cend() const {
0235 auto It = NL.find(A);
0236 if (It == NL.end())
0237 return const_iterator();
0238 return const_iterator(It->second.end(), &M, A);
0239 }
0240
0241 const_iterator end() const { return cend(); }
0242
0243 size_type size() const {
0244 auto I = NL.find(A);
0245 if (I == NL.end())
0246 return 0;
0247 else
0248 return I->second.size();
0249 }
0250
0251 bool empty() const { return NL.count(A) == 0; };
0252
0253 InOutEdgeView(GraphT &G, VertexIdentifier A)
0254 : M(G.Edges), A(A), NL(isOut ? G.OutNeighbors : G.InNeighbors) {}
0255 };
0256
0257
0258
0259
0260
0261 using ConstVertexIterator = typename VertexMapT::const_iterator;
0262
0263
0264
0265
0266 using VertexIterator = typename VertexMapT::iterator;
0267
0268
0269
0270
0271
0272
0273 template <bool isConst> class VertexView {
0274 public:
0275 using iterator =
0276 std::conditional_t<isConst, ConstVertexIterator, VertexIterator>;
0277 using const_iterator = ConstVertexIterator;
0278 using GraphT = std::conditional_t<isConst, const Graph, Graph>;
0279
0280 private:
0281 GraphT &G;
0282
0283 public:
0284 iterator begin() { return G.Vertices.begin(); }
0285 iterator end() { return G.Vertices.end(); }
0286 const_iterator cbegin() const { return G.Vertices.cbegin(); }
0287 const_iterator cend() const { return G.Vertices.cend(); }
0288 const_iterator begin() const { return G.Vertices.begin(); }
0289 const_iterator end() const { return G.Vertices.end(); }
0290 size_type size() const { return G.Vertices.size(); }
0291 bool empty() const { return G.Vertices.empty(); }
0292 VertexView(GraphT &_G) : G(_G) {}
0293 };
0294
0295
0296
0297
0298 using ConstEdgeIterator = typename EdgeMapT::const_iterator;
0299
0300
0301
0302
0303 using EdgeIterator = typename EdgeMapT::iterator;
0304
0305
0306
0307
0308
0309
0310 template <bool isConst> class EdgeView {
0311 public:
0312 using iterator =
0313 std::conditional_t<isConst, ConstEdgeIterator, EdgeIterator>;
0314 using const_iterator = ConstEdgeIterator;
0315 using GraphT = std::conditional_t<isConst, const Graph, Graph>;
0316
0317 private:
0318 GraphT &G;
0319
0320 public:
0321 iterator begin() { return G.Edges.begin(); }
0322 iterator end() { return G.Edges.end(); }
0323 const_iterator cbegin() const { return G.Edges.cbegin(); }
0324 const_iterator cend() const { return G.Edges.cend(); }
0325 const_iterator begin() const { return G.Edges.begin(); }
0326 const_iterator end() const { return G.Edges.end(); }
0327 size_type size() const { return G.Edges.size(); }
0328 bool empty() const { return G.Edges.empty(); }
0329 EdgeView(GraphT &_G) : G(_G) {}
0330 };
0331
0332 public:
0333
0334
0335
0336
0337
0338
0339
0340 void clear() {
0341 Edges.clear();
0342 Vertices.clear();
0343 InNeighbors.clear();
0344 OutNeighbors.clear();
0345 }
0346
0347
0348
0349 VertexView<false> vertices() { return VertexView<false>(*this); }
0350
0351 VertexView<true> vertices() const { return VertexView<true>(*this); }
0352
0353
0354
0355 EdgeView<false> edges() { return EdgeView<false>(*this); }
0356
0357 EdgeView<true> edges() const { return EdgeView<true>(*this); }
0358
0359
0360
0361 InOutEdgeView<false, true> outEdges(const VertexIdentifier I) {
0362 return InOutEdgeView<false, true>(*this, I);
0363 }
0364
0365 InOutEdgeView<true, true> outEdges(const VertexIdentifier I) const {
0366 return InOutEdgeView<true, true>(*this, I);
0367 }
0368
0369
0370
0371 InOutEdgeView<false, false> inEdges(const VertexIdentifier I) {
0372 return InOutEdgeView<false, false>(*this, I);
0373 }
0374
0375 InOutEdgeView<true, false> inEdges(const VertexIdentifier I) const {
0376 return InOutEdgeView<true, false>(*this, I);
0377 }
0378
0379
0380
0381 VertexAttribute &operator[](const VertexIdentifier &I) { return Vertices[I]; }
0382
0383
0384
0385
0386 EdgeAttribute &operator[](const EdgeIdentifier &I) {
0387 Vertices.try_emplace(I.first);
0388 Vertices.try_emplace(I.second);
0389 InNeighbors[I.second].insert(I.first);
0390 OutNeighbors[I.first].insert(I.second);
0391 return Edges[I];
0392 }
0393
0394
0395 Expected<VertexAttribute &> at(const VertexIdentifier &I) {
0396 auto It = Vertices.find(I);
0397 if (It == Vertices.end())
0398 return make_error<StringError>(
0399 "Vertex Identifier Does Not Exist",
0400 std::make_error_code(std::errc::invalid_argument));
0401 return It->second;
0402 }
0403
0404 Expected<const VertexAttribute &> at(const VertexIdentifier &I) const {
0405 auto It = Vertices.find(I);
0406 if (It == Vertices.end())
0407 return make_error<StringError>(
0408 "Vertex Identifier Does Not Exist",
0409 std::make_error_code(std::errc::invalid_argument));
0410 return It->second;
0411 }
0412
0413
0414 Expected<EdgeAttribute &> at(const EdgeIdentifier &I) {
0415 auto It = Edges.find(I);
0416 if (It == Edges.end())
0417 return make_error<StringError>(
0418 "Edge Identifier Does Not Exist",
0419 std::make_error_code(std::errc::invalid_argument));
0420 return It->second;
0421 }
0422
0423 Expected<const EdgeAttribute &> at(const EdgeIdentifier &I) const {
0424 auto It = Edges.find(I);
0425 if (It == Edges.end())
0426 return make_error<StringError>(
0427 "Edge Identifier Does Not Exist",
0428 std::make_error_code(std::errc::invalid_argument));
0429 return It->second;
0430 }
0431
0432
0433
0434 size_type count(const VertexIdentifier &I) const {
0435 return Vertices.count(I);
0436 }
0437
0438
0439
0440 size_type count(const EdgeIdentifier &I) const { return Edges.count(I); }
0441
0442
0443
0444 std::pair<VertexIterator, bool>
0445 insert(const std::pair<VertexIdentifier, VertexAttribute> &Val) {
0446 return Vertices.insert(Val);
0447 }
0448
0449 std::pair<VertexIterator, bool>
0450 insert(std::pair<VertexIdentifier, VertexAttribute> &&Val) {
0451 return Vertices.insert(std::move(Val));
0452 }
0453
0454
0455
0456
0457 std::pair<EdgeIterator, bool>
0458 insert(const std::pair<EdgeIdentifier, EdgeAttribute> &Val) {
0459 const auto &p = Edges.insert(Val);
0460 if (p.second) {
0461 const auto &EI = Val.first;
0462 Vertices.FindAndConstruct(EI.first);
0463 Vertices.FindAndConstruct(EI.second);
0464 InNeighbors[EI.second].insert(EI.first);
0465 OutNeighbors[EI.first].insert(EI.second);
0466 };
0467
0468 return p;
0469 }
0470
0471
0472
0473
0474 std::pair<EdgeIterator, bool>
0475 insert(std::pair<EdgeIdentifier, EdgeAttribute> &&Val) {
0476 auto EI = Val.first;
0477 const auto &p = Edges.insert(std::move(Val));
0478 if (p.second) {
0479 Vertices.try_emplace(EI.first);
0480 Vertices.try_emplace(EI.second);
0481 InNeighbors[EI.second].insert(EI.first);
0482 OutNeighbors[EI.first].insert(EI.second);
0483 };
0484
0485 return p;
0486 }
0487 };
0488 }
0489 }
0490 #endif