1 // Copyright 2021 The Tint Authors. 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 SRC_WRITER_SPIRV_SCALAR_CONSTANT_H_ 16 #define SRC_WRITER_SPIRV_SCALAR_CONSTANT_H_ 17 18 #include <stdint.h> 19 20 #include <cstring> 21 #include <functional> 22 23 #include "src/utils/hash.h" 24 25 namespace tint { 26 27 // Forward declarations 28 namespace sem { 29 class Call; 30 } // namespace sem 31 32 namespace writer { 33 namespace spirv { 34 35 /// ScalarConstant represents a scalar constant value 36 struct ScalarConstant { 37 /// The constant value 38 union Value { 39 /// The value as a bool 40 bool b; 41 /// The value as a uint32_t 42 uint32_t u32; 43 /// The value as a int32_t 44 int32_t i32; 45 /// The value as a float 46 float f32; 47 48 /// The value that is wide enough to encompass all other types (including 49 /// future 64-bit data types). 50 uint64_t u64; 51 }; 52 53 /// The kind of constant 54 enum class Kind { kBool, kU32, kI32, kF32 }; 55 56 /// Constructor ScalarConstantScalarConstant57 inline ScalarConstant() { value.u64 = 0; } 58 59 /// @param value the value of the constant 60 /// @returns a new ScalarConstant with the provided value and kind Kind::kU32 U32ScalarConstant61 static inline ScalarConstant U32(uint32_t value) { 62 ScalarConstant c; 63 c.value.u32 = value; 64 c.kind = Kind::kU32; 65 return c; 66 } 67 68 /// @param value the value of the constant 69 /// @returns a new ScalarConstant with the provided value and kind Kind::kI32 I32ScalarConstant70 static inline ScalarConstant I32(int32_t value) { 71 ScalarConstant c; 72 c.value.i32 = value; 73 c.kind = Kind::kI32; 74 return c; 75 } 76 77 /// @param value the value of the constant 78 /// @returns a new ScalarConstant with the provided value and kind Kind::kI32 F32ScalarConstant79 static inline ScalarConstant F32(float value) { 80 ScalarConstant c; 81 c.value.f32 = value; 82 c.kind = Kind::kF32; 83 return c; 84 } 85 86 /// @param value the value of the constant 87 /// @returns a new ScalarConstant with the provided value and kind Kind::kBool BoolScalarConstant88 static inline ScalarConstant Bool(bool value) { 89 ScalarConstant c; 90 c.value.b = value; 91 c.kind = Kind::kBool; 92 return c; 93 } 94 95 /// Equality operator 96 /// @param rhs the ScalarConstant to compare against 97 /// @returns true if this ScalarConstant is equal to `rhs` 98 inline bool operator==(const ScalarConstant& rhs) const { 99 return value.u64 == rhs.value.u64 && kind == rhs.kind && 100 is_spec_op == rhs.is_spec_op && constant_id == rhs.constant_id; 101 } 102 103 /// Inequality operator 104 /// @param rhs the ScalarConstant to compare against 105 /// @returns true if this ScalarConstant is not equal to `rhs` 106 inline bool operator!=(const ScalarConstant& rhs) const { 107 return !(*this == rhs); 108 } 109 110 /// @returns this ScalarConstant as a specialization op with the given 111 /// specialization constant identifier 112 /// @param id the constant identifier AsSpecOpScalarConstant113 ScalarConstant AsSpecOp(uint32_t id) const { 114 auto ret = *this; 115 ret.is_spec_op = true; 116 ret.constant_id = id; 117 return ret; 118 } 119 120 /// The constant value 121 Value value; 122 /// The constant value kind 123 Kind kind = Kind::kBool; 124 /// True if the constant is a specialization op 125 bool is_spec_op = false; 126 /// The identifier if a specialization op 127 uint32_t constant_id = 0; 128 }; 129 130 } // namespace spirv 131 } // namespace writer 132 } // namespace tint 133 134 namespace std { 135 136 /// Custom std::hash specialization for tint::Symbol so symbols can be used as 137 /// keys for std::unordered_map and std::unordered_set. 138 template <> 139 class hash<tint::writer::spirv::ScalarConstant> { 140 public: 141 /// @param c the ScalarConstant 142 /// @return the Symbol internal value operator()143 inline std::size_t operator()( 144 const tint::writer::spirv::ScalarConstant& c) const { 145 uint32_t value = 0; 146 std::memcpy(&value, &c.value, sizeof(value)); 147 return tint::utils::Hash(value, c.kind); 148 } 149 }; 150 151 } // namespace std 152 153 #endif // SRC_WRITER_SPIRV_SCALAR_CONSTANT_H_ 154