GCC Code Coverage Report


Directory: ./
File: openvdb_ax/openvdb_ax/compiler/AttributeRegistry.h
Date: 2022-07-25 17:40:05
Exec Total Coverage
Lines: 63 64 98.4%
Functions: 6 6 100.0%
Branches: 70 96 72.9%

Line Branch Exec Source
1 // Copyright Contributors to the OpenVDB Project
2 // SPDX-License-Identifier: MPL-2.0/
3
4 /// @file compiler/AttributeRegistry.h
5 ///
6 /// @authors Nick Avramoussis, Francisco Gochez
7 ///
8 /// @brief These classes contain lists of expected attributes and volumes
9 /// which are populated by compiler during its internal code generation.
10 /// These will then be requested from the inputs to the executable
11 /// when execute is called. In this way, accesses are requested at
12 /// execution time, allowing the executable objects to be shared and
13 /// stored.
14 ///
15
16 #ifndef OPENVDB_AX_COMPILER_TARGET_REGISTRY_HAS_BEEN_INCLUDED
17 #define OPENVDB_AX_COMPILER_TARGET_REGISTRY_HAS_BEEN_INCLUDED
18
19 #include "../ast/AST.h"
20 #include "../ast/Tokens.h"
21 #include "../ast/Scanners.h"
22
23 #include <openvdb/version.h>
24 #include <openvdb/Types.h>
25 #include <openvdb/util/Name.h>
26
27 #include <unordered_map>
28
29 namespace openvdb {
30 OPENVDB_USE_VERSION_NAMESPACE
31 namespace OPENVDB_VERSION_NAME {
32
33 namespace ax {
34
35 /// @brief This class stores a list of access names, types and their dependency
36 /// connections.
37 ///
38 1537 class AttributeRegistry
39 {
40 public:
41 using Ptr = std::shared_ptr<AttributeRegistry>;
42 using ConstPtr = std::shared_ptr<const AttributeRegistry>;
43
44 /// @brief Registered access details, including its name, type and whether
45 /// a write handle is required
46 ///
47 struct AccessData
48 {
49 /// @brief Storage for access name, type and writesTo details
50 /// @param name The name of the access
51 /// @param type The typename of the access
52 /// @param readsFrom Whether the access is read from
53 /// @param writesTo Whether the access is written to
54 AccessData(const Name& name,
55 const ast::tokens::CoreType type,
56 const bool readsFrom,
57 const bool writesTo)
58
1/2
✓ Branch 1 taken 5132 times.
✗ Branch 2 not taken.
10149 : mAttrib(name, type)
59 , mAccess(readsFrom, writesTo)
60 , mUses()
61 , mDependencies() {}
62
63
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 5062 times.
5402 bool reads() const { return mAccess.first; }
64
8/8
✓ Branch 0 taken 286 times.
✓ Branch 1 taken 9866 times.
✓ Branch 2 taken 146 times.
✓ Branch 3 taken 4940 times.
✓ Branch 4 taken 9996 times.
✓ Branch 5 taken 139 times.
✓ Branch 6 taken 4915 times.
✓ Branch 7 taken 139 times.
30427 bool writes() const { return mAccess.second; }
65 50328 const std::string tokenname() const { return mAttrib.tokenname(); }
66 const std::string& name() const { return mAttrib.name(); }
67 ast::tokens::CoreType type() const { return mAttrib.type(); }
68 const std::vector<const AccessData*>& deps() const { return mDependencies; }
69 const std::vector<const AccessData*>& uses() const { return mUses; }
70
71 128215 bool dependson(const AccessData* data) const {
72
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 128215 times.
128215 assert(data);
73
2/2
✓ Branch 0 taken 27843 times.
✓ Branch 1 taken 124770 times.
152613 for (auto& dep : mDependencies) {
74
2/2
✓ Branch 0 taken 3445 times.
✓ Branch 1 taken 24398 times.
27843 if (dep == data) return true;
75 }
76 124770 return false;
77 }
78
79 bool affectsothers() const {
80
4/4
✓ Branch 0 taken 212 times.
✓ Branch 1 taken 3541 times.
✓ Branch 2 taken 972 times.
✓ Branch 3 taken 4581 times.
9306 for (auto& dep : mUses) {
81
5/6
✓ Branch 0 taken 186 times.
✓ Branch 1 taken 26 times.
✓ Branch 2 taken 334 times.
✓ Branch 3 taken 638 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 334 times.
1184 if (dep != this) return true;
82 }
83 return false;
84 }
85
86 private:
87 friend AttributeRegistry;
88
89 const ast::Attribute mAttrib;
90 const std::pair<bool, bool> mAccess;
91 std::vector<const AccessData*> mUses; // Accesses which depend on this access
92 std::vector<const AccessData*> mDependencies; // Accesses which this access depends on
93 };
94
95 using AccessDataVec = std::vector<AccessData>;
96
97 inline static AttributeRegistry::Ptr create(const ast::Tree& tree);
98
99 inline bool isReadable(const std::string& name, const ast::tokens::CoreType type) const
100 {
101 return this->accessPattern(name, type).first;
102 }
103
104 /// @brief Returns whether or not an access is required to be written to.
105 /// If no access with this name has been registered, returns false
106 /// @param name The name of the access
107 /// @param type The type of the access
108 inline bool isWritable(const std::string& name, const ast::tokens::CoreType type) const
109 {
110 return this->accessPattern(name, type).second;
111 }
112
113 inline std::pair<bool,bool>
114 accessPattern(const std::string& name, const ast::tokens::CoreType type) const
115 {
116 auto* data = this->get(name, type);
117 if (!data) return std::pair<bool,bool>(false,false);
118 return data->mAccess;
119 }
120
121 /// @brief Returns whether or not an access is registered.
122 /// @param name The name of the access
123 /// @param type The type of the access
124 inline bool isRegistered(const std::string& name, const ast::tokens::CoreType type) const
125 {
126 return this->accessIndex(name, type) != -1;
127 }
128
129 /// @brief Returns whether or not an access is registered.
130 /// @param name The name of the access
131 /// @param type The type of the access
132 inline int64_t
133 10145 accessIndex(const std::string& name,
134 const ast::tokens::CoreType type) const
135 {
136 int64_t i = 0;
137
1/2
✓ Branch 0 taken 68747 times.
✗ Branch 1 not taken.
68747 for (const auto& data : mAccesses) {
138
4/4
✓ Branch 0 taken 49015 times.
✓ Branch 1 taken 19732 times.
✓ Branch 2 taken 10145 times.
✓ Branch 3 taken 38870 times.
68747 if (data.type() == type && data.name() == name) {
139 10145 return i;
140 }
141 58602 ++i;
142 }
143 return -1;
144 }
145
146 const AccessData*
147 1428 get(const std::string& name, const ast::tokens::CoreType type) const
148 {
149
2/2
✓ Branch 0 taken 8219 times.
✓ Branch 1 taken 3 times.
8222 for (const auto& data : mAccesses) {
150
2/2
✓ Branch 0 taken 6520 times.
✓ Branch 1 taken 1699 times.
8219 if ((type == ast::tokens::UNKNOWN || data.type() == type)
151
3/4
✓ Branch 0 taken 8219 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 1425 times.
✓ Branch 3 taken 5095 times.
14739 && data.name() == name) {
152 1425 return &data;
153 }
154 }
155 3 return nullptr;
156 }
157
158 /// @brief Returns a const reference to the vector of registered accesss
159 inline const AccessDataVec& data() const { return mAccesses; }
160
161 void print(std::ostream& os) const;
162
163 private:
164 AttributeRegistry() : mAccesses() {}
165
166 /// @brief Add an access to the registry, returns an index into
167 /// the registry for that access
168 /// @param name The name of the access
169 /// @param type The typename of the access
170 /// @param writesTo Whether the access is required to be writeable
171 ///
172 inline void
173 addData(const Name& name,
174 const ast::tokens::CoreType type,
175 const bool readsfrom,
176 const bool writesto) {
177
1/2
✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
10149 mAccesses.emplace_back(name, type, readsfrom, writesto);
178 10149 }
179
180 AccessDataVec mAccesses;
181 };
182
183
184 /////////////////////////////////////////////////////////////////////
185 /////////////////////////////////////////////////////////////////////
186
187
188 1537 inline AttributeRegistry::Ptr AttributeRegistry::create(const ast::Tree& tree)
189 {
190 1537 AttributeRegistry::Ptr registry(new AttributeRegistry());
191 1537 std::vector<std::string> read, write, all;
192
1/2
✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
1537 ast::catalogueAttributeTokens(tree, &read, &write, &all);
193
194
1/2
✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
1537 size_t idx = 0;
195 std::unordered_map<std::string, size_t> indexmap;
196
197 auto dataBuilder =
198 4611 [&](const std::vector<std::string>& attribs,
199 const bool readFlag,
200 const bool writeFlag)
201 {
202 std::string name, type;
203
2/2
✓ Branch 0 taken 10149 times.
✓ Branch 1 taken 4611 times.
14760 for (const auto& attrib : attribs) {
204
1/2
✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
10149 ast::Attribute::nametypeFromToken(attrib, &name, &type);
205 const ast::tokens::CoreType typetoken =
206 10149 ast::tokens::tokenFromTypeString(type);
207
1/2
✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
10149 registry->addData(name, typetoken, readFlag, writeFlag);
208
1/2
✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
10149 indexmap[attrib] = idx++;
209 }
210 4611 };
211
212 // insert all data
213
214
1/2
✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
1537 dataBuilder(read, true, false);
215
1/2
✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
1537 dataBuilder(write, false, true);
216
1/2
✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
1537 dataBuilder(all, true, true);
217
218 4611 auto depBuilder = [&](const std::vector<std::string>& attribs) {
219
220 std::string name, type;
221
2/2
✓ Branch 0 taken 10149 times.
✓ Branch 1 taken 4611 times.
14760 for (const auto& attrib : attribs) {
222
1/2
✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
10149 ast::Attribute::nametypeFromToken(attrib, &name, &type);
223 const ast::tokens::CoreType typetoken =
224 10149 ast::tokens::tokenFromTypeString(type);
225
226 2277 std::vector<std::string> deps;
227
1/2
✓ Branch 1 taken 10149 times.
✗ Branch 2 not taken.
10149 ast::attributeDependencyTokens(tree, name, typetoken, deps);
228
2/2
✓ Branch 0 taken 7872 times.
✓ Branch 1 taken 2277 times.
10149 if (deps.empty()) continue;
229
230
2/4
✗ Branch 1 not taken.
✓ Branch 2 taken 2277 times.
✓ Branch 5 taken 2277 times.
✗ Branch 6 not taken.
5062 assert(indexmap.find(attrib) != indexmap.cend());
231 2277 const size_t index = indexmap.at(attrib);
232 2277 AccessData& access = registry->mAccesses[index];
233
2/2
✓ Branch 0 taken 2785 times.
✓ Branch 1 taken 2277 times.
5062 for (const std::string& dep : deps) {
234
2/4
✗ Branch 0 not taken.
✓ Branch 1 taken 2785 times.
✓ Branch 4 taken 2785 times.
✗ Branch 5 not taken.
2785 assert(indexmap.find(dep) != indexmap.cend());
235 2785 const size_t depindex = indexmap.at(dep);
236
1/2
✓ Branch 1 taken 2785 times.
✗ Branch 2 not taken.
2785 access.mDependencies.emplace_back(&registry->mAccesses[depindex]);
237 }
238 }
239 4611 };
240
241 // initialize dependencies
242
243
1/2
✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
1537 depBuilder(read);
244
1/2
✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
1537 depBuilder(write);
245
1/2
✓ Branch 1 taken 1537 times.
✗ Branch 2 not taken.
1537 depBuilder(all);
246
247 // Update usage from deps
248
249
2/2
✓ Branch 0 taken 10149 times.
✓ Branch 1 taken 1537 times.
11686 for (AccessData& access : registry->mAccesses) {
250
2/2
✓ Branch 0 taken 127353 times.
✓ Branch 1 taken 10149 times.
137502 for (const AccessData& next : registry->mAccesses) {
251 // don't skip self depends as it may write to itself
252 // i.e. @a = @a + 1; should add a self usage
253
2/2
✓ Branch 1 taken 2785 times.
✓ Branch 2 taken 124568 times.
127353 if (next.dependson(&access)) {
254
1/2
✓ Branch 1 taken 2785 times.
✗ Branch 2 not taken.
2785 access.mUses.emplace_back(&next);
255 }
256 }
257 }
258
259 1537 return registry;
260 }
261
262 inline void AttributeRegistry::print(std::ostream& os) const
263 {
264 size_t idx = 0;
265 for (const auto& data : mAccesses) {
266 os << "Attribute: " << data.name() << ", type: " <<
267 ast::tokens::typeStringFromToken(data.type()) << '\n';
268 os << " " << "Index : " << idx << '\n';
269 os << std::boolalpha;
270 os << " " << "Reads From : " << data.reads() << '\n';
271 os << " " << "Writes To : " << data.writes() << '\n';
272 os << std::noboolalpha;
273 os << " " << "Dependencies : " << data.mDependencies.size() << '\n';
274 for (const auto& dep : data.mDependencies) {
275 os << " " << "Attribute: " << dep->name() << " type: " <<
276 ast::tokens::typeStringFromToken(dep->type()) << '\n';
277 }
278 os << " " << "Usage : " << data.mUses.size() << '\n';
279 for (const auto& dep : data.mUses) {
280 os << " " << "Attribute: " << dep->name() << " type: " <<
281 ast::tokens::typeStringFromToken(dep->type()) << '\n';
282 }
283 os << '\n';
284 ++idx;
285 }
286 }
287
288 } // namespace ax
289 } // namespace OPENVDB_VERSION_NAME
290 } // namespace openvdb
291
292 #endif // OPENVDB_AX_COMPILER_TARGET_REGISTRY_HAS_BEEN_INCLUDED
293
294