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