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