Coverage Report

Created: 2023-12-11 06:17

/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_