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