blob: 522ed6a87016ef717f08ff888e316b7e2fda4eef [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
Nicolas Capens157ba262019-12-10 17:49:14 -050021namespace rr {
22
23// Forward declarations
24class Value;
25
26class Void;
27class Bool;
28class Byte;
29class SByte;
30class Short;
31class UShort;
32class Int;
33class UInt;
34class Long;
35class Half;
36class Float;
37class Float4;
38
Ben Clayton713b8d32019-12-17 20:37:56 +000039template<class T>
40class Pointer;
41template<class T>
42class LValue;
43template<class T>
44class RValue;
Nicolas Capens157ba262019-12-10 17:49:14 -050045
Nicolas Capens157ba262019-12-10 17:49:14 -050046// IsDefined<T>::value is true if T is a valid type, otherwise false.
Ben Clayton713b8d32019-12-17 20:37:56 +000047template<typename T, typename Enable = void>
Nicolas Capens157ba262019-12-10 17:49:14 -050048struct IsDefined
Ben Clayton351be422019-04-30 12:26:57 +010049{
Nicolas Capens157ba262019-12-10 17:49:14 -050050 static constexpr bool value = false;
51};
Ben Clayton351be422019-04-30 12:26:57 +010052
Ben Clayton713b8d32019-12-17 20:37:56 +000053template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +000054struct IsDefined<T, std::enable_if_t<(sizeof(T) > 0)>>
Nicolas Capens157ba262019-12-10 17:49:14 -050055{
56 static constexpr bool value = true;
57};
Ben Clayton351be422019-04-30 12:26:57 +010058
Ben Clayton713b8d32019-12-17 20:37:56 +000059template<>
Nicolas Capens157ba262019-12-10 17:49:14 -050060struct IsDefined<void>
61{
62 static constexpr bool value = true;
63};
Ben Clayton351be422019-04-30 12:26:57 +010064
Nicolas Capens157ba262019-12-10 17:49:14 -050065// CToReactorT<T> resolves to the corresponding Reactor type for the given C
66// template type T.
Ben Clayton713b8d32019-12-17 20:37:56 +000067template<typename T, typename ENABLE = void>
68struct CToReactor;
69template<typename T>
70using CToReactorT = typename CToReactor<T>::type;
Ben Clayton663dcef2019-11-26 11:01:48 +000071
Nicolas Capens157ba262019-12-10 17:49:14 -050072// CToReactor specializations for POD types.
Ben Clayton713b8d32019-12-17 20:37:56 +000073template<>
74struct CToReactor<void>
75{
76 using type = Void;
77};
78template<>
79struct CToReactor<bool>
80{
81 using type = Bool;
82 static Bool cast(bool);
83};
84template<>
85struct CToReactor<uint8_t>
86{
87 using type = Byte;
88 static Byte cast(uint8_t);
89};
90template<>
91struct CToReactor<int8_t>
92{
93 using type = SByte;
94 static SByte cast(int8_t);
95};
96template<>
97struct CToReactor<int16_t>
98{
99 using type = Short;
100 static Short cast(int16_t);
101};
102template<>
103struct CToReactor<uint16_t>
104{
105 using type = UShort;
106 static UShort cast(uint16_t);
107};
108template<>
109struct CToReactor<int32_t>
110{
111 using type = Int;
112 static Int cast(int32_t);
113};
114template<>
115struct CToReactor<uint32_t>
116{
117 using type = UInt;
118 static UInt cast(uint32_t);
119};
120template<>
121struct CToReactor<float>
122{
123 using type = Float;
124 static Float cast(float);
125};
126template<>
127struct CToReactor<float[4]>
128{
129 using type = Float4;
130 static Float4 cast(float[4]);
131};
Ben Clayton351be422019-04-30 12:26:57 +0100132
Nicolas Capens157ba262019-12-10 17:49:14 -0500133// TODO: Long has no constructor that takes a uint64_t
Ben Clayton713b8d32019-12-17 20:37:56 +0000134template<>
135struct CToReactor<uint64_t>
136{
137 using type = Long; /* static Long cast(uint64_t); */
138};
Ben Clayton351be422019-04-30 12:26:57 +0100139
Nicolas Capens157ba262019-12-10 17:49:14 -0500140// HasReactorType<T>::value resolves to true iff there exists a
141// CToReactorT specialization for type T.
142template<typename T>
Ben Clayton713b8d32019-12-17 20:37:56 +0000143using HasReactorType = IsDefined<CToReactorT<T>>;
Ben Clayton351be422019-04-30 12:26:57 +0100144
Nicolas Capens157ba262019-12-10 17:49:14 -0500145// 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>.
Ben Clayton713b8d32019-12-17 20:37:56 +0000150template<typename T, typename ENABLE = void>
151struct CToReactorPtr
Nicolas Capens157ba262019-12-10 17:49:14 -0500152{
153 using type = Pointer<Byte>;
Ben Clayton713b8d32019-12-17 20:37:56 +0000154 static inline type cast(const T *v); // implemented in Traits.inl
Nicolas Capens157ba262019-12-10 17:49:14 -0500155};
Ben Clayton351be422019-04-30 12:26:57 +0100156
Nicolas Capens157ba262019-12-10 17:49:14 -0500157// CToReactorPtr specialization for T types that have a CToReactorT<>
158// specialization.
Ben Clayton713b8d32019-12-17 20:37:56 +0000159template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +0000160struct CToReactorPtr<T, std::enable_if_t<HasReactorType<T>::value>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500161{
Ben Clayton713b8d32019-12-17 20:37:56 +0000162 using type = Pointer<CToReactorT<T>>;
163 static inline type cast(const T *v); // implemented in Traits.inl
Nicolas Capens157ba262019-12-10 17:49:14 -0500164};
Ben Clayton51f08312019-11-08 14:39:26 +0000165
Nicolas Capens157ba262019-12-10 17:49:14 -0500166// CToReactorPtr specialization for void*.
167// Maps to Pointer<Byte> instead of Pointer<Void>.
Ben Clayton713b8d32019-12-17 20:37:56 +0000168template<>
169struct CToReactorPtr<void, void>
Nicolas Capens157ba262019-12-10 17:49:14 -0500170{
171 using type = Pointer<Byte>;
Ben Clayton713b8d32019-12-17 20:37:56 +0000172 static inline type cast(const void *v); // implemented in Traits.inl
Nicolas Capens157ba262019-12-10 17:49:14 -0500173};
Ben Clayton351be422019-04-30 12:26:57 +0100174
Nicolas Capens157ba262019-12-10 17:49:14 -0500175// 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.
Ben Clayton713b8d32019-12-17 20:37:56 +0000179template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +0000180struct CToReactorPtr<T, std::enable_if_t<std::is_function<T>::value>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500181{
182 using type = Pointer<Byte>;
Ben Clayton713b8d32019-12-17 20:37:56 +0000183 static inline type cast(T *v); // implemented in Traits.inl
Nicolas Capens157ba262019-12-10 17:49:14 -0500184};
Ben Clayton663dcef2019-11-26 11:01:48 +0000185
Ben Clayton713b8d32019-12-17 20:37:56 +0000186template<typename T>
187using CToReactorPtrT = typename CToReactorPtr<T>::type;
Ben Claytona9f511b2019-11-18 22:18:48 +0000188
Nicolas Capens157ba262019-12-10 17:49:14 -0500189// 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>.
193template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +0000194struct CToReactor<T, std::enable_if_t<std::is_pointer<T>::value>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500195{
196 using elem = typename std::remove_pointer<T>::type;
197 using type = CToReactorPtrT<elem>;
Ben Clayton713b8d32019-12-17 20:37:56 +0000198 static inline type cast(T v); // implemented in Traits.inl
Nicolas Capens157ba262019-12-10 17:49:14 -0500199};
Ben Clayton351be422019-04-30 12:26:57 +0100200
Nicolas Capens157ba262019-12-10 17:49:14 -0500201// CToReactor specialization for enum types.
202template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +0000203struct CToReactor<T, std::enable_if_t<std::is_enum<T>::value>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500204{
205 using underlying = typename std::underlying_type<T>::type;
206 using type = CToReactorT<underlying>;
Ben Clayton713b8d32019-12-17 20:37:56 +0000207 static type cast(T v); // implemented in Traits.inl
Nicolas Capens157ba262019-12-10 17:49:14 -0500208};
Ben Claytona9f511b2019-11-18 22:18:48 +0000209
Nicolas Capens157ba262019-12-10 17:49:14 -0500210// IsRValue::value is true if T is of type RValue<X>, where X is any type.
Ben Clayton713b8d32019-12-17 20:37:56 +0000211template<typename T, typename Enable = void>
212struct IsRValue
213{
214 static constexpr bool value = false;
215};
216template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +0000217struct IsRValue<T, std::enable_if_t<IsDefined<typename T::rvalue_underlying_type>::value>>
Ben Clayton713b8d32019-12-17 20:37:56 +0000218{
219 static constexpr bool value = true;
220};
Ben Claytona9f511b2019-11-18 22:18:48 +0000221
Nicolas Capens157ba262019-12-10 17:49:14 -0500222// IsLValue::value is true if T is of, or derives from type LValue<T>.
Ben Clayton713b8d32019-12-17 20:37:56 +0000223template<typename T>
224struct IsLValue
225{
226 static constexpr bool value = std::is_base_of<LValue<T>, T>::value;
227};
Ben Claytona9f511b2019-11-18 22:18:48 +0000228
Nicolas Capens157ba262019-12-10 17:49:14 -0500229// IsReference::value is true if T is of type Reference<X>, where X is any type.
Ben Clayton713b8d32019-12-17 20:37:56 +0000230template<typename T, typename Enable = void>
231struct IsReference
232{
233 static constexpr bool value = false;
234};
235template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +0000236struct IsReference<T, std::enable_if_t<IsDefined<typename T::reference_underlying_type>::value>>
Ben Clayton713b8d32019-12-17 20:37:56 +0000237{
238 static constexpr bool value = true;
239};
Ben Clayton351be422019-04-30 12:26:57 +0100240
Nicolas Capens157ba262019-12-10 17:49:14 -0500241// ReactorTypeT<T> returns the LValue Reactor type for T.
242// T can be a C-type, RValue or LValue.
Ben Clayton713b8d32019-12-17 20:37:56 +0000243template<typename T, typename ENABLE = void>
244struct ReactorType;
245template<typename T>
246using ReactorTypeT = typename ReactorType<T>::type;
247template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +0000248struct ReactorType<T, std::enable_if_t<IsDefined<CToReactorT<T>>::value>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500249{
250 using type = CToReactorT<T>;
251 static type cast(T v) { return CToReactor<T>::cast(v); }
252};
Ben Clayton713b8d32019-12-17 20:37:56 +0000253template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +0000254struct ReactorType<T, std::enable_if_t<IsRValue<T>::value>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500255{
256 using type = typename T::rvalue_underlying_type;
257 static type cast(T v) { return type(v); }
258};
Ben Clayton713b8d32019-12-17 20:37:56 +0000259template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +0000260struct ReactorType<T, std::enable_if_t<IsLValue<T>::value>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500261{
262 using type = T;
263 static type cast(T v) { return type(v); }
264};
Ben Clayton713b8d32019-12-17 20:37:56 +0000265template<typename T>
Ben Clayton316f0cb2020-01-08 23:12:14 +0000266struct ReactorType<T, std::enable_if_t<IsReference<T>::value>>
Nicolas Capens157ba262019-12-10 17:49:14 -0500267{
268 using type = T;
269 static type cast(T v) { return type(v); }
270};
Ben Clayton208ed402019-05-03 22:30:03 +0100271
Nicolas Capens157ba262019-12-10 17:49:14 -0500272// Reactor types that can be used as a return type for a function.
Ben Clayton713b8d32019-12-17 20:37:56 +0000273template<typename T>
274struct CanBeUsedAsReturn
275{
276 static constexpr bool value = false;
277};
278template<>
279struct CanBeUsedAsReturn<Void>
280{
281 static constexpr bool value = true;
282};
283template<>
284struct CanBeUsedAsReturn<Int>
285{
286 static constexpr bool value = true;
287};
288template<>
289struct CanBeUsedAsReturn<UInt>
290{
291 static constexpr bool value = true;
292};
293template<>
294struct CanBeUsedAsReturn<Float>
295{
296 static constexpr bool value = true;
297};
298template<typename T>
299struct CanBeUsedAsReturn<Pointer<T>>
300{
301 static constexpr bool value = true;
302};
Ben Clayton351be422019-04-30 12:26:57 +0100303
Nicolas Capens157ba262019-12-10 17:49:14 -0500304// Reactor types that can be used as a parameter types for a function.
Ben Clayton713b8d32019-12-17 20:37:56 +0000305template<typename T>
306struct CanBeUsedAsParameter
307{
308 static constexpr bool value = false;
309};
310template<>
311struct CanBeUsedAsParameter<Int>
312{
313 static constexpr bool value = true;
314};
315template<>
316struct CanBeUsedAsParameter<UInt>
317{
318 static constexpr bool value = true;
319};
320template<>
321struct CanBeUsedAsParameter<Float>
322{
323 static constexpr bool value = true;
324};
325template<typename T>
326struct CanBeUsedAsParameter<Pointer<T>>
327{
328 static constexpr bool value = true;
329};
Ben Clayton351be422019-04-30 12:26:57 +0100330
Nicolas Capens157ba262019-12-10 17:49:14 -0500331// AssertParameterTypeIsValid statically asserts that all template parameter
332// types can be used as a Reactor function parameter.
Ben Clayton713b8d32019-12-17 20:37:56 +0000333template<typename T, typename... other>
Nicolas Capens157ba262019-12-10 17:49:14 -0500334struct AssertParameterTypeIsValid : AssertParameterTypeIsValid<other...>
335{
336 static_assert(CanBeUsedAsParameter<T>::value, "Invalid parameter type");
337};
338template<typename T>
339struct AssertParameterTypeIsValid<T>
340{
341 static_assert(CanBeUsedAsParameter<T>::value, "Invalid parameter type");
342};
Ben Clayton351be422019-04-30 12:26:57 +0100343
Nicolas Capens157ba262019-12-10 17:49:14 -0500344// AssertFunctionSignatureIsValid statically asserts that the Reactor
345// function signature is valid.
346template<typename Return, typename... Arguments>
347class AssertFunctionSignatureIsValid;
348template<typename Return>
Ben Clayton713b8d32019-12-17 20:37:56 +0000349class AssertFunctionSignatureIsValid<Return(Void)>
350{};
Nicolas Capens157ba262019-12-10 17:49:14 -0500351template<typename Return, typename... Arguments>
352class AssertFunctionSignatureIsValid<Return(Arguments...)>
353{
354 static_assert(CanBeUsedAsReturn<Return>::value, "Invalid return type");
355 static_assert(sizeof(AssertParameterTypeIsValid<Arguments...>) >= 0, "");
356};
Ben Clayton351be422019-04-30 12:26:57 +0100357
Nicolas Capens157ba262019-12-10 17:49:14 -0500358} // namespace rr
Ben Clayton351be422019-04-30 12:26:57 +0100359
Ben Clayton713b8d32019-12-17 20:37:56 +0000360#endif // rr_Traits_hpp