xref: /aosp_15_r20/external/angle/src/compiler/translator/StaticType.h (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
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