blob: a7d9e7c10af1d17e2ab60244092d8d3dd8b402fe [file] [log] [blame]
// Copyright (c) 2016 Google Inc.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// This file provides a class hierarchy for representing SPIR-V types.
#ifndef LIBSPIRV_OPT_TYPES_H_
#define LIBSPIRV_OPT_TYPES_H_
#include <string>
#include <unordered_map>
#include <vector>
#include "spirv-tools/libspirv.h"
#include "spirv/1.1/spirv.h"
namespace spvtools {
namespace opt {
namespace analysis {
class Void;
class Bool;
class Integer;
class Float;
class Vector;
class Matrix;
class Image;
class Sampler;
class SampledImage;
class Array;
class RuntimeArray;
class Struct;
class Opaque;
class Pointer;
class Function;
class Event;
class DeviceEvent;
class ReserveId;
class Queue;
class Pipe;
class ForwardPointer;
class PipeStorage;
class NamedBarrier;
// Abstract class for a SPIR-V type. It has a bunch of As<sublcass>() methods,
// which is used as a way to probe the actual <subclass>.
class Type {
public:
virtual ~Type() {}
// Attaches a decoration directly on this type.
void AddDecoration(std::vector<uint32_t>&& d) {
decorations_.push_back(std::move(d));
}
// Returns the decorations on this type as a string.
std::string GetDecorationStr() const;
// Returns true if this type has exactly the same decorations as |that| type.
bool HasSameDecorations(const Type* that) const;
// Returns true if this type is exactly the same as |that| type, including
// decorations.
virtual bool IsSame(Type* that) const = 0;
// Returns a human-readable string to represent this type.
virtual std::string str() const = 0;
// Returns true if there is no decoration on this type. For struct types,
// returns true only when there is no decoration for both the struct type
// and the struct members.
virtual bool decoration_empty() const { return decorations_.empty(); }
// A bunch of methods for casting this type to a given type. Returns this if the
// cast can be done, nullptr otherwise.
#define DeclareCastMethod(target) \
virtual target* As##target() { return nullptr; } \
virtual const target* As##target() const { return nullptr; }
DeclareCastMethod(Void);
DeclareCastMethod(Bool);
DeclareCastMethod(Integer);
DeclareCastMethod(Float);
DeclareCastMethod(Vector);
DeclareCastMethod(Matrix);
DeclareCastMethod(Image);
DeclareCastMethod(Sampler);
DeclareCastMethod(SampledImage);
DeclareCastMethod(Array);
DeclareCastMethod(RuntimeArray);
DeclareCastMethod(Struct);
DeclareCastMethod(Opaque);
DeclareCastMethod(Pointer);
DeclareCastMethod(Function);
DeclareCastMethod(Event);
DeclareCastMethod(DeviceEvent);
DeclareCastMethod(ReserveId);
DeclareCastMethod(Queue);
DeclareCastMethod(Pipe);
DeclareCastMethod(ForwardPointer);
DeclareCastMethod(PipeStorage);
DeclareCastMethod(NamedBarrier);
#undef DeclareCastMethod
protected:
// Decorations attached to this type. Each decoration is encoded as a vector
// of uint32_t numbers. The first uint32_t number is the decoration value,
// and the rest are the parameters to the decoration (if exists).
std::vector<std::vector<uint32_t>> decorations_;
};
class Integer : public Type {
public:
Integer(uint32_t w, bool is_signed) : width_(w), signed_(is_signed) {}
Integer(const Integer&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
Integer* AsInteger() override { return this; }
const Integer* AsInteger() const override { return this; }
uint32_t width() const { return width_; }
bool IsSigned() const { return signed_; }
private:
uint32_t width_; // bit width
bool signed_; // true if this integer is signed
};
class Float : public Type {
public:
Float(uint32_t w) : width_(w) {}
Float(const Float&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
Float* AsFloat() override { return this; }
const Float* AsFloat() const override { return this; }
uint32_t width() const { return width_; }
private:
uint32_t width_; // bit width
};
class Vector : public Type {
public:
Vector(Type* element_type, uint32_t count);
Vector(const Vector&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
const Type* element_type() const { return element_type_; }
uint32_t element_count() const { return count_; }
Vector* AsVector() override { return this; }
const Vector* AsVector() const override { return this; }
private:
Type* element_type_;
uint32_t count_;
};
class Matrix : public Type {
public:
Matrix(Type* element_type, uint32_t count);
Matrix(const Matrix&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
const Type* element_type() const { return element_type_; }
uint32_t element_count() const { return count_; }
Matrix* AsMatrix() override { return this; }
const Matrix* AsMatrix() const override { return this; }
private:
Type* element_type_;
uint32_t count_;
};
class Image : public Type {
public:
Image(Type* sampled_type, SpvDim dim, uint32_t depth, uint32_t arrayed,
uint32_t ms, uint32_t sampled, SpvImageFormat format,
SpvAccessQualifier access_qualifier = SpvAccessQualifierReadOnly);
Image(const Image&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
Image* AsImage() override { return this; }
const Image* AsImage() const override { return this; }
private:
Type* sampled_type_;
SpvDim dim_;
uint32_t depth_;
uint32_t arrayed_;
uint32_t ms_;
uint32_t sampled_;
SpvImageFormat format_;
SpvAccessQualifier access_qualifier_;
};
class SampledImage : public Type {
public:
SampledImage(Type* image_type) : image_type_(image_type) {}
SampledImage(const SampledImage&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
SampledImage* AsSampledImage() override { return this; }
const SampledImage* AsSampledImage() const override { return this; }
private:
Type* image_type_;
};
class Array : public Type {
public:
Array(Type* element_type, uint32_t length_id);
Array(const Array&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
const Type* element_type() const { return element_type_; }
Array* AsArray() override { return this; }
const Array* AsArray() const override { return this; }
private:
Type* element_type_;
uint32_t length_id_;
};
class RuntimeArray : public Type {
public:
RuntimeArray(Type* element_type);
RuntimeArray(const RuntimeArray&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
const Type* element_type() const { return element_type_; }
RuntimeArray* AsRuntimeArray() override { return this; }
const RuntimeArray* AsRuntimeArray() const override { return this; }
private:
Type* element_type_;
};
class Struct : public Type {
public:
Struct(const std::vector<Type*>& element_types);
Struct(const Struct&) = default;
void AddMemeberDecoration(uint32_t index, std::vector<uint32_t>&& decoration);
bool IsSame(Type* that) const override;
std::string str() const override;
bool decoration_empty() const override {
return decorations_.empty() && element_decorations_.empty();
}
Struct* AsStruct() override { return this; }
const Struct* AsStruct() const override { return this; }
private:
std::vector<Type*> element_types_;
// We can attach decorations to struct members and that should not affect the
// underlying element type. So we need an extra data structure here to keep
// track of element type decorations.
std::unordered_map<uint32_t, std::vector<std::vector<uint32_t>>>
element_decorations_;
};
class Opaque : public Type {
public:
Opaque(std::string name) : name_(std::move(name)) {}
Opaque(const Opaque&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
Opaque* AsOpaque() override { return this; }
const Opaque* AsOpaque() const override { return this; }
private:
std::string name_;
};
class Pointer : public Type {
public:
Pointer(Type* pointee_type, SpvStorageClass storage_class);
Pointer(const Pointer&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
const Type* pointee_type() const { return pointee_type_; }
Pointer* AsPointer() override { return this; }
const Pointer* AsPointer() const override { return this; }
private:
Type* pointee_type_;
SpvStorageClass storage_class_;
};
class Function : public Type {
public:
Function(Type* return_type, const std::vector<Type*>& param_types);
Function(const Function&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
Function* AsFunction() override { return this; }
const Function* AsFunction() const override { return this; }
private:
Type* return_type_;
std::vector<Type*> param_types_;
};
class Pipe : public Type {
public:
Pipe(SpvAccessQualifier access_qualifier)
: access_qualifier_(access_qualifier) {}
Pipe(const Pipe&) = default;
bool IsSame(Type* that) const override;
std::string str() const override;
Pipe* AsPipe() override { return this; }
const Pipe* AsPipe() const override { return this; }
private:
SpvAccessQualifier access_qualifier_;
};
class ForwardPointer : public Type {
public:
ForwardPointer(uint32_t id, SpvStorageClass storage_class)
: target_id_(id), storage_class_(storage_class), pointer_(nullptr) {}
ForwardPointer(const ForwardPointer&) = default;
uint32_t target_id() const { return target_id_; }
void SetTargetPointer(Pointer* pointer) { pointer_ = pointer; }
bool IsSame(Type* that) const override;
std::string str() const override;
ForwardPointer* AsForwardPointer() override { return this; }
const ForwardPointer* AsForwardPointer() const override { return this; }
private:
uint32_t target_id_;
SpvStorageClass storage_class_;
Pointer* pointer_;
};
#define DefineParameterlessType(type, name) \
class type : public Type { \
public: \
type() = default; \
type(const type&) = default; \
\
bool IsSame(Type* that) const override { \
return that->As##type() && HasSameDecorations(that); \
} \
std::string str() const override { return #name; } \
\
type* As##type() override { return this; } \
const type* As##type() const override { return this; } \
};
DefineParameterlessType(Void, void);
DefineParameterlessType(Bool, bool);
DefineParameterlessType(Sampler, sampler);
DefineParameterlessType(Event, event);
DefineParameterlessType(DeviceEvent, device_event);
DefineParameterlessType(ReserveId, reserve_id);
DefineParameterlessType(Queue, queue);
DefineParameterlessType(PipeStorage, pipe_storage);
DefineParameterlessType(NamedBarrier, named_barrier);
#undef DefineParameterlessType
} // namespace analysis
} // namespace opt
} // namespace spvtools
#endif // LIBSPIRV_OPT_TYPES_H_