• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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