1717#ifndef wasm_analysis_lattices_flat_h
1818#define wasm_analysis_lattices_flat_h
1919
20+ #include < tuple>
21+ #include < type_traits>
2022#include < variant>
2123
2224#if __cplusplus >= 202002L
2325#include < concepts>
2426#endif
2527
26- #include " .. /lattice.h"
28+ #include " analysis /lattice.h"
2729#include " support/utilities.h"
2830
2931namespace wasm ::analysis {
@@ -33,27 +35,48 @@ namespace wasm::analysis {
3335template <typename T>
3436concept Flattenable = std::copyable<T> && std::equality_comparable<T>;
3537
36- // Given a type T , Flat<T> is the lattice where none of the values of T are
37- // comparable except with themselves, but they are all greater than a common
38- // bottom element not in T and less than a common top element also not in T .
39- template <Flattenable T>
38+ // Given types Ts... , Flat<T... > is the lattice where none of the values of any
39+ // T are comparable except with themselves, but they are all greater than a
40+ // common bottom element and less than a common top element.
41+ template <Flattenable T, Flattenable... Ts >
4042#else
41- template <typename T>
43+ template <typename T, typename ... Ts >
4244#endif
4345struct Flat {
4446private:
45- struct Bot {};
46- struct Top {};
47+ struct Bot : std::monostate {};
48+ struct Top : std::monostate {};
49+
50+ template <std::size_t I>
51+ using TI = std::tuple_element_t <I, std::tuple<T, Ts...>>;
4752
4853public:
49- struct Element : std::variant<Bot, T , Top> {
54+ struct Element : std::variant<T, Ts..., Bot , Top> {
5055 bool isBottom () const noexcept { return std::get_if<Bot>(this ); }
5156 bool isTop () const noexcept { return std::get_if<Top>(this ); }
52- const T* getVal () const noexcept { return std::get_if<T>(this ); }
53- T* getVal () noexcept { return std::get_if<T>(this ); }
57+ template <typename U = T> const U* getVal () const noexcept {
58+ return std::get_if<U>(this );
59+ }
60+ template <typename U = T> U* getVal () noexcept {
61+ return std::get_if<U>(this );
62+ }
63+ template <std::size_t I> const TI<I>* getVal () const noexcept {
64+ return std::get_if<I>(this );
65+ }
66+ template <std::size_t I> TI<I>* getVal () noexcept {
67+ return std::get_if<I>(this );
68+ }
5469 bool operator ==(const Element& other) const noexcept {
55- return ((isBottom () && other.isBottom ()) || (isTop () && other.isTop ()) ||
56- (getVal () && other.getVal () && *getVal () == *other.getVal ()));
70+ return this ->index () == other.index () &&
71+ std::visit (
72+ [](const auto & a, const auto & b) {
73+ if constexpr (std::is_same_v<decltype (a), decltype (b)>) {
74+ return a == b;
75+ }
76+ return false ;
77+ },
78+ *this ,
79+ other);
5780 }
5881 bool operator !=(const Element& other) const noexcept {
5982 return !(*this == other);
@@ -62,18 +85,21 @@ struct Flat {
6285
6386 Element getBottom () const noexcept { return Element{Bot{}}; }
6487 Element getTop () const noexcept { return Element{Top{}}; }
65- Element get (T&& val) const noexcept { return Element{std::move (val)}; }
88+ template <typename U> Element get (U&& val) const noexcept {
89+ return Element{std::move (val)};
90+ }
6691
6792 LatticeComparison compare (const Element& a, const Element& b) const noexcept {
68- if (a.index () < b.index ()) {
69- return LESS;
70- } else if (a.index () > b.index ()) {
71- return GREATER;
72- } else if (auto pA = a.getVal (); pA && *pA != *b.getVal ()) {
73- return NO_RELATION;
74- } else {
93+ if (a == b) {
7594 return EQUAL;
7695 }
96+ if (a.isTop () || b.isBottom ()) {
97+ return GREATER;
98+ }
99+ if (a.isBottom () || b.isTop ()) {
100+ return LESS;
101+ }
102+ return NO_RELATION;
77103 }
78104
79105 bool join (Element& joinee, const Element& joiner) const noexcept {
0 commit comments