// Copyright 2019 The SwiftShader Authors. All Rights Reserved. // // 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 rr_Traits_hpp #define rr_Traits_hpp #include #include #ifdef Bool # undef Bool // b/127920555 #endif namespace rr { // Forward declarations class Value; class Void; class Bool; class Byte; class SByte; class Short; class UShort; class Int; class UInt; class Long; class Half; class Float; class Float4; template class Pointer; template class LValue; template class RValue; // IsDefined::value is true if T is a valid type, otherwise false. template struct IsDefined { static constexpr bool value = false; }; template struct IsDefined 0)>> { static constexpr bool value = true; }; template<> struct IsDefined { static constexpr bool value = true; }; // CToReactorT resolves to the corresponding Reactor type for the given C // template type T. template struct CToReactor; template using CToReactorT = typename CToReactor::type; // CToReactor specializations for POD types. template<> struct CToReactor { using type = Void; }; template<> struct CToReactor { using type = Bool; static Bool cast(bool); }; template<> struct CToReactor { using type = Byte; static Byte cast(uint8_t); }; template<> struct CToReactor { using type = SByte; static SByte cast(int8_t); }; template<> struct CToReactor { using type = Short; static Short cast(int16_t); }; template<> struct CToReactor { using type = UShort; static UShort cast(uint16_t); }; template<> struct CToReactor { using type = Int; static Int cast(int32_t); }; template<> struct CToReactor { using type = UInt; static UInt cast(uint32_t); }; template<> struct CToReactor { using type = Float; static Float cast(float); }; template<> struct CToReactor { using type = Float4; static Float4 cast(float[4]); }; // TODO: Long has no constructor that takes a uint64_t template<> struct CToReactor { using type = Long; /* static Long cast(uint64_t); */ }; // HasReactorType::value resolves to true iff there exists a // CToReactorT specialization for type T. template using HasReactorType = IsDefined>; // CToReactorPtr::type resolves to the corresponding Reactor Pointer<> // type for T*. // For T types that have a CToReactorT<> specialization, // CToReactorPtr::type resolves to Pointer< CToReactorT >, otherwise // CToReactorPtr::type resolves to Pointer. template struct CToReactorPtr { using type = Pointer; static inline type cast(const T *v); // implemented in Traits.inl }; // CToReactorPtr specialization for T types that have a CToReactorT<> // specialization. template struct CToReactorPtr::value>> { using type = Pointer>; static inline type cast(const T *v); // implemented in Traits.inl }; // CToReactorPtr specialization for void*. // Maps to Pointer instead of Pointer. template<> struct CToReactorPtr { using type = Pointer; static inline type cast(const void *v); // implemented in Traits.inl }; // CToReactorPtr specialization for function pointer types. // Maps to Pointer. // Drops the 'const' qualifier from the cast() method to avoid warnings // about const having no meaning for function types. template struct CToReactorPtr::value>> { using type = Pointer; static inline type cast(T *v); // implemented in Traits.inl }; template using CToReactorPtrT = typename CToReactorPtr::type; // CToReactor specialization for pointer types. // For T types that have a CToReactorT<> specialization, // CToReactorT::type resolves to Pointer< CToReactorT >, otherwise // CToReactorT::type resolves to Pointer. template struct CToReactor::value>> { using elem = typename std::remove_pointer::type; using type = CToReactorPtrT; static inline type cast(T v); // implemented in Traits.inl }; // CToReactor specialization for enum types. template struct CToReactor::value>> { using underlying = typename std::underlying_type::type; using type = CToReactorT; static type cast(T v); // implemented in Traits.inl }; // IsRValue::value is true if T is of type RValue, where X is any type. template struct IsRValue { static constexpr bool value = false; }; template struct IsRValue::value>> { static constexpr bool value = true; }; // IsLValue::value is true if T is of, or derives from type LValue. template struct IsLValue { static constexpr bool value = std::is_base_of, T>::value; }; // IsReference::value is true if T is of type Reference, where X is any type. template struct IsReference { static constexpr bool value = false; }; template struct IsReference::value>> { static constexpr bool value = true; }; // ReactorTypeT returns the LValue Reactor type for T. // T can be a C-type, RValue or LValue. template struct ReactorType; template using ReactorTypeT = typename ReactorType::type; template struct ReactorType>::value>> { using type = CToReactorT; static type cast(T v) { return CToReactor::cast(v); } }; template struct ReactorType::value>> { using type = typename T::rvalue_underlying_type; static type cast(T v) { return type(v); } }; template struct ReactorType::value>> { using type = T; static type cast(T v) { return type(v); } }; template struct ReactorType::value>> { using type = T; static type cast(T v) { return type(v); } }; // Reactor types that can be used as a return type for a function. template struct CanBeUsedAsReturn { static constexpr bool value = false; }; template<> struct CanBeUsedAsReturn { static constexpr bool value = true; }; template<> struct CanBeUsedAsReturn { static constexpr bool value = true; }; template<> struct CanBeUsedAsReturn { static constexpr bool value = true; }; template<> struct CanBeUsedAsReturn { static constexpr bool value = true; }; template struct CanBeUsedAsReturn> { static constexpr bool value = true; }; // Reactor types that can be used as a parameter types for a function. template struct CanBeUsedAsParameter { static constexpr bool value = false; }; template<> struct CanBeUsedAsParameter { static constexpr bool value = true; }; template<> struct CanBeUsedAsParameter { static constexpr bool value = true; }; template<> struct CanBeUsedAsParameter { static constexpr bool value = true; }; template struct CanBeUsedAsParameter> { static constexpr bool value = true; }; // AssertParameterTypeIsValid statically asserts that all template parameter // types can be used as a Reactor function parameter. template struct AssertParameterTypeIsValid : AssertParameterTypeIsValid { static_assert(CanBeUsedAsParameter::value, "Invalid parameter type"); }; template struct AssertParameterTypeIsValid { static_assert(CanBeUsedAsParameter::value, "Invalid parameter type"); }; // AssertFunctionSignatureIsValid statically asserts that the Reactor // function signature is valid. template class AssertFunctionSignatureIsValid; template class AssertFunctionSignatureIsValid {}; template class AssertFunctionSignatureIsValid { static_assert(CanBeUsedAsReturn::value, "Invalid return type"); static_assert(sizeof(AssertParameterTypeIsValid) >= 0, ""); }; } // namespace rr #endif // rr_Traits_hpp