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, unsigned char primarySize = 1, unsigned char secondarySize = 1>
GetBasic()198 constexpr const TType *GetBasic()
199 {
200 return Get<basicType, EbpUndefined, EvqGlobal, primarySize, secondarySize>();
201 }
202
203 template <TBasicType basicType, unsigned char primarySize = 1, unsigned char secondarySize = 1>
GetTemporary()204 constexpr const TType *GetTemporary()
205 {
206 return Get<basicType, EbpUndefined, EvqTemporary, primarySize, secondarySize>();
207 }
208
209 template <TBasicType basicType,
210 TQualifier qualifier,
211 unsigned char primarySize = 1,
212 unsigned char secondarySize = 1>
GetQualified()213 const TType *GetQualified()
214 {
215 return Get<basicType, EbpUndefined, qualifier, primarySize, secondarySize>();
216 }
217
218 // Dynamic lookup methods (convert runtime values to template args)
219
220 namespace Helpers
221 {
222
223 // Helper which takes secondarySize statically but primarySize dynamically.
224 template <TBasicType basicType,
225 TPrecision precision,
226 TQualifier qualifier,
227 unsigned char secondarySize>
GetForVecMatHelper(unsigned char primarySize)228 constexpr const TType *GetForVecMatHelper(unsigned char primarySize)
229 {
230 static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt ||
231 basicType == EbtBool,
232 "unsupported basicType");
233 switch (primarySize)
234 {
235 case 1:
236 return Get<basicType, precision, qualifier, 1, secondarySize>();
237 case 2:
238 return Get<basicType, precision, qualifier, 2, secondarySize>();
239 case 3:
240 return Get<basicType, precision, qualifier, 3, secondarySize>();
241 case 4:
242 return Get<basicType, precision, qualifier, 4, secondarySize>();
243 default:
244 UNREACHABLE();
245 return GetBasic<EbtVoid>();
246 }
247 }
248
249 } // namespace Helpers
250
251 template <TBasicType basicType,
252 TPrecision precision = EbpUndefined,
253 TQualifier qualifier = EvqGlobal>
254 constexpr const TType *GetForVecMat(unsigned char primarySize, unsigned char secondarySize = 1)
255 {
256 static_assert(basicType == EbtFloat || basicType == EbtInt || basicType == EbtUInt ||
257 basicType == EbtBool,
258 "unsupported basicType");
259 switch (secondarySize)
260 {
261 case 1:
262 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 1>(primarySize);
263 case 2:
264 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 2>(primarySize);
265 case 3:
266 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 3>(primarySize);
267 case 4:
268 return Helpers::GetForVecMatHelper<basicType, precision, qualifier, 4>(primarySize);
269 default:
270 UNREACHABLE();
271 return GetBasic<EbtVoid>();
272 }
273 }
274
275 template <TBasicType basicType, TPrecision precision = EbpUndefined>
GetForVec(TQualifier qualifier,unsigned char size)276 constexpr const TType *GetForVec(TQualifier qualifier, unsigned char size)
277 {
278 switch (qualifier)
279 {
280 case EvqGlobal:
281 return Helpers::GetForVecMatHelper<basicType, precision, EvqGlobal, 1>(size);
282 case EvqOut:
283 return Helpers::GetForVecMatHelper<basicType, precision, EvqOut, 1>(size);
284 default:
285 UNREACHABLE();
286 return GetBasic<EbtVoid>();
287 }
288 }
289
290 } // namespace StaticType
291
292 } // namespace sh
293
294 #endif // COMPILER_TRANSLATOR_STATIC_TYPE_H_
295