1 // Copyright 2019 The SwiftShader Authors. All Rights Reserved. 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 rr_Traits_hpp 16 #define rr_Traits_hpp 17 18 #include <stdint.h> 19 #include <type_traits> 20 21 #ifdef Bool 22 # undef Bool // b/127920555 23 #endif 24 25 namespace rr { 26 27 // Forward declarations 28 class Value; 29 30 class Void; 31 class Bool; 32 class Byte; 33 class SByte; 34 class Short; 35 class UShort; 36 class Int; 37 class UInt; 38 class Long; 39 class Half; 40 class Float; 41 class Float4; 42 43 template<class T> 44 class Pointer; 45 template<class T> 46 class LValue; 47 template<class T> 48 class RValue; 49 50 // IsDefined<T>::value is true if T is a valid type, otherwise false. 51 template<typename T, typename Enable = void> 52 struct IsDefined 53 { 54 static constexpr bool value = false; 55 }; 56 57 template<typename T> 58 struct IsDefined<T, std::enable_if_t<(sizeof(T) > 0)>> 59 { 60 static constexpr bool value = true; 61 }; 62 63 template<> 64 struct IsDefined<void> 65 { 66 static constexpr bool value = true; 67 }; 68 69 // CToReactorT<T> resolves to the corresponding Reactor type for the given C 70 // template type T. 71 template<typename T, typename ENABLE = void> 72 struct CToReactor; 73 template<typename T> 74 using CToReactorT = typename CToReactor<T>::type; 75 76 // CToReactor specializations for POD types. 77 template<> 78 struct CToReactor<void> 79 { 80 using type = Void; 81 }; 82 template<> 83 struct CToReactor<bool> 84 { 85 using type = Bool; 86 static Bool cast(bool); 87 }; 88 template<> 89 struct CToReactor<uint8_t> 90 { 91 using type = Byte; 92 static Byte cast(uint8_t); 93 }; 94 template<> 95 struct CToReactor<int8_t> 96 { 97 using type = SByte; 98 static SByte cast(int8_t); 99 }; 100 template<> 101 struct CToReactor<int16_t> 102 { 103 using type = Short; 104 static Short cast(int16_t); 105 }; 106 template<> 107 struct CToReactor<uint16_t> 108 { 109 using type = UShort; 110 static UShort cast(uint16_t); 111 }; 112 template<> 113 struct CToReactor<int32_t> 114 { 115 using type = Int; 116 static Int cast(int32_t); 117 }; 118 template<> 119 struct CToReactor<uint32_t> 120 { 121 using type = UInt; 122 static UInt cast(uint32_t); 123 }; 124 template<> 125 struct CToReactor<float> 126 { 127 using type = Float; 128 static Float cast(float); 129 }; 130 template<> 131 struct CToReactor<float[4]> 132 { 133 using type = Float4; 134 static Float4 cast(float[4]); 135 }; 136 137 // TODO: Long has no constructor that takes a uint64_t 138 template<> 139 struct CToReactor<uint64_t> 140 { 141 using type = Long; /* static Long cast(uint64_t); */ 142 }; 143 144 // HasReactorType<T>::value resolves to true iff there exists a 145 // CToReactorT specialization for type T. 146 template<typename T> 147 using HasReactorType = IsDefined<CToReactorT<T>>; 148 149 // CToReactorPtr<T>::type resolves to the corresponding Reactor Pointer<> 150 // type for T*. 151 // For T types that have a CToReactorT<> specialization, 152 // CToReactorPtr<T>::type resolves to Pointer< CToReactorT<T> >, otherwise 153 // CToReactorPtr<T>::type resolves to Pointer<Byte>. 154 template<typename T, typename ENABLE = void> 155 struct CToReactorPtr 156 { 157 using type = Pointer<Byte>; 158 static inline type cast(const T *v); // implemented in Traits.inl 159 }; 160 161 // CToReactorPtr specialization for T types that have a CToReactorT<> 162 // specialization. 163 template<typename T> 164 struct CToReactorPtr<T, std::enable_if_t<HasReactorType<T>::value>> 165 { 166 using type = Pointer<CToReactorT<T>>; 167 static inline type cast(const T *v); // implemented in Traits.inl 168 }; 169 170 // CToReactorPtr specialization for void*. 171 // Maps to Pointer<Byte> instead of Pointer<Void>. 172 template<> 173 struct CToReactorPtr<void, void> 174 { 175 using type = Pointer<Byte>; 176 static inline type cast(const void *v); // implemented in Traits.inl 177 }; 178 179 // CToReactorPtr specialization for function pointer types. 180 // Maps to Pointer<Byte>. 181 // Drops the 'const' qualifier from the cast() method to avoid warnings 182 // about const having no meaning for function types. 183 template<typename T> 184 struct CToReactorPtr<T, std::enable_if_t<std::is_function<T>::value>> 185 { 186 using type = Pointer<Byte>; 187 static inline type cast(T *v); // implemented in Traits.inl 188 }; 189 190 template<typename T> 191 using CToReactorPtrT = typename CToReactorPtr<T>::type; 192 193 // CToReactor specialization for pointer types. 194 // For T types that have a CToReactorT<> specialization, 195 // CToReactorT<T*>::type resolves to Pointer< CToReactorT<T> >, otherwise 196 // CToReactorT<T*>::type resolves to Pointer<Byte>. 197 template<typename T> 198 struct CToReactor<T, std::enable_if_t<std::is_pointer<T>::value>> 199 { 200 using elem = typename std::remove_pointer<T>::type; 201 using type = CToReactorPtrT<elem>; 202 static inline type cast(T v); // implemented in Traits.inl 203 }; 204 205 // CToReactor specialization for enum types. 206 template<typename T> 207 struct CToReactor<T, std::enable_if_t<std::is_enum<T>::value>> 208 { 209 using underlying = typename std::underlying_type<T>::type; 210 using type = CToReactorT<underlying>; 211 static type cast(T v); // implemented in Traits.inl 212 }; 213 214 // IsRValue::value is true if T is of type RValue<X>, where X is any type. 215 template<typename T, typename Enable = void> 216 struct IsRValue 217 { 218 static constexpr bool value = false; 219 }; 220 template<typename T> 221 struct IsRValue<T, std::enable_if_t<IsDefined<typename T::rvalue_underlying_type>::value>> 222 { 223 static constexpr bool value = true; 224 }; 225 226 // IsLValue::value is true if T is of, or derives from type LValue<T>. 227 template<typename T> 228 struct IsLValue 229 { 230 static constexpr bool value = std::is_base_of<LValue<T>, T>::value; 231 }; 232 233 // IsReference::value is true if T is of type Reference<X>, where X is any type. 234 template<typename T, typename Enable = void> 235 struct IsReference 236 { 237 static constexpr bool value = false; 238 }; 239 template<typename T> 240 struct IsReference<T, std::enable_if_t<IsDefined<typename T::reference_underlying_type>::value>> 241 { 242 static constexpr bool value = true; 243 }; 244 245 // ReactorTypeT<T> returns the LValue Reactor type for T. 246 // T can be a C-type, RValue or LValue. 247 template<typename T, typename ENABLE = void> 248 struct ReactorType; 249 template<typename T> 250 using ReactorTypeT = typename ReactorType<T>::type; 251 template<typename T> 252 struct ReactorType<T, std::enable_if_t<IsDefined<CToReactorT<T>>::value>> 253 { 254 using type = CToReactorT<T>; castrr::ReactorType255 static type cast(T v) { return CToReactor<T>::cast(v); } 256 }; 257 template<typename T> 258 struct ReactorType<T, std::enable_if_t<IsRValue<T>::value>> 259 { 260 using type = typename T::rvalue_underlying_type; castrr::ReactorType261 static type cast(T v) { return type(v); } 262 }; 263 template<typename T> 264 struct ReactorType<T, std::enable_if_t<IsLValue<T>::value>> 265 { 266 using type = T; castrr::ReactorType267 static type cast(T v) { return type(v); } 268 }; 269 template<typename T> 270 struct ReactorType<T, std::enable_if_t<IsReference<T>::value>> 271 { 272 using type = T; castrr::ReactorType273 static type cast(T v) { return type(v); } 274 }; 275 276 // Reactor types that can be used as a return type for a function. 277 template<typename T> 278 struct CanBeUsedAsReturn 279 { 280 static constexpr bool value = false; 281 }; 282 template<> 283 struct CanBeUsedAsReturn<Void> 284 { 285 static constexpr bool value = true; 286 }; 287 template<> 288 struct CanBeUsedAsReturn<Int> 289 { 290 static constexpr bool value = true; 291 }; 292 template<> 293 struct CanBeUsedAsReturn<UInt> 294 { 295 static constexpr bool value = true; 296 }; 297 template<> 298 struct CanBeUsedAsReturn<Float> 299 { 300 static constexpr bool value = true; 301 }; 302 template<typename T> 303 struct CanBeUsedAsReturn<Pointer<T>> 304 { 305 static constexpr bool value = true; 306 }; 307 308 // Reactor types that can be used as a parameter types for a function. 309 template<typename T> 310 struct CanBeUsedAsParameter 311 { 312 static constexpr bool value = false; 313 }; 314 template<> 315 struct CanBeUsedAsParameter<Int> 316 { 317 static constexpr bool value = true; 318 }; 319 template<> 320 struct CanBeUsedAsParameter<UInt> 321 { 322 static constexpr bool value = true; 323 }; 324 template<> 325 struct CanBeUsedAsParameter<Float> 326 { 327 static constexpr bool value = true; 328 }; 329 template<typename T> 330 struct CanBeUsedAsParameter<Pointer<T>> 331 { 332 static constexpr bool value = true; 333 }; 334 335 // AssertParameterTypeIsValid statically asserts that all template parameter 336 // types can be used as a Reactor function parameter. 337 template<typename T, typename... other> 338 struct AssertParameterTypeIsValid : AssertParameterTypeIsValid<other...> 339 { 340 static_assert(CanBeUsedAsParameter<T>::value, "Invalid parameter type"); 341 }; 342 template<typename T> 343 struct AssertParameterTypeIsValid<T> 344 { 345 static_assert(CanBeUsedAsParameter<T>::value, "Invalid parameter type"); 346 }; 347 348 // AssertFunctionSignatureIsValid statically asserts that the Reactor 349 // function signature is valid. 350 template<typename Return, typename... Arguments> 351 class AssertFunctionSignatureIsValid; 352 template<typename Return> 353 class AssertFunctionSignatureIsValid<Return(Void)> 354 {}; 355 template<typename Return, typename... Arguments> 356 class AssertFunctionSignatureIsValid<Return(Arguments...)> 357 { 358 static_assert(CanBeUsedAsReturn<Return>::value, "Invalid return type"); 359 static_assert(sizeof(AssertParameterTypeIsValid<Arguments...>) >= 0, ""); 360 }; 361 362 } // namespace rr 363 364 #endif // rr_Traits_hpp 365