Home | History | Annotate | Download | only in opt
      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:
     59   virtual ~Type() {}
     60 
     61   // Attaches a decoration directly on this type.
     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.
     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:
    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 
    125   Integer* AsInteger() override { return this; }
    126   const Integer* AsInteger() const override { return this; }
    127   uint32_t width() const { return width_; }
    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:
    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 
    143   Float* AsFloat() override { return this; }
    144   const Float* AsFloat() const override { return this; }
    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;
    158   const Type* element_type() const { return element_type_; }
    159   uint32_t element_count() const { return count_; }
    160 
    161   Vector* AsVector() override { return this; }
    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;
    176   const Type* element_type() const { return element_type_; }
    177   uint32_t element_count() const { return count_; }
    178 
    179   Matrix* AsMatrix() override { return this; }
    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 
    197   Image* AsImage() override { return this; }
    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:
    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 
    219   SampledImage* AsSampledImage() override { return this; }
    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;
    233   const Type* element_type() const { return element_type_; }
    234   uint32_t LengthId() const { return length_id_; }
    235 
    236   Array* AsArray() override { return this; }
    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;
    251   const Type* element_type() const { return element_type_; }
    252 
    253   RuntimeArray* AsRuntimeArray() override { return this; }
    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;
    271   const std::vector<Type*>& element_types() const { return element_types_; }
    272   bool decoration_empty() const override {
    273     return decorations_.empty() && element_decorations_.empty();
    274   }
    275 
    276   Struct* AsStruct() override { return this; }
    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:
    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 
    296   Opaque* AsOpaque() override { return this; }
    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;
    310   const Type* pointee_type() const { return pointee_type_; }
    311 
    312   Pointer* AsPointer() override { return this; }
    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 
    328   Function* AsFunction() override { return this; }
    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:
    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 
    345   Pipe* AsPipe() override { return this; }
    346   const Pipe* AsPipe() const override { return this; }
    347 
    348  private:
    349   SpvAccessQualifier access_qualifier_;
    350 };
    351 
    352 class ForwardPointer : public Type {
    353  public:
    354   ForwardPointer(uint32_t id, SpvStorageClass storage_class)
    355       : target_id_(id), storage_class_(storage_class), pointer_(nullptr) {}
    356   ForwardPointer(const ForwardPointer&) = default;
    357 
    358   uint32_t target_id() const { return target_id_; }
    359   void SetTargetPointer(Pointer* pointer) { pointer_ = pointer; }
    360 
    361   bool IsSame(Type* that) const override;
    362   std::string str() const override;
    363 
    364   ForwardPointer* AsForwardPointer() override { return this; }
    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