1 //
2 // Copyright 2017 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // Compile-time instances of many common TType values. These are looked up
7 // (statically or dynamically) through the methods defined in the namespace.
8 //
9
10 #ifndef COMPILER_TRANSLATOR_STATIC_TYPE_H_
11 #define COMPILER_TRANSLATOR_STATIC_TYPE_H_
12
13 #include "compiler/translator/Types.h"
14
15 namespace sh
16 {
17
18 namespace StaticType
19 {
20
21 namespace Helpers
22 {
23
24 //
25 // Generation and static allocation of type mangled name values.
26 //
27
28 // Size of the constexpr-generated mangled name.
29 // If this value is too small, the compiler will produce errors.
30 static constexpr size_t kStaticMangledNameLength = TBasicMangledName::mangledNameSize + 1;
31
32 // Type which holds the mangled names for constexpr-generated TTypes.
33 // This simple struct is needed so that a char array can be returned by value.
34 struct StaticMangledName
35 {
36 // If this array is too small, the compiler will produce errors.
37 char name[kStaticMangledNameLength + 1] = {};
38 };
39
40 // Generates a mangled name for a TType given its parameters.
BuildStaticMangledName(TBasicType basicType,TPrecision precision,TQualifier qualifier,unsigned char primarySize,unsigned char secondarySize)41 constexpr StaticMangledName BuildStaticMangledName(TBasicType basicType,
42 TPrecision precision,
43 TQualifier qualifier,
44 unsigned char primarySize,
45 unsigned char secondarySize)
46 {
47 StaticMangledName name = {};
48 name.name[0] = TType::GetSizeMangledName(primarySize, secondarySize);
49 TBasicMangledName typeName(basicType);
50 char *mangledName = typeName.getName();
51 static_assert(TBasicMangledName::mangledNameSize == 2, "Mangled name size is not 2");
52 name.name[1] = mangledName[0];
53 name.name[2] = mangledName[1];
54 name.name[3] = '\0';
55 return name;
56 }
57
58 // Similar mangled name builder but for array types. Currently, only single-dimension arrays of
59 // single-digit size are necessary and supported.
60 static constexpr size_t kStaticArrayMangledNameLength = kStaticMangledNameLength + 2;
61 struct StaticArrayMangledName
62 {
63 char name[kStaticArrayMangledNameLength + 1] = {};
64 };
BuildStaticArrayMangledName(TBasicType basicType,TPrecision precision,TQualifier qualifier,unsigned char primarySize,unsigned char secondarySize,const unsigned int * arraySizes,size_t numArraySizes)65 constexpr StaticArrayMangledName BuildStaticArrayMangledName(TBasicType basicType,
66 TPrecision precision,
67 TQualifier qualifier,
68 unsigned char primarySize,
69 unsigned char secondarySize,
70 const unsigned int *arraySizes,
71 size_t numArraySizes)
72 {
73 StaticMangledName nonArrayName =
74 BuildStaticMangledName(basicType, precision, qualifier, primarySize, secondarySize);
75
76 StaticArrayMangledName arrayName = {};
77 static_assert(kStaticMangledNameLength == 3, "Static mangled name size is not 3");
78
79 arrayName.name[0] = nonArrayName.name[0];
80 arrayName.name[1] = nonArrayName.name[1];
81 arrayName.name[2] = nonArrayName.name[2];
82 arrayName.name[3] = 'x';
83 arrayName.name[4] = static_cast<char>('0' + arraySizes[0]);
84 arrayName.name[5] = '\0';
85 return arrayName;
86 }
87
88 // This "variable" contains the mangled names for every constexpr-generated TType.
89 // If kMangledNameInstance<B, P, Q, PS, SS> is used anywhere (specifally
90 // in instance, below), this is where the appropriate type will be stored.
91 template <TBasicType basicType,
92 TPrecision precision,
93 TQualifier qualifier,
94 unsigned char primarySize,
95 unsigned char secondarySize>
96 static constexpr StaticMangledName kMangledNameInstance =
97 BuildStaticMangledName(basicType, precision, qualifier, primarySize, secondarySize);
98
99 // Same as kMangledNameInstance, but for array types.
100 template <TBasicType basicType,
101 TPrecision precision,
102 TQualifier qualifier,
103 unsigned char primarySize,
104 unsigned char secondarySize,
105 const unsigned int *arraySizes,
106 size_t numArraySizes>
107 static constexpr StaticArrayMangledName kMangledNameArrayInstance =
108 BuildStaticArrayMangledName(basicType,
109 precision,
110 qualifier,
111 primarySize,
112 secondarySize,
113 arraySizes,
114 numArraySizes);
115
116 //
117 // Generation and static allocation of TType values.
118 //
119
120 // This "variable" contains every constexpr-generated TType.
121 // If instance<B, P, Q, PS, SS> is used anywhere (specifally
122 // in Get, below), this is where the appropriate type will be stored.
123 //
124 // TODO(crbug.com/981610): This is constexpr but doesn't follow the kConstant naming convention
125 // because TType has a mutable member that prevents it from being in .data.rel.ro and makes the
126 // Android Binary Size builder complain when ANGLE is rolled in Chromium.
127 template <TBasicType basicType,
128 TPrecision precision,
129 TQualifier qualifier,
130 unsigned char primarySize,
131 unsigned char secondarySize>
132 static constexpr TType instance =
133 TType(basicType,
134 precision,
135 qualifier,
136 primarySize,
137 secondarySize,
138 TSpan<const unsigned int>(),
139 kMangledNameInstance<basicType, precision, qualifier, primarySize, secondarySize>.name);
140
141 // Same as instance, but for array types.
142 template <TBasicType basicType,
143 TPrecision precision,
144 TQualifier qualifier,
145 unsigned char primarySize,
146 unsigned char secondarySize,
147 const unsigned int *arraySizes,
148 size_t numArraySizes>
149 static constexpr TType arrayInstance =
150 TType(basicType,
151 precision,
152 qualifier,
153 primarySize,
154 secondarySize,
155 TSpan<const unsigned int>(arraySizes, numArraySizes),
156 kMangledNameArrayInstance<basicType, precision, qualifier, primarySize, secondarySize, arraySizes, numArraySizes>.name);
157
158 } // namespace Helpers
159
160 //
161 // Fully-qualified type lookup.
162 //
163
164 template <TBasicType basicType,
165 TPrecision precision,
166 TQualifier qualifier,
167 unsigned char primarySize,
168 unsigned char secondarySize>
Get()169 constexpr const TType *Get()
170 {
171 static_assert(1 <= primarySize && primarySize <= 4, "primarySize out of bounds");
172 static_assert(1 <= secondarySize && secondarySize <= 4, "secondarySize out of bounds");
173 return &Helpers::instance<basicType, precision, qualifier, primarySize, secondarySize>;
174 }
175
176 template <TBasicType basicType,
177 TPrecision precision,
178 TQualifier qualifier,
179 unsigned char primarySize,
180 unsigned char secondarySize,
181 const unsigned int *arraySizes,
182 size_t numArraySizes>
GetArray()183 constexpr const TType *GetArray()
184 {
185 static_assert(1 <= primarySize && primarySize <= 4, "primarySize out of bounds");
186 static_assert(1 <= secondarySize && secondarySize <= 4, "secondarySize out of bounds");
187 static_assert(numArraySizes == 1, "only single-dimension static types are supported");
188 static_assert(arraySizes[0] < 10, "only single-digit dimensions are supported in static types");
189 return &Helpers::arrayInstance<basicType, precision, qualifier, primarySize, secondarySize,
190 arraySizes, numArraySizes>;
191 }
192
193 //
194 // Overloads
195 //
196
197 template <TBasicType basicType,
198 TPrecision precision,
199 unsigned char primarySize = 1,
200 unsigned char secondarySize = 1>
GetBasic()201 constexpr const TType *GetBasic()
202 {
203 return Get<basicType, precision, EvqGlobal, primarySize, secondarySize>();
204 }
205
206 template <TBasicType basicType,
207 TPrecision precision,
208 unsigned char primarySize = 1,
209 unsigned char secondarySize = 1>
GetTemporary()210 constexpr const TType *GetTemporary()
211 {
212 return Get<basicType, precision, EvqTemporary, primarySize, secondarySize>();
213 }
214
215 template <TBasicType basicType,
216 TPrecision precision,
217 TQualifier qualifier,
218 unsigned char primarySize = 1,
219 unsigned char secondarySize = 1>
GetQualified()220 const TType *GetQualified()
221 {
222 return Get<basicType, precision, qualifier, primarySize, secondarySize>();
223 }
224
225 // Dynamic lookup methods (convert runtime values to template args)
226
227 namespace Helpers
228 {
229
230 // Helper which takes secondarySize statically but primarySize dynamically.
231 template <TBasicType basicType,
232 TPrecision precision,
233 TQualifier qualifier,
234 unsigned char secondarySize>
GetForVecMatHelper(unsigned char primarySize)235 constexpr const TType *GetForVecMatHelper(unsigned char primarySize)
236 {
237 static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt ||
238 basicType == EbtBool,
239 "unsupported basicType");
240 switch (primarySize)
241 {
242 case 1:
243 return Get<basicType, precision, qualifier, 1, secondarySize>();
244 case 2:
245 return Get<basicType, precision, qualifier, 2, secondarySize>();
246 case 3:
247 return Get<basicType, precision, qualifier, 3, secondarySize>();
248 case 4:
249 return Get<basicType, precision, qualifier, 4, secondarySize>();
250 default:
251 UNREACHABLE();
252 return GetBasic<EbtVoid, EbpUndefined>();
253 }
254 }
255
256 } // namespace Helpers
257
258 template <TBasicType basicType, TPrecision precision, TQualifier qualifier = EvqGlobal>
259 constexpr const TType *GetForVecMat(unsigned char primarySize, unsigned char secondarySize = 1)
260 {
261 static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt ||
262 basicType == EbtBool,
263 "unsupported basicType");
264 switch (secondarySize)
265 {
266 case 1:
267 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 1>(primarySize);
268 case 2:
269 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 2>(primarySize);
270 case 3:
271 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 3>(primarySize);
272 case 4:
273 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 4>(primarySize);
274 default:
275 UNREACHABLE();
276 return GetBasic<EbtVoid, EbpUndefined>();
277 }
278 }
279
280 template <TBasicType basicType, TPrecision precision>
GetForVec(TQualifier qualifier,unsigned char size)281 constexpr const TType *GetForVec(TQualifier qualifier, unsigned char size)
282 {
283 switch (qualifier)
284 {
285 case EvqGlobal:
286 return Helpers::GetForVecMatHelper<basicType, precision, EvqGlobal, 1>(size);
287 case EvqParamOut:
288 return Helpers::GetForVecMatHelper<basicType, precision, EvqParamOut, 1>(size);
289 default:
290 UNREACHABLE();
291 return GetBasic<EbtVoid, EbpUndefined>();
292 }
293 }
294
295 } // namespace StaticType
296
297 } // namespace sh
298
299 #endif // COMPILER_TRANSLATOR_STATIC_TYPE_H_
300