/proc/self/cwd/src/ir/value.h
Line | Count | Source (jump to first uncovered line) |
1 | | //----------------------------------------------------------------------------- |
2 | | // Copyright 2021 Google LLC |
3 | | // |
4 | | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | | // you may not use this file except in compliance with the License. |
6 | | // You may obtain a copy of the License at |
7 | | // |
8 | | // https://www.apache.org/licenses/LICENSE-2.0 |
9 | | // |
10 | | // Unless required by applicable law or agreed to in writing, software |
11 | | // distributed under the License is distributed on an "AS IS" BASIS, |
12 | | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | | // See the License for the specific language governing permissions and |
14 | | // limitations under the License. |
15 | | //---------------------------------------------------------------------------- |
16 | | #ifndef SRC_IR_VALUE_H_ |
17 | | #define SRC_IR_VALUE_H_ |
18 | | |
19 | | #include <cstdint> |
20 | | #include <variant> |
21 | | #include <vector> |
22 | | |
23 | | #include "absl/container/flat_hash_map.h" |
24 | | #include "absl/strings/str_format.h" |
25 | | #include "src/common/utils/iterator_range.h" |
26 | | |
27 | | namespace raksha::ir { |
28 | | |
29 | | using ValueIndexType = uint64_t; |
30 | | static constexpr ValueIndexType kDefaultValueIndex = 0; |
31 | | |
32 | | class Block; |
33 | | class Operation; |
34 | | class Operator; |
35 | | class Value; |
36 | | class SsaNames; |
37 | | class Storage; |
38 | | |
39 | | namespace value { |
40 | | |
41 | | // TODO: validate fields. |
42 | | |
43 | | template <typename T> |
44 | | class IndexedValue { |
45 | | public: |
46 | | IndexedValue(const T& element, uint64_t index) |
47 | | : element_(&element), index_(index) {} |
48 | | |
49 | | template <typename H> |
50 | 0 | friend H AbslHashValue(H h, const IndexedValue<T>& v) { |
51 | 0 | return H::combine(std::move(h), v.element_, v.index_); |
52 | 0 | } Unexecuted instantiation: absl::hash_internal::MixingHashState raksha::ir::value::AbslHashValue<absl::hash_internal::MixingHashState>(absl::hash_internal::MixingHashState, raksha::ir::value::IndexedValue<raksha::ir::Block> const&) Unexecuted instantiation: absl::hash_internal::MixingHashState raksha::ir::value::AbslHashValue<absl::hash_internal::MixingHashState>(absl::hash_internal::MixingHashState, raksha::ir::value::IndexedValue<raksha::ir::Operation> const&) |
53 | | |
54 | 0 | const T& element() const { return *element_; } Unexecuted instantiation: raksha::ir::value::IndexedValue<raksha::ir::Block>::element() const Unexecuted instantiation: raksha::ir::value::IndexedValue<raksha::ir::Operation>::element() const |
55 | | uint64_t index() const { return index_; } |
56 | | |
57 | 0 | bool operator==(const IndexedValue<T>& other) const { |
58 | 0 | return (element_ == other.element_) && (index_ == other.index_); |
59 | 0 | } Unexecuted instantiation: raksha::ir::value::IndexedValue<raksha::ir::Block>::operator==(raksha::ir::value::IndexedValue<raksha::ir::Block> const&) const Unexecuted instantiation: raksha::ir::value::IndexedValue<raksha::ir::Operation>::operator==(raksha::ir::value::IndexedValue<raksha::ir::Operation> const&) const |
60 | | |
61 | | private: |
62 | | const T* element_; |
63 | | uint64_t index_; |
64 | | }; |
65 | | |
66 | | // Indicates the argument to a block. |
67 | | class BlockArgument : public IndexedValue<Block> { |
68 | | public: |
69 | | using IndexedValue<Block>::IndexedValue; |
70 | 0 | const Block& block() const { return element(); } |
71 | | }; |
72 | | |
73 | | // Indicates the result of an operation. |
74 | | class OperationResult : public IndexedValue<Operation> { |
75 | | public: |
76 | | // If you have an `Operation` that should produce a single result value, this |
77 | | // factory helper will produce an `OperationResult` with the default output |
78 | | // index 0 for you. |
79 | | static OperationResult MakeDefaultOperationResult( |
80 | 0 | const Operation& operation) { |
81 | 0 | return OperationResult(operation, kDefaultValueIndex); |
82 | 0 | } |
83 | | static OperationResult MakeOperationResult(const Operation& operation, |
84 | 0 | const uint64_t index) { |
85 | 0 | return OperationResult(operation, index); |
86 | 0 | } |
87 | | |
88 | | using IndexedValue<Operation>::IndexedValue; |
89 | 0 | const Operation& operation() const { return element(); } |
90 | | }; |
91 | | |
92 | | // Indicates the value in a storage. |
93 | | class StoredValue { |
94 | | public: |
95 | 0 | StoredValue(const Storage& storage) : storage_(&storage) {} |
96 | | |
97 | | StoredValue(const StoredValue&) = default; |
98 | | StoredValue& operator=(const StoredValue&) = default; |
99 | | |
100 | | template <typename H> |
101 | 0 | friend H AbslHashValue(H h, const StoredValue& v) { |
102 | 0 | return H::combine(std::move(h), v.storage_); |
103 | 0 | } |
104 | | |
105 | 0 | const Storage& storage() const { return *storage_; } |
106 | | |
107 | 0 | bool operator==(const StoredValue& other) const { |
108 | 0 | return storage_ == other.storage_; |
109 | 0 | } |
110 | | |
111 | | private: |
112 | | const Storage* storage_; |
113 | | }; |
114 | | |
115 | | // A special value to indicate that it can be anything. |
116 | | class Any { |
117 | | public: |
118 | 0 | std::string ToString() const { return "<<ANY>>"; } |
119 | | |
120 | | template <typename H> |
121 | 1.89k | friend H AbslHashValue(H h, const Any& v) { |
122 | 1.89k | return H::combine(std::move(h), true); |
123 | 1.89k | } |
124 | | |
125 | | // Two `Any`s are always the same, as `Any` has no internal structure to |
126 | | // differ. |
127 | 1.89k | bool operator==(const Any& other) const { return true; } |
128 | | }; |
129 | | |
130 | | } // namespace value |
131 | | |
132 | | // A class that represents a data value. |
133 | | class Value { |
134 | | public: |
135 | | using Variants = std::variant<value::BlockArgument, value::OperationResult, |
136 | | value::StoredValue, value::Any>; |
137 | | |
138 | | // If you have an `Operation` that should produce a single result value, this |
139 | | // helper will produce an `OperationResult`-variant `Value` with the default |
140 | | // index 0 for you. |
141 | 0 | static Value MakeDefaultOperationResultValue(const Operation& op) { |
142 | 0 | return Value(value::OperationResult::MakeDefaultOperationResult(op)); |
143 | 0 | } |
144 | | static Value MakeOperationResultValue(const Operation& op, |
145 | 0 | const uint64_t index) { |
146 | 0 | return Value(value::OperationResult::MakeOperationResult(op, index)); |
147 | 0 | } |
148 | | |
149 | 947 | explicit Value(Variants value) : value_(std::move(value)) {} |
150 | | |
151 | | // friend bool operator ==(const Value& lhs, const Value &rhs); |
152 | | template <typename H> |
153 | 1.89k | friend H AbslHashValue(H h, const Value& v) { |
154 | 1.89k | return H::combine(std::move(h), v.value_); |
155 | 1.89k | } |
156 | | |
157 | | // A downcast operation. Just delegates directly to std::get on variants. |
158 | | template <class T> |
159 | | const T& As() const { |
160 | | return std::get<T>(value_); |
161 | | } |
162 | | |
163 | | // A dynamic downcast operation. Just delegates directly to std::get_if on |
164 | | // variants. |
165 | | template <class T> |
166 | | const T* If() const { |
167 | | return std::get_if<T>(&value_); |
168 | | } |
169 | | |
170 | | // Return whether the two `Value`s are identical representations. If they |
171 | | // are different, this does not necessarily mean that they do not |
172 | | // *evaluate* to the same value. |
173 | 1.89k | bool operator==(const Value& other) const { return value_ == other.value_; } |
174 | | |
175 | | private: |
176 | | friend std::string ValueToString(Value, SsaNames&); |
177 | | Variants value_; |
178 | | }; |
179 | | |
180 | | using ValueList = std::vector<Value>; |
181 | | using ValueRange = utils::iterator_range<ValueList::const_iterator>; |
182 | | using IndexedValueMap = absl::flat_hash_map<std::string, Value>; |
183 | | using IndexedValueListMap = absl::flat_hash_map<std::string, ValueList>; |
184 | | |
185 | | } // namespace raksha::ir |
186 | | |
187 | | #endif // SRC_IR_VALUE_H_ |