• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright 2021 The Tint Authors.
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 stateied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 
15 #include "src/reader/spirv/parser_type.h"
16 
17 #include <string>
18 #include <unordered_map>
19 #include <utility>
20 
21 #include "src/program_builder.h"
22 #include "src/utils/map.h"
23 #include "src/utils/hash.h"
24 
25 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Type);
26 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Void);
27 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Bool);
28 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::U32);
29 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::F32);
30 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::I32);
31 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Pointer);
32 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Reference);
33 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Vector);
34 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Matrix);
35 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Array);
36 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Sampler);
37 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Texture);
38 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::DepthTexture);
39 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::DepthMultisampledTexture);
40 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::MultisampledTexture);
41 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::SampledTexture);
42 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::StorageTexture);
43 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Named);
44 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Alias);
45 TINT_INSTANTIATE_TYPEINFO(tint::reader::spirv::Struct);
46 
47 namespace tint {
48 namespace reader {
49 namespace spirv {
50 
51 namespace {
52 struct PointerHasher {
operator ()tint::reader::spirv::__anon042a5b850111::PointerHasher53   size_t operator()(const Pointer& t) const {
54     return utils::Hash(t.type, t.storage_class);
55   }
56 };
57 
58 struct ReferenceHasher {
operator ()tint::reader::spirv::__anon042a5b850111::ReferenceHasher59   size_t operator()(const Reference& t) const {
60     return utils::Hash(t.type, t.storage_class);
61   }
62 };
63 
64 struct VectorHasher {
operator ()tint::reader::spirv::__anon042a5b850111::VectorHasher65   size_t operator()(const Vector& t) const {
66     return utils::Hash(t.type, t.size);
67   }
68 };
69 
70 struct MatrixHasher {
operator ()tint::reader::spirv::__anon042a5b850111::MatrixHasher71   size_t operator()(const Matrix& t) const {
72     return utils::Hash(t.type, t.columns, t.rows);
73   }
74 };
75 
76 struct ArrayHasher {
operator ()tint::reader::spirv::__anon042a5b850111::ArrayHasher77   size_t operator()(const Array& t) const {
78     return utils::Hash(t.type, t.size, t.stride);
79   }
80 };
81 
82 struct MultisampledTextureHasher {
operator ()tint::reader::spirv::__anon042a5b850111::MultisampledTextureHasher83   size_t operator()(const MultisampledTexture& t) const {
84     return utils::Hash(t.dims, t.type);
85   }
86 };
87 
88 struct SampledTextureHasher {
operator ()tint::reader::spirv::__anon042a5b850111::SampledTextureHasher89   size_t operator()(const SampledTexture& t) const {
90     return utils::Hash(t.dims, t.type);
91   }
92 };
93 
94 struct StorageTextureHasher {
operator ()tint::reader::spirv::__anon042a5b850111::StorageTextureHasher95   size_t operator()(const StorageTexture& t) const {
96     return utils::Hash(t.dims, t.format, t.access);
97   }
98 };
99 }  // namespace
100 
operator ==(const Pointer & a,const Pointer & b)101 static bool operator==(const Pointer& a, const Pointer& b) {
102   return a.type == b.type && a.storage_class == b.storage_class;
103 }
104 
operator ==(const Reference & a,const Reference & b)105 static bool operator==(const Reference& a, const Reference& b) {
106   return a.type == b.type && a.storage_class == b.storage_class;
107 }
108 
operator ==(const Vector & a,const Vector & b)109 static bool operator==(const Vector& a, const Vector& b) {
110   return a.type == b.type && a.size == b.size;
111 }
112 
operator ==(const Matrix & a,const Matrix & b)113 static bool operator==(const Matrix& a, const Matrix& b) {
114   return a.type == b.type && a.columns == b.columns && a.rows == b.rows;
115 }
116 
operator ==(const Array & a,const Array & b)117 static bool operator==(const Array& a, const Array& b) {
118   return a.type == b.type && a.size == b.size && a.stride == b.stride;
119 }
120 
operator ==(const MultisampledTexture & a,const MultisampledTexture & b)121 static bool operator==(const MultisampledTexture& a,
122                        const MultisampledTexture& b) {
123   return a.dims == b.dims && a.type == b.type;
124 }
125 
operator ==(const SampledTexture & a,const SampledTexture & b)126 static bool operator==(const SampledTexture& a, const SampledTexture& b) {
127   return a.dims == b.dims && a.type == b.type;
128 }
129 
operator ==(const StorageTexture & a,const StorageTexture & b)130 static bool operator==(const StorageTexture& a, const StorageTexture& b) {
131   return a.dims == b.dims && a.format == b.format;
132 }
133 
Build(ProgramBuilder & b) const134 const ast::Type* Void::Build(ProgramBuilder& b) const {
135   return b.ty.void_();
136 }
137 
Build(ProgramBuilder & b) const138 const ast::Type* Bool::Build(ProgramBuilder& b) const {
139   return b.ty.bool_();
140 }
141 
Build(ProgramBuilder & b) const142 const ast::Type* U32::Build(ProgramBuilder& b) const {
143   return b.ty.u32();
144 }
145 
Build(ProgramBuilder & b) const146 const ast::Type* F32::Build(ProgramBuilder& b) const {
147   return b.ty.f32();
148 }
149 
Build(ProgramBuilder & b) const150 const ast::Type* I32::Build(ProgramBuilder& b) const {
151   return b.ty.i32();
152 }
153 
Pointer(const Type * t,ast::StorageClass s)154 Pointer::Pointer(const Type* t, ast::StorageClass s)
155     : type(t), storage_class(s) {}
156 Pointer::Pointer(const Pointer&) = default;
157 
Build(ProgramBuilder & b) const158 const ast::Type* Pointer::Build(ProgramBuilder& b) const {
159   return b.ty.pointer(type->Build(b), storage_class);
160 }
161 
Reference(const Type * t,ast::StorageClass s)162 Reference::Reference(const Type* t, ast::StorageClass s)
163     : type(t), storage_class(s) {}
164 Reference::Reference(const Reference&) = default;
165 
Build(ProgramBuilder & b) const166 const ast::Type* Reference::Build(ProgramBuilder& b) const {
167   return type->Build(b);
168 }
169 
Vector(const Type * t,uint32_t s)170 Vector::Vector(const Type* t, uint32_t s) : type(t), size(s) {}
171 Vector::Vector(const Vector&) = default;
172 
Build(ProgramBuilder & b) const173 const ast::Type* Vector::Build(ProgramBuilder& b) const {
174   return b.ty.vec(type->Build(b), size);
175 }
176 
Matrix(const Type * t,uint32_t c,uint32_t r)177 Matrix::Matrix(const Type* t, uint32_t c, uint32_t r)
178     : type(t), columns(c), rows(r) {}
179 Matrix::Matrix(const Matrix&) = default;
180 
Build(ProgramBuilder & b) const181 const ast::Type* Matrix::Build(ProgramBuilder& b) const {
182   return b.ty.mat(type->Build(b), columns, rows);
183 }
184 
Array(const Type * t,uint32_t sz,uint32_t st)185 Array::Array(const Type* t, uint32_t sz, uint32_t st)
186     : type(t), size(sz), stride(st) {}
187 Array::Array(const Array&) = default;
188 
Build(ProgramBuilder & b) const189 const ast::Type* Array::Build(ProgramBuilder& b) const {
190   if (size > 0) {
191     return b.ty.array(type->Build(b), size, stride);
192   } else {
193     return b.ty.array(type->Build(b), nullptr, stride);
194   }
195 }
196 
Sampler(ast::SamplerKind k)197 Sampler::Sampler(ast::SamplerKind k) : kind(k) {}
198 Sampler::Sampler(const Sampler&) = default;
199 
Build(ProgramBuilder & b) const200 const ast::Type* Sampler::Build(ProgramBuilder& b) const {
201   return b.ty.sampler(kind);
202 }
203 
Texture(ast::TextureDimension d)204 Texture::Texture(ast::TextureDimension d) : dims(d) {}
205 Texture::Texture(const Texture&) = default;
206 
DepthTexture(ast::TextureDimension d)207 DepthTexture::DepthTexture(ast::TextureDimension d) : Base(d) {}
208 DepthTexture::DepthTexture(const DepthTexture&) = default;
209 
Build(ProgramBuilder & b) const210 const ast::Type* DepthTexture::Build(ProgramBuilder& b) const {
211   return b.ty.depth_texture(dims);
212 }
213 
DepthMultisampledTexture(ast::TextureDimension d)214 DepthMultisampledTexture::DepthMultisampledTexture(ast::TextureDimension d)
215     : Base(d) {}
216 DepthMultisampledTexture::DepthMultisampledTexture(
217     const DepthMultisampledTexture&) = default;
218 
Build(ProgramBuilder & b) const219 const ast::Type* DepthMultisampledTexture::Build(ProgramBuilder& b) const {
220   return b.ty.depth_multisampled_texture(dims);
221 }
222 
MultisampledTexture(ast::TextureDimension d,const Type * t)223 MultisampledTexture::MultisampledTexture(ast::TextureDimension d, const Type* t)
224     : Base(d), type(t) {}
225 MultisampledTexture::MultisampledTexture(const MultisampledTexture&) = default;
226 
Build(ProgramBuilder & b) const227 const ast::Type* MultisampledTexture::Build(ProgramBuilder& b) const {
228   return b.ty.multisampled_texture(dims, type->Build(b));
229 }
230 
SampledTexture(ast::TextureDimension d,const Type * t)231 SampledTexture::SampledTexture(ast::TextureDimension d, const Type* t)
232     : Base(d), type(t) {}
233 SampledTexture::SampledTexture(const SampledTexture&) = default;
234 
Build(ProgramBuilder & b) const235 const ast::Type* SampledTexture::Build(ProgramBuilder& b) const {
236   return b.ty.sampled_texture(dims, type->Build(b));
237 }
238 
StorageTexture(ast::TextureDimension d,ast::ImageFormat f,ast::Access a)239 StorageTexture::StorageTexture(ast::TextureDimension d,
240                                ast::ImageFormat f,
241                                ast::Access a)
242     : Base(d), format(f), access(a) {}
243 StorageTexture::StorageTexture(const StorageTexture&) = default;
244 
Build(ProgramBuilder & b) const245 const ast::Type* StorageTexture::Build(ProgramBuilder& b) const {
246   return b.ty.storage_texture(dims, format, access);
247 }
248 
Named(Symbol n)249 Named::Named(Symbol n) : name(n) {}
250 Named::Named(const Named&) = default;
251 Named::~Named() = default;
252 
Alias(Symbol n,const Type * ty)253 Alias::Alias(Symbol n, const Type* ty) : Base(n), type(ty) {}
254 Alias::Alias(const Alias&) = default;
255 
Build(ProgramBuilder & b) const256 const ast::Type* Alias::Build(ProgramBuilder& b) const {
257   return b.ty.type_name(name);
258 }
259 
Struct(Symbol n,TypeList m)260 Struct::Struct(Symbol n, TypeList m) : Base(n), members(std::move(m)) {}
261 Struct::Struct(const Struct&) = default;
262 Struct::~Struct() = default;
263 
Build(ProgramBuilder & b) const264 const ast::Type* Struct::Build(ProgramBuilder& b) const {
265   return b.ty.type_name(name);
266 }
267 
268 /// The PIMPL state of the Types object.
269 struct TypeManager::State {
270   /// The allocator of types
271   BlockAllocator<Type> allocator_;
272   /// The lazily-created Void type
273   spirv::Void const* void_ = nullptr;
274   /// The lazily-created Bool type
275   spirv::Bool const* bool_ = nullptr;
276   /// The lazily-created U32 type
277   spirv::U32 const* u32_ = nullptr;
278   /// The lazily-created F32 type
279   spirv::F32 const* f32_ = nullptr;
280   /// The lazily-created I32 type
281   spirv::I32 const* i32_ = nullptr;
282   /// Map of Pointer to the returned Pointer type instance
283   std::unordered_map<spirv::Pointer, const spirv::Pointer*, PointerHasher>
284       pointers_;
285   /// Map of Reference to the returned Reference type instance
286   std::unordered_map<spirv::Reference, const spirv::Reference*, ReferenceHasher>
287       references_;
288   /// Map of Vector to the returned Vector type instance
289   std::unordered_map<spirv::Vector, const spirv::Vector*, VectorHasher>
290       vectors_;
291   /// Map of Matrix to the returned Matrix type instance
292   std::unordered_map<spirv::Matrix, const spirv::Matrix*, MatrixHasher>
293       matrices_;
294   /// Map of Array to the returned Array type instance
295   std::unordered_map<spirv::Array, const spirv::Array*, ArrayHasher> arrays_;
296   /// Map of type name to returned Alias instance
297   std::unordered_map<Symbol, const spirv::Alias*> aliases_;
298   /// Map of type name to returned Struct instance
299   std::unordered_map<Symbol, const spirv::Struct*> structs_;
300   /// Map of ast::SamplerKind to returned Sampler instance
301   std::unordered_map<ast::SamplerKind, const spirv::Sampler*> samplers_;
302   /// Map of ast::TextureDimension to returned DepthTexture instance
303   std::unordered_map<ast::TextureDimension, const spirv::DepthTexture*>
304       depth_textures_;
305   /// Map of ast::TextureDimension to returned DepthMultisampledTexture instance
306   std::unordered_map<ast::TextureDimension,
307                      const spirv::DepthMultisampledTexture*>
308       depth_multisampled_textures_;
309   /// Map of MultisampledTexture to the returned MultisampledTexture type
310   /// instance
311   std::unordered_map<spirv::MultisampledTexture,
312                      const spirv::MultisampledTexture*,
313                      MultisampledTextureHasher>
314       multisampled_textures_;
315   /// Map of SampledTexture to the returned SampledTexture type instance
316   std::unordered_map<spirv::SampledTexture,
317                      const spirv::SampledTexture*,
318                      SampledTextureHasher>
319       sampled_textures_;
320   /// Map of StorageTexture to the returned StorageTexture type instance
321   std::unordered_map<spirv::StorageTexture,
322                      const spirv::StorageTexture*,
323                      StorageTextureHasher>
324       storage_textures_;
325 };
326 
UnwrapPtr() const327 const Type* Type::UnwrapPtr() const {
328   const Type* type = this;
329   while (auto* ptr = type->As<Pointer>()) {
330     type = ptr->type;
331   }
332   return type;
333 }
334 
UnwrapRef() const335 const Type* Type::UnwrapRef() const {
336   const Type* type = this;
337   while (auto* ptr = type->As<Reference>()) {
338     type = ptr->type;
339   }
340   return type;
341 }
342 
UnwrapAlias() const343 const Type* Type::UnwrapAlias() const {
344   const Type* type = this;
345   while (auto* alias = type->As<Alias>()) {
346     type = alias->type;
347   }
348   return type;
349 }
350 
UnwrapAll() const351 const Type* Type::UnwrapAll() const {
352   auto* type = this;
353   while (true) {
354     if (auto* alias = type->As<Alias>()) {
355       type = alias->type;
356     } else if (auto* ptr = type->As<Pointer>()) {
357       type = ptr->type;
358     } else {
359       break;
360     }
361   }
362   return type;
363 }
364 
IsFloatScalar() const365 bool Type::IsFloatScalar() const {
366   return Is<F32>();
367 }
368 
IsFloatScalarOrVector() const369 bool Type::IsFloatScalarOrVector() const {
370   return IsFloatScalar() || IsFloatVector();
371 }
372 
IsFloatVector() const373 bool Type::IsFloatVector() const {
374   return Is([](const Vector* v) { return v->type->IsFloatScalar(); });
375 }
376 
IsIntegerScalar() const377 bool Type::IsIntegerScalar() const {
378   return IsAnyOf<U32, I32>();
379 }
380 
IsIntegerScalarOrVector() const381 bool Type::IsIntegerScalarOrVector() const {
382   return IsUnsignedScalarOrVector() || IsSignedScalarOrVector();
383 }
384 
IsScalar() const385 bool Type::IsScalar() const {
386   return IsAnyOf<F32, U32, I32, Bool>();
387 }
388 
IsSignedIntegerVector() const389 bool Type::IsSignedIntegerVector() const {
390   return Is([](const Vector* v) { return v->type->Is<I32>(); });
391 }
392 
IsSignedScalarOrVector() const393 bool Type::IsSignedScalarOrVector() const {
394   return Is<I32>() || IsSignedIntegerVector();
395 }
396 
IsUnsignedIntegerVector() const397 bool Type::IsUnsignedIntegerVector() const {
398   return Is([](const Vector* v) { return v->type->Is<U32>(); });
399 }
400 
IsUnsignedScalarOrVector() const401 bool Type::IsUnsignedScalarOrVector() const {
402   return Is<U32>() || IsUnsignedIntegerVector();
403 }
404 
TypeManager()405 TypeManager::TypeManager() {
406   state = std::make_unique<State>();
407 }
408 
409 TypeManager::~TypeManager() = default;
410 
Void()411 const spirv::Void* TypeManager::Void() {
412   if (!state->void_) {
413     state->void_ = state->allocator_.Create<spirv::Void>();
414   }
415   return state->void_;
416 }
417 
Bool()418 const spirv::Bool* TypeManager::Bool() {
419   if (!state->bool_) {
420     state->bool_ = state->allocator_.Create<spirv::Bool>();
421   }
422   return state->bool_;
423 }
424 
U32()425 const spirv::U32* TypeManager::U32() {
426   if (!state->u32_) {
427     state->u32_ = state->allocator_.Create<spirv::U32>();
428   }
429   return state->u32_;
430 }
431 
F32()432 const spirv::F32* TypeManager::F32() {
433   if (!state->f32_) {
434     state->f32_ = state->allocator_.Create<spirv::F32>();
435   }
436   return state->f32_;
437 }
438 
I32()439 const spirv::I32* TypeManager::I32() {
440   if (!state->i32_) {
441     state->i32_ = state->allocator_.Create<spirv::I32>();
442   }
443   return state->i32_;
444 }
445 
Pointer(const Type * el,ast::StorageClass sc)446 const spirv::Pointer* TypeManager::Pointer(const Type* el,
447                                            ast::StorageClass sc) {
448   return utils::GetOrCreate(state->pointers_, spirv::Pointer(el, sc), [&] {
449     return state->allocator_.Create<spirv::Pointer>(el, sc);
450   });
451 }
452 
Reference(const Type * el,ast::StorageClass sc)453 const spirv::Reference* TypeManager::Reference(const Type* el,
454                                                ast::StorageClass sc) {
455   return utils::GetOrCreate(state->references_, spirv::Reference(el, sc), [&] {
456     return state->allocator_.Create<spirv::Reference>(el, sc);
457   });
458 }
459 
Vector(const Type * el,uint32_t size)460 const spirv::Vector* TypeManager::Vector(const Type* el, uint32_t size) {
461   return utils::GetOrCreate(state->vectors_, spirv::Vector(el, size), [&] {
462     return state->allocator_.Create<spirv::Vector>(el, size);
463   });
464 }
465 
Matrix(const Type * el,uint32_t columns,uint32_t rows)466 const spirv::Matrix* TypeManager::Matrix(const Type* el,
467                                          uint32_t columns,
468                                          uint32_t rows) {
469   return utils::GetOrCreate(
470       state->matrices_, spirv::Matrix(el, columns, rows), [&] {
471         return state->allocator_.Create<spirv::Matrix>(el, columns, rows);
472       });
473 }
474 
Array(const Type * el,uint32_t size,uint32_t stride)475 const spirv::Array* TypeManager::Array(const Type* el,
476                                        uint32_t size,
477                                        uint32_t stride) {
478   return utils::GetOrCreate(
479       state->arrays_, spirv::Array(el, size, stride),
480       [&] { return state->allocator_.Create<spirv::Array>(el, size, stride); });
481 }
482 
Alias(Symbol name,const Type * ty)483 const spirv::Alias* TypeManager::Alias(Symbol name, const Type* ty) {
484   return utils::GetOrCreate(state->aliases_, name, [&] {
485     return state->allocator_.Create<spirv::Alias>(name, ty);
486   });
487 }
488 
Struct(Symbol name,TypeList members)489 const spirv::Struct* TypeManager::Struct(Symbol name, TypeList members) {
490   return utils::GetOrCreate(state->structs_, name, [&] {
491     return state->allocator_.Create<spirv::Struct>(name, std::move(members));
492   });
493 }
494 
Sampler(ast::SamplerKind kind)495 const spirv::Sampler* TypeManager::Sampler(ast::SamplerKind kind) {
496   return utils::GetOrCreate(state->samplers_, kind, [&] {
497     return state->allocator_.Create<spirv::Sampler>(kind);
498   });
499 }
500 
DepthTexture(ast::TextureDimension dims)501 const spirv::DepthTexture* TypeManager::DepthTexture(
502     ast::TextureDimension dims) {
503   return utils::GetOrCreate(state->depth_textures_, dims, [&] {
504     return state->allocator_.Create<spirv::DepthTexture>(dims);
505   });
506 }
507 
DepthMultisampledTexture(ast::TextureDimension dims)508 const spirv::DepthMultisampledTexture* TypeManager::DepthMultisampledTexture(
509     ast::TextureDimension dims) {
510   return utils::GetOrCreate(state->depth_multisampled_textures_, dims, [&] {
511     return state->allocator_.Create<spirv::DepthMultisampledTexture>(dims);
512   });
513 }
514 
MultisampledTexture(ast::TextureDimension dims,const Type * ty)515 const spirv::MultisampledTexture* TypeManager::MultisampledTexture(
516     ast::TextureDimension dims,
517     const Type* ty) {
518   return utils::GetOrCreate(
519       state->multisampled_textures_, spirv::MultisampledTexture(dims, ty), [&] {
520         return state->allocator_.Create<spirv::MultisampledTexture>(dims, ty);
521       });
522 }
523 
SampledTexture(ast::TextureDimension dims,const Type * ty)524 const spirv::SampledTexture* TypeManager::SampledTexture(
525     ast::TextureDimension dims,
526     const Type* ty) {
527   return utils::GetOrCreate(
528       state->sampled_textures_, spirv::SampledTexture(dims, ty), [&] {
529         return state->allocator_.Create<spirv::SampledTexture>(dims, ty);
530       });
531 }
532 
StorageTexture(ast::TextureDimension dims,ast::ImageFormat fmt,ast::Access access)533 const spirv::StorageTexture* TypeManager::StorageTexture(
534     ast::TextureDimension dims,
535     ast::ImageFormat fmt,
536     ast::Access access) {
537   return utils::GetOrCreate(
538       state->storage_textures_, spirv::StorageTexture(dims, fmt, access), [&] {
539         return state->allocator_.Create<spirv::StorageTexture>(dims, fmt,
540                                                                access);
541       });
542 }
543 
544 // Debug String() methods for Type classes. Only enabled in debug builds.
545 #ifndef NDEBUG
String() const546 std::string Void::String() const {
547   return "void";
548 }
549 
String() const550 std::string Bool::String() const {
551   return "bool";
552 }
553 
String() const554 std::string U32::String() const {
555   return "u32";
556 }
557 
String() const558 std::string F32::String() const {
559   return "f32";
560 }
561 
String() const562 std::string I32::String() const {
563   return "i32";
564 }
565 
String() const566 std::string Pointer::String() const {
567   std::stringstream ss;
568   ss << "ptr<" << std::string(ast::ToString(storage_class)) << ", "
569      << type->String() + ">";
570   return ss.str();
571 }
572 
String() const573 std::string Reference::String() const {
574   std::stringstream ss;
575   ss << "ref<" + std::string(ast::ToString(storage_class)) << ", "
576      << type->String() << ">";
577   return ss.str();
578 }
579 
String() const580 std::string Vector::String() const {
581   std::stringstream ss;
582   ss << "vec" << size << "<" << type->String() << ">";
583   return ss.str();
584 }
585 
String() const586 std::string Matrix::String() const {
587   std::stringstream ss;
588   ss << "mat" << columns << "x" << rows << "<" << type->String() << ">";
589   return ss.str();
590 }
591 
String() const592 std::string Array::String() const {
593   std::stringstream ss;
594   ss << "array<" << type->String() << ", " << size << ", " << stride << ">";
595   return ss.str();
596 }
597 
String() const598 std::string Sampler::String() const {
599   switch (kind) {
600     case ast::SamplerKind::kSampler:
601       return "sampler";
602     case ast::SamplerKind::kComparisonSampler:
603       return "sampler_comparison";
604   }
605   return "<unknown sampler>";
606 }
607 
String() const608 std::string DepthTexture::String() const {
609   std::stringstream ss;
610   ss << "depth_" << dims;
611   return ss.str();
612 }
613 
String() const614 std::string DepthMultisampledTexture::String() const {
615   std::stringstream ss;
616   ss << "depth_multisampled_" << dims;
617   return ss.str();
618 }
619 
String() const620 std::string MultisampledTexture::String() const {
621   std::stringstream ss;
622   ss << "texture_multisampled_" << dims << "<" << type << ">";
623   return ss.str();
624 }
625 
String() const626 std::string SampledTexture::String() const {
627   std::stringstream ss;
628   ss << "texture_" << dims << "<" << type << ">";
629   return ss.str();
630 }
631 
String() const632 std::string StorageTexture::String() const {
633   std::stringstream ss;
634   ss << "texture_storage_" << dims << "<" << format << ", " << access << ">";
635   return ss.str();
636 }
637 
String() const638 std::string Named::String() const {
639   return name.to_str();
640 }
641 #endif  // NDEBUG
642 
643 }  // namespace spirv
644 }  // namespace reader
645 }  // namespace tint
646