Talvos  0.1
SPIR-V interpreter and dynamic analysis framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros
Type.cpp
Go to the documentation of this file.
1 // Copyright (c) 2018 the Talvos developers. All rights reserved.
2 //
3 // This file is distributed under a three-clause BSD license. For full license
4 // terms please see the LICENSE file distributed with this source code.
5 
8 
9 #include <spirv/unified1/spirv.h>
10 
11 #include "talvos/Image.h"
12 #include "talvos/Type.h"
13 
14 #include <cassert>
15 #include <iostream>
16 
17 namespace talvos
18 {
19 
20 uint32_t Type::getBitWidth() const
21 {
22  assert(isInt() || isFloat());
23  return BitWidth;
24 }
25 
26 size_t Type::getElementOffset(uint64_t Index) const
27 {
28  if (Id == STRUCT)
29  return ElementOffsets[Index];
30  else if (Id == VECTOR || Id == MATRIX)
31  return ElementType->getSize() * Index;
32  else if (Id == ARRAY || Id == POINTER || Id == RUNTIME_ARRAY)
33  return ArrayStride * Index;
34  assert(false && "Not an aggregate type");
35  abort();
36 }
37 
38 const Type *Type::getElementType(uint64_t Index) const
39 {
40  if (Id == STRUCT)
41  {
42  assert(Index < ElementCount);
43  return ElementTypes[Index].first;
44  }
45  else
46  return ElementType;
47 }
48 
49 const Type *Type::getScalarType() const
50 {
51  if (Id == VECTOR)
52  return ElementType;
53  else
54  {
55  assert(isScalar());
56  return this;
57  }
58 }
59 
60 uint32_t Type::getStorageClass() const
61 {
62  assert(Id == POINTER);
63  return StorageClass;
64 }
65 
66 const std::map<uint32_t, uint32_t> &
67 Type::getStructMemberDecorations(uint32_t Index) const
68 {
69  return ElementTypes[Index].second;
70 }
71 
72 bool Type::isComposite() const
73 {
74  return (Id == ARRAY || Id == STRUCT || Id == VECTOR || Id == MATRIX);
75 }
76 
77 bool Type::isScalar() const
78 {
79  return (Id == BOOL) || (Id == INT) || (Id == FLOAT) || (Id == POINTER);
80 }
81 
82 std::ostream &operator<<(std::ostream &Stream, const Type *Ty)
83 {
84  switch (Ty->Id)
85  {
86  case Type::VOID:
87  Stream << "void";
88  break;
89  case Type::BOOL:
90  Stream << "bool";
91  break;
92  case Type::INT:
93  Stream << "int" << Ty->BitWidth;
94  break;
95  case Type::FLOAT:
96  Stream << "float" << Ty->BitWidth;
97  break;
98  case Type::VECTOR:
99  Stream << Ty->ElementType << "v" << Ty->ElementCount;
100  break;
101  case Type::MATRIX:
102  Stream << Ty->ElementType->ElementType << " mat" << Ty->ElementCount << "x"
103  << Ty->ElementType->ElementCount;
104  break;
105  case Type::IMAGE:
106  Stream << "image ";
107 
108  switch (Ty->Dimensionality)
109  {
110 #define CASE(X) \
111  case SpvDim##X: \
112  Stream << #X; \
113  break
114  CASE(1D);
115  CASE(2D);
116  CASE(3D);
117  CASE(Cube);
118  CASE(Rect);
119  CASE(Buffer);
120  CASE(SubpassData);
121 #undef CASE
122  default:
123  Stream << "<unknown>";
124  break;
125  }
126 
127  Stream << " ";
128  switch (Ty->Format)
129  {
130 #define CASE(X) \
131  case SpvImageFormat##X: \
132  Stream << #X; \
133  break
134  CASE(Unknown);
135  CASE(Rgba32f);
136  CASE(Rgba16f);
137  CASE(R32f);
138  CASE(Rgba8);
139  CASE(Rgba8Snorm);
140  CASE(Rg32f);
141  CASE(Rg16f);
142  CASE(R11fG11fB10f);
143  CASE(R16f);
144  CASE(Rgba16);
145  CASE(Rgb10A2);
146  CASE(Rg16);
147  CASE(Rg8);
148  CASE(R16);
149  CASE(R8);
150  CASE(Rgba16Snorm);
151  CASE(Rg16Snorm);
152  CASE(Rg8Snorm);
153  CASE(R16Snorm);
154  CASE(R8Snorm);
155  CASE(Rgba32i);
156  CASE(Rgba16i);
157  CASE(Rgba8i);
158  CASE(R32i);
159  CASE(Rg32i);
160  CASE(Rg16i);
161  CASE(Rg8i);
162  CASE(R16i);
163  CASE(R8i);
164  CASE(Rgba32ui);
165  CASE(Rgba16ui);
166  CASE(Rgba8ui);
167  CASE(R32ui);
168  CASE(Rgb10a2ui);
169  CASE(Rg32ui);
170  CASE(Rg16ui);
171  CASE(Rg8ui);
172  CASE(R16ui);
173  CASE(R8ui);
174 #undef CASE
175  default:
176  Stream << "<unknown>";
177  break;
178  }
179 
180  // TODO: Show other image info
181 
182  break;
183  case Type::SAMPLER:
184  Stream << "sampler";
185  break;
186  case Type::SAMPLED_IMAGE:
187  Stream << "sampled " << Ty->getElementType();
188  break;
189  case Type::ARRAY:
190  Stream << Ty->ElementType << "[" << Ty->ElementCount << "]";
191  break;
192  case Type::RUNTIME_ARRAY:
193  Stream << Ty->ElementType << "[]";
194  break;
195  case Type::STRUCT:
196  {
197  Stream << "struct {";
198  for (unsigned i = 0; i < Ty->ElementCount; i++)
199  {
200  if (i > 0)
201  Stream << ",";
202  Stream << Ty->ElementTypes[i].first;
203  // TODO: Show member offsets?
204  }
205  Stream << "}";
206  break;
207  }
208  case Type::POINTER:
209  Stream << Ty->ElementType << "*";
210  break;
211  case Type::FUNCTION:
212  {
213  Stream << Ty->ReturnType << " function (";
214  for (unsigned i = 0; i < Ty->ArgumentTypes.size(); i++)
215  {
216  if (i > 0)
217  Stream << ",";
218  Stream << Ty->ArgumentTypes[i];
219  }
220  Stream << ")";
221  break;
222  }
223  default:
224  Stream << "<unhandled type>";
225  break;
226  }
227  return Stream;
228 }
229 
230 std::unique_ptr<Type> Type::getArray(const Type *ElemType,
231  uint32_t ElementCount,
232  uint32_t ArrayStride)
233 {
234  assert(ArrayStride >= ElemType->getSize());
235  std::unique_ptr<Type> T(new Type(ARRAY, ElementCount * ArrayStride));
236  T->ElementType = ElemType;
238  T->ArrayStride = ArrayStride;
239  return T;
240 }
241 
242 std::unique_ptr<Type> Type::getBool()
243 {
244  return std::unique_ptr<Type>(new Type(BOOL, 1));
245 }
246 
247 std::unique_ptr<Type> Type::getFloat(uint32_t Width)
248 {
249  std::unique_ptr<Type> T(new Type(FLOAT, Width / 8));
250  T->BitWidth = Width;
251  return T;
252 }
253 
254 std::unique_ptr<Type> Type::getInt(uint32_t Width)
255 {
256  std::unique_ptr<Type> T(new Type(INT, Width / 8));
257  T->BitWidth = Width;
258  return T;
259 }
260 
261 std::unique_ptr<Type>
262 Type::getFunction(const Type *ReturnType,
263  const std::vector<const Type *> &ArgTypes)
264 {
265  std::unique_ptr<Type> T(new Type(FUNCTION, 0));
266  T->ReturnType = ReturnType;
267  T->ArgumentTypes = ArgTypes;
268  return T;
269 }
270 
271 std::unique_ptr<Type> Type::getImage(const Type *SampledType, uint32_t Dim,
272  uint32_t Depth, bool Arrayed, bool MS,
273  uint32_t Sampled, uint32_t Format)
274 {
275  std::unique_ptr<Type> T(new Type(IMAGE, sizeof(ImageView *)));
276  T->ElementType = SampledType;
277  T->Dimensionality = Dim;
278  T->Depth = Depth;
279  T->Arrayed = Arrayed;
280  T->Multisampled = MS;
281  T->Sampled = Sampled;
282  T->Format = Format;
283  return T;
284 }
285 
286 std::unique_ptr<Type> Type::getMatrix(const Type *ColumnType,
287  uint32_t NumColumns)
288 {
289  std::unique_ptr<Type> T(new Type(MATRIX, NumColumns * ColumnType->getSize()));
290  T->ElementType = ColumnType;
291  T->ElementCount = NumColumns;
292  return T;
293 }
294 
295 std::unique_ptr<Type> Type::getPointer(uint32_t StorageClass,
296  const Type *ElemType,
297  uint32_t ArrayStride)
298 {
299  std::unique_ptr<Type> T(new Type(POINTER, sizeof(uint64_t)));
300  T->StorageClass = StorageClass;
301  T->ElementType = ElemType;
302  T->ArrayStride = ArrayStride;
303  return T;
304 }
305 
306 std::unique_ptr<Type> Type::getRuntimeArray(const Type *ElemType,
307  uint32_t ArrayStride)
308 {
309  assert(ArrayStride >= ElemType->getSize());
310  std::unique_ptr<Type> T(new Type(RUNTIME_ARRAY, 0));
311  T->ElementType = ElemType;
313  return T;
314 }
315 
316 std::unique_ptr<Type> Type::getSampledImage(const Type *ImageType)
317 {
318  std::unique_ptr<Type> T(new Type(SAMPLED_IMAGE, sizeof(SampledImage)));
319  T->ElementType = ImageType;
320  return T;
321 }
322 
323 std::unique_ptr<Type> Type::getSampler()
324 {
325  return std::unique_ptr<Type>(new Type(SAMPLER, sizeof(uint64_t)));
326 }
327 
328 std::unique_ptr<Type> Type::getStruct(const StructElementTypeList &ElemTypes)
329 {
330  // Build list of member offsets, using Offset decoration if supplied.
331  size_t CurrentOffset = 0;
332  std::vector<size_t> Offsets(ElemTypes.size());
333  for (size_t i = 0; i < ElemTypes.size(); i++)
334  {
335  if (ElemTypes[i].second.count(SpvDecorationOffset))
336  Offsets[i] = ElemTypes[i].second.at(SpvDecorationOffset);
337  else
338  Offsets[i] = CurrentOffset;
339 
340  // Special case for size of a matrix with an explicit layout.
341  if (ElemTypes[i].first->isMatrix() &&
342  ElemTypes[i].second.count(SpvDecorationMatrixStride))
343  {
344  const Type *MatrixType = ElemTypes[i].first;
345  const Type *VectorType = MatrixType->getElementType();
346  uint32_t MatrixStride = ElemTypes[i].second.at(SpvDecorationMatrixStride);
347 
348  // Calculate size of matrix based on stride and layout.
349  size_t MatrixSize;
350  if (ElemTypes[i].second.count(SpvDecorationColMajor))
351  MatrixSize = MatrixType->getElementCount() * MatrixStride;
352  else
353  MatrixSize = VectorType->getElementCount() * MatrixStride;
354 
355  CurrentOffset = Offsets[i] + MatrixSize;
356  }
357  else
358  CurrentOffset = Offsets[i] + ElemTypes[i].first->getSize();
359  }
360 
361  std::unique_ptr<Type> T(new Type(STRUCT, CurrentOffset));
362  T->ElementTypes = ElemTypes;
363  T->ElementOffsets = Offsets;
364  T->ElementCount = (uint32_t)ElemTypes.size();
365  return T;
366 }
367 
368 std::unique_ptr<Type> Type::getVector(const Type *ElemType, uint32_t ElemCount)
369 {
370  assert(ElemType->isScalar());
371  std::unique_ptr<Type> T(new Type(VECTOR, ElemCount * ElemType->getSize()));
372  T->ElementType = ElemType;
373  T->ElementCount = ElemCount;
374  return T;
375 }
376 
377 std::unique_ptr<Type> Type::getVoid()
378 {
379  return std::unique_ptr<Type>(new Type(VOID, 0));
380 }
381 
382 } // namespace talvos
static std::unique_ptr< Type > getVector(const Type *ElemType, uint32_t ElemCount)
Create a vector type.
Definition: Type.cpp:368
static std::unique_ptr< Type > getVoid()
Create a void type.
Definition: Type.cpp:377
bool isScalar() const
Returns true if this is a scalar type.
Definition: Type.cpp:77
uint32_t Depth
Valid for image types.
Definition: Type.h:213
bool isFloat() const
Returns true if this is a floating point type.
Definition: Type.h:107
uint32_t Sampled
Valid for image types.
Definition: Type.h:216
bool Arrayed
Valid for image types.
Definition: Type.h:214
static std::unique_ptr< Type > getPointer(uint32_t StorageClass, const Type *ElemType, uint32_t ArrayStride)
Create a pointer type.
Definition: Type.cpp:295
size_t getSize() const
Returns the size of this type in bytes.
Definition: Type.h:81
uint32_t StorageClass
Valid for pointer types.
Definition: Type.h:200
std::vector< size_t > ElementOffsets
Valid for struct types.
Definition: Type.h:207
A combination of an image and a sampler used to access it.
Definition: Image.h:268
static std::unique_ptr< Type > getSampledImage(const Type *ImageType)
Create a sampled image type.
Definition: Type.cpp:316
std::vector< std::pair< const Type *, std::map< uint32_t, uint32_t > > > StructElementTypeList
A list of types used for structure members.
Definition: Type.h:22
uint32_t BitWidth
Valid for integer and floating point types.
Definition: Type.h:198
static std::unique_ptr< Type > getBool()
Create a boolean type.
Definition: Type.cpp:242
size_t getElementOffset(uint64_t Index) const
Returns the byte offset of the element at Index.
Definition: Type.cpp:26
const Type * getElementType(uint64_t Index=0) const
Returns the type of the element at Index.
Definition: Type.cpp:38
const Type * getScalarType() const
Returns the element type for vector types, or this for scalar types.
Definition: Type.cpp:49
bool isInt() const
Returns true if this is an integer type.
Definition: Type.h:110
static std::unique_ptr< Type > getSampler()
Create a sampler type.
Definition: Type.cpp:323
static std::unique_ptr< Type > getImage(const Type *SampledType, uint32_t Dim, uint32_t Depth, bool Arrayed, bool MS, uint32_t Sampled, uint32_t Format)
Create an image type.
Definition: Type.cpp:271
This class represents a view into a range of image subresources.
Definition: Image.h:178
Type(TypeId Id, size_t ByteSize)
Create a new type.
Definition: Type.h:186
const Type * ReturnType
Valid for function types.
Definition: Type.h:209
const std::map< uint32_t, uint32_t > & getStructMemberDecorations(uint32_t Index) const
Returns the decoration map for the structure member at Index.
Definition: Type.cpp:67
uint32_t Dimensionality
Valid for image types.
Definition: Type.h:212
uint32_t getElementCount() const
Returns the number of elements in this array, struct, or vector type.
Definition: Type.h:64
std::vector< const Type * > ArgumentTypes
Valid for function types.
Definition: Type.h:210
This file declares the Type class.
uint32_t ArrayStride
Valid for array and pointer types.
Definition: Type.h:204
bool isComposite() const
Returns true if this is an array, struct, or vector type.
Definition: Type.cpp:72
static std::unique_ptr< Type > getInt(uint32_t Width)
Create an integer type.
Definition: Type.cpp:254
This file declares data structures and functions for handling images.
uint32_t getBitWidth() const
Returns the bit-width of this type.
Definition: Type.cpp:20
uint32_t getStorageClass() const
Returns the storage class of this type.
Definition: Type.cpp:60
#define CASE(X)
std::ostream & operator<<(std::ostream &Stream, const Dim3 &D)
Definition: Dim3.cpp:16
static std::unique_ptr< Type > getRuntimeArray(const Type *ElemType, uint32_t ArrayStride)
Create a runtime array type.
Definition: Type.cpp:306
uint32_t Format
Valid for image types.
Definition: Type.h:217
static std::unique_ptr< Type > getStruct(const StructElementTypeList &ElemTypes)
Create a structure type.
Definition: Type.cpp:328
uint32_t ElementCount
Valid for composite types.
Definition: Type.h:203
This class represents a SPIR-V type.
Definition: Type.h:33
static std::unique_ptr< Type > getFunction(const Type *ReturnType, const std::vector< const Type * > &ArgTypes)
Create a function type.
Definition: Type.cpp:262
TypeId Id
The ID of this type.
Definition: Type.h:192
const Type * ElementType
Valid for pointer and composite types.
Definition: Type.h:202
static std::unique_ptr< Type > getFloat(uint32_t Width)
Create a floating point type.
Definition: Type.cpp:247
static std::unique_ptr< Type > getArray(const Type *ElemType, uint32_t ElementCount, uint32_t ArrayStride)
Create an array type.
Definition: Type.cpp:230
static std::unique_ptr< Type > getMatrix(const Type *ColumnType, uint32_t NumColumns)
Create a matrix type.
Definition: Type.cpp:286
StructElementTypeList ElementTypes
Valid for struct types.
Definition: Type.h:206