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 #ifndef LIBSPIRV_OPT_CONSTANTS_H_ 16 #define LIBSPIRV_OPT_CONSTANTS_H_ 17 18 #include <memory> 19 #include <utility> 20 #include <vector> 21 22 #include "make_unique.h" 23 #include "types.h" 24 25 namespace spvtools { 26 namespace opt { 27 namespace analysis { 28 29 // Class hierarchy to represent the normal constants defined through 30 // OpConstantTrue, OpConstantFalse, OpConstant, OpConstantNull and 31 // OpConstantComposite instructions. 32 // TODO(qining): Add class for constants defined with OpConstantSampler. 33 class Constant; 34 class ScalarConstant; 35 class IntConstant; 36 class FloatConstant; 37 class BoolConstant; 38 class CompositeConstant; 39 class StructConstant; 40 class VectorConstant; 41 class ArrayConstant; 42 class NullConstant; 43 44 // Abstract class for a SPIR-V constant. It has a bunch of As<subclass> methods, 45 // which is used as a way to probe the actual <subclass> 46 class Constant { 47 public: 48 Constant() = delete; 49 virtual ~Constant() {} 50 51 // Make a deep copy of this constant. 52 virtual std::unique_ptr<Constant> Copy() const = 0; 53 54 // reflections 55 virtual ScalarConstant* AsScalarConstant() { return nullptr; } 56 virtual IntConstant* AsIntConstant() { return nullptr; } 57 virtual FloatConstant* AsFloatConstant() { return nullptr; } 58 virtual BoolConstant* AsBoolConstant() { return nullptr; } 59 virtual CompositeConstant* AsCompositeConstant() { return nullptr; } 60 virtual StructConstant* AsStructConstant() { return nullptr; } 61 virtual VectorConstant* AsVectorConstant() { return nullptr; } 62 virtual ArrayConstant* AsArrayConstant() { return nullptr; } 63 virtual NullConstant* AsNullConstant() { return nullptr; } 64 65 virtual const ScalarConstant* AsScalarConstant() const { return nullptr; } 66 virtual const IntConstant* AsIntConstant() const { return nullptr; } 67 virtual const FloatConstant* AsFloatConstant() const { return nullptr; } 68 virtual const BoolConstant* AsBoolConstant() const { return nullptr; } 69 virtual const CompositeConstant* AsCompositeConstant() const { 70 return nullptr; 71 } 72 virtual const StructConstant* AsStructConstant() const { return nullptr; } 73 virtual const VectorConstant* AsVectorConstant() const { return nullptr; } 74 virtual const ArrayConstant* AsArrayConstant() const { return nullptr; } 75 virtual const NullConstant* AsNullConstant() const { return nullptr; } 76 77 const analysis::Type* type() const { return type_; } 78 79 protected: 80 Constant(const analysis::Type* ty) : type_(ty) {} 81 82 // The type of this constant. 83 const analysis::Type* type_; 84 }; 85 86 // Abstract class for scalar type constants. 87 class ScalarConstant : public Constant { 88 public: 89 ScalarConstant() = delete; 90 ScalarConstant* AsScalarConstant() override { return this; } 91 const ScalarConstant* AsScalarConstant() const override { return this; } 92 93 // Returns a const reference of the value of this constant in 32-bit words. 94 virtual const std::vector<uint32_t>& words() const { return words_; } 95 96 protected: 97 ScalarConstant(const analysis::Type* ty, const std::vector<uint32_t>& w) 98 : Constant(ty), words_(w) {} 99 ScalarConstant(const analysis::Type* ty, std::vector<uint32_t>&& w) 100 : Constant(ty), words_(std::move(w)) {} 101 std::vector<uint32_t> words_; 102 }; 103 104 // Integer type constant. 105 class IntConstant : public ScalarConstant { 106 public: 107 IntConstant(const analysis::Integer* ty, const std::vector<uint32_t>& w) 108 : ScalarConstant(ty, w) {} 109 IntConstant(const analysis::Integer* ty, std::vector<uint32_t>&& w) 110 : ScalarConstant(ty, std::move(w)) {} 111 112 IntConstant* AsIntConstant() override { return this; } 113 const IntConstant* AsIntConstant() const override { return this; } 114 115 // Make a copy of this IntConstant instance. 116 std::unique_ptr<IntConstant> CopyIntConstant() const { 117 return MakeUnique<IntConstant>(type_->AsInteger(), words_); 118 } 119 std::unique_ptr<Constant> Copy() const override { 120 return std::unique_ptr<Constant>(CopyIntConstant().release()); 121 } 122 }; 123 124 // Float type constant. 125 class FloatConstant : public ScalarConstant { 126 public: 127 FloatConstant(const analysis::Float* ty, const std::vector<uint32_t>& w) 128 : ScalarConstant(ty, w) {} 129 FloatConstant(const analysis::Float* ty, std::vector<uint32_t>&& w) 130 : ScalarConstant(ty, std::move(w)) {} 131 132 FloatConstant* AsFloatConstant() override { return this; } 133 const FloatConstant* AsFloatConstant() const override { return this; } 134 135 // Make a copy of this FloatConstant instance. 136 std::unique_ptr<FloatConstant> CopyFloatConstant() const { 137 return MakeUnique<FloatConstant>(type_->AsFloat(), words_); 138 } 139 std::unique_ptr<Constant> Copy() const override { 140 return std::unique_ptr<Constant>(CopyFloatConstant().release()); 141 } 142 }; 143 144 // Bool type constant. 145 class BoolConstant : public ScalarConstant { 146 public: 147 BoolConstant(const analysis::Bool* ty, bool v) 148 : ScalarConstant(ty, {static_cast<uint32_t>(v)}), value_(v) {} 149 150 BoolConstant* AsBoolConstant() override { return this; } 151 const BoolConstant* AsBoolConstant() const override { return this; } 152 153 // Make a copy of this BoolConstant instance. 154 std::unique_ptr<BoolConstant> CopyBoolConstant() const { 155 return MakeUnique<BoolConstant>(type_->AsBool(), value_); 156 } 157 std::unique_ptr<Constant> Copy() const override { 158 return std::unique_ptr<Constant>(CopyBoolConstant().release()); 159 } 160 161 bool value() const { return value_; } 162 163 private: 164 bool value_; 165 }; 166 167 // Abstract class for composite constants. 168 class CompositeConstant : public Constant { 169 public: 170 CompositeConstant() = delete; 171 CompositeConstant* AsCompositeConstant() override { return this; } 172 const CompositeConstant* AsCompositeConstant() const override { return this; } 173 174 // Returns a const reference of the components holded in this composite 175 // constant. 176 virtual const std::vector<const Constant*>& GetComponents() const { 177 return components_; 178 } 179 180 protected: 181 CompositeConstant(const analysis::Type* ty) : Constant(ty), components_() {} 182 CompositeConstant(const analysis::Type* ty, 183 const std::vector<const Constant*>& components) 184 : Constant(ty), components_(components) {} 185 CompositeConstant(const analysis::Type* ty, 186 std::vector<const Constant*>&& components) 187 : Constant(ty), components_(std::move(components)) {} 188 std::vector<const Constant*> components_; 189 }; 190 191 // Struct type constant. 192 class StructConstant : public CompositeConstant { 193 public: 194 StructConstant(const analysis::Struct* ty) : CompositeConstant(ty) {} 195 StructConstant(const analysis::Struct* ty, 196 const std::vector<const Constant*>& components) 197 : CompositeConstant(ty, components) {} 198 StructConstant(const analysis::Struct* ty, 199 std::vector<const Constant*>&& components) 200 : CompositeConstant(ty, std::move(components)) {} 201 202 StructConstant* AsStructConstant() override { return this; } 203 const StructConstant* AsStructConstant() const override { return this; } 204 205 // Make a copy of this StructConstant instance. 206 std::unique_ptr<StructConstant> CopyStructConstant() const { 207 return MakeUnique<StructConstant>(type_->AsStruct(), components_); 208 } 209 std::unique_ptr<Constant> Copy() const override { 210 return std::unique_ptr<Constant>(CopyStructConstant().release()); 211 } 212 }; 213 214 // Vector type constant. 215 class VectorConstant : public CompositeConstant { 216 public: 217 VectorConstant(const analysis::Vector* ty) 218 : CompositeConstant(ty), component_type_(ty->element_type()) {} 219 VectorConstant(const analysis::Vector* ty, 220 const std::vector<const Constant*>& components) 221 : CompositeConstant(ty, components), 222 component_type_(ty->element_type()) {} 223 VectorConstant(const analysis::Vector* ty, 224 std::vector<const Constant*>&& components) 225 : CompositeConstant(ty, std::move(components)), 226 component_type_(ty->element_type()) {} 227 228 VectorConstant* AsVectorConstant() override { return this; } 229 const VectorConstant* AsVectorConstant() const override { return this; } 230 231 // Make a copy of this VectorConstant instance. 232 std::unique_ptr<VectorConstant> CopyVectorConstant() const { 233 auto another = MakeUnique<VectorConstant>(type_->AsVector()); 234 another->components_.insert(another->components_.end(), components_.begin(), 235 components_.end()); 236 return another; 237 } 238 std::unique_ptr<Constant> Copy() const override { 239 return std::unique_ptr<Constant>(CopyVectorConstant().release()); 240 } 241 242 const analysis::Type* component_type() { return component_type_; } 243 244 private: 245 const analysis::Type* component_type_; 246 }; 247 248 // Array type constant. 249 class ArrayConstant : public CompositeConstant { 250 public: 251 ArrayConstant(const analysis::Array* ty) : CompositeConstant(ty) {} 252 ArrayConstant(const analysis::Array* ty, 253 const std::vector<const Constant*>& components) 254 : CompositeConstant(ty, components) {} 255 ArrayConstant(const analysis::Array* ty, 256 std::vector<const Constant*>&& components) 257 : CompositeConstant(ty, std::move(components)) {} 258 259 ArrayConstant* AsArrayConstant() override { return this; } 260 const ArrayConstant* AsArrayConstant() const override { return this; } 261 262 // Make a copy of this ArrayConstant instance. 263 std::unique_ptr<ArrayConstant> CopyArrayConstant() const { 264 return MakeUnique<ArrayConstant>(type_->AsArray(), components_); 265 } 266 std::unique_ptr<Constant> Copy() const override { 267 return std::unique_ptr<Constant>(CopyArrayConstant().release()); 268 } 269 }; 270 271 // Null type constant. 272 class NullConstant : public Constant { 273 public: 274 NullConstant(const analysis::Type* ty) : Constant(ty) {} 275 NullConstant* AsNullConstant() override { return this; } 276 const NullConstant* AsNullConstant() const override { return this; } 277 278 // Make a copy of this NullConstant instance. 279 std::unique_ptr<NullConstant> CopyNullConstant() const { 280 return MakeUnique<NullConstant>(type_); 281 } 282 std::unique_ptr<Constant> Copy() const override { 283 return std::unique_ptr<Constant>(CopyNullConstant().release()); 284 } 285 }; 286 287 } // namespace analysis 288 } // namespace opt 289 } // namespace spvtools 290 291 #endif // LIBSPIRV_OPT_CONSTANTS_H_ 292