• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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