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,uint8_t primarySize,uint8_t secondarySize)41 constexpr StaticMangledName BuildStaticMangledName(TBasicType basicType,
42 TPrecision precision,
43 TQualifier qualifier,
44 uint8_t primarySize,
45 uint8_t 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,uint8_t primarySize,uint8_t secondarySize,const unsigned int * arraySizes,size_t numArraySizes)65 constexpr StaticArrayMangledName BuildStaticArrayMangledName(TBasicType basicType,
66 TPrecision precision,
67 TQualifier qualifier,
68 uint8_t primarySize,
69 uint8_t 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 uint8_t primarySize,
95 uint8_t 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 uint8_t primarySize,
104 uint8_t 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 uint8_t primarySize,
131 uint8_t 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 uint8_t primarySize,
146 uint8_t 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 uint8_t primarySize,
168 uint8_t 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 uint8_t primarySize,
180 uint8_t 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 uint8_t primarySize = 1,
200 uint8_t 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 uint8_t primarySize = 1,
209 uint8_t 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 uint8_t primarySize = 1,
219 uint8_t secondarySize = 1>
GetQualified()220 constexpr 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, TPrecision precision, TQualifier qualifier, uint8_t secondarySize>
GetForVecMatHelper(uint8_t primarySize)232 constexpr const TType *GetForVecMatHelper(uint8_t primarySize)
233 {
234 static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt ||
235 basicType == EbtBool,
236 "unsupported basicType");
237 switch (primarySize)
238 {
239 case 1:
240 return Get<basicType, precision, qualifier, 1, secondarySize>();
241 case 2:
242 return Get<basicType, precision, qualifier, 2, secondarySize>();
243 case 3:
244 return Get<basicType, precision, qualifier, 3, secondarySize>();
245 case 4:
246 return Get<basicType, precision, qualifier, 4, secondarySize>();
247 default:
248 UNREACHABLE();
249 return GetBasic<EbtVoid, EbpUndefined>();
250 }
251 }
252
253 } // namespace Helpers
254
255 template <TBasicType basicType, TPrecision precision, TQualifier qualifier = EvqGlobal>
256 constexpr const TType *GetForVecMat(uint8_t primarySize, uint8_t secondarySize = 1)
257 {
258 static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt ||
259 basicType == EbtBool,
260 "unsupported basicType");
261 switch (secondarySize)
262 {
263 case 1:
264 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 1>(primarySize);
265 case 2:
266 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 2>(primarySize);
267 case 3:
268 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 3>(primarySize);
269 case 4:
270 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 4>(primarySize);
271 default:
272 UNREACHABLE();
273 return GetBasic<EbtVoid, EbpUndefined>();
274 }
275 }
276
277 template <TBasicType basicType, TPrecision precision>
GetForVec(TQualifier qualifier,uint8_t size)278 constexpr const TType *GetForVec(TQualifier qualifier, uint8_t size)
279 {
280 switch (qualifier)
281 {
282 case EvqGlobal:
283 return Helpers::GetForVecMatHelper<basicType, precision, EvqGlobal, 1>(size);
284 case EvqParamOut:
285 return Helpers::GetForVecMatHelper<basicType, precision, EvqParamOut, 1>(size);
286 default:
287 UNREACHABLE();
288 return GetBasic<EbtVoid, EbpUndefined>();
289 }
290 }
291
292 } // namespace StaticType
293
294 } // namespace sh
295
296 #endif // COMPILER_TRANSLATOR_STATIC_TYPE_H_
297