1111#define PHASAR_PHASARLLVM_UTILS_LATTICEDOMAIN_H
1212
1313#include " llvm/Support/ErrorHandling.h"
14+ #include " llvm/Support/raw_ostream.h"
1415
1516#include < iostream>
1617#include < type_traits>
@@ -23,7 +24,11 @@ namespace psr {
2324// / the lattice.
2425struct Top {};
2526
26- static inline std::ostream &operator <<(std::ostream &OS, Top /* unused*/ ) {
27+ inline std::ostream &operator <<(std::ostream &OS, Top /* unused*/ ) {
28+ return OS << " Top" ;
29+ }
30+
31+ inline llvm::raw_ostream &operator <<(llvm::raw_ostream &OS, Top /* unused*/ ) {
2732 return OS << " Top" ;
2833}
2934
@@ -32,17 +37,66 @@ static inline std::ostream &operator<<(std::ostream &OS, Top /*unused*/) {
3237// / of the lattice.
3338struct Bottom {};
3439
35- static inline std::ostream &operator <<(std::ostream &OS, Bottom /* unused*/ ) {
40+ inline std::ostream &operator <<(std::ostream &OS, Bottom /* unused*/ ) {
3641 return OS << " Bottom" ;
3742}
3843
39- // / A easy shorthand to construct a complete lattice of L.
40- template <typename L> using LatticeDomain = std::variant<L, Top, Bottom>;
44+ inline llvm::raw_ostream &operator <<(llvm::raw_ostream &OS, Bottom /* unused*/ ) {
45+ return OS << " Bottom" ;
46+ }
4147
48+ // / A easy shorthand to construct a complete lattice of L.
4249template <typename L>
50+ struct LatticeDomain : public std ::variant<Top, L, Bottom> {
51+ using std::variant<Top, L, Bottom>::variant;
52+
53+ [[nodiscard]] inline bool isBottom () const noexcept {
54+ return std::holds_alternative<Bottom>(*this );
55+ }
56+ [[nodiscard]] inline bool isTop () const noexcept {
57+ return std::holds_alternative<Top>(*this );
58+ }
59+ [[nodiscard]] inline L *getValueOrNull () noexcept {
60+ return std::get_if<L>(this );
61+ }
62+ [[nodiscard]] inline const L *getValueOrNull () const noexcept {
63+ return std::get_if<L>(this );
64+ }
65+ };
66+
67+ // template <typename L> using LatticeDomain = std::variant<L, Top, Bottom>;
68+
69+ template <typename L,
70+ typename = std::void_t <decltype (std::declval<std::ostream &>()
71+ << std::declval<L>())>>
4372inline std::ostream &operator <<(std::ostream &OS, const LatticeDomain<L> &LD) {
44- std::visit ([&OS](const auto &LVal) { OS << LVal; }, LD);
45- return OS;
73+ if (LD.isBottom ()) {
74+ return OS << " Bottom" ;
75+ }
76+ if (LD.isTop ()) {
77+ return OS << " Top" ;
78+ }
79+
80+ const auto *Val = LD.getValueOrNull ();
81+ assert (Val && " Only alternative remaining is L" );
82+ return OS << *Val;
83+ }
84+
85+ template <typename L,
86+ typename = std::void_t <decltype (std::declval<llvm::raw_ostream &>()
87+ << std::declval<L>())>>
88+ inline llvm::raw_ostream &operator <<(llvm::raw_ostream &OS,
89+ const LatticeDomain<L> &LD) {
90+ if (LD.isBottom ()) {
91+ return OS << " Bottom" ;
92+ }
93+ if (LD.isTop ()) {
94+ return OS << " Top" ;
95+ }
96+
97+ const auto *Val = LD.getValueOrNull ();
98+ assert (Val && " Only alternative remaining is L" );
99+ return OS << *Val;
46100}
47101
48102template <typename L>
@@ -52,10 +106,9 @@ inline bool operator==(const LatticeDomain<L> &Lhs,
52106 return false ;
53107 }
54108
55- if (auto LhsPtr = std::get_if<L>(&Lhs)) {
56- if (auto RhsPtr = std::get_if<L>(&Rhs)) {
57- return *LhsPtr == *RhsPtr;
58- }
109+ if (auto LhsPtr = Lhs.getValueOrNull ()) {
110+ // / No need to check whether Lhs is an L; the indices are already the same
111+ return *LhsPtr == *Rhs.getValueOrNull ();
59112 }
60113
61114 return true ;
@@ -65,7 +118,7 @@ template <
65118 typename L, typename LL,
66119 typename = std::void_t <decltype (std::declval<LL>() == std::declval<L>())>>
67120inline bool operator ==(const LL &Lhs, const LatticeDomain<L> Rhs) {
68- if (const auto *RVal = std::get_if<L>(& Rhs)) {
121+ if (const auto *RVal = Rhs. getValueOrNull ( )) {
69122 return Lhs == *RVal;
70123 }
71124 return false ;
@@ -87,26 +140,28 @@ inline bool operator!=(const LatticeDomain<L> &Lhs,
87140template <typename L>
88141inline bool operator <(const LatticeDomain<L> &Lhs,
89142 const LatticeDomain<L> &Rhs) {
90- // Top < (Lhs::L < Rhs::L) < Bottom
91- if (std::holds_alternative<Top>( Rhs)) {
143+ // / Top < (Lhs::L < Rhs::L) < Bottom
144+ if (Rhs. isTop ( )) {
92145 return false ;
93146 }
94- if (std::holds_alternative<Top>( Lhs)) {
147+ if (Lhs. isTop ( )) {
95148 return true ;
96149 }
97150
98- if (auto LhsPtr = std::get_if<L>(& Lhs)) {
99- if (auto RhsPtr = std::get_if<L>(& Rhs)) {
151+ if (auto LhsPtr = Lhs. getValueOrNull ( )) {
152+ if (auto RhsPtr = Rhs. getValueOrNull ( )) {
100153 return *LhsPtr < *RhsPtr;
101154 }
102155 }
103156
104- if (std::holds_alternative<Bottom>(Rhs)) {
105- return !std::holds_alternative<Bottom>(Lhs);
106- }
107- if (std::holds_alternative<Bottom>(Lhs)) {
157+ if (Lhs.isBottom ()) {
108158 return false ;
109159 }
160+
161+ if (Rhs.isBottom ()) {
162+ return true ;
163+ }
164+
110165 llvm_unreachable (" All comparision cases should be handled above." );
111166}
112167
0 commit comments