// 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. #ifndef LIBSPIRV_OPT_CONSTANTS_H_ #define LIBSPIRV_OPT_CONSTANTS_H_ #include #include #include #include "make_unique.h" #include "types.h" namespace spvtools { namespace opt { namespace analysis { // Class hierarchy to represent the normal constants defined through // OpConstantTrue, OpConstantFalse, OpConstant, OpConstantNull and // OpConstantComposite instructions. // TODO(qining): Add class for constants defined with OpConstantSampler. class Constant; class ScalarConstant; class IntConstant; class FloatConstant; class BoolConstant; class CompositeConstant; class StructConstant; class VectorConstant; class ArrayConstant; class NullConstant; // Abstract class for a SPIR-V constant. It has a bunch of As methods, // which is used as a way to probe the actual class Constant { public: Constant() = delete; virtual ~Constant() {} // Make a deep copy of this constant. virtual std::unique_ptr Copy() const = 0; // reflections virtual ScalarConstant* AsScalarConstant() { return nullptr; } virtual IntConstant* AsIntConstant() { return nullptr; } virtual FloatConstant* AsFloatConstant() { return nullptr; } virtual BoolConstant* AsBoolConstant() { return nullptr; } virtual CompositeConstant* AsCompositeConstant() { return nullptr; } virtual StructConstant* AsStructConstant() { return nullptr; } virtual VectorConstant* AsVectorConstant() { return nullptr; } virtual ArrayConstant* AsArrayConstant() { return nullptr; } virtual NullConstant* AsNullConstant() { return nullptr; } virtual const ScalarConstant* AsScalarConstant() const { return nullptr; } virtual const IntConstant* AsIntConstant() const { return nullptr; } virtual const FloatConstant* AsFloatConstant() const { return nullptr; } virtual const BoolConstant* AsBoolConstant() const { return nullptr; } virtual const CompositeConstant* AsCompositeConstant() const { return nullptr; } virtual const StructConstant* AsStructConstant() const { return nullptr; } virtual const VectorConstant* AsVectorConstant() const { return nullptr; } virtual const ArrayConstant* AsArrayConstant() const { return nullptr; } virtual const NullConstant* AsNullConstant() const { return nullptr; } const analysis::Type* type() const { return type_; } protected: Constant(const analysis::Type* ty) : type_(ty) {} // The type of this constant. const analysis::Type* type_; }; // Abstract class for scalar type constants. class ScalarConstant : public Constant { public: ScalarConstant() = delete; ScalarConstant* AsScalarConstant() override { return this; } const ScalarConstant* AsScalarConstant() const override { return this; } // Returns a const reference of the value of this constant in 32-bit words. virtual const std::vector& words() const { return words_; } protected: ScalarConstant(const analysis::Type* ty, const std::vector& w) : Constant(ty), words_(w) {} ScalarConstant(const analysis::Type* ty, std::vector&& w) : Constant(ty), words_(std::move(w)) {} std::vector words_; }; // Integer type constant. class IntConstant : public ScalarConstant { public: IntConstant(const analysis::Integer* ty, const std::vector& w) : ScalarConstant(ty, w) {} IntConstant(const analysis::Integer* ty, std::vector&& w) : ScalarConstant(ty, std::move(w)) {} IntConstant* AsIntConstant() override { return this; } const IntConstant* AsIntConstant() const override { return this; } // Make a copy of this IntConstant instance. std::unique_ptr CopyIntConstant() const { return MakeUnique(type_->AsInteger(), words_); } std::unique_ptr Copy() const override { return std::unique_ptr(CopyIntConstant().release()); } }; // Float type constant. class FloatConstant : public ScalarConstant { public: FloatConstant(const analysis::Float* ty, const std::vector& w) : ScalarConstant(ty, w) {} FloatConstant(const analysis::Float* ty, std::vector&& w) : ScalarConstant(ty, std::move(w)) {} FloatConstant* AsFloatConstant() override { return this; } const FloatConstant* AsFloatConstant() const override { return this; } // Make a copy of this FloatConstant instance. std::unique_ptr CopyFloatConstant() const { return MakeUnique(type_->AsFloat(), words_); } std::unique_ptr Copy() const override { return std::unique_ptr(CopyFloatConstant().release()); } }; // Bool type constant. class BoolConstant : public ScalarConstant { public: BoolConstant(const analysis::Bool* ty, bool v) : ScalarConstant(ty, {static_cast(v)}), value_(v) {} BoolConstant* AsBoolConstant() override { return this; } const BoolConstant* AsBoolConstant() const override { return this; } // Make a copy of this BoolConstant instance. std::unique_ptr CopyBoolConstant() const { return MakeUnique(type_->AsBool(), value_); } std::unique_ptr Copy() const override { return std::unique_ptr(CopyBoolConstant().release()); } bool value() const { return value_; } private: bool value_; }; // Abstract class for composite constants. class CompositeConstant : public Constant { public: CompositeConstant() = delete; CompositeConstant* AsCompositeConstant() override { return this; } const CompositeConstant* AsCompositeConstant() const override { return this; } // Returns a const reference of the components holded in this composite // constant. virtual const std::vector& GetComponents() const { return components_; } protected: CompositeConstant(const analysis::Type* ty) : Constant(ty), components_() {} CompositeConstant(const analysis::Type* ty, const std::vector& components) : Constant(ty), components_(components) {} CompositeConstant(const analysis::Type* ty, std::vector&& components) : Constant(ty), components_(std::move(components)) {} std::vector components_; }; // Struct type constant. class StructConstant : public CompositeConstant { public: StructConstant(const analysis::Struct* ty) : CompositeConstant(ty) {} StructConstant(const analysis::Struct* ty, const std::vector& components) : CompositeConstant(ty, components) {} StructConstant(const analysis::Struct* ty, std::vector&& components) : CompositeConstant(ty, std::move(components)) {} StructConstant* AsStructConstant() override { return this; } const StructConstant* AsStructConstant() const override { return this; } // Make a copy of this StructConstant instance. std::unique_ptr CopyStructConstant() const { return MakeUnique(type_->AsStruct(), components_); } std::unique_ptr Copy() const override { return std::unique_ptr(CopyStructConstant().release()); } }; // Vector type constant. class VectorConstant : public CompositeConstant { public: VectorConstant(const analysis::Vector* ty) : CompositeConstant(ty), component_type_(ty->element_type()) {} VectorConstant(const analysis::Vector* ty, const std::vector& components) : CompositeConstant(ty, components), component_type_(ty->element_type()) {} VectorConstant(const analysis::Vector* ty, std::vector&& components) : CompositeConstant(ty, std::move(components)), component_type_(ty->element_type()) {} VectorConstant* AsVectorConstant() override { return this; } const VectorConstant* AsVectorConstant() const override { return this; } // Make a copy of this VectorConstant instance. std::unique_ptr CopyVectorConstant() const { auto another = MakeUnique(type_->AsVector()); another->components_.insert(another->components_.end(), components_.begin(), components_.end()); return another; } std::unique_ptr Copy() const override { return std::unique_ptr(CopyVectorConstant().release()); } const analysis::Type* component_type() { return component_type_; } private: const analysis::Type* component_type_; }; // Array type constant. class ArrayConstant : public CompositeConstant { public: ArrayConstant(const analysis::Array* ty) : CompositeConstant(ty) {} ArrayConstant(const analysis::Array* ty, const std::vector& components) : CompositeConstant(ty, components) {} ArrayConstant(const analysis::Array* ty, std::vector&& components) : CompositeConstant(ty, std::move(components)) {} ArrayConstant* AsArrayConstant() override { return this; } const ArrayConstant* AsArrayConstant() const override { return this; } // Make a copy of this ArrayConstant instance. std::unique_ptr CopyArrayConstant() const { return MakeUnique(type_->AsArray(), components_); } std::unique_ptr Copy() const override { return std::unique_ptr(CopyArrayConstant().release()); } }; // Null type constant. class NullConstant : public Constant { public: NullConstant(const analysis::Type* ty) : Constant(ty) {} NullConstant* AsNullConstant() override { return this; } const NullConstant* AsNullConstant() const override { return this; } // Make a copy of this NullConstant instance. std::unique_ptr CopyNullConstant() const { return MakeUnique(type_); } std::unique_ptr Copy() const override { return std::unique_ptr(CopyNullConstant().release()); } }; } // namespace analysis } // namespace opt } // namespace spvtools #endif // LIBSPIRV_OPT_CONSTANTS_H_