1 // Copyright (c) 2016 Google Inc.
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14
15 #include "source/opt/types.h"
16
17 #include <algorithm>
18 #include <cassert>
19 #include <cstdint>
20 #include <sstream>
21 #include <string>
22 #include <unordered_set>
23
24 #include "source/util/make_unique.h"
25 #include "spirv/unified1/spirv.h"
26
27 namespace spvtools {
28 namespace opt {
29 namespace analysis {
30
31 using U32VecVec = std::vector<std::vector<uint32_t>>;
32
33 namespace {
34
35 // Returns true if the two vector of vectors are identical.
CompareTwoVectors(const U32VecVec a,const U32VecVec b)36 bool CompareTwoVectors(const U32VecVec a, const U32VecVec b) {
37 const auto size = a.size();
38 if (size != b.size()) return false;
39
40 if (size == 0) return true;
41 if (size == 1) return a.front() == b.front();
42
43 std::vector<const std::vector<uint32_t>*> a_ptrs, b_ptrs;
44 a_ptrs.reserve(size);
45 a_ptrs.reserve(size);
46 for (uint32_t i = 0; i < size; ++i) {
47 a_ptrs.push_back(&a[i]);
48 b_ptrs.push_back(&b[i]);
49 }
50
51 const auto cmp = [](const std::vector<uint32_t>* m,
52 const std::vector<uint32_t>* n) {
53 return m->front() < n->front();
54 };
55
56 std::sort(a_ptrs.begin(), a_ptrs.end(), cmp);
57 std::sort(b_ptrs.begin(), b_ptrs.end(), cmp);
58
59 for (uint32_t i = 0; i < size; ++i) {
60 if (*a_ptrs[i] != *b_ptrs[i]) return false;
61 }
62 return true;
63 }
64
65 } // anonymous namespace
66
GetDecorationStr() const67 std::string Type::GetDecorationStr() const {
68 std::ostringstream oss;
69 oss << "[[";
70 for (const auto& decoration : decorations_) {
71 oss << "(";
72 for (size_t i = 0; i < decoration.size(); ++i) {
73 oss << (i > 0 ? ", " : "");
74 oss << decoration.at(i);
75 }
76 oss << ")";
77 }
78 oss << "]]";
79 return oss.str();
80 }
81
HasSameDecorations(const Type * that) const82 bool Type::HasSameDecorations(const Type* that) const {
83 return CompareTwoVectors(decorations_, that->decorations_);
84 }
85
IsUniqueType(bool allowVariablePointers) const86 bool Type::IsUniqueType(bool allowVariablePointers) const {
87 switch (kind_) {
88 case kPointer:
89 return !allowVariablePointers;
90 case kStruct:
91 case kArray:
92 case kRuntimeArray:
93 return false;
94 default:
95 return true;
96 }
97 }
98
Clone() const99 std::unique_ptr<Type> Type::Clone() const {
100 std::unique_ptr<Type> type;
101 switch (kind_) {
102 #define DeclareKindCase(kind) \
103 case k##kind: \
104 type = MakeUnique<kind>(*this->As##kind()); \
105 break
106 DeclareKindCase(Void);
107 DeclareKindCase(Bool);
108 DeclareKindCase(Integer);
109 DeclareKindCase(Float);
110 DeclareKindCase(Vector);
111 DeclareKindCase(Matrix);
112 DeclareKindCase(Image);
113 DeclareKindCase(Sampler);
114 DeclareKindCase(SampledImage);
115 DeclareKindCase(Array);
116 DeclareKindCase(RuntimeArray);
117 DeclareKindCase(Struct);
118 DeclareKindCase(Opaque);
119 DeclareKindCase(Pointer);
120 DeclareKindCase(Function);
121 DeclareKindCase(Event);
122 DeclareKindCase(DeviceEvent);
123 DeclareKindCase(ReserveId);
124 DeclareKindCase(Queue);
125 DeclareKindCase(Pipe);
126 DeclareKindCase(ForwardPointer);
127 DeclareKindCase(PipeStorage);
128 DeclareKindCase(NamedBarrier);
129 DeclareKindCase(AccelerationStructureNV);
130 DeclareKindCase(CooperativeMatrixNV);
131 DeclareKindCase(RayQueryKHR);
132 #undef DeclareKindCase
133 default:
134 assert(false && "Unhandled type");
135 }
136 return type;
137 }
138
RemoveDecorations() const139 std::unique_ptr<Type> Type::RemoveDecorations() const {
140 std::unique_ptr<Type> type(Clone());
141 type->ClearDecorations();
142 return type;
143 }
144
operator ==(const Type & other) const145 bool Type::operator==(const Type& other) const {
146 if (kind_ != other.kind_) return false;
147
148 switch (kind_) {
149 #define DeclareKindCase(kind) \
150 case k##kind: \
151 return As##kind()->IsSame(&other)
152 DeclareKindCase(Void);
153 DeclareKindCase(Bool);
154 DeclareKindCase(Integer);
155 DeclareKindCase(Float);
156 DeclareKindCase(Vector);
157 DeclareKindCase(Matrix);
158 DeclareKindCase(Image);
159 DeclareKindCase(Sampler);
160 DeclareKindCase(SampledImage);
161 DeclareKindCase(Array);
162 DeclareKindCase(RuntimeArray);
163 DeclareKindCase(Struct);
164 DeclareKindCase(Opaque);
165 DeclareKindCase(Pointer);
166 DeclareKindCase(Function);
167 DeclareKindCase(Event);
168 DeclareKindCase(DeviceEvent);
169 DeclareKindCase(ReserveId);
170 DeclareKindCase(Queue);
171 DeclareKindCase(Pipe);
172 DeclareKindCase(ForwardPointer);
173 DeclareKindCase(PipeStorage);
174 DeclareKindCase(NamedBarrier);
175 DeclareKindCase(AccelerationStructureNV);
176 DeclareKindCase(CooperativeMatrixNV);
177 DeclareKindCase(RayQueryKHR);
178 #undef DeclareKindCase
179 default:
180 assert(false && "Unhandled type");
181 return false;
182 }
183 }
184
GetHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const185 void Type::GetHashWords(std::vector<uint32_t>* words,
186 std::unordered_set<const Type*>* seen) const {
187 if (!seen->insert(this).second) {
188 return;
189 }
190
191 words->push_back(kind_);
192 for (const auto& d : decorations_) {
193 for (auto w : d) {
194 words->push_back(w);
195 }
196 }
197
198 switch (kind_) {
199 #define DeclareKindCase(type) \
200 case k##type: \
201 As##type()->GetExtraHashWords(words, seen); \
202 break
203 DeclareKindCase(Void);
204 DeclareKindCase(Bool);
205 DeclareKindCase(Integer);
206 DeclareKindCase(Float);
207 DeclareKindCase(Vector);
208 DeclareKindCase(Matrix);
209 DeclareKindCase(Image);
210 DeclareKindCase(Sampler);
211 DeclareKindCase(SampledImage);
212 DeclareKindCase(Array);
213 DeclareKindCase(RuntimeArray);
214 DeclareKindCase(Struct);
215 DeclareKindCase(Opaque);
216 DeclareKindCase(Pointer);
217 DeclareKindCase(Function);
218 DeclareKindCase(Event);
219 DeclareKindCase(DeviceEvent);
220 DeclareKindCase(ReserveId);
221 DeclareKindCase(Queue);
222 DeclareKindCase(Pipe);
223 DeclareKindCase(ForwardPointer);
224 DeclareKindCase(PipeStorage);
225 DeclareKindCase(NamedBarrier);
226 DeclareKindCase(AccelerationStructureNV);
227 DeclareKindCase(CooperativeMatrixNV);
228 DeclareKindCase(RayQueryKHR);
229 #undef DeclareKindCase
230 default:
231 assert(false && "Unhandled type");
232 break;
233 }
234
235 seen->erase(this);
236 }
237
HashValue() const238 size_t Type::HashValue() const {
239 std::u32string h;
240 std::vector<uint32_t> words;
241 GetHashWords(&words);
242 for (auto w : words) {
243 h.push_back(w);
244 }
245
246 return std::hash<std::u32string>()(h);
247 }
248
IsSameImpl(const Type * that,IsSameCache *) const249 bool Integer::IsSameImpl(const Type* that, IsSameCache*) const {
250 const Integer* it = that->AsInteger();
251 return it && width_ == it->width_ && signed_ == it->signed_ &&
252 HasSameDecorations(that);
253 }
254
str() const255 std::string Integer::str() const {
256 std::ostringstream oss;
257 oss << (signed_ ? "s" : "u") << "int" << width_;
258 return oss.str();
259 }
260
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > *) const261 void Integer::GetExtraHashWords(std::vector<uint32_t>* words,
262 std::unordered_set<const Type*>*) const {
263 words->push_back(width_);
264 words->push_back(signed_);
265 }
266
IsSameImpl(const Type * that,IsSameCache *) const267 bool Float::IsSameImpl(const Type* that, IsSameCache*) const {
268 const Float* ft = that->AsFloat();
269 return ft && width_ == ft->width_ && HasSameDecorations(that);
270 }
271
str() const272 std::string Float::str() const {
273 std::ostringstream oss;
274 oss << "float" << width_;
275 return oss.str();
276 }
277
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > *) const278 void Float::GetExtraHashWords(std::vector<uint32_t>* words,
279 std::unordered_set<const Type*>*) const {
280 words->push_back(width_);
281 }
282
Vector(const Type * type,uint32_t count)283 Vector::Vector(const Type* type, uint32_t count)
284 : Type(kVector), element_type_(type), count_(count) {
285 assert(type->AsBool() || type->AsInteger() || type->AsFloat());
286 }
287
IsSameImpl(const Type * that,IsSameCache * seen) const288 bool Vector::IsSameImpl(const Type* that, IsSameCache* seen) const {
289 const Vector* vt = that->AsVector();
290 if (!vt) return false;
291 return count_ == vt->count_ &&
292 element_type_->IsSameImpl(vt->element_type_, seen) &&
293 HasSameDecorations(that);
294 }
295
str() const296 std::string Vector::str() const {
297 std::ostringstream oss;
298 oss << "<" << element_type_->str() << ", " << count_ << ">";
299 return oss.str();
300 }
301
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const302 void Vector::GetExtraHashWords(std::vector<uint32_t>* words,
303 std::unordered_set<const Type*>* seen) const {
304 element_type_->GetHashWords(words, seen);
305 words->push_back(count_);
306 }
307
Matrix(const Type * type,uint32_t count)308 Matrix::Matrix(const Type* type, uint32_t count)
309 : Type(kMatrix), element_type_(type), count_(count) {
310 assert(type->AsVector());
311 }
312
IsSameImpl(const Type * that,IsSameCache * seen) const313 bool Matrix::IsSameImpl(const Type* that, IsSameCache* seen) const {
314 const Matrix* mt = that->AsMatrix();
315 if (!mt) return false;
316 return count_ == mt->count_ &&
317 element_type_->IsSameImpl(mt->element_type_, seen) &&
318 HasSameDecorations(that);
319 }
320
str() const321 std::string Matrix::str() const {
322 std::ostringstream oss;
323 oss << "<" << element_type_->str() << ", " << count_ << ">";
324 return oss.str();
325 }
326
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const327 void Matrix::GetExtraHashWords(std::vector<uint32_t>* words,
328 std::unordered_set<const Type*>* seen) const {
329 element_type_->GetHashWords(words, seen);
330 words->push_back(count_);
331 }
332
Image(Type * type,SpvDim dimen,uint32_t d,bool array,bool multisample,uint32_t sampling,SpvImageFormat f,SpvAccessQualifier qualifier)333 Image::Image(Type* type, SpvDim dimen, uint32_t d, bool array, bool multisample,
334 uint32_t sampling, SpvImageFormat f, SpvAccessQualifier qualifier)
335 : Type(kImage),
336 sampled_type_(type),
337 dim_(dimen),
338 depth_(d),
339 arrayed_(array),
340 ms_(multisample),
341 sampled_(sampling),
342 format_(f),
343 access_qualifier_(qualifier) {
344 // TODO(antiagainst): check sampled_type
345 }
346
IsSameImpl(const Type * that,IsSameCache * seen) const347 bool Image::IsSameImpl(const Type* that, IsSameCache* seen) const {
348 const Image* it = that->AsImage();
349 if (!it) return false;
350 return dim_ == it->dim_ && depth_ == it->depth_ && arrayed_ == it->arrayed_ &&
351 ms_ == it->ms_ && sampled_ == it->sampled_ && format_ == it->format_ &&
352 access_qualifier_ == it->access_qualifier_ &&
353 sampled_type_->IsSameImpl(it->sampled_type_, seen) &&
354 HasSameDecorations(that);
355 }
356
str() const357 std::string Image::str() const {
358 std::ostringstream oss;
359 oss << "image(" << sampled_type_->str() << ", " << dim_ << ", " << depth_
360 << ", " << arrayed_ << ", " << ms_ << ", " << sampled_ << ", " << format_
361 << ", " << access_qualifier_ << ")";
362 return oss.str();
363 }
364
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const365 void Image::GetExtraHashWords(std::vector<uint32_t>* words,
366 std::unordered_set<const Type*>* seen) const {
367 sampled_type_->GetHashWords(words, seen);
368 words->push_back(dim_);
369 words->push_back(depth_);
370 words->push_back(arrayed_);
371 words->push_back(ms_);
372 words->push_back(sampled_);
373 words->push_back(format_);
374 words->push_back(access_qualifier_);
375 }
376
IsSameImpl(const Type * that,IsSameCache * seen) const377 bool SampledImage::IsSameImpl(const Type* that, IsSameCache* seen) const {
378 const SampledImage* sit = that->AsSampledImage();
379 if (!sit) return false;
380 return image_type_->IsSameImpl(sit->image_type_, seen) &&
381 HasSameDecorations(that);
382 }
383
str() const384 std::string SampledImage::str() const {
385 std::ostringstream oss;
386 oss << "sampled_image(" << image_type_->str() << ")";
387 return oss.str();
388 }
389
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const390 void SampledImage::GetExtraHashWords(
391 std::vector<uint32_t>* words, std::unordered_set<const Type*>* seen) const {
392 image_type_->GetHashWords(words, seen);
393 }
394
Array(const Type * type,const Array::LengthInfo & length_info_arg)395 Array::Array(const Type* type, const Array::LengthInfo& length_info_arg)
396 : Type(kArray), element_type_(type), length_info_(length_info_arg) {
397 assert(type != nullptr);
398 assert(!type->AsVoid());
399 // We always have a word to say which case we're in, followed
400 // by at least one more word.
401 assert(length_info_arg.words.size() >= 2);
402 }
403
IsSameImpl(const Type * that,IsSameCache * seen) const404 bool Array::IsSameImpl(const Type* that, IsSameCache* seen) const {
405 const Array* at = that->AsArray();
406 if (!at) return false;
407 bool is_same = element_type_->IsSameImpl(at->element_type_, seen);
408 is_same = is_same && HasSameDecorations(that);
409 is_same = is_same && (length_info_.words == at->length_info_.words);
410 return is_same;
411 }
412
str() const413 std::string Array::str() const {
414 std::ostringstream oss;
415 oss << "[" << element_type_->str() << ", id(" << LengthId() << "), words(";
416 const char* spacer = "";
417 for (auto w : length_info_.words) {
418 oss << spacer << w;
419 spacer = ",";
420 }
421 oss << ")]";
422 return oss.str();
423 }
424
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const425 void Array::GetExtraHashWords(std::vector<uint32_t>* words,
426 std::unordered_set<const Type*>* seen) const {
427 element_type_->GetHashWords(words, seen);
428 // This should mirror the logic in IsSameImpl
429 words->insert(words->end(), length_info_.words.begin(),
430 length_info_.words.end());
431 }
432
ReplaceElementType(const Type * type)433 void Array::ReplaceElementType(const Type* type) { element_type_ = type; }
434
RuntimeArray(const Type * type)435 RuntimeArray::RuntimeArray(const Type* type)
436 : Type(kRuntimeArray), element_type_(type) {
437 assert(!type->AsVoid());
438 }
439
IsSameImpl(const Type * that,IsSameCache * seen) const440 bool RuntimeArray::IsSameImpl(const Type* that, IsSameCache* seen) const {
441 const RuntimeArray* rat = that->AsRuntimeArray();
442 if (!rat) return false;
443 return element_type_->IsSameImpl(rat->element_type_, seen) &&
444 HasSameDecorations(that);
445 }
446
str() const447 std::string RuntimeArray::str() const {
448 std::ostringstream oss;
449 oss << "[" << element_type_->str() << "]";
450 return oss.str();
451 }
452
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const453 void RuntimeArray::GetExtraHashWords(
454 std::vector<uint32_t>* words, std::unordered_set<const Type*>* seen) const {
455 element_type_->GetHashWords(words, seen);
456 }
457
ReplaceElementType(const Type * type)458 void RuntimeArray::ReplaceElementType(const Type* type) {
459 element_type_ = type;
460 }
461
Struct(const std::vector<const Type * > & types)462 Struct::Struct(const std::vector<const Type*>& types)
463 : Type(kStruct), element_types_(types) {
464 for (const auto* t : types) {
465 (void)t;
466 assert(!t->AsVoid());
467 }
468 }
469
AddMemberDecoration(uint32_t index,std::vector<uint32_t> && decoration)470 void Struct::AddMemberDecoration(uint32_t index,
471 std::vector<uint32_t>&& decoration) {
472 if (index >= element_types_.size()) {
473 assert(0 && "index out of bound");
474 return;
475 }
476
477 element_decorations_[index].push_back(std::move(decoration));
478 }
479
IsSameImpl(const Type * that,IsSameCache * seen) const480 bool Struct::IsSameImpl(const Type* that, IsSameCache* seen) const {
481 const Struct* st = that->AsStruct();
482 if (!st) return false;
483 if (element_types_.size() != st->element_types_.size()) return false;
484 const auto size = element_decorations_.size();
485 if (size != st->element_decorations_.size()) return false;
486 if (!HasSameDecorations(that)) return false;
487
488 for (size_t i = 0; i < element_types_.size(); ++i) {
489 if (!element_types_[i]->IsSameImpl(st->element_types_[i], seen))
490 return false;
491 }
492 for (const auto& p : element_decorations_) {
493 if (st->element_decorations_.count(p.first) == 0) return false;
494 if (!CompareTwoVectors(p.second, st->element_decorations_.at(p.first)))
495 return false;
496 }
497 return true;
498 }
499
str() const500 std::string Struct::str() const {
501 std::ostringstream oss;
502 oss << "{";
503 const size_t count = element_types_.size();
504 for (size_t i = 0; i < count; ++i) {
505 oss << element_types_[i]->str();
506 if (i + 1 != count) oss << ", ";
507 }
508 oss << "}";
509 return oss.str();
510 }
511
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const512 void Struct::GetExtraHashWords(std::vector<uint32_t>* words,
513 std::unordered_set<const Type*>* seen) const {
514 for (auto* t : element_types_) {
515 t->GetHashWords(words, seen);
516 }
517 for (const auto& pair : element_decorations_) {
518 words->push_back(pair.first);
519 for (const auto& d : pair.second) {
520 for (auto w : d) {
521 words->push_back(w);
522 }
523 }
524 }
525 }
526
IsSameImpl(const Type * that,IsSameCache *) const527 bool Opaque::IsSameImpl(const Type* that, IsSameCache*) const {
528 const Opaque* ot = that->AsOpaque();
529 if (!ot) return false;
530 return name_ == ot->name_ && HasSameDecorations(that);
531 }
532
str() const533 std::string Opaque::str() const {
534 std::ostringstream oss;
535 oss << "opaque('" << name_ << "')";
536 return oss.str();
537 }
538
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > *) const539 void Opaque::GetExtraHashWords(std::vector<uint32_t>* words,
540 std::unordered_set<const Type*>*) const {
541 for (auto c : name_) {
542 words->push_back(static_cast<char32_t>(c));
543 }
544 }
545
Pointer(const Type * type,SpvStorageClass sc)546 Pointer::Pointer(const Type* type, SpvStorageClass sc)
547 : Type(kPointer), pointee_type_(type), storage_class_(sc) {}
548
IsSameImpl(const Type * that,IsSameCache * seen) const549 bool Pointer::IsSameImpl(const Type* that, IsSameCache* seen) const {
550 const Pointer* pt = that->AsPointer();
551 if (!pt) return false;
552 if (storage_class_ != pt->storage_class_) return false;
553 auto p = seen->insert(std::make_pair(this, that->AsPointer()));
554 if (!p.second) {
555 return true;
556 }
557 bool same_pointee = pointee_type_->IsSameImpl(pt->pointee_type_, seen);
558 seen->erase(p.first);
559 if (!same_pointee) {
560 return false;
561 }
562 return HasSameDecorations(that);
563 }
564
str() const565 std::string Pointer::str() const {
566 std::ostringstream os;
567 os << pointee_type_->str() << " " << static_cast<uint32_t>(storage_class_)
568 << "*";
569 return os.str();
570 }
571
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const572 void Pointer::GetExtraHashWords(std::vector<uint32_t>* words,
573 std::unordered_set<const Type*>* seen) const {
574 pointee_type_->GetHashWords(words, seen);
575 words->push_back(storage_class_);
576 }
577
SetPointeeType(const Type * type)578 void Pointer::SetPointeeType(const Type* type) { pointee_type_ = type; }
579
Function(const Type * ret_type,const std::vector<const Type * > & params)580 Function::Function(const Type* ret_type, const std::vector<const Type*>& params)
581 : Type(kFunction), return_type_(ret_type), param_types_(params) {}
582
Function(const Type * ret_type,std::vector<const Type * > & params)583 Function::Function(const Type* ret_type, std::vector<const Type*>& params)
584 : Type(kFunction), return_type_(ret_type), param_types_(params) {}
585
IsSameImpl(const Type * that,IsSameCache * seen) const586 bool Function::IsSameImpl(const Type* that, IsSameCache* seen) const {
587 const Function* ft = that->AsFunction();
588 if (!ft) return false;
589 if (!return_type_->IsSameImpl(ft->return_type_, seen)) return false;
590 if (param_types_.size() != ft->param_types_.size()) return false;
591 for (size_t i = 0; i < param_types_.size(); ++i) {
592 if (!param_types_[i]->IsSameImpl(ft->param_types_[i], seen)) return false;
593 }
594 return HasSameDecorations(that);
595 }
596
str() const597 std::string Function::str() const {
598 std::ostringstream oss;
599 const size_t count = param_types_.size();
600 oss << "(";
601 for (size_t i = 0; i < count; ++i) {
602 oss << param_types_[i]->str();
603 if (i + 1 != count) oss << ", ";
604 }
605 oss << ") -> " << return_type_->str();
606 return oss.str();
607 }
608
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const609 void Function::GetExtraHashWords(std::vector<uint32_t>* words,
610 std::unordered_set<const Type*>* seen) const {
611 return_type_->GetHashWords(words, seen);
612 for (const auto* t : param_types_) {
613 t->GetHashWords(words, seen);
614 }
615 }
616
SetReturnType(const Type * type)617 void Function::SetReturnType(const Type* type) { return_type_ = type; }
618
IsSameImpl(const Type * that,IsSameCache *) const619 bool Pipe::IsSameImpl(const Type* that, IsSameCache*) const {
620 const Pipe* pt = that->AsPipe();
621 if (!pt) return false;
622 return access_qualifier_ == pt->access_qualifier_ && HasSameDecorations(that);
623 }
624
str() const625 std::string Pipe::str() const {
626 std::ostringstream oss;
627 oss << "pipe(" << access_qualifier_ << ")";
628 return oss.str();
629 }
630
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > *) const631 void Pipe::GetExtraHashWords(std::vector<uint32_t>* words,
632 std::unordered_set<const Type*>*) const {
633 words->push_back(access_qualifier_);
634 }
635
IsSameImpl(const Type * that,IsSameCache *) const636 bool ForwardPointer::IsSameImpl(const Type* that, IsSameCache*) const {
637 const ForwardPointer* fpt = that->AsForwardPointer();
638 if (!fpt) return false;
639 return (pointer_ && fpt->pointer_ ? *pointer_ == *fpt->pointer_
640 : target_id_ == fpt->target_id_) &&
641 storage_class_ == fpt->storage_class_ && HasSameDecorations(that);
642 }
643
str() const644 std::string ForwardPointer::str() const {
645 std::ostringstream oss;
646 oss << "forward_pointer(";
647 if (pointer_ != nullptr) {
648 oss << pointer_->str();
649 } else {
650 oss << target_id_;
651 }
652 oss << ")";
653 return oss.str();
654 }
655
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * seen) const656 void ForwardPointer::GetExtraHashWords(
657 std::vector<uint32_t>* words, std::unordered_set<const Type*>* seen) const {
658 words->push_back(target_id_);
659 words->push_back(storage_class_);
660 if (pointer_) pointer_->GetHashWords(words, seen);
661 }
662
CooperativeMatrixNV(const Type * type,const uint32_t scope,const uint32_t rows,const uint32_t columns)663 CooperativeMatrixNV::CooperativeMatrixNV(const Type* type, const uint32_t scope,
664 const uint32_t rows,
665 const uint32_t columns)
666 : Type(kCooperativeMatrixNV),
667 component_type_(type),
668 scope_id_(scope),
669 rows_id_(rows),
670 columns_id_(columns) {
671 assert(type != nullptr);
672 assert(scope != 0);
673 assert(rows != 0);
674 assert(columns != 0);
675 }
676
str() const677 std::string CooperativeMatrixNV::str() const {
678 std::ostringstream oss;
679 oss << "<" << component_type_->str() << ", " << scope_id_ << ", " << rows_id_
680 << ", " << columns_id_ << ">";
681 return oss.str();
682 }
683
GetExtraHashWords(std::vector<uint32_t> * words,std::unordered_set<const Type * > * pSet) const684 void CooperativeMatrixNV::GetExtraHashWords(
685 std::vector<uint32_t>* words, std::unordered_set<const Type*>* pSet) const {
686 component_type_->GetHashWords(words, pSet);
687 words->push_back(scope_id_);
688 words->push_back(rows_id_);
689 words->push_back(columns_id_);
690 }
691
IsSameImpl(const Type * that,IsSameCache * seen) const692 bool CooperativeMatrixNV::IsSameImpl(const Type* that,
693 IsSameCache* seen) const {
694 const CooperativeMatrixNV* mt = that->AsCooperativeMatrixNV();
695 if (!mt) return false;
696 return component_type_->IsSameImpl(mt->component_type_, seen) &&
697 scope_id_ == mt->scope_id_ && rows_id_ == mt->rows_id_ &&
698 columns_id_ == mt->columns_id_ && HasSameDecorations(that);
699 }
700
701 } // namespace analysis
702 } // namespace opt
703 } // namespace spvtools
704