• 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 // This file provides a class hierarchy for representing SPIR-V types.
16 
17 #ifndef LIBSPIRV_OPT_TYPES_H_
18 #define LIBSPIRV_OPT_TYPES_H_
19 
20 #include <string>
21 #include <unordered_map>
22 #include <vector>
23 
24 #include "spirv-tools/libspirv.h"
25 #include "spirv/1.2/spirv.h"
26 
27 namespace spvtools {
28 namespace opt {
29 namespace analysis {
30 
31 class Void;
32 class Bool;
33 class Integer;
34 class Float;
35 class Vector;
36 class Matrix;
37 class Image;
38 class Sampler;
39 class SampledImage;
40 class Array;
41 class RuntimeArray;
42 class Struct;
43 class Opaque;
44 class Pointer;
45 class Function;
46 class Event;
47 class DeviceEvent;
48 class ReserveId;
49 class Queue;
50 class Pipe;
51 class ForwardPointer;
52 class PipeStorage;
53 class NamedBarrier;
54 
55 // Abstract class for a SPIR-V type. It has a bunch of As<sublcass>() methods,
56 // which is used as a way to probe the actual <subclass>.
57 class Type {
58  public:
~Type()59   virtual ~Type() {}
60 
61   // Attaches a decoration directly on this type.
AddDecoration(std::vector<uint32_t> && d)62   void AddDecoration(std::vector<uint32_t>&& d) {
63     decorations_.push_back(std::move(d));
64   }
65   // Returns the decorations on this type as a string.
66   std::string GetDecorationStr() const;
67   // Returns true if this type has exactly the same decorations as |that| type.
68   bool HasSameDecorations(const Type* that) const;
69   // Returns true if this type is exactly the same as |that| type, including
70   // decorations.
71   virtual bool IsSame(Type* that) const = 0;
72   // Returns a human-readable string to represent this type.
73   virtual std::string str() const = 0;
74 
75   // Returns true if there is no decoration on this type. For struct types,
76   // returns true only when there is no decoration for both the struct type
77   // and the struct members.
decoration_empty()78   virtual bool decoration_empty() const { return decorations_.empty(); }
79 
80 // A bunch of methods for casting this type to a given type. Returns this if the
81 // cast can be done, nullptr otherwise.
82 #define DeclareCastMethod(target)                  \
83   virtual target* As##target() { return nullptr; } \
84   virtual const target* As##target() const { return nullptr; }
85   DeclareCastMethod(Void);
86   DeclareCastMethod(Bool);
87   DeclareCastMethod(Integer);
88   DeclareCastMethod(Float);
89   DeclareCastMethod(Vector);
90   DeclareCastMethod(Matrix);
91   DeclareCastMethod(Image);
92   DeclareCastMethod(Sampler);
93   DeclareCastMethod(SampledImage);
94   DeclareCastMethod(Array);
95   DeclareCastMethod(RuntimeArray);
96   DeclareCastMethod(Struct);
97   DeclareCastMethod(Opaque);
98   DeclareCastMethod(Pointer);
99   DeclareCastMethod(Function);
100   DeclareCastMethod(Event);
101   DeclareCastMethod(DeviceEvent);
102   DeclareCastMethod(ReserveId);
103   DeclareCastMethod(Queue);
104   DeclareCastMethod(Pipe);
105   DeclareCastMethod(ForwardPointer);
106   DeclareCastMethod(PipeStorage);
107   DeclareCastMethod(NamedBarrier);
108 #undef DeclareCastMethod
109 
110  protected:
111   // Decorations attached to this type. Each decoration is encoded as a vector
112   // of uint32_t numbers. The first uint32_t number is the decoration value,
113   // and the rest are the parameters to the decoration (if exists).
114   std::vector<std::vector<uint32_t>> decorations_;
115 };
116 
117 class Integer : public Type {
118  public:
Integer(uint32_t w,bool is_signed)119   Integer(uint32_t w, bool is_signed) : width_(w), signed_(is_signed) {}
120   Integer(const Integer&) = default;
121 
122   bool IsSame(Type* that) const override;
123   std::string str() const override;
124 
AsInteger()125   Integer* AsInteger() override { return this; }
AsInteger()126   const Integer* AsInteger() const override { return this; }
width()127   uint32_t width() const { return width_; }
IsSigned()128   bool IsSigned() const { return signed_; }
129 
130  private:
131   uint32_t width_;  // bit width
132   bool signed_;     // true if this integer is signed
133 };
134 
135 class Float : public Type {
136  public:
Float(uint32_t w)137   Float(uint32_t w) : width_(w) {}
138   Float(const Float&) = default;
139 
140   bool IsSame(Type* that) const override;
141   std::string str() const override;
142 
AsFloat()143   Float* AsFloat() override { return this; }
AsFloat()144   const Float* AsFloat() const override { return this; }
width()145   uint32_t width() const { return width_; }
146 
147  private:
148   uint32_t width_;  // bit width
149 };
150 
151 class Vector : public Type {
152  public:
153   Vector(Type* element_type, uint32_t count);
154   Vector(const Vector&) = default;
155 
156   bool IsSame(Type* that) const override;
157   std::string str() const override;
element_type()158   const Type* element_type() const { return element_type_; }
element_count()159   uint32_t element_count() const { return count_; }
160 
AsVector()161   Vector* AsVector() override { return this; }
AsVector()162   const Vector* AsVector() const override { return this; }
163 
164  private:
165   Type* element_type_;
166   uint32_t count_;
167 };
168 
169 class Matrix : public Type {
170  public:
171   Matrix(Type* element_type, uint32_t count);
172   Matrix(const Matrix&) = default;
173 
174   bool IsSame(Type* that) const override;
175   std::string str() const override;
element_type()176   const Type* element_type() const { return element_type_; }
element_count()177   uint32_t element_count() const { return count_; }
178 
AsMatrix()179   Matrix* AsMatrix() override { return this; }
AsMatrix()180   const Matrix* AsMatrix() const override { return this; }
181 
182  private:
183   Type* element_type_;
184   uint32_t count_;
185 };
186 
187 class Image : public Type {
188  public:
189   Image(Type* sampled_type, SpvDim dim, uint32_t depth, uint32_t arrayed,
190         uint32_t ms, uint32_t sampled, SpvImageFormat format,
191         SpvAccessQualifier access_qualifier = SpvAccessQualifierReadOnly);
192   Image(const Image&) = default;
193 
194   bool IsSame(Type* that) const override;
195   std::string str() const override;
196 
AsImage()197   Image* AsImage() override { return this; }
AsImage()198   const Image* AsImage() const override { return this; }
199 
200  private:
201   Type* sampled_type_;
202   SpvDim dim_;
203   uint32_t depth_;
204   uint32_t arrayed_;
205   uint32_t ms_;
206   uint32_t sampled_;
207   SpvImageFormat format_;
208   SpvAccessQualifier access_qualifier_;
209 };
210 
211 class SampledImage : public Type {
212  public:
SampledImage(Type * image_type)213   SampledImage(Type* image_type) : image_type_(image_type) {}
214   SampledImage(const SampledImage&) = default;
215 
216   bool IsSame(Type* that) const override;
217   std::string str() const override;
218 
AsSampledImage()219   SampledImage* AsSampledImage() override { return this; }
AsSampledImage()220   const SampledImage* AsSampledImage() const override { return this; }
221 
222  private:
223   Type* image_type_;
224 };
225 
226 class Array : public Type {
227  public:
228   Array(Type* element_type, uint32_t length_id);
229   Array(const Array&) = default;
230 
231   bool IsSame(Type* that) const override;
232   std::string str() const override;
element_type()233   const Type* element_type() const { return element_type_; }
LengthId()234   uint32_t LengthId() const { return length_id_; }
235 
AsArray()236   Array* AsArray() override { return this; }
AsArray()237   const Array* AsArray() const override { return this; }
238 
239  private:
240   Type* element_type_;
241   uint32_t length_id_;
242 };
243 
244 class RuntimeArray : public Type {
245  public:
246   RuntimeArray(Type* element_type);
247   RuntimeArray(const RuntimeArray&) = default;
248 
249   bool IsSame(Type* that) const override;
250   std::string str() const override;
element_type()251   const Type* element_type() const { return element_type_; }
252 
AsRuntimeArray()253   RuntimeArray* AsRuntimeArray() override { return this; }
AsRuntimeArray()254   const RuntimeArray* AsRuntimeArray() const override { return this; }
255 
256  private:
257   Type* element_type_;
258 };
259 
260 class Struct : public Type {
261  public:
262   Struct(const std::vector<Type*>& element_types);
263   Struct(const Struct&) = default;
264 
265   // Adds a decoration to the member at the given index.  The first word is the
266   // decoration enum, and the remaining words, if any, are its operands.
267   void AddMemberDecoration(uint32_t index, std::vector<uint32_t>&& decoration);
268 
269   bool IsSame(Type* that) const override;
270   std::string str() const override;
element_types()271   const std::vector<Type*>& element_types() const { return element_types_; }
decoration_empty()272   bool decoration_empty() const override {
273     return decorations_.empty() && element_decorations_.empty();
274   }
275 
AsStruct()276   Struct* AsStruct() override { return this; }
AsStruct()277   const Struct* AsStruct() const override { return this; }
278 
279  private:
280   std::vector<Type*> element_types_;
281   // We can attach decorations to struct members and that should not affect the
282   // underlying element type. So we need an extra data structure here to keep
283   // track of element type decorations.
284   std::unordered_map<uint32_t, std::vector<std::vector<uint32_t>>>
285       element_decorations_;
286 };
287 
288 class Opaque : public Type {
289  public:
Opaque(std::string name)290   Opaque(std::string name) : name_(std::move(name)) {}
291   Opaque(const Opaque&) = default;
292 
293   bool IsSame(Type* that) const override;
294   std::string str() const override;
295 
AsOpaque()296   Opaque* AsOpaque() override { return this; }
AsOpaque()297   const Opaque* AsOpaque() const override { return this; }
298 
299  private:
300   std::string name_;
301 };
302 
303 class Pointer : public Type {
304  public:
305   Pointer(Type* pointee_type, SpvStorageClass storage_class);
306   Pointer(const Pointer&) = default;
307 
308   bool IsSame(Type* that) const override;
309   std::string str() const override;
pointee_type()310   const Type* pointee_type() const { return pointee_type_; }
311 
AsPointer()312   Pointer* AsPointer() override { return this; }
AsPointer()313   const Pointer* AsPointer() const override { return this; }
314 
315  private:
316   Type* pointee_type_;
317   SpvStorageClass storage_class_;
318 };
319 
320 class Function : public Type {
321  public:
322   Function(Type* return_type, const std::vector<Type*>& param_types);
323   Function(const Function&) = default;
324 
325   bool IsSame(Type* that) const override;
326   std::string str() const override;
327 
AsFunction()328   Function* AsFunction() override { return this; }
AsFunction()329   const Function* AsFunction() const override { return this; }
330 
331  private:
332   Type* return_type_;
333   std::vector<Type*> param_types_;
334 };
335 
336 class Pipe : public Type {
337  public:
Pipe(SpvAccessQualifier access_qualifier)338   Pipe(SpvAccessQualifier access_qualifier)
339       : access_qualifier_(access_qualifier) {}
340   Pipe(const Pipe&) = default;
341 
342   bool IsSame(Type* that) const override;
343   std::string str() const override;
344 
AsPipe()345   Pipe* AsPipe() override { return this; }
AsPipe()346   const Pipe* AsPipe() const override { return this; }
347 
348  private:
349   SpvAccessQualifier access_qualifier_;
350 };
351 
352 class ForwardPointer : public Type {
353  public:
ForwardPointer(uint32_t id,SpvStorageClass storage_class)354   ForwardPointer(uint32_t id, SpvStorageClass storage_class)
355       : target_id_(id), storage_class_(storage_class), pointer_(nullptr) {}
356   ForwardPointer(const ForwardPointer&) = default;
357 
target_id()358   uint32_t target_id() const { return target_id_; }
SetTargetPointer(Pointer * pointer)359   void SetTargetPointer(Pointer* pointer) { pointer_ = pointer; }
360 
361   bool IsSame(Type* that) const override;
362   std::string str() const override;
363 
AsForwardPointer()364   ForwardPointer* AsForwardPointer() override { return this; }
AsForwardPointer()365   const ForwardPointer* AsForwardPointer() const override { return this; }
366 
367  private:
368   uint32_t target_id_;
369   SpvStorageClass storage_class_;
370   Pointer* pointer_;
371 };
372 
373 #define DefineParameterlessType(type, name)                \
374   class type : public Type {                               \
375    public:                                                 \
376     type() = default;                                      \
377     type(const type&) = default;                           \
378                                                            \
379     bool IsSame(Type* that) const override {               \
380       return that->As##type() && HasSameDecorations(that); \
381     }                                                      \
382     std::string str() const override { return #name; }     \
383                                                            \
384     type* As##type() override { return this; }             \
385     const type* As##type() const override { return this; } \
386   };
387 DefineParameterlessType(Void, void);
388 DefineParameterlessType(Bool, bool);
389 DefineParameterlessType(Sampler, sampler);
390 DefineParameterlessType(Event, event);
391 DefineParameterlessType(DeviceEvent, device_event);
392 DefineParameterlessType(ReserveId, reserve_id);
393 DefineParameterlessType(Queue, queue);
394 DefineParameterlessType(PipeStorage, pipe_storage);
395 DefineParameterlessType(NamedBarrier, named_barrier);
396 #undef DefineParameterlessType
397 
398 }  // namespace analysis
399 }  // namespace opt
400 }  // namespace spvtools
401 
402 #endif  // LIBSPIRV_OPT_TYPES_H_
403