blob: 840d198054115fd11c6aed1b3e3a38c4fb381f96 [file] [log] [blame]
Ben Clayton351be422019-04-30 12:26:57 +01001// 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
25namespace 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
42 template<class T> class Pointer;
43 template<class T> class LValue;
44 template<class T> 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, typename std::enable_if<(sizeof(T)>0)>::type>
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 // CToReactor<T> resolves to the corresponding Reactor type for the given C
66 // template type T.
67 template<typename T, typename ENABLE = void> struct CToReactorT;
68 template<typename T> using CToReactor = typename CToReactorT<T>::type;
69
70 // CToReactorT specializations for POD types.
71 template<> struct CToReactorT<void> { using type = Void; };
72 template<> struct CToReactorT<bool> { using type = Bool; };
73 template<> struct CToReactorT<uint8_t> { using type = Byte; };
74 template<> struct CToReactorT<int8_t> { using type = SByte; };
75 template<> struct CToReactorT<int16_t> { using type = Short; };
76 template<> struct CToReactorT<uint16_t> { using type = UShort; };
77 template<> struct CToReactorT<int32_t> { using type = Int; };
78 template<> struct CToReactorT<uint64_t> { using type = Long; };
79 template<> struct CToReactorT<uint32_t> { using type = UInt; };
80 template<> struct CToReactorT<float> { using type = Float; };
81
82 // CToReactorPtrT<T>::type resolves to the corresponding Reactor Pointer<>
83 // type for T*.
84 // For T types that have a CToReactorT<> specialization,
85 // CToReactorPtrT<T>::type resolves to Pointer< CToReactorT<T> >, otherwise
86 // CToReactorPtrT<T>::type resolves to Pointer<Byte>.
87 template<typename T, typename ENABLE = void> struct CToReactorPtrT { using type = Pointer<Byte>; };
88 template<typename T> using CToReactorPtr = typename CToReactorPtrT<T>::type;
89 template<typename T> struct CToReactorPtrT<T, typename std::enable_if< IsDefined< typename CToReactorT<T>::type >::value>::type >
90 {
91 using type = Pointer< typename CToReactorT<T>::type >;
92 };
93
94 // CToReactorT specialization for pointer types.
95 // For T types that have a CToReactorT<> specialization,
96 // CToReactorT<T*>::type resolves to Pointer< CToReactorT<T> >, otherwise
97 // CToReactorT<T*>::type resolves to Pointer<Byte>.
98 template<typename T>
99 struct CToReactorT<T, typename std::enable_if<std::is_pointer<T>::value>::type>
100 {
101 using elem = typename std::remove_pointer<T>::type;
102 using type = CToReactorPtr<elem>;
103 };
104
105 // CToReactorT specialization for void*.
106 // Maps to Pointer<Byte> instead of Pointer<Void>.
107 template<> struct CToReactorT<void*> { using type = Pointer<Byte>; };
108
109 // CToReactorT specialization for enum types.
110 template<typename T>
111 struct CToReactorT<T, typename std::enable_if<std::is_enum<T>::value>::type>
112 {
113 using underlying = typename std::underlying_type<T>::type;
114 using type = typename CToReactorT<underlying>::type;
115 };
116
117 // IsRValue::value is true if T is of type RValue<X>, where X is any type.
118 template <typename T, typename Enable = void> struct IsRValue { static constexpr bool value = false; };
119 template <typename T> struct IsRValue<T, typename std::enable_if<IsDefined<typename T::rvalue_underlying_type>::value>::type> { static constexpr bool value = true; };
120
121 // IsLValue::value is true if T is of, or derives from type LValue<T>.
122 template <typename T> struct IsLValue { static constexpr bool value = std::is_base_of<LValue<T>, T>::value; };
123
Ben Clayton208ed402019-05-03 22:30:03 +0100124 // IsReference::value is true if T is of type Reference<X>, where X is any type.
125 template <typename T, typename Enable = void> struct IsReference { static constexpr bool value = false; };
126 template <typename T> struct IsReference<T, typename std::enable_if<IsDefined<typename T::reference_underlying_type>::value>::type> { static constexpr bool value = true; };
127
Ben Clayton351be422019-04-30 12:26:57 +0100128 // ReactorType<T> returns the LValue Reactor type for T.
129 // T can be a C-type, RValue or LValue.
130 template<typename T, typename ENABLE = void> struct ReactorTypeT;
131 template<typename T> using ReactorType = typename ReactorTypeT<T>::type;
132 template<typename T> struct ReactorTypeT<T, typename std::enable_if<IsDefined<CToReactor<T>>::value>::type> { using type = CToReactor<T>; };
133 template<typename T> struct ReactorTypeT<T, typename std::enable_if<IsRValue<T>::value>::type> { using type = typename T::rvalue_underlying_type; };
134 template<typename T> struct ReactorTypeT<T, typename std::enable_if<IsLValue<T>::value>::type> { using type = T; };
Ben Clayton208ed402019-05-03 22:30:03 +0100135 template<typename T> struct ReactorTypeT<T, typename std::enable_if<IsReference<T>::value>::type> { using type = T; };
136
Ben Clayton351be422019-04-30 12:26:57 +0100137
138 // Reactor types that can be used as a return type for a function.
139 template <typename T> struct CanBeUsedAsReturn { static constexpr bool value = false; };
140 template <> struct CanBeUsedAsReturn<Void> { static constexpr bool value = true; };
141 template <> struct CanBeUsedAsReturn<Int> { static constexpr bool value = true; };
142 template <> struct CanBeUsedAsReturn<UInt> { static constexpr bool value = true; };
143 template <> struct CanBeUsedAsReturn<Float> { static constexpr bool value = true; };
144 template <typename T> struct CanBeUsedAsReturn<Pointer<T>> { static constexpr bool value = true; };
145
146 // Reactor types that can be used as a parameter types for a function.
147 template <typename T> struct CanBeUsedAsParameter { static constexpr bool value = false; };
148 template <> struct CanBeUsedAsParameter<Int> { static constexpr bool value = true; };
149 template <> struct CanBeUsedAsParameter<UInt> { static constexpr bool value = true; };
150 template <> struct CanBeUsedAsParameter<Float> { static constexpr bool value = true; };
151 template <typename T> struct CanBeUsedAsParameter<Pointer<T>> { static constexpr bool value = true; };
152
153 // AssertParameterTypeIsValid statically asserts that all template parameter
154 // types can be used as a Reactor function parameter.
155 template<typename T, typename ... other>
156 struct AssertParameterTypeIsValid : AssertParameterTypeIsValid<other...>
157 {
158 static_assert(CanBeUsedAsParameter<T>::value, "Invalid parameter type");
159 };
160 template<typename T>
161 struct AssertParameterTypeIsValid<T>
162 {
163 static_assert(CanBeUsedAsParameter<T>::value, "Invalid parameter type");
164 };
165
166 // AssertFunctionSignatureIsValid statically asserts that the Reactor
167 // function signature is valid.
168 template<typename Return, typename... Arguments>
169 class AssertFunctionSignatureIsValid;
170 template<typename Return>
171 class AssertFunctionSignatureIsValid<Return(Void)> {};
172 template<typename Return, typename... Arguments>
173 class AssertFunctionSignatureIsValid<Return(Arguments...)>
174 {
175 static_assert(CanBeUsedAsReturn<Return>::value, "Invalid return type");
176 static_assert(sizeof(AssertParameterTypeIsValid<Arguments...>) >= 0, "");
177 };
178
179} // namespace rr
180
181#endif // rr_Traits_hpp