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