MimIR
MimIR is my Intermediate Representation
Loading...
Searching...
No Matches
util.h
Go to the documentation of this file.
1#pragma once
2
3#include <cstdint>
4#include <cstring>
5
6#include <algorithm>
7#include <bit>
8#include <iterator>
9#include <queue>
10#include <stack>
11#include <string>
12#include <string_view>
13#include <type_traits>
14#include <utility>
15
16#include <absl/container/flat_hash_map.h>
17#include <absl/container/flat_hash_set.h>
18#include <absl/container/node_hash_map.h>
19#include <absl/container/node_hash_set.h>
20#include <fe/assert.h>
21
22#include "mim/util/hash.h"
23
24namespace mim {
25
26/// @name Utility Functions
27///@{
28
29/// A bitcast from @p src of type @p S to @p D, supporting different sizes.
30template<class D, class S>
31constexpr D bitcast_resize(const S& src) noexcept
32 requires(std::is_trivially_copyable_v<S> && std::is_trivially_copyable_v<D>)
33{
34 if constexpr (sizeof(D) == sizeof(S)) {
35 return std::bit_cast<D>(src);
36 } else {
37 D dst{}; // zero-fill
38 constexpr std::size_t n = (sizeof(D) < sizeof(S)) ? sizeof(D) : sizeof(S);
39 std::memcpy(&dst, &src, n);
40 return dst;
41 }
42}
43
44constexpr std::uint64_t pad(std::uint64_t offset, std::uint64_t align) noexcept {
45 assert(align != 0);
46
47 auto mod = offset % align;
48 if (mod) offset += align - mod;
49 return offset;
50}
51///@}
52
53/// @name Algorithms
54///@{
55template<class I, class T, class L>
56constexpr I binary_find(I begin, I end, T val, L lt) noexcept {
57 static_assert(std::random_access_iterator<I>);
58 I i;
59 if (std::distance(begin, end) < 16)
60 for (i = begin; i != end && lt(*i, val); ++i) {}
61 else
62 i = std::lower_bound(begin, end, val, lt);
63 return (i != end && !lt(val, *i)) ? i : end;
64}
65
66/// Like `std::string::substr`, but works on `std::string_view` instead.
67constexpr std::string_view subview(std::string_view s, size_t i, size_t n = std::string_view::npos) noexcept {
68 n = std::min(n, s.size());
69 return {s.data() + i, n - i};
70}
71
72/// Replaces all occurrences of @p what with @p repl.
73inline void find_and_replace(std::string& str, std::string_view what, std::string_view repl) {
74 for (size_t pos = str.find(what); pos != std::string::npos; pos = str.find(what, pos + repl.size()))
75 str.replace(pos, what.size(), repl);
76}
77///@}
78
79/// @name Helpers for Containers
80///@{
81template<class S>
82auto pop(S& s) -> decltype(s.top(), typename S::value_type()) {
83 auto val = s.top();
84 s.pop();
85 return val;
86}
87
88template<class Q>
89auto pop(Q& q) -> decltype(q.front(), typename Q::value_type()) {
90 auto val = q.front();
91 q.pop();
92 return val;
93}
94
95/// Yields pointer to element (or the element itself if it is already a pointer), if found and `nullptr` otherwise.
96/// @warning If the element is **not** already a pointer, this lookup will simply take the address of this element.
97/// This means that, e.g., a rehash of an `absl::flat_hash_map` will invalidate this pointer.
98template<class C, class K>
99auto lookup(const C& container, const K& key) {
100 auto i = container.find(key);
101 if constexpr (std::is_pointer_v<typename C::mapped_type>)
102 return i != container.end() ? i->second : nullptr;
103 else
104 return i != container.end() ? &i->second : nullptr;
105}
106
107/// Looks up @p key in @p container, asserts that it exists, and returns the mapped value.
108template<class C, class K>
109auto assert_lookup(C& container, const K& key) {
110 auto i = container.find(key);
111 assert(i != container.end());
112 return i->second;
113}
114
115/// Invokes `emplace` on @p container, asserts that insertion actually happened, and returns the iterator.
116template<class C, class... Args>
117auto assert_emplace(C& container, Args&&... args) {
118 auto [i, ins] = container.emplace(std::forward<Args>(args)...);
119 assert_unused(ins);
120 return i;
121}
122///@}
123
124template<class Set>
126public:
127 using T = typename std::remove_reference_t<Set>::value_type;
128
129 unique_queue() = default;
131 : done_(set) {}
132
133 bool push(T val) {
134 if (done_.emplace(val).second) {
135 queue_.emplace(val);
136 return true;
137 }
138 return false;
139 }
140
141 bool empty() const { return queue_.empty(); }
142 T pop() { return mim::pop(queue_); }
143 T& front() { return queue_.front(); }
144 T& back() { return queue_.back(); }
145 void clear() {
146 done_.clear();
147 queue_ = {};
148 }
149
150private:
151 Set done_;
152 std::queue<T> queue_;
153};
154
155template<class T>
156struct GIDHash {
157 constexpr size_t operator()(T p) const noexcept { return hash(p->gid()); }
158};
159
160template<class T>
161struct GIDLt {
162 constexpr bool operator()(T a, T b) const noexcept { return a->gid() < b->gid(); }
163};
164
165// clang-format off
166/// @name GID
167///@{
168template<class K, class V> using GIDMap = absl::flat_hash_map<K, V, GIDHash<K>>;
169template<class K> using GIDSet = absl::flat_hash_set<K, GIDHash<K>>;
170template<class K, class V> using GIDNodeMap = absl::node_hash_map<K, V, GIDHash<K>>;
171template<class K> using GIDNodeSet = absl::node_hash_set<K, GIDHash<K>>;
172///@}
173
174} // namespace mim
bool empty() const
Definition util.h:141
unique_queue()=default
unique_queue(Set set)
Definition util.h:130
typename std::remove_reference_t< Set >::value_type T
Definition util.h:127
void clear()
Definition util.h:145
bool push(T val)
Definition util.h:133
Definition ast.h:14
auto pop(S &s) -> decltype(s.top(), typename S::value_type())
Definition util.h:82
auto assert_emplace(C &container, Args &&... args)
Invokes emplace on container, asserts that insertion actually happened, and returns the iterator.
Definition util.h:117
auto lookup(const C &container, const K &key)
Yields pointer to element (or the element itself if it is already a pointer), if found and nullptr ot...
Definition util.h:99
constexpr I binary_find(I begin, I end, T val, L lt) noexcept
Definition util.h:56
absl::flat_hash_map< K, V, GIDHash< K > > GIDMap
Definition util.h:168
constexpr std::uint64_t pad(std::uint64_t offset, std::uint64_t align) noexcept
Definition util.h:44
constexpr std::string_view subview(std::string_view s, size_t i, size_t n=std::string_view::npos) noexcept
Like std::string::substr, but works on std::string_view instead.
Definition util.h:67
void find_and_replace(std::string &str, std::string_view what, std::string_view repl)
Replaces all occurrences of what with repl.
Definition util.h:73
constexpr size_t hash(size_t h) noexcept
Definition hash.h:32
absl::node_hash_set< K, GIDHash< K > > GIDNodeSet
Definition util.h:171
absl::node_hash_map< K, V, GIDHash< K > > GIDNodeMap
Definition util.h:170
absl::flat_hash_set< K, GIDHash< K > > GIDSet
Definition util.h:169
auto assert_lookup(C &container, const K &key)
Looks up key in container, asserts that it exists, and returns the mapped value.
Definition util.h:109
constexpr D bitcast_resize(const S &src) noexcept
A bitcast from src of type S to D, supporting different sizes.
Definition util.h:31
constexpr size_t operator()(T p) const noexcept
Definition util.h:157
constexpr bool operator()(T a, T b) const noexcept
Definition util.h:162