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