xref: /aosp_15_r20/external/angle/src/compiler/translator/ParseContext.cpp (revision 8975f5c5ed3d1c378011245431ada316dfb6f244)
1*8975f5c5SAndroid Build Coastguard Worker //
2*8975f5c5SAndroid Build Coastguard Worker // Copyright 2002 The ANGLE Project Authors. All rights reserved.
3*8975f5c5SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
4*8975f5c5SAndroid Build Coastguard Worker // found in the LICENSE file.
5*8975f5c5SAndroid Build Coastguard Worker //
6*8975f5c5SAndroid Build Coastguard Worker 
7*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/ParseContext.h"
8*8975f5c5SAndroid Build Coastguard Worker 
9*8975f5c5SAndroid Build Coastguard Worker #include <stdarg.h>
10*8975f5c5SAndroid Build Coastguard Worker #include <stdio.h>
11*8975f5c5SAndroid Build Coastguard Worker 
12*8975f5c5SAndroid Build Coastguard Worker #include "common/mathutil.h"
13*8975f5c5SAndroid Build Coastguard Worker #include "common/utilities.h"
14*8975f5c5SAndroid Build Coastguard Worker #include "compiler/preprocessor/SourceLocation.h"
15*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/Declarator.h"
16*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/StaticType.h"
17*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/ValidateGlobalInitializer.h"
18*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/ValidateSwitch.h"
19*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/glslang.h"
20*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/tree_util/IntermNode_util.h"
21*8975f5c5SAndroid Build Coastguard Worker #include "compiler/translator/util.h"
22*8975f5c5SAndroid Build Coastguard Worker 
23*8975f5c5SAndroid Build Coastguard Worker namespace sh
24*8975f5c5SAndroid Build Coastguard Worker {
25*8975f5c5SAndroid Build Coastguard Worker 
26*8975f5c5SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////
27*8975f5c5SAndroid Build Coastguard Worker //
28*8975f5c5SAndroid Build Coastguard Worker // Sub- vector and matrix fields
29*8975f5c5SAndroid Build Coastguard Worker //
30*8975f5c5SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////
31*8975f5c5SAndroid Build Coastguard Worker 
32*8975f5c5SAndroid Build Coastguard Worker namespace
33*8975f5c5SAndroid Build Coastguard Worker {
34*8975f5c5SAndroid Build Coastguard Worker 
35*8975f5c5SAndroid Build Coastguard Worker const int kWebGLMaxStructNesting = 4;
36*8975f5c5SAndroid Build Coastguard Worker 
37*8975f5c5SAndroid Build Coastguard Worker struct IsSamplerFunc
38*8975f5c5SAndroid Build Coastguard Worker {
operator ()sh::__anon9e080a080111::IsSamplerFunc39*8975f5c5SAndroid Build Coastguard Worker     bool operator()(TBasicType type) { return IsSampler(type); }
40*8975f5c5SAndroid Build Coastguard Worker };
41*8975f5c5SAndroid Build Coastguard Worker struct IsOpaqueFunc
42*8975f5c5SAndroid Build Coastguard Worker {
operator ()sh::__anon9e080a080111::IsOpaqueFunc43*8975f5c5SAndroid Build Coastguard Worker     bool operator()(TBasicType type) { return IsOpaqueType(type); }
44*8975f5c5SAndroid Build Coastguard Worker };
45*8975f5c5SAndroid Build Coastguard Worker 
46*8975f5c5SAndroid Build Coastguard Worker template <typename OpaqueFunc>
47*8975f5c5SAndroid Build Coastguard Worker bool ContainsOpaque(const TStructure *structType);
48*8975f5c5SAndroid Build Coastguard Worker 
49*8975f5c5SAndroid Build Coastguard Worker template <typename OpaqueFunc>
ContainsOpaque(const TType & type)50*8975f5c5SAndroid Build Coastguard Worker bool ContainsOpaque(const TType &type)
51*8975f5c5SAndroid Build Coastguard Worker {
52*8975f5c5SAndroid Build Coastguard Worker     if (OpaqueFunc{}(type.getBasicType()))
53*8975f5c5SAndroid Build Coastguard Worker     {
54*8975f5c5SAndroid Build Coastguard Worker         return true;
55*8975f5c5SAndroid Build Coastguard Worker     }
56*8975f5c5SAndroid Build Coastguard Worker     if (type.getBasicType() == EbtStruct)
57*8975f5c5SAndroid Build Coastguard Worker     {
58*8975f5c5SAndroid Build Coastguard Worker         return ContainsOpaque<OpaqueFunc>(type.getStruct());
59*8975f5c5SAndroid Build Coastguard Worker     }
60*8975f5c5SAndroid Build Coastguard Worker 
61*8975f5c5SAndroid Build Coastguard Worker     return false;
62*8975f5c5SAndroid Build Coastguard Worker }
63*8975f5c5SAndroid Build Coastguard Worker 
64*8975f5c5SAndroid Build Coastguard Worker template <typename OpaqueFunc>
ContainsOpaque(const TStructure * structType)65*8975f5c5SAndroid Build Coastguard Worker bool ContainsOpaque(const TStructure *structType)
66*8975f5c5SAndroid Build Coastguard Worker {
67*8975f5c5SAndroid Build Coastguard Worker     for (const auto &field : structType->fields())
68*8975f5c5SAndroid Build Coastguard Worker     {
69*8975f5c5SAndroid Build Coastguard Worker         if (ContainsOpaque<OpaqueFunc>(*field->type()))
70*8975f5c5SAndroid Build Coastguard Worker             return true;
71*8975f5c5SAndroid Build Coastguard Worker     }
72*8975f5c5SAndroid Build Coastguard Worker     return false;
73*8975f5c5SAndroid Build Coastguard Worker }
74*8975f5c5SAndroid Build Coastguard Worker 
75*8975f5c5SAndroid Build Coastguard Worker // Get a token from an image argument to use as an error message token.
GetImageArgumentToken(TIntermTyped * imageNode)76*8975f5c5SAndroid Build Coastguard Worker const char *GetImageArgumentToken(TIntermTyped *imageNode)
77*8975f5c5SAndroid Build Coastguard Worker {
78*8975f5c5SAndroid Build Coastguard Worker     ASSERT(IsImage(imageNode->getBasicType()));
79*8975f5c5SAndroid Build Coastguard Worker     while (imageNode->getAsBinaryNode() &&
80*8975f5c5SAndroid Build Coastguard Worker            (imageNode->getAsBinaryNode()->getOp() == EOpIndexIndirect ||
81*8975f5c5SAndroid Build Coastguard Worker             imageNode->getAsBinaryNode()->getOp() == EOpIndexDirect))
82*8975f5c5SAndroid Build Coastguard Worker     {
83*8975f5c5SAndroid Build Coastguard Worker         imageNode = imageNode->getAsBinaryNode()->getLeft();
84*8975f5c5SAndroid Build Coastguard Worker     }
85*8975f5c5SAndroid Build Coastguard Worker     TIntermSymbol *imageSymbol = imageNode->getAsSymbolNode();
86*8975f5c5SAndroid Build Coastguard Worker     if (imageSymbol)
87*8975f5c5SAndroid Build Coastguard Worker     {
88*8975f5c5SAndroid Build Coastguard Worker         return imageSymbol->getName().data();
89*8975f5c5SAndroid Build Coastguard Worker     }
90*8975f5c5SAndroid Build Coastguard Worker     return "image";
91*8975f5c5SAndroid Build Coastguard Worker }
92*8975f5c5SAndroid Build Coastguard Worker 
CanSetDefaultPrecisionOnType(const TPublicType & type)93*8975f5c5SAndroid Build Coastguard Worker bool CanSetDefaultPrecisionOnType(const TPublicType &type)
94*8975f5c5SAndroid Build Coastguard Worker {
95*8975f5c5SAndroid Build Coastguard Worker     if (!SupportsPrecision(type.getBasicType()))
96*8975f5c5SAndroid Build Coastguard Worker     {
97*8975f5c5SAndroid Build Coastguard Worker         return false;
98*8975f5c5SAndroid Build Coastguard Worker     }
99*8975f5c5SAndroid Build Coastguard Worker     if (type.getBasicType() == EbtUInt)
100*8975f5c5SAndroid Build Coastguard Worker     {
101*8975f5c5SAndroid Build Coastguard Worker         // ESSL 3.00.4 section 4.5.4
102*8975f5c5SAndroid Build Coastguard Worker         return false;
103*8975f5c5SAndroid Build Coastguard Worker     }
104*8975f5c5SAndroid Build Coastguard Worker     if (type.isAggregate())
105*8975f5c5SAndroid Build Coastguard Worker     {
106*8975f5c5SAndroid Build Coastguard Worker         // Not allowed to set for aggregate types
107*8975f5c5SAndroid Build Coastguard Worker         return false;
108*8975f5c5SAndroid Build Coastguard Worker     }
109*8975f5c5SAndroid Build Coastguard Worker     return true;
110*8975f5c5SAndroid Build Coastguard Worker }
111*8975f5c5SAndroid Build Coastguard Worker 
112*8975f5c5SAndroid Build Coastguard Worker // Map input primitive types to input array sizes in a geometry shader.
GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType)113*8975f5c5SAndroid Build Coastguard Worker GLuint GetGeometryShaderInputArraySize(TLayoutPrimitiveType primitiveType)
114*8975f5c5SAndroid Build Coastguard Worker {
115*8975f5c5SAndroid Build Coastguard Worker     switch (primitiveType)
116*8975f5c5SAndroid Build Coastguard Worker     {
117*8975f5c5SAndroid Build Coastguard Worker         case EptPoints:
118*8975f5c5SAndroid Build Coastguard Worker             return 1u;
119*8975f5c5SAndroid Build Coastguard Worker         case EptLines:
120*8975f5c5SAndroid Build Coastguard Worker             return 2u;
121*8975f5c5SAndroid Build Coastguard Worker         case EptTriangles:
122*8975f5c5SAndroid Build Coastguard Worker             return 3u;
123*8975f5c5SAndroid Build Coastguard Worker         case EptLinesAdjacency:
124*8975f5c5SAndroid Build Coastguard Worker             return 4u;
125*8975f5c5SAndroid Build Coastguard Worker         case EptTrianglesAdjacency:
126*8975f5c5SAndroid Build Coastguard Worker             return 6u;
127*8975f5c5SAndroid Build Coastguard Worker         default:
128*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
129*8975f5c5SAndroid Build Coastguard Worker             return 0u;
130*8975f5c5SAndroid Build Coastguard Worker     }
131*8975f5c5SAndroid Build Coastguard Worker }
132*8975f5c5SAndroid Build Coastguard Worker 
IsBufferOrSharedVariable(TIntermTyped * var)133*8975f5c5SAndroid Build Coastguard Worker bool IsBufferOrSharedVariable(TIntermTyped *var)
134*8975f5c5SAndroid Build Coastguard Worker {
135*8975f5c5SAndroid Build Coastguard Worker     if (var->isInterfaceBlock() || var->getQualifier() == EvqBuffer ||
136*8975f5c5SAndroid Build Coastguard Worker         var->getQualifier() == EvqShared)
137*8975f5c5SAndroid Build Coastguard Worker     {
138*8975f5c5SAndroid Build Coastguard Worker         return true;
139*8975f5c5SAndroid Build Coastguard Worker     }
140*8975f5c5SAndroid Build Coastguard Worker     return false;
141*8975f5c5SAndroid Build Coastguard Worker }
142*8975f5c5SAndroid Build Coastguard Worker 
FindLValueBase(TIntermTyped * node)143*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *FindLValueBase(TIntermTyped *node)
144*8975f5c5SAndroid Build Coastguard Worker {
145*8975f5c5SAndroid Build Coastguard Worker     do
146*8975f5c5SAndroid Build Coastguard Worker     {
147*8975f5c5SAndroid Build Coastguard Worker         const TIntermBinary *binary = node->getAsBinaryNode();
148*8975f5c5SAndroid Build Coastguard Worker         if (binary == nullptr)
149*8975f5c5SAndroid Build Coastguard Worker         {
150*8975f5c5SAndroid Build Coastguard Worker             return node;
151*8975f5c5SAndroid Build Coastguard Worker         }
152*8975f5c5SAndroid Build Coastguard Worker 
153*8975f5c5SAndroid Build Coastguard Worker         TOperator op = binary->getOp();
154*8975f5c5SAndroid Build Coastguard Worker         if (op != EOpIndexDirect && op != EOpIndexIndirect)
155*8975f5c5SAndroid Build Coastguard Worker         {
156*8975f5c5SAndroid Build Coastguard Worker             return static_cast<TIntermTyped *>(nullptr);
157*8975f5c5SAndroid Build Coastguard Worker         }
158*8975f5c5SAndroid Build Coastguard Worker 
159*8975f5c5SAndroid Build Coastguard Worker         node = binary->getLeft();
160*8975f5c5SAndroid Build Coastguard Worker     } while (true);
161*8975f5c5SAndroid Build Coastguard Worker }
162*8975f5c5SAndroid Build Coastguard Worker 
AddAdvancedBlendEquation(gl::BlendEquationType eq,TLayoutQualifier * qualifier)163*8975f5c5SAndroid Build Coastguard Worker void AddAdvancedBlendEquation(gl::BlendEquationType eq, TLayoutQualifier *qualifier)
164*8975f5c5SAndroid Build Coastguard Worker {
165*8975f5c5SAndroid Build Coastguard Worker     qualifier->advancedBlendEquations.set(static_cast<uint32_t>(eq));
166*8975f5c5SAndroid Build Coastguard Worker }
167*8975f5c5SAndroid Build Coastguard Worker 
IsValidWithPixelLocalStorage(TLayoutImageInternalFormat internalFormat)168*8975f5c5SAndroid Build Coastguard Worker constexpr bool IsValidWithPixelLocalStorage(TLayoutImageInternalFormat internalFormat)
169*8975f5c5SAndroid Build Coastguard Worker {
170*8975f5c5SAndroid Build Coastguard Worker     switch (internalFormat)
171*8975f5c5SAndroid Build Coastguard Worker     {
172*8975f5c5SAndroid Build Coastguard Worker         case EiifRGBA8:
173*8975f5c5SAndroid Build Coastguard Worker         case EiifRGBA8I:
174*8975f5c5SAndroid Build Coastguard Worker         case EiifRGBA8UI:
175*8975f5c5SAndroid Build Coastguard Worker         case EiifR32F:
176*8975f5c5SAndroid Build Coastguard Worker         case EiifR32UI:
177*8975f5c5SAndroid Build Coastguard Worker             return true;
178*8975f5c5SAndroid Build Coastguard Worker         default:
179*8975f5c5SAndroid Build Coastguard Worker             return false;
180*8975f5c5SAndroid Build Coastguard Worker     }
181*8975f5c5SAndroid Build Coastguard Worker }
182*8975f5c5SAndroid Build Coastguard Worker 
ImageFormatToPLSFormat(TLayoutImageInternalFormat format)183*8975f5c5SAndroid Build Coastguard Worker constexpr ShPixelLocalStorageFormat ImageFormatToPLSFormat(TLayoutImageInternalFormat format)
184*8975f5c5SAndroid Build Coastguard Worker {
185*8975f5c5SAndroid Build Coastguard Worker     switch (format)
186*8975f5c5SAndroid Build Coastguard Worker     {
187*8975f5c5SAndroid Build Coastguard Worker         default:
188*8975f5c5SAndroid Build Coastguard Worker             return ShPixelLocalStorageFormat::NotPLS;
189*8975f5c5SAndroid Build Coastguard Worker         case EiifRGBA8:
190*8975f5c5SAndroid Build Coastguard Worker             return ShPixelLocalStorageFormat::RGBA8;
191*8975f5c5SAndroid Build Coastguard Worker         case EiifRGBA8I:
192*8975f5c5SAndroid Build Coastguard Worker             return ShPixelLocalStorageFormat::RGBA8I;
193*8975f5c5SAndroid Build Coastguard Worker         case EiifRGBA8UI:
194*8975f5c5SAndroid Build Coastguard Worker             return ShPixelLocalStorageFormat::RGBA8UI;
195*8975f5c5SAndroid Build Coastguard Worker         case EiifR32F:
196*8975f5c5SAndroid Build Coastguard Worker             return ShPixelLocalStorageFormat::R32F;
197*8975f5c5SAndroid Build Coastguard Worker         case EiifR32UI:
198*8975f5c5SAndroid Build Coastguard Worker             return ShPixelLocalStorageFormat::R32UI;
199*8975f5c5SAndroid Build Coastguard Worker     }
200*8975f5c5SAndroid Build Coastguard Worker }
201*8975f5c5SAndroid Build Coastguard Worker 
UsesDerivatives(TIntermAggregate * functionCall)202*8975f5c5SAndroid Build Coastguard Worker bool UsesDerivatives(TIntermAggregate *functionCall)
203*8975f5c5SAndroid Build Coastguard Worker {
204*8975f5c5SAndroid Build Coastguard Worker     const TOperator op = functionCall->getOp();
205*8975f5c5SAndroid Build Coastguard Worker     if (BuiltInGroup::IsDerivativesFS(op))
206*8975f5c5SAndroid Build Coastguard Worker     {
207*8975f5c5SAndroid Build Coastguard Worker         return true;
208*8975f5c5SAndroid Build Coastguard Worker     }
209*8975f5c5SAndroid Build Coastguard Worker     switch (op)
210*8975f5c5SAndroid Build Coastguard Worker     {
211*8975f5c5SAndroid Build Coastguard Worker         // TextureFirstVersions with implicit LOD
212*8975f5c5SAndroid Build Coastguard Worker         case EOpTexture2D:
213*8975f5c5SAndroid Build Coastguard Worker         case EOpTexture2DProj:
214*8975f5c5SAndroid Build Coastguard Worker         case EOpTextureCube:
215*8975f5c5SAndroid Build Coastguard Worker         case EOpTexture3D:
216*8975f5c5SAndroid Build Coastguard Worker         case EOpTexture3DProj:
217*8975f5c5SAndroid Build Coastguard Worker         case EOpShadow2DEXT:
218*8975f5c5SAndroid Build Coastguard Worker         case EOpShadow2DProjEXT:
219*8975f5c5SAndroid Build Coastguard Worker         // TextureFirstVersionsBias
220*8975f5c5SAndroid Build Coastguard Worker         case EOpTexture2DBias:
221*8975f5c5SAndroid Build Coastguard Worker         case EOpTexture2DProjBias:
222*8975f5c5SAndroid Build Coastguard Worker         case EOpTextureCubeBias:
223*8975f5c5SAndroid Build Coastguard Worker         case EOpTexture3DBias:
224*8975f5c5SAndroid Build Coastguard Worker         case EOpTexture3DProjBias:
225*8975f5c5SAndroid Build Coastguard Worker         // TextureNoBias
226*8975f5c5SAndroid Build Coastguard Worker         case EOpTexture:
227*8975f5c5SAndroid Build Coastguard Worker         case EOpTextureProj:
228*8975f5c5SAndroid Build Coastguard Worker         // TextureBias
229*8975f5c5SAndroid Build Coastguard Worker         case EOpTextureBias:
230*8975f5c5SAndroid Build Coastguard Worker         case EOpTextureProjBias:
231*8975f5c5SAndroid Build Coastguard Worker         // TextureOffsetNoBias
232*8975f5c5SAndroid Build Coastguard Worker         case EOpTextureOffset:
233*8975f5c5SAndroid Build Coastguard Worker         case EOpTextureProjOffset:
234*8975f5c5SAndroid Build Coastguard Worker         // TextureOffsetBias
235*8975f5c5SAndroid Build Coastguard Worker         case EOpTextureOffsetBias:
236*8975f5c5SAndroid Build Coastguard Worker         case EOpTextureProjOffsetBias:
237*8975f5c5SAndroid Build Coastguard Worker         // TextureQueryLod
238*8975f5c5SAndroid Build Coastguard Worker         case EOpTextureQueryLOD:
239*8975f5c5SAndroid Build Coastguard Worker             return true;
240*8975f5c5SAndroid Build Coastguard Worker         default:
241*8975f5c5SAndroid Build Coastguard Worker             return false;
242*8975f5c5SAndroid Build Coastguard Worker     }
243*8975f5c5SAndroid Build Coastguard Worker }
244*8975f5c5SAndroid Build Coastguard Worker }  // namespace
245*8975f5c5SAndroid Build Coastguard Worker 
246*8975f5c5SAndroid Build Coastguard Worker // This tracks each binding point's current default offset for inheritance of subsequent
247*8975f5c5SAndroid Build Coastguard Worker // variables using the same binding, and keeps offsets unique and non overlapping.
248*8975f5c5SAndroid Build Coastguard Worker // See GLSL ES 3.1, section 4.4.6.
249*8975f5c5SAndroid Build Coastguard Worker class TParseContext::AtomicCounterBindingState
250*8975f5c5SAndroid Build Coastguard Worker {
251*8975f5c5SAndroid Build Coastguard Worker   public:
AtomicCounterBindingState()252*8975f5c5SAndroid Build Coastguard Worker     AtomicCounterBindingState() : mDefaultOffset(0) {}
253*8975f5c5SAndroid Build Coastguard Worker     // Inserts a new span and returns -1 if overlapping, else returns the starting offset of
254*8975f5c5SAndroid Build Coastguard Worker     // newly inserted span.
insertSpan(int start,size_t length)255*8975f5c5SAndroid Build Coastguard Worker     int insertSpan(int start, size_t length)
256*8975f5c5SAndroid Build Coastguard Worker     {
257*8975f5c5SAndroid Build Coastguard Worker         gl::RangeI newSpan(start, start + static_cast<int>(length));
258*8975f5c5SAndroid Build Coastguard Worker         for (const auto &span : mSpans)
259*8975f5c5SAndroid Build Coastguard Worker         {
260*8975f5c5SAndroid Build Coastguard Worker             if (newSpan.intersects(span))
261*8975f5c5SAndroid Build Coastguard Worker             {
262*8975f5c5SAndroid Build Coastguard Worker                 return -1;
263*8975f5c5SAndroid Build Coastguard Worker             }
264*8975f5c5SAndroid Build Coastguard Worker         }
265*8975f5c5SAndroid Build Coastguard Worker         mSpans.push_back(newSpan);
266*8975f5c5SAndroid Build Coastguard Worker         mDefaultOffset = newSpan.high();
267*8975f5c5SAndroid Build Coastguard Worker         return start;
268*8975f5c5SAndroid Build Coastguard Worker     }
269*8975f5c5SAndroid Build Coastguard Worker     // Inserts a new span starting from the default offset.
appendSpan(size_t length)270*8975f5c5SAndroid Build Coastguard Worker     int appendSpan(size_t length) { return insertSpan(mDefaultOffset, length); }
setDefaultOffset(int offset)271*8975f5c5SAndroid Build Coastguard Worker     void setDefaultOffset(int offset) { mDefaultOffset = offset; }
272*8975f5c5SAndroid Build Coastguard Worker 
273*8975f5c5SAndroid Build Coastguard Worker   private:
274*8975f5c5SAndroid Build Coastguard Worker     int mDefaultOffset;
275*8975f5c5SAndroid Build Coastguard Worker     std::vector<gl::RangeI> mSpans;
276*8975f5c5SAndroid Build Coastguard Worker };
277*8975f5c5SAndroid Build Coastguard Worker 
TParseContext(TSymbolTable & symt,TExtensionBehavior & ext,sh::GLenum type,ShShaderSpec spec,const ShCompileOptions & options,TDiagnostics * diagnostics,const ShBuiltInResources & resources,ShShaderOutput outputType)278*8975f5c5SAndroid Build Coastguard Worker TParseContext::TParseContext(TSymbolTable &symt,
279*8975f5c5SAndroid Build Coastguard Worker                              TExtensionBehavior &ext,
280*8975f5c5SAndroid Build Coastguard Worker                              sh::GLenum type,
281*8975f5c5SAndroid Build Coastguard Worker                              ShShaderSpec spec,
282*8975f5c5SAndroid Build Coastguard Worker                              const ShCompileOptions &options,
283*8975f5c5SAndroid Build Coastguard Worker                              TDiagnostics *diagnostics,
284*8975f5c5SAndroid Build Coastguard Worker                              const ShBuiltInResources &resources,
285*8975f5c5SAndroid Build Coastguard Worker                              ShShaderOutput outputType)
286*8975f5c5SAndroid Build Coastguard Worker     : symbolTable(symt),
287*8975f5c5SAndroid Build Coastguard Worker       mDeferredNonEmptyDeclarationErrorCheck(false),
288*8975f5c5SAndroid Build Coastguard Worker       mShaderType(type),
289*8975f5c5SAndroid Build Coastguard Worker       mShaderSpec(spec),
290*8975f5c5SAndroid Build Coastguard Worker       mCompileOptions(options),
291*8975f5c5SAndroid Build Coastguard Worker       mShaderVersion(100),
292*8975f5c5SAndroid Build Coastguard Worker       mTreeRoot(nullptr),
293*8975f5c5SAndroid Build Coastguard Worker       mLoopNestingLevel(0),
294*8975f5c5SAndroid Build Coastguard Worker       mStructNestingLevel(0),
295*8975f5c5SAndroid Build Coastguard Worker       mSwitchNestingLevel(0),
296*8975f5c5SAndroid Build Coastguard Worker       mCurrentFunctionType(nullptr),
297*8975f5c5SAndroid Build Coastguard Worker       mFunctionReturnsValue(false),
298*8975f5c5SAndroid Build Coastguard Worker       mFragmentPrecisionHighOnESSL1(false),
299*8975f5c5SAndroid Build Coastguard Worker       mEarlyFragmentTestsSpecified(false),
300*8975f5c5SAndroid Build Coastguard Worker       mHasDiscard(false),
301*8975f5c5SAndroid Build Coastguard Worker       mSampleQualifierSpecified(false),
302*8975f5c5SAndroid Build Coastguard Worker       mPositionRedeclaredForSeparateShaderObject(false),
303*8975f5c5SAndroid Build Coastguard Worker       mPointSizeRedeclaredForSeparateShaderObject(false),
304*8975f5c5SAndroid Build Coastguard Worker       mPositionOrPointSizeUsedForSeparateShaderObject(false),
305*8975f5c5SAndroid Build Coastguard Worker       mUsesDerivatives(false),
306*8975f5c5SAndroid Build Coastguard Worker       mDefaultUniformMatrixPacking(EmpColumnMajor),
307*8975f5c5SAndroid Build Coastguard Worker       mDefaultUniformBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
308*8975f5c5SAndroid Build Coastguard Worker       mDefaultBufferMatrixPacking(EmpColumnMajor),
309*8975f5c5SAndroid Build Coastguard Worker       mDefaultBufferBlockStorage(sh::IsWebGLBasedSpec(spec) ? EbsStd140 : EbsShared),
310*8975f5c5SAndroid Build Coastguard Worker       mDiagnostics(diagnostics),
311*8975f5c5SAndroid Build Coastguard Worker       mDirectiveHandler(ext, *mDiagnostics, mShaderVersion, mShaderType),
312*8975f5c5SAndroid Build Coastguard Worker       mPreprocessor(mDiagnostics, &mDirectiveHandler, angle::pp::PreprocessorSettings(spec)),
313*8975f5c5SAndroid Build Coastguard Worker       mScanner(nullptr),
314*8975f5c5SAndroid Build Coastguard Worker       mMaxExpressionComplexity(static_cast<size_t>(options.limitExpressionComplexity
315*8975f5c5SAndroid Build Coastguard Worker                                                        ? resources.MaxExpressionComplexity
316*8975f5c5SAndroid Build Coastguard Worker                                                        : std::numeric_limits<size_t>::max())),
317*8975f5c5SAndroid Build Coastguard Worker       mMaxStatementDepth(static_cast<size_t>(resources.MaxStatementDepth)),
318*8975f5c5SAndroid Build Coastguard Worker       mMinProgramTexelOffset(resources.MinProgramTexelOffset),
319*8975f5c5SAndroid Build Coastguard Worker       mMaxProgramTexelOffset(resources.MaxProgramTexelOffset),
320*8975f5c5SAndroid Build Coastguard Worker       mMinProgramTextureGatherOffset(resources.MinProgramTextureGatherOffset),
321*8975f5c5SAndroid Build Coastguard Worker       mMaxProgramTextureGatherOffset(resources.MaxProgramTextureGatherOffset),
322*8975f5c5SAndroid Build Coastguard Worker       mComputeShaderLocalSizeDeclared(false),
323*8975f5c5SAndroid Build Coastguard Worker       mComputeShaderLocalSize(-1),
324*8975f5c5SAndroid Build Coastguard Worker       mNumViews(-1),
325*8975f5c5SAndroid Build Coastguard Worker       mMaxNumViews(resources.MaxViewsOVR),
326*8975f5c5SAndroid Build Coastguard Worker       mMaxImageUnits(resources.MaxImageUnits),
327*8975f5c5SAndroid Build Coastguard Worker       mMaxCombinedTextureImageUnits(resources.MaxCombinedTextureImageUnits),
328*8975f5c5SAndroid Build Coastguard Worker       mMaxUniformLocations(resources.MaxUniformLocations),
329*8975f5c5SAndroid Build Coastguard Worker       mMaxUniformBufferBindings(resources.MaxUniformBufferBindings),
330*8975f5c5SAndroid Build Coastguard Worker       mMaxVertexAttribs(resources.MaxVertexAttribs),
331*8975f5c5SAndroid Build Coastguard Worker       mMaxAtomicCounterBindings(resources.MaxAtomicCounterBindings),
332*8975f5c5SAndroid Build Coastguard Worker       mMaxAtomicCounterBufferSize(resources.MaxAtomicCounterBufferSize),
333*8975f5c5SAndroid Build Coastguard Worker       mMaxShaderStorageBufferBindings(resources.MaxShaderStorageBufferBindings),
334*8975f5c5SAndroid Build Coastguard Worker       mMaxPixelLocalStoragePlanes(resources.MaxPixelLocalStoragePlanes),
335*8975f5c5SAndroid Build Coastguard Worker       mDeclaringFunction(false),
336*8975f5c5SAndroid Build Coastguard Worker       mGeometryShaderInputPrimitiveType(EptUndefined),
337*8975f5c5SAndroid Build Coastguard Worker       mGeometryShaderOutputPrimitiveType(EptUndefined),
338*8975f5c5SAndroid Build Coastguard Worker       mGeometryShaderInvocations(0),
339*8975f5c5SAndroid Build Coastguard Worker       mGeometryShaderMaxVertices(-1),
340*8975f5c5SAndroid Build Coastguard Worker       mMaxGeometryShaderInvocations(resources.MaxGeometryShaderInvocations),
341*8975f5c5SAndroid Build Coastguard Worker       mMaxGeometryShaderMaxVertices(resources.MaxGeometryOutputVertices),
342*8975f5c5SAndroid Build Coastguard Worker       mGeometryInputArraySize(0),
343*8975f5c5SAndroid Build Coastguard Worker       mMaxPatchVertices(resources.MaxPatchVertices),
344*8975f5c5SAndroid Build Coastguard Worker       mTessControlShaderOutputVertices(0),
345*8975f5c5SAndroid Build Coastguard Worker       mTessEvaluationShaderInputPrimitiveType(EtetUndefined),
346*8975f5c5SAndroid Build Coastguard Worker       mTessEvaluationShaderInputVertexSpacingType(EtetUndefined),
347*8975f5c5SAndroid Build Coastguard Worker       mTessEvaluationShaderInputOrderingType(EtetUndefined),
348*8975f5c5SAndroid Build Coastguard Worker       mTessEvaluationShaderInputPointType(EtetUndefined),
349*8975f5c5SAndroid Build Coastguard Worker       mHasAnyPreciseType(false),
350*8975f5c5SAndroid Build Coastguard Worker       mAdvancedBlendEquations(0),
351*8975f5c5SAndroid Build Coastguard Worker       mFunctionBodyNewScope(false),
352*8975f5c5SAndroid Build Coastguard Worker       mOutputType(outputType)
353*8975f5c5SAndroid Build Coastguard Worker {}
354*8975f5c5SAndroid Build Coastguard Worker 
~TParseContext()355*8975f5c5SAndroid Build Coastguard Worker TParseContext::~TParseContext() {}
356*8975f5c5SAndroid Build Coastguard Worker 
anyMultiviewExtensionAvailable()357*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::anyMultiviewExtensionAvailable()
358*8975f5c5SAndroid Build Coastguard Worker {
359*8975f5c5SAndroid Build Coastguard Worker     return isExtensionEnabled(TExtension::OVR_multiview) ||
360*8975f5c5SAndroid Build Coastguard Worker            isExtensionEnabled(TExtension::OVR_multiview2);
361*8975f5c5SAndroid Build Coastguard Worker }
362*8975f5c5SAndroid Build Coastguard Worker 
parseVectorFields(const TSourceLoc & line,const ImmutableString & compString,int vecSize,TVector<int> * fieldOffsets)363*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::parseVectorFields(const TSourceLoc &line,
364*8975f5c5SAndroid Build Coastguard Worker                                       const ImmutableString &compString,
365*8975f5c5SAndroid Build Coastguard Worker                                       int vecSize,
366*8975f5c5SAndroid Build Coastguard Worker                                       TVector<int> *fieldOffsets)
367*8975f5c5SAndroid Build Coastguard Worker {
368*8975f5c5SAndroid Build Coastguard Worker     ASSERT(fieldOffsets);
369*8975f5c5SAndroid Build Coastguard Worker     size_t fieldCount = compString.length();
370*8975f5c5SAndroid Build Coastguard Worker     if (fieldCount > 4u)
371*8975f5c5SAndroid Build Coastguard Worker     {
372*8975f5c5SAndroid Build Coastguard Worker         error(line, "illegal vector field selection", compString);
373*8975f5c5SAndroid Build Coastguard Worker         return false;
374*8975f5c5SAndroid Build Coastguard Worker     }
375*8975f5c5SAndroid Build Coastguard Worker     fieldOffsets->resize(fieldCount);
376*8975f5c5SAndroid Build Coastguard Worker 
377*8975f5c5SAndroid Build Coastguard Worker     enum
378*8975f5c5SAndroid Build Coastguard Worker     {
379*8975f5c5SAndroid Build Coastguard Worker         exyzw,
380*8975f5c5SAndroid Build Coastguard Worker         ergba,
381*8975f5c5SAndroid Build Coastguard Worker         estpq
382*8975f5c5SAndroid Build Coastguard Worker     } fieldSet[4];
383*8975f5c5SAndroid Build Coastguard Worker 
384*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
385*8975f5c5SAndroid Build Coastguard Worker     {
386*8975f5c5SAndroid Build Coastguard Worker         switch (compString[i])
387*8975f5c5SAndroid Build Coastguard Worker         {
388*8975f5c5SAndroid Build Coastguard Worker             case 'x':
389*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 0;
390*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = exyzw;
391*8975f5c5SAndroid Build Coastguard Worker                 break;
392*8975f5c5SAndroid Build Coastguard Worker             case 'r':
393*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 0;
394*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = ergba;
395*8975f5c5SAndroid Build Coastguard Worker                 break;
396*8975f5c5SAndroid Build Coastguard Worker             case 's':
397*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 0;
398*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = estpq;
399*8975f5c5SAndroid Build Coastguard Worker                 break;
400*8975f5c5SAndroid Build Coastguard Worker             case 'y':
401*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 1;
402*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = exyzw;
403*8975f5c5SAndroid Build Coastguard Worker                 break;
404*8975f5c5SAndroid Build Coastguard Worker             case 'g':
405*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 1;
406*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = ergba;
407*8975f5c5SAndroid Build Coastguard Worker                 break;
408*8975f5c5SAndroid Build Coastguard Worker             case 't':
409*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 1;
410*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = estpq;
411*8975f5c5SAndroid Build Coastguard Worker                 break;
412*8975f5c5SAndroid Build Coastguard Worker             case 'z':
413*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 2;
414*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = exyzw;
415*8975f5c5SAndroid Build Coastguard Worker                 break;
416*8975f5c5SAndroid Build Coastguard Worker             case 'b':
417*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 2;
418*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = ergba;
419*8975f5c5SAndroid Build Coastguard Worker                 break;
420*8975f5c5SAndroid Build Coastguard Worker             case 'p':
421*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 2;
422*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = estpq;
423*8975f5c5SAndroid Build Coastguard Worker                 break;
424*8975f5c5SAndroid Build Coastguard Worker 
425*8975f5c5SAndroid Build Coastguard Worker             case 'w':
426*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 3;
427*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = exyzw;
428*8975f5c5SAndroid Build Coastguard Worker                 break;
429*8975f5c5SAndroid Build Coastguard Worker             case 'a':
430*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 3;
431*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = ergba;
432*8975f5c5SAndroid Build Coastguard Worker                 break;
433*8975f5c5SAndroid Build Coastguard Worker             case 'q':
434*8975f5c5SAndroid Build Coastguard Worker                 (*fieldOffsets)[i] = 3;
435*8975f5c5SAndroid Build Coastguard Worker                 fieldSet[i]        = estpq;
436*8975f5c5SAndroid Build Coastguard Worker                 break;
437*8975f5c5SAndroid Build Coastguard Worker             default:
438*8975f5c5SAndroid Build Coastguard Worker                 error(line, "illegal vector field selection", compString);
439*8975f5c5SAndroid Build Coastguard Worker                 return false;
440*8975f5c5SAndroid Build Coastguard Worker         }
441*8975f5c5SAndroid Build Coastguard Worker     }
442*8975f5c5SAndroid Build Coastguard Worker 
443*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int i = 0u; i < fieldOffsets->size(); ++i)
444*8975f5c5SAndroid Build Coastguard Worker     {
445*8975f5c5SAndroid Build Coastguard Worker         if ((*fieldOffsets)[i] >= vecSize)
446*8975f5c5SAndroid Build Coastguard Worker         {
447*8975f5c5SAndroid Build Coastguard Worker             error(line, "vector field selection out of range", compString);
448*8975f5c5SAndroid Build Coastguard Worker             return false;
449*8975f5c5SAndroid Build Coastguard Worker         }
450*8975f5c5SAndroid Build Coastguard Worker 
451*8975f5c5SAndroid Build Coastguard Worker         if (i > 0)
452*8975f5c5SAndroid Build Coastguard Worker         {
453*8975f5c5SAndroid Build Coastguard Worker             if (fieldSet[i] != fieldSet[i - 1])
454*8975f5c5SAndroid Build Coastguard Worker             {
455*8975f5c5SAndroid Build Coastguard Worker                 error(line, "illegal - vector component fields not from the same set", compString);
456*8975f5c5SAndroid Build Coastguard Worker                 return false;
457*8975f5c5SAndroid Build Coastguard Worker             }
458*8975f5c5SAndroid Build Coastguard Worker         }
459*8975f5c5SAndroid Build Coastguard Worker     }
460*8975f5c5SAndroid Build Coastguard Worker 
461*8975f5c5SAndroid Build Coastguard Worker     return true;
462*8975f5c5SAndroid Build Coastguard Worker }
463*8975f5c5SAndroid Build Coastguard Worker 
464*8975f5c5SAndroid Build Coastguard Worker ///////////////////////////////////////////////////////////////////////
465*8975f5c5SAndroid Build Coastguard Worker //
466*8975f5c5SAndroid Build Coastguard Worker // Errors
467*8975f5c5SAndroid Build Coastguard Worker //
468*8975f5c5SAndroid Build Coastguard Worker ////////////////////////////////////////////////////////////////////////
469*8975f5c5SAndroid Build Coastguard Worker 
470*8975f5c5SAndroid Build Coastguard Worker //
471*8975f5c5SAndroid Build Coastguard Worker // Used by flex/bison to output all syntax and parsing errors.
472*8975f5c5SAndroid Build Coastguard Worker //
error(const TSourceLoc & loc,const char * reason,const char * token)473*8975f5c5SAndroid Build Coastguard Worker void TParseContext::error(const TSourceLoc &loc, const char *reason, const char *token)
474*8975f5c5SAndroid Build Coastguard Worker {
475*8975f5c5SAndroid Build Coastguard Worker     mDiagnostics->error(loc, reason, token);
476*8975f5c5SAndroid Build Coastguard Worker }
477*8975f5c5SAndroid Build Coastguard Worker 
error(const TSourceLoc & loc,const char * reason,const ImmutableString & token)478*8975f5c5SAndroid Build Coastguard Worker void TParseContext::error(const TSourceLoc &loc, const char *reason, const ImmutableString &token)
479*8975f5c5SAndroid Build Coastguard Worker {
480*8975f5c5SAndroid Build Coastguard Worker     mDiagnostics->error(loc, reason, token.data());
481*8975f5c5SAndroid Build Coastguard Worker }
482*8975f5c5SAndroid Build Coastguard Worker 
warning(const TSourceLoc & loc,const char * reason,const char * token)483*8975f5c5SAndroid Build Coastguard Worker void TParseContext::warning(const TSourceLoc &loc, const char *reason, const char *token)
484*8975f5c5SAndroid Build Coastguard Worker {
485*8975f5c5SAndroid Build Coastguard Worker     mDiagnostics->warning(loc, reason, token);
486*8975f5c5SAndroid Build Coastguard Worker }
487*8975f5c5SAndroid Build Coastguard Worker 
errorIfPLSDeclared(const TSourceLoc & loc,PLSIllegalOperations op)488*8975f5c5SAndroid Build Coastguard Worker void TParseContext::errorIfPLSDeclared(const TSourceLoc &loc, PLSIllegalOperations op)
489*8975f5c5SAndroid Build Coastguard Worker {
490*8975f5c5SAndroid Build Coastguard Worker     if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
491*8975f5c5SAndroid Build Coastguard Worker     {
492*8975f5c5SAndroid Build Coastguard Worker         return;
493*8975f5c5SAndroid Build Coastguard Worker     }
494*8975f5c5SAndroid Build Coastguard Worker     if (mPLSFormats.empty())
495*8975f5c5SAndroid Build Coastguard Worker     {
496*8975f5c5SAndroid Build Coastguard Worker         // No pixel local storage uniforms have been declared yet. Remember this potential error in
497*8975f5c5SAndroid Build Coastguard Worker         // case PLS gets declared later.
498*8975f5c5SAndroid Build Coastguard Worker         mPLSPotentialErrors.emplace_back(loc, op);
499*8975f5c5SAndroid Build Coastguard Worker         return;
500*8975f5c5SAndroid Build Coastguard Worker     }
501*8975f5c5SAndroid Build Coastguard Worker     switch (op)
502*8975f5c5SAndroid Build Coastguard Worker     {
503*8975f5c5SAndroid Build Coastguard Worker         case PLSIllegalOperations::Discard:
504*8975f5c5SAndroid Build Coastguard Worker             error(loc, "illegal discard when pixel local storage is declared", "discard");
505*8975f5c5SAndroid Build Coastguard Worker             break;
506*8975f5c5SAndroid Build Coastguard Worker         case PLSIllegalOperations::ReturnFromMain:
507*8975f5c5SAndroid Build Coastguard Worker             error(loc, "illegal return from main when pixel local storage is declared", "return");
508*8975f5c5SAndroid Build Coastguard Worker             break;
509*8975f5c5SAndroid Build Coastguard Worker         case PLSIllegalOperations::AssignFragDepth:
510*8975f5c5SAndroid Build Coastguard Worker             error(loc, "value not assignable when pixel local storage is declared", "gl_FragDepth");
511*8975f5c5SAndroid Build Coastguard Worker             break;
512*8975f5c5SAndroid Build Coastguard Worker         case PLSIllegalOperations::AssignSampleMask:
513*8975f5c5SAndroid Build Coastguard Worker             error(loc, "value not assignable when pixel local storage is declared",
514*8975f5c5SAndroid Build Coastguard Worker                   "gl_SampleMask");
515*8975f5c5SAndroid Build Coastguard Worker             break;
516*8975f5c5SAndroid Build Coastguard Worker         case PLSIllegalOperations::FragDataIndexNonzero:
517*8975f5c5SAndroid Build Coastguard Worker             error(loc, "illegal nonzero index qualifier when pixel local storage is declared",
518*8975f5c5SAndroid Build Coastguard Worker                   "layout");
519*8975f5c5SAndroid Build Coastguard Worker             break;
520*8975f5c5SAndroid Build Coastguard Worker         case PLSIllegalOperations::EnableAdvancedBlendEquation:
521*8975f5c5SAndroid Build Coastguard Worker             error(loc, "illegal advanced blend equation when pixel local storage is declared",
522*8975f5c5SAndroid Build Coastguard Worker                   "layout");
523*8975f5c5SAndroid Build Coastguard Worker             break;
524*8975f5c5SAndroid Build Coastguard Worker     }
525*8975f5c5SAndroid Build Coastguard Worker }
526*8975f5c5SAndroid Build Coastguard Worker 
outOfRangeError(bool isError,const TSourceLoc & loc,const char * reason,const char * token)527*8975f5c5SAndroid Build Coastguard Worker void TParseContext::outOfRangeError(bool isError,
528*8975f5c5SAndroid Build Coastguard Worker                                     const TSourceLoc &loc,
529*8975f5c5SAndroid Build Coastguard Worker                                     const char *reason,
530*8975f5c5SAndroid Build Coastguard Worker                                     const char *token)
531*8975f5c5SAndroid Build Coastguard Worker {
532*8975f5c5SAndroid Build Coastguard Worker     if (isError)
533*8975f5c5SAndroid Build Coastguard Worker     {
534*8975f5c5SAndroid Build Coastguard Worker         error(loc, reason, token);
535*8975f5c5SAndroid Build Coastguard Worker     }
536*8975f5c5SAndroid Build Coastguard Worker     else
537*8975f5c5SAndroid Build Coastguard Worker     {
538*8975f5c5SAndroid Build Coastguard Worker         warning(loc, reason, token);
539*8975f5c5SAndroid Build Coastguard Worker     }
540*8975f5c5SAndroid Build Coastguard Worker }
541*8975f5c5SAndroid Build Coastguard Worker 
setTreeRoot(TIntermBlock * treeRoot)542*8975f5c5SAndroid Build Coastguard Worker void TParseContext::setTreeRoot(TIntermBlock *treeRoot)
543*8975f5c5SAndroid Build Coastguard Worker {
544*8975f5c5SAndroid Build Coastguard Worker     mTreeRoot = treeRoot;
545*8975f5c5SAndroid Build Coastguard Worker     mTreeRoot->setIsTreeRoot();
546*8975f5c5SAndroid Build Coastguard Worker }
547*8975f5c5SAndroid Build Coastguard Worker 
548*8975f5c5SAndroid Build Coastguard Worker //
549*8975f5c5SAndroid Build Coastguard Worker // Same error message for all places assignments don't work.
550*8975f5c5SAndroid Build Coastguard Worker //
assignError(const TSourceLoc & line,const char * op,const TType & left,const TType & right)551*8975f5c5SAndroid Build Coastguard Worker void TParseContext::assignError(const TSourceLoc &line,
552*8975f5c5SAndroid Build Coastguard Worker                                 const char *op,
553*8975f5c5SAndroid Build Coastguard Worker                                 const TType &left,
554*8975f5c5SAndroid Build Coastguard Worker                                 const TType &right)
555*8975f5c5SAndroid Build Coastguard Worker {
556*8975f5c5SAndroid Build Coastguard Worker     TInfoSinkBase reasonStream;
557*8975f5c5SAndroid Build Coastguard Worker     reasonStream << "cannot convert from '" << right << "' to '" << left << "'";
558*8975f5c5SAndroid Build Coastguard Worker     error(line, reasonStream.c_str(), op);
559*8975f5c5SAndroid Build Coastguard Worker }
560*8975f5c5SAndroid Build Coastguard Worker 
561*8975f5c5SAndroid Build Coastguard Worker //
562*8975f5c5SAndroid Build Coastguard Worker // Same error message for all places unary operations don't work.
563*8975f5c5SAndroid Build Coastguard Worker //
unaryOpError(const TSourceLoc & line,const char * op,const TType & operand)564*8975f5c5SAndroid Build Coastguard Worker void TParseContext::unaryOpError(const TSourceLoc &line, const char *op, const TType &operand)
565*8975f5c5SAndroid Build Coastguard Worker {
566*8975f5c5SAndroid Build Coastguard Worker     TInfoSinkBase reasonStream;
567*8975f5c5SAndroid Build Coastguard Worker     reasonStream << "wrong operand type - no operation '" << op
568*8975f5c5SAndroid Build Coastguard Worker                  << "' exists that takes an operand of type " << operand
569*8975f5c5SAndroid Build Coastguard Worker                  << " (or there is no acceptable conversion)";
570*8975f5c5SAndroid Build Coastguard Worker     error(line, reasonStream.c_str(), op);
571*8975f5c5SAndroid Build Coastguard Worker }
572*8975f5c5SAndroid Build Coastguard Worker 
573*8975f5c5SAndroid Build Coastguard Worker //
574*8975f5c5SAndroid Build Coastguard Worker // Same error message for all binary operations don't work.
575*8975f5c5SAndroid Build Coastguard Worker //
binaryOpError(const TSourceLoc & line,const char * op,const TType & left,const TType & right)576*8975f5c5SAndroid Build Coastguard Worker void TParseContext::binaryOpError(const TSourceLoc &line,
577*8975f5c5SAndroid Build Coastguard Worker                                   const char *op,
578*8975f5c5SAndroid Build Coastguard Worker                                   const TType &left,
579*8975f5c5SAndroid Build Coastguard Worker                                   const TType &right)
580*8975f5c5SAndroid Build Coastguard Worker {
581*8975f5c5SAndroid Build Coastguard Worker     TInfoSinkBase reasonStream;
582*8975f5c5SAndroid Build Coastguard Worker     reasonStream << "wrong operand types - no operation '" << op
583*8975f5c5SAndroid Build Coastguard Worker                  << "' exists that takes a left-hand operand of type '" << left
584*8975f5c5SAndroid Build Coastguard Worker                  << "' and a right operand of type '" << right
585*8975f5c5SAndroid Build Coastguard Worker                  << "' (or there is no acceptable conversion)";
586*8975f5c5SAndroid Build Coastguard Worker     error(line, reasonStream.c_str(), op);
587*8975f5c5SAndroid Build Coastguard Worker }
588*8975f5c5SAndroid Build Coastguard Worker 
checkPrecisionSpecified(const TSourceLoc & line,TPrecision precision,TBasicType type)589*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkPrecisionSpecified(const TSourceLoc &line,
590*8975f5c5SAndroid Build Coastguard Worker                                             TPrecision precision,
591*8975f5c5SAndroid Build Coastguard Worker                                             TBasicType type)
592*8975f5c5SAndroid Build Coastguard Worker {
593*8975f5c5SAndroid Build Coastguard Worker     if (precision != EbpUndefined && !SupportsPrecision(type))
594*8975f5c5SAndroid Build Coastguard Worker     {
595*8975f5c5SAndroid Build Coastguard Worker         error(line, "illegal type for precision qualifier", getBasicString(type));
596*8975f5c5SAndroid Build Coastguard Worker     }
597*8975f5c5SAndroid Build Coastguard Worker 
598*8975f5c5SAndroid Build Coastguard Worker     if (precision == EbpUndefined)
599*8975f5c5SAndroid Build Coastguard Worker     {
600*8975f5c5SAndroid Build Coastguard Worker         switch (type)
601*8975f5c5SAndroid Build Coastguard Worker         {
602*8975f5c5SAndroid Build Coastguard Worker             case EbtFloat:
603*8975f5c5SAndroid Build Coastguard Worker                 error(line, "No precision specified for (float)", "");
604*8975f5c5SAndroid Build Coastguard Worker                 return;
605*8975f5c5SAndroid Build Coastguard Worker             case EbtInt:
606*8975f5c5SAndroid Build Coastguard Worker             case EbtUInt:
607*8975f5c5SAndroid Build Coastguard Worker                 UNREACHABLE();  // there's always a predeclared qualifier
608*8975f5c5SAndroid Build Coastguard Worker                 error(line, "No precision specified (int)", "");
609*8975f5c5SAndroid Build Coastguard Worker                 return;
610*8975f5c5SAndroid Build Coastguard Worker             default:
611*8975f5c5SAndroid Build Coastguard Worker                 if (IsOpaqueType(type))
612*8975f5c5SAndroid Build Coastguard Worker                 {
613*8975f5c5SAndroid Build Coastguard Worker                     error(line, "No precision specified", getBasicString(type));
614*8975f5c5SAndroid Build Coastguard Worker                     return;
615*8975f5c5SAndroid Build Coastguard Worker                 }
616*8975f5c5SAndroid Build Coastguard Worker         }
617*8975f5c5SAndroid Build Coastguard Worker     }
618*8975f5c5SAndroid Build Coastguard Worker }
619*8975f5c5SAndroid Build Coastguard Worker 
markStaticReadIfSymbol(TIntermNode * node)620*8975f5c5SAndroid Build Coastguard Worker void TParseContext::markStaticReadIfSymbol(TIntermNode *node)
621*8975f5c5SAndroid Build Coastguard Worker {
622*8975f5c5SAndroid Build Coastguard Worker     TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
623*8975f5c5SAndroid Build Coastguard Worker     if (swizzleNode)
624*8975f5c5SAndroid Build Coastguard Worker     {
625*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(swizzleNode->getOperand());
626*8975f5c5SAndroid Build Coastguard Worker         return;
627*8975f5c5SAndroid Build Coastguard Worker     }
628*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *binaryNode = node->getAsBinaryNode();
629*8975f5c5SAndroid Build Coastguard Worker     if (binaryNode)
630*8975f5c5SAndroid Build Coastguard Worker     {
631*8975f5c5SAndroid Build Coastguard Worker         switch (binaryNode->getOp())
632*8975f5c5SAndroid Build Coastguard Worker         {
633*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirect:
634*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexIndirect:
635*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirectStruct:
636*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirectInterfaceBlock:
637*8975f5c5SAndroid Build Coastguard Worker                 markStaticReadIfSymbol(binaryNode->getLeft());
638*8975f5c5SAndroid Build Coastguard Worker                 return;
639*8975f5c5SAndroid Build Coastguard Worker             default:
640*8975f5c5SAndroid Build Coastguard Worker                 return;
641*8975f5c5SAndroid Build Coastguard Worker         }
642*8975f5c5SAndroid Build Coastguard Worker     }
643*8975f5c5SAndroid Build Coastguard Worker     TIntermSymbol *symbolNode = node->getAsSymbolNode();
644*8975f5c5SAndroid Build Coastguard Worker     if (symbolNode)
645*8975f5c5SAndroid Build Coastguard Worker     {
646*8975f5c5SAndroid Build Coastguard Worker         symbolTable.markStaticRead(symbolNode->variable());
647*8975f5c5SAndroid Build Coastguard Worker     }
648*8975f5c5SAndroid Build Coastguard Worker }
649*8975f5c5SAndroid Build Coastguard Worker 
650*8975f5c5SAndroid Build Coastguard Worker // Both test and if necessary, spit out an error, to see if the node is really
651*8975f5c5SAndroid Build Coastguard Worker // an l-value that can be operated on this way.
checkCanBeLValue(const TSourceLoc & line,const char * op,TIntermTyped * node)652*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkCanBeLValue(const TSourceLoc &line, const char *op, TIntermTyped *node)
653*8975f5c5SAndroid Build Coastguard Worker {
654*8975f5c5SAndroid Build Coastguard Worker     TIntermSwizzle *swizzleNode = node->getAsSwizzleNode();
655*8975f5c5SAndroid Build Coastguard Worker     if (swizzleNode)
656*8975f5c5SAndroid Build Coastguard Worker     {
657*8975f5c5SAndroid Build Coastguard Worker         bool ok = checkCanBeLValue(line, op, swizzleNode->getOperand());
658*8975f5c5SAndroid Build Coastguard Worker         if (ok && swizzleNode->hasDuplicateOffsets())
659*8975f5c5SAndroid Build Coastguard Worker         {
660*8975f5c5SAndroid Build Coastguard Worker             error(line, " l-value of swizzle cannot have duplicate components", op);
661*8975f5c5SAndroid Build Coastguard Worker             return false;
662*8975f5c5SAndroid Build Coastguard Worker         }
663*8975f5c5SAndroid Build Coastguard Worker         return ok;
664*8975f5c5SAndroid Build Coastguard Worker     }
665*8975f5c5SAndroid Build Coastguard Worker 
666*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *binaryNode = node->getAsBinaryNode();
667*8975f5c5SAndroid Build Coastguard Worker     if (binaryNode)
668*8975f5c5SAndroid Build Coastguard Worker     {
669*8975f5c5SAndroid Build Coastguard Worker         switch (binaryNode->getOp())
670*8975f5c5SAndroid Build Coastguard Worker         {
671*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirect:
672*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexIndirect:
673*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirectStruct:
674*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirectInterfaceBlock:
675*8975f5c5SAndroid Build Coastguard Worker                 if (node->getMemoryQualifier().readonly)
676*8975f5c5SAndroid Build Coastguard Worker                 {
677*8975f5c5SAndroid Build Coastguard Worker                     error(line, "can't modify a readonly variable", op);
678*8975f5c5SAndroid Build Coastguard Worker                     return false;
679*8975f5c5SAndroid Build Coastguard Worker                 }
680*8975f5c5SAndroid Build Coastguard Worker                 return checkCanBeLValue(line, op, binaryNode->getLeft());
681*8975f5c5SAndroid Build Coastguard Worker             default:
682*8975f5c5SAndroid Build Coastguard Worker                 break;
683*8975f5c5SAndroid Build Coastguard Worker         }
684*8975f5c5SAndroid Build Coastguard Worker         error(line, " l-value required", op);
685*8975f5c5SAndroid Build Coastguard Worker         return false;
686*8975f5c5SAndroid Build Coastguard Worker     }
687*8975f5c5SAndroid Build Coastguard Worker 
688*8975f5c5SAndroid Build Coastguard Worker     std::string message;
689*8975f5c5SAndroid Build Coastguard Worker     switch (node->getQualifier())
690*8975f5c5SAndroid Build Coastguard Worker     {
691*8975f5c5SAndroid Build Coastguard Worker         case EvqConst:
692*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify a const";
693*8975f5c5SAndroid Build Coastguard Worker             break;
694*8975f5c5SAndroid Build Coastguard Worker         case EvqParamConst:
695*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify a const";
696*8975f5c5SAndroid Build Coastguard Worker             break;
697*8975f5c5SAndroid Build Coastguard Worker         case EvqAttribute:
698*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify an attribute";
699*8975f5c5SAndroid Build Coastguard Worker             break;
700*8975f5c5SAndroid Build Coastguard Worker         case EvqFragmentIn:
701*8975f5c5SAndroid Build Coastguard Worker         case EvqVertexIn:
702*8975f5c5SAndroid Build Coastguard Worker         case EvqGeometryIn:
703*8975f5c5SAndroid Build Coastguard Worker         case EvqTessControlIn:
704*8975f5c5SAndroid Build Coastguard Worker         case EvqTessEvaluationIn:
705*8975f5c5SAndroid Build Coastguard Worker         case EvqSmoothIn:
706*8975f5c5SAndroid Build Coastguard Worker         case EvqFlatIn:
707*8975f5c5SAndroid Build Coastguard Worker         case EvqNoPerspectiveIn:
708*8975f5c5SAndroid Build Coastguard Worker         case EvqCentroidIn:
709*8975f5c5SAndroid Build Coastguard Worker         case EvqSampleIn:
710*8975f5c5SAndroid Build Coastguard Worker         case EvqNoPerspectiveCentroidIn:
711*8975f5c5SAndroid Build Coastguard Worker         case EvqNoPerspectiveSampleIn:
712*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify an input";
713*8975f5c5SAndroid Build Coastguard Worker             break;
714*8975f5c5SAndroid Build Coastguard Worker         case EvqUniform:
715*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify a uniform";
716*8975f5c5SAndroid Build Coastguard Worker             break;
717*8975f5c5SAndroid Build Coastguard Worker         case EvqVaryingIn:
718*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify a varying";
719*8975f5c5SAndroid Build Coastguard Worker             break;
720*8975f5c5SAndroid Build Coastguard Worker         case EvqFragCoord:
721*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_FragCoord";
722*8975f5c5SAndroid Build Coastguard Worker             break;
723*8975f5c5SAndroid Build Coastguard Worker         case EvqFrontFacing:
724*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_FrontFacing";
725*8975f5c5SAndroid Build Coastguard Worker             break;
726*8975f5c5SAndroid Build Coastguard Worker         case EvqHelperInvocation:
727*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_HelperInvocation";
728*8975f5c5SAndroid Build Coastguard Worker             break;
729*8975f5c5SAndroid Build Coastguard Worker         case EvqPointCoord:
730*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_PointCoord";
731*8975f5c5SAndroid Build Coastguard Worker             break;
732*8975f5c5SAndroid Build Coastguard Worker         case EvqNumWorkGroups:
733*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_NumWorkGroups";
734*8975f5c5SAndroid Build Coastguard Worker             break;
735*8975f5c5SAndroid Build Coastguard Worker         case EvqWorkGroupSize:
736*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_WorkGroupSize";
737*8975f5c5SAndroid Build Coastguard Worker             break;
738*8975f5c5SAndroid Build Coastguard Worker         case EvqWorkGroupID:
739*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_WorkGroupID";
740*8975f5c5SAndroid Build Coastguard Worker             break;
741*8975f5c5SAndroid Build Coastguard Worker         case EvqLocalInvocationID:
742*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_LocalInvocationID";
743*8975f5c5SAndroid Build Coastguard Worker             break;
744*8975f5c5SAndroid Build Coastguard Worker         case EvqGlobalInvocationID:
745*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_GlobalInvocationID";
746*8975f5c5SAndroid Build Coastguard Worker             break;
747*8975f5c5SAndroid Build Coastguard Worker         case EvqLocalInvocationIndex:
748*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_LocalInvocationIndex";
749*8975f5c5SAndroid Build Coastguard Worker             break;
750*8975f5c5SAndroid Build Coastguard Worker         case EvqViewIDOVR:
751*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_ViewID_OVR";
752*8975f5c5SAndroid Build Coastguard Worker             break;
753*8975f5c5SAndroid Build Coastguard Worker         case EvqComputeIn:
754*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify work group size variable";
755*8975f5c5SAndroid Build Coastguard Worker             break;
756*8975f5c5SAndroid Build Coastguard Worker         case EvqPerVertexIn:
757*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify any member in gl_in";
758*8975f5c5SAndroid Build Coastguard Worker             break;
759*8975f5c5SAndroid Build Coastguard Worker         case EvqPrimitiveIDIn:
760*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_PrimitiveIDIn";
761*8975f5c5SAndroid Build Coastguard Worker             break;
762*8975f5c5SAndroid Build Coastguard Worker         case EvqInvocationID:
763*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_InvocationID";
764*8975f5c5SAndroid Build Coastguard Worker             break;
765*8975f5c5SAndroid Build Coastguard Worker         case EvqPrimitiveID:
766*8975f5c5SAndroid Build Coastguard Worker             if (mShaderType == GL_FRAGMENT_SHADER)
767*8975f5c5SAndroid Build Coastguard Worker             {
768*8975f5c5SAndroid Build Coastguard Worker                 message = "can't modify gl_PrimitiveID in a fragment shader";
769*8975f5c5SAndroid Build Coastguard Worker             }
770*8975f5c5SAndroid Build Coastguard Worker             break;
771*8975f5c5SAndroid Build Coastguard Worker         case EvqLayerIn:
772*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_Layer in a fragment shader";
773*8975f5c5SAndroid Build Coastguard Worker             break;
774*8975f5c5SAndroid Build Coastguard Worker         case EvqSampleID:
775*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_SampleID";
776*8975f5c5SAndroid Build Coastguard Worker             break;
777*8975f5c5SAndroid Build Coastguard Worker         case EvqSampleMaskIn:
778*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_SampleMaskIn";
779*8975f5c5SAndroid Build Coastguard Worker             break;
780*8975f5c5SAndroid Build Coastguard Worker         case EvqSamplePosition:
781*8975f5c5SAndroid Build Coastguard Worker             message = "can't modify gl_SamplePosition";
782*8975f5c5SAndroid Build Coastguard Worker             break;
783*8975f5c5SAndroid Build Coastguard Worker         case EvqClipDistance:
784*8975f5c5SAndroid Build Coastguard Worker             if (mShaderType == GL_FRAGMENT_SHADER)
785*8975f5c5SAndroid Build Coastguard Worker             {
786*8975f5c5SAndroid Build Coastguard Worker                 message = "can't modify gl_ClipDistance in a fragment shader";
787*8975f5c5SAndroid Build Coastguard Worker             }
788*8975f5c5SAndroid Build Coastguard Worker             break;
789*8975f5c5SAndroid Build Coastguard Worker         case EvqCullDistance:
790*8975f5c5SAndroid Build Coastguard Worker             if (mShaderType == GL_FRAGMENT_SHADER)
791*8975f5c5SAndroid Build Coastguard Worker             {
792*8975f5c5SAndroid Build Coastguard Worker                 message = "can't modify gl_CullDistance in a fragment shader";
793*8975f5c5SAndroid Build Coastguard Worker             }
794*8975f5c5SAndroid Build Coastguard Worker             break;
795*8975f5c5SAndroid Build Coastguard Worker         case EvqFragDepth:
796*8975f5c5SAndroid Build Coastguard Worker             errorIfPLSDeclared(line, PLSIllegalOperations::AssignFragDepth);
797*8975f5c5SAndroid Build Coastguard Worker             break;
798*8975f5c5SAndroid Build Coastguard Worker         case EvqSampleMask:
799*8975f5c5SAndroid Build Coastguard Worker             errorIfPLSDeclared(line, PLSIllegalOperations::AssignSampleMask);
800*8975f5c5SAndroid Build Coastguard Worker             break;
801*8975f5c5SAndroid Build Coastguard Worker         default:
802*8975f5c5SAndroid Build Coastguard Worker             //
803*8975f5c5SAndroid Build Coastguard Worker             // Type that can't be written to?
804*8975f5c5SAndroid Build Coastguard Worker             //
805*8975f5c5SAndroid Build Coastguard Worker             if (node->getBasicType() == EbtVoid)
806*8975f5c5SAndroid Build Coastguard Worker             {
807*8975f5c5SAndroid Build Coastguard Worker                 message = "can't modify void";
808*8975f5c5SAndroid Build Coastguard Worker             }
809*8975f5c5SAndroid Build Coastguard Worker             if (IsOpaqueType(node->getBasicType()))
810*8975f5c5SAndroid Build Coastguard Worker             {
811*8975f5c5SAndroid Build Coastguard Worker                 message = "can't modify a variable with type ";
812*8975f5c5SAndroid Build Coastguard Worker                 message += getBasicString(node->getBasicType());
813*8975f5c5SAndroid Build Coastguard Worker             }
814*8975f5c5SAndroid Build Coastguard Worker             else if (node->getMemoryQualifier().readonly)
815*8975f5c5SAndroid Build Coastguard Worker             {
816*8975f5c5SAndroid Build Coastguard Worker                 message = "can't modify a readonly variable";
817*8975f5c5SAndroid Build Coastguard Worker             }
818*8975f5c5SAndroid Build Coastguard Worker     }
819*8975f5c5SAndroid Build Coastguard Worker 
820*8975f5c5SAndroid Build Coastguard Worker     ASSERT(binaryNode == nullptr && swizzleNode == nullptr);
821*8975f5c5SAndroid Build Coastguard Worker     TIntermSymbol *symNode = node->getAsSymbolNode();
822*8975f5c5SAndroid Build Coastguard Worker     if (message.empty() && symNode != nullptr)
823*8975f5c5SAndroid Build Coastguard Worker     {
824*8975f5c5SAndroid Build Coastguard Worker         symbolTable.markStaticWrite(symNode->variable());
825*8975f5c5SAndroid Build Coastguard Worker         return true;
826*8975f5c5SAndroid Build Coastguard Worker     }
827*8975f5c5SAndroid Build Coastguard Worker 
828*8975f5c5SAndroid Build Coastguard Worker     std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
829*8975f5c5SAndroid Build Coastguard Worker     reasonStream << "l-value required";
830*8975f5c5SAndroid Build Coastguard Worker     if (!message.empty())
831*8975f5c5SAndroid Build Coastguard Worker     {
832*8975f5c5SAndroid Build Coastguard Worker         if (symNode)
833*8975f5c5SAndroid Build Coastguard Worker         {
834*8975f5c5SAndroid Build Coastguard Worker             // Symbol inside an expression can't be nameless.
835*8975f5c5SAndroid Build Coastguard Worker             ASSERT(symNode->variable().symbolType() != SymbolType::Empty);
836*8975f5c5SAndroid Build Coastguard Worker             const ImmutableString &symbol = symNode->getName();
837*8975f5c5SAndroid Build Coastguard Worker             reasonStream << " (" << message << " \"" << symbol << "\")";
838*8975f5c5SAndroid Build Coastguard Worker         }
839*8975f5c5SAndroid Build Coastguard Worker         else
840*8975f5c5SAndroid Build Coastguard Worker         {
841*8975f5c5SAndroid Build Coastguard Worker             reasonStream << " (" << message << ")";
842*8975f5c5SAndroid Build Coastguard Worker         }
843*8975f5c5SAndroid Build Coastguard Worker     }
844*8975f5c5SAndroid Build Coastguard Worker     std::string reason = reasonStream.str();
845*8975f5c5SAndroid Build Coastguard Worker     error(line, reason.c_str(), op);
846*8975f5c5SAndroid Build Coastguard Worker 
847*8975f5c5SAndroid Build Coastguard Worker     return false;
848*8975f5c5SAndroid Build Coastguard Worker }
849*8975f5c5SAndroid Build Coastguard Worker 
850*8975f5c5SAndroid Build Coastguard Worker // Both test, and if necessary spit out an error, to see if the node is really
851*8975f5c5SAndroid Build Coastguard Worker // a constant.
checkIsConst(TIntermTyped * node)852*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkIsConst(TIntermTyped *node)
853*8975f5c5SAndroid Build Coastguard Worker {
854*8975f5c5SAndroid Build Coastguard Worker     if (node->getQualifier() != EvqConst)
855*8975f5c5SAndroid Build Coastguard Worker     {
856*8975f5c5SAndroid Build Coastguard Worker         error(node->getLine(), "constant expression required", "");
857*8975f5c5SAndroid Build Coastguard Worker     }
858*8975f5c5SAndroid Build Coastguard Worker }
859*8975f5c5SAndroid Build Coastguard Worker 
860*8975f5c5SAndroid Build Coastguard Worker // Both test, and if necessary spit out an error, to see if the node is really
861*8975f5c5SAndroid Build Coastguard Worker // an integer.
checkIsScalarInteger(TIntermTyped * node,const char * token)862*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkIsScalarInteger(TIntermTyped *node, const char *token)
863*8975f5c5SAndroid Build Coastguard Worker {
864*8975f5c5SAndroid Build Coastguard Worker     if (!node->isScalarInt())
865*8975f5c5SAndroid Build Coastguard Worker     {
866*8975f5c5SAndroid Build Coastguard Worker         error(node->getLine(), "integer expression required", token);
867*8975f5c5SAndroid Build Coastguard Worker     }
868*8975f5c5SAndroid Build Coastguard Worker }
869*8975f5c5SAndroid Build Coastguard Worker 
870*8975f5c5SAndroid Build Coastguard Worker // Both test, and if necessary spit out an error, to see if we are currently
871*8975f5c5SAndroid Build Coastguard Worker // globally scoped.
checkIsAtGlobalLevel(const TSourceLoc & line,const char * token)872*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkIsAtGlobalLevel(const TSourceLoc &line, const char *token)
873*8975f5c5SAndroid Build Coastguard Worker {
874*8975f5c5SAndroid Build Coastguard Worker     if (!symbolTable.atGlobalLevel())
875*8975f5c5SAndroid Build Coastguard Worker     {
876*8975f5c5SAndroid Build Coastguard Worker         error(line, "only allowed at global scope", token);
877*8975f5c5SAndroid Build Coastguard Worker         return false;
878*8975f5c5SAndroid Build Coastguard Worker     }
879*8975f5c5SAndroid Build Coastguard Worker     return true;
880*8975f5c5SAndroid Build Coastguard Worker }
881*8975f5c5SAndroid Build Coastguard Worker 
checkIsValidExpressionStatement(const TSourceLoc & line,TIntermTyped * expr)882*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkIsValidExpressionStatement(const TSourceLoc &line, TIntermTyped *expr)
883*8975f5c5SAndroid Build Coastguard Worker {
884*8975f5c5SAndroid Build Coastguard Worker     if (expr->isInterfaceBlock())
885*8975f5c5SAndroid Build Coastguard Worker     {
886*8975f5c5SAndroid Build Coastguard Worker         error(line, "expression statement is not allowed for interface blocks", "");
887*8975f5c5SAndroid Build Coastguard Worker     }
888*8975f5c5SAndroid Build Coastguard Worker }
889*8975f5c5SAndroid Build Coastguard Worker 
890*8975f5c5SAndroid Build Coastguard Worker // ESSL 3.00.5 sections 3.8 and 3.9.
891*8975f5c5SAndroid Build Coastguard Worker // If it starts "gl_" or contains two consecutive underscores, it's reserved.
892*8975f5c5SAndroid Build Coastguard Worker // Also checks for "webgl_" and "_webgl_" reserved identifiers if parsing a webgl shader.
checkIsNotReserved(const TSourceLoc & line,const ImmutableString & identifier)893*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkIsNotReserved(const TSourceLoc &line, const ImmutableString &identifier)
894*8975f5c5SAndroid Build Coastguard Worker {
895*8975f5c5SAndroid Build Coastguard Worker     static const char *reservedErrMsg = "reserved built-in name";
896*8975f5c5SAndroid Build Coastguard Worker     if (gl::IsBuiltInName(identifier.data()))
897*8975f5c5SAndroid Build Coastguard Worker     {
898*8975f5c5SAndroid Build Coastguard Worker         error(line, reservedErrMsg, "gl_");
899*8975f5c5SAndroid Build Coastguard Worker         return false;
900*8975f5c5SAndroid Build Coastguard Worker     }
901*8975f5c5SAndroid Build Coastguard Worker     if (sh::IsWebGLBasedSpec(mShaderSpec))
902*8975f5c5SAndroid Build Coastguard Worker     {
903*8975f5c5SAndroid Build Coastguard Worker         if (identifier.beginsWith("webgl_"))
904*8975f5c5SAndroid Build Coastguard Worker         {
905*8975f5c5SAndroid Build Coastguard Worker             error(line, reservedErrMsg, "webgl_");
906*8975f5c5SAndroid Build Coastguard Worker             return false;
907*8975f5c5SAndroid Build Coastguard Worker         }
908*8975f5c5SAndroid Build Coastguard Worker         if (identifier.beginsWith("_webgl_"))
909*8975f5c5SAndroid Build Coastguard Worker         {
910*8975f5c5SAndroid Build Coastguard Worker             error(line, reservedErrMsg, "_webgl_");
911*8975f5c5SAndroid Build Coastguard Worker             return false;
912*8975f5c5SAndroid Build Coastguard Worker         }
913*8975f5c5SAndroid Build Coastguard Worker     }
914*8975f5c5SAndroid Build Coastguard Worker     if (identifier.contains("__"))
915*8975f5c5SAndroid Build Coastguard Worker     {
916*8975f5c5SAndroid Build Coastguard Worker         if (sh::IsWebGLBasedSpec(mShaderSpec))
917*8975f5c5SAndroid Build Coastguard Worker         {
918*8975f5c5SAndroid Build Coastguard Worker             error(line,
919*8975f5c5SAndroid Build Coastguard Worker                   "identifiers containing two consecutive underscores (__) are reserved as "
920*8975f5c5SAndroid Build Coastguard Worker                   "possible future keywords",
921*8975f5c5SAndroid Build Coastguard Worker                   identifier);
922*8975f5c5SAndroid Build Coastguard Worker             return false;
923*8975f5c5SAndroid Build Coastguard Worker         }
924*8975f5c5SAndroid Build Coastguard Worker         else
925*8975f5c5SAndroid Build Coastguard Worker         {
926*8975f5c5SAndroid Build Coastguard Worker             // Using double underscores is allowed, but may result in unintended behaviors, so a
927*8975f5c5SAndroid Build Coastguard Worker             // warning is issued.
928*8975f5c5SAndroid Build Coastguard Worker             // OpenGL ES Shader Language 3.2 specification:
929*8975f5c5SAndroid Build Coastguard Worker             // > 3.7. Keywords
930*8975f5c5SAndroid Build Coastguard Worker             // > ...
931*8975f5c5SAndroid Build Coastguard Worker             // > In addition, all identifiers containing two consecutive underscores (__) are
932*8975f5c5SAndroid Build Coastguard Worker             // > reserved for use by underlying software layers. Defining such a name in a shader
933*8975f5c5SAndroid Build Coastguard Worker             // > does not itself result in an error, but may result in unintended behaviors that
934*8975f5c5SAndroid Build Coastguard Worker             // > stem from having multiple definitions of the same name.
935*8975f5c5SAndroid Build Coastguard Worker             warning(line,
936*8975f5c5SAndroid Build Coastguard Worker                     "all identifiers containing two consecutive underscores (__) are reserved - "
937*8975f5c5SAndroid Build Coastguard Worker                     "unintented behaviors are possible",
938*8975f5c5SAndroid Build Coastguard Worker                     identifier.data());
939*8975f5c5SAndroid Build Coastguard Worker         }
940*8975f5c5SAndroid Build Coastguard Worker     }
941*8975f5c5SAndroid Build Coastguard Worker     return true;
942*8975f5c5SAndroid Build Coastguard Worker }
943*8975f5c5SAndroid Build Coastguard Worker 
944*8975f5c5SAndroid Build Coastguard Worker // Make sure the argument types are correct for constructing a specific type.
checkConstructorArguments(const TSourceLoc & line,const TIntermSequence & arguments,const TType & type)945*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkConstructorArguments(const TSourceLoc &line,
946*8975f5c5SAndroid Build Coastguard Worker                                               const TIntermSequence &arguments,
947*8975f5c5SAndroid Build Coastguard Worker                                               const TType &type)
948*8975f5c5SAndroid Build Coastguard Worker {
949*8975f5c5SAndroid Build Coastguard Worker     if (arguments.empty())
950*8975f5c5SAndroid Build Coastguard Worker     {
951*8975f5c5SAndroid Build Coastguard Worker         error(line, "constructor does not have any arguments", "constructor");
952*8975f5c5SAndroid Build Coastguard Worker         return false;
953*8975f5c5SAndroid Build Coastguard Worker     }
954*8975f5c5SAndroid Build Coastguard Worker 
955*8975f5c5SAndroid Build Coastguard Worker     for (TIntermNode *arg : arguments)
956*8975f5c5SAndroid Build Coastguard Worker     {
957*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(arg);
958*8975f5c5SAndroid Build Coastguard Worker         const TIntermTyped *argTyped = arg->getAsTyped();
959*8975f5c5SAndroid Build Coastguard Worker         ASSERT(argTyped != nullptr);
960*8975f5c5SAndroid Build Coastguard Worker         if (type.getBasicType() != EbtStruct && IsOpaqueType(argTyped->getBasicType()))
961*8975f5c5SAndroid Build Coastguard Worker         {
962*8975f5c5SAndroid Build Coastguard Worker             std::string reason("cannot convert a variable with type ");
963*8975f5c5SAndroid Build Coastguard Worker             reason += getBasicString(argTyped->getBasicType());
964*8975f5c5SAndroid Build Coastguard Worker             error(line, reason.c_str(), "constructor");
965*8975f5c5SAndroid Build Coastguard Worker             return false;
966*8975f5c5SAndroid Build Coastguard Worker         }
967*8975f5c5SAndroid Build Coastguard Worker         else if (argTyped->getMemoryQualifier().writeonly)
968*8975f5c5SAndroid Build Coastguard Worker         {
969*8975f5c5SAndroid Build Coastguard Worker             error(line, "cannot convert a variable with writeonly", "constructor");
970*8975f5c5SAndroid Build Coastguard Worker             return false;
971*8975f5c5SAndroid Build Coastguard Worker         }
972*8975f5c5SAndroid Build Coastguard Worker         if (argTyped->getBasicType() == EbtVoid)
973*8975f5c5SAndroid Build Coastguard Worker         {
974*8975f5c5SAndroid Build Coastguard Worker             error(line, "cannot convert a void", "constructor");
975*8975f5c5SAndroid Build Coastguard Worker             return false;
976*8975f5c5SAndroid Build Coastguard Worker         }
977*8975f5c5SAndroid Build Coastguard Worker     }
978*8975f5c5SAndroid Build Coastguard Worker 
979*8975f5c5SAndroid Build Coastguard Worker     if (type.isArray())
980*8975f5c5SAndroid Build Coastguard Worker     {
981*8975f5c5SAndroid Build Coastguard Worker         // The size of an unsized constructor should already have been determined.
982*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!type.isUnsizedArray());
983*8975f5c5SAndroid Build Coastguard Worker         if (static_cast<size_t>(type.getOutermostArraySize()) != arguments.size())
984*8975f5c5SAndroid Build Coastguard Worker         {
985*8975f5c5SAndroid Build Coastguard Worker             error(line, "array constructor needs one argument per array element", "constructor");
986*8975f5c5SAndroid Build Coastguard Worker             return false;
987*8975f5c5SAndroid Build Coastguard Worker         }
988*8975f5c5SAndroid Build Coastguard Worker         // GLSL ES 3.00 section 5.4.4: Each argument must be the same type as the element type of
989*8975f5c5SAndroid Build Coastguard Worker         // the array.
990*8975f5c5SAndroid Build Coastguard Worker         for (TIntermNode *const &argNode : arguments)
991*8975f5c5SAndroid Build Coastguard Worker         {
992*8975f5c5SAndroid Build Coastguard Worker             const TType &argType = argNode->getAsTyped()->getType();
993*8975f5c5SAndroid Build Coastguard Worker             if (mShaderVersion < 310 && argType.isArray())
994*8975f5c5SAndroid Build Coastguard Worker             {
995*8975f5c5SAndroid Build Coastguard Worker                 error(line, "constructing from a non-dereferenced array", "constructor");
996*8975f5c5SAndroid Build Coastguard Worker                 return false;
997*8975f5c5SAndroid Build Coastguard Worker             }
998*8975f5c5SAndroid Build Coastguard Worker             if (!argType.isElementTypeOf(type))
999*8975f5c5SAndroid Build Coastguard Worker             {
1000*8975f5c5SAndroid Build Coastguard Worker                 error(line, "Array constructor argument has an incorrect type", "constructor");
1001*8975f5c5SAndroid Build Coastguard Worker                 return false;
1002*8975f5c5SAndroid Build Coastguard Worker             }
1003*8975f5c5SAndroid Build Coastguard Worker         }
1004*8975f5c5SAndroid Build Coastguard Worker     }
1005*8975f5c5SAndroid Build Coastguard Worker     else if (type.getBasicType() == EbtStruct)
1006*8975f5c5SAndroid Build Coastguard Worker     {
1007*8975f5c5SAndroid Build Coastguard Worker         const TFieldList &fields = type.getStruct()->fields();
1008*8975f5c5SAndroid Build Coastguard Worker         if (fields.size() != arguments.size())
1009*8975f5c5SAndroid Build Coastguard Worker         {
1010*8975f5c5SAndroid Build Coastguard Worker             error(line,
1011*8975f5c5SAndroid Build Coastguard Worker                   "Number of constructor parameters does not match the number of structure fields",
1012*8975f5c5SAndroid Build Coastguard Worker                   "constructor");
1013*8975f5c5SAndroid Build Coastguard Worker             return false;
1014*8975f5c5SAndroid Build Coastguard Worker         }
1015*8975f5c5SAndroid Build Coastguard Worker 
1016*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0; i < fields.size(); i++)
1017*8975f5c5SAndroid Build Coastguard Worker         {
1018*8975f5c5SAndroid Build Coastguard Worker             if (i >= arguments.size() ||
1019*8975f5c5SAndroid Build Coastguard Worker                 arguments[i]->getAsTyped()->getType() != *fields[i]->type())
1020*8975f5c5SAndroid Build Coastguard Worker             {
1021*8975f5c5SAndroid Build Coastguard Worker                 error(line, "Structure constructor arguments do not match structure fields",
1022*8975f5c5SAndroid Build Coastguard Worker                       "constructor");
1023*8975f5c5SAndroid Build Coastguard Worker                 return false;
1024*8975f5c5SAndroid Build Coastguard Worker             }
1025*8975f5c5SAndroid Build Coastguard Worker         }
1026*8975f5c5SAndroid Build Coastguard Worker     }
1027*8975f5c5SAndroid Build Coastguard Worker     else
1028*8975f5c5SAndroid Build Coastguard Worker     {
1029*8975f5c5SAndroid Build Coastguard Worker         // We're constructing a scalar, vector, or matrix.
1030*8975f5c5SAndroid Build Coastguard Worker 
1031*8975f5c5SAndroid Build Coastguard Worker         // Note: It's okay to have too many components available, but not okay to have unused
1032*8975f5c5SAndroid Build Coastguard Worker         // arguments. 'full' will go to true when enough args have been seen. If we loop again,
1033*8975f5c5SAndroid Build Coastguard Worker         // there is an extra argument, so 'overFull' will become true.
1034*8975f5c5SAndroid Build Coastguard Worker 
1035*8975f5c5SAndroid Build Coastguard Worker         size_t size    = 0;
1036*8975f5c5SAndroid Build Coastguard Worker         bool full      = false;
1037*8975f5c5SAndroid Build Coastguard Worker         bool overFull  = false;
1038*8975f5c5SAndroid Build Coastguard Worker         bool matrixArg = false;
1039*8975f5c5SAndroid Build Coastguard Worker         for (TIntermNode *arg : arguments)
1040*8975f5c5SAndroid Build Coastguard Worker         {
1041*8975f5c5SAndroid Build Coastguard Worker             const TIntermTyped *argTyped = arg->getAsTyped();
1042*8975f5c5SAndroid Build Coastguard Worker             ASSERT(argTyped != nullptr);
1043*8975f5c5SAndroid Build Coastguard Worker 
1044*8975f5c5SAndroid Build Coastguard Worker             if (argTyped->getBasicType() == EbtStruct)
1045*8975f5c5SAndroid Build Coastguard Worker             {
1046*8975f5c5SAndroid Build Coastguard Worker                 error(line, "a struct cannot be used as a constructor argument for this type",
1047*8975f5c5SAndroid Build Coastguard Worker                       "constructor");
1048*8975f5c5SAndroid Build Coastguard Worker                 return false;
1049*8975f5c5SAndroid Build Coastguard Worker             }
1050*8975f5c5SAndroid Build Coastguard Worker             if (argTyped->getBasicType() == EbtInterfaceBlock)
1051*8975f5c5SAndroid Build Coastguard Worker             {
1052*8975f5c5SAndroid Build Coastguard Worker                 error(line,
1053*8975f5c5SAndroid Build Coastguard Worker                       "an interface block cannot be used as a constructor argument for this type",
1054*8975f5c5SAndroid Build Coastguard Worker                       "constructor");
1055*8975f5c5SAndroid Build Coastguard Worker                 return false;
1056*8975f5c5SAndroid Build Coastguard Worker             }
1057*8975f5c5SAndroid Build Coastguard Worker             if (argTyped->getType().isArray())
1058*8975f5c5SAndroid Build Coastguard Worker             {
1059*8975f5c5SAndroid Build Coastguard Worker                 error(line, "constructing from a non-dereferenced array", "constructor");
1060*8975f5c5SAndroid Build Coastguard Worker                 return false;
1061*8975f5c5SAndroid Build Coastguard Worker             }
1062*8975f5c5SAndroid Build Coastguard Worker             if (argTyped->getType().isMatrix())
1063*8975f5c5SAndroid Build Coastguard Worker             {
1064*8975f5c5SAndroid Build Coastguard Worker                 matrixArg = true;
1065*8975f5c5SAndroid Build Coastguard Worker             }
1066*8975f5c5SAndroid Build Coastguard Worker 
1067*8975f5c5SAndroid Build Coastguard Worker             size += argTyped->getType().getObjectSize();
1068*8975f5c5SAndroid Build Coastguard Worker             if (full)
1069*8975f5c5SAndroid Build Coastguard Worker             {
1070*8975f5c5SAndroid Build Coastguard Worker                 overFull = true;
1071*8975f5c5SAndroid Build Coastguard Worker             }
1072*8975f5c5SAndroid Build Coastguard Worker             if (size >= type.getObjectSize())
1073*8975f5c5SAndroid Build Coastguard Worker             {
1074*8975f5c5SAndroid Build Coastguard Worker                 full = true;
1075*8975f5c5SAndroid Build Coastguard Worker             }
1076*8975f5c5SAndroid Build Coastguard Worker         }
1077*8975f5c5SAndroid Build Coastguard Worker 
1078*8975f5c5SAndroid Build Coastguard Worker         if (type.isMatrix() && matrixArg)
1079*8975f5c5SAndroid Build Coastguard Worker         {
1080*8975f5c5SAndroid Build Coastguard Worker             if (arguments.size() != 1)
1081*8975f5c5SAndroid Build Coastguard Worker             {
1082*8975f5c5SAndroid Build Coastguard Worker                 error(line, "constructing matrix from matrix can only take one argument",
1083*8975f5c5SAndroid Build Coastguard Worker                       "constructor");
1084*8975f5c5SAndroid Build Coastguard Worker                 return false;
1085*8975f5c5SAndroid Build Coastguard Worker             }
1086*8975f5c5SAndroid Build Coastguard Worker         }
1087*8975f5c5SAndroid Build Coastguard Worker         else
1088*8975f5c5SAndroid Build Coastguard Worker         {
1089*8975f5c5SAndroid Build Coastguard Worker             if (size != 1 && size < type.getObjectSize())
1090*8975f5c5SAndroid Build Coastguard Worker             {
1091*8975f5c5SAndroid Build Coastguard Worker                 error(line, "not enough data provided for construction", "constructor");
1092*8975f5c5SAndroid Build Coastguard Worker                 return false;
1093*8975f5c5SAndroid Build Coastguard Worker             }
1094*8975f5c5SAndroid Build Coastguard Worker             if (overFull)
1095*8975f5c5SAndroid Build Coastguard Worker             {
1096*8975f5c5SAndroid Build Coastguard Worker                 error(line, "too many arguments", "constructor");
1097*8975f5c5SAndroid Build Coastguard Worker                 return false;
1098*8975f5c5SAndroid Build Coastguard Worker             }
1099*8975f5c5SAndroid Build Coastguard Worker         }
1100*8975f5c5SAndroid Build Coastguard Worker     }
1101*8975f5c5SAndroid Build Coastguard Worker 
1102*8975f5c5SAndroid Build Coastguard Worker     return true;
1103*8975f5c5SAndroid Build Coastguard Worker }
1104*8975f5c5SAndroid Build Coastguard Worker 
1105*8975f5c5SAndroid Build Coastguard Worker // This function checks to see if a void variable has been declared and raise an error message for
1106*8975f5c5SAndroid Build Coastguard Worker // such a case
1107*8975f5c5SAndroid Build Coastguard Worker //
1108*8975f5c5SAndroid Build Coastguard Worker // returns true in case of an error
1109*8975f5c5SAndroid Build Coastguard Worker //
checkIsNonVoid(const TSourceLoc & line,const ImmutableString & identifier,const TBasicType & type)1110*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkIsNonVoid(const TSourceLoc &line,
1111*8975f5c5SAndroid Build Coastguard Worker                                    const ImmutableString &identifier,
1112*8975f5c5SAndroid Build Coastguard Worker                                    const TBasicType &type)
1113*8975f5c5SAndroid Build Coastguard Worker {
1114*8975f5c5SAndroid Build Coastguard Worker     if (type == EbtVoid)
1115*8975f5c5SAndroid Build Coastguard Worker     {
1116*8975f5c5SAndroid Build Coastguard Worker         error(line, "illegal use of type 'void'", identifier);
1117*8975f5c5SAndroid Build Coastguard Worker         return false;
1118*8975f5c5SAndroid Build Coastguard Worker     }
1119*8975f5c5SAndroid Build Coastguard Worker 
1120*8975f5c5SAndroid Build Coastguard Worker     return true;
1121*8975f5c5SAndroid Build Coastguard Worker }
1122*8975f5c5SAndroid Build Coastguard Worker 
1123*8975f5c5SAndroid Build Coastguard Worker // This function checks to see if the node (for the expression) contains a scalar boolean expression
1124*8975f5c5SAndroid Build Coastguard Worker // or not.
checkIsScalarBool(const TSourceLoc & line,const TIntermTyped * type)1125*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkIsScalarBool(const TSourceLoc &line, const TIntermTyped *type)
1126*8975f5c5SAndroid Build Coastguard Worker {
1127*8975f5c5SAndroid Build Coastguard Worker     if (type->getBasicType() != EbtBool || !type->isScalar())
1128*8975f5c5SAndroid Build Coastguard Worker     {
1129*8975f5c5SAndroid Build Coastguard Worker         error(line, "boolean expression expected", "");
1130*8975f5c5SAndroid Build Coastguard Worker         return false;
1131*8975f5c5SAndroid Build Coastguard Worker     }
1132*8975f5c5SAndroid Build Coastguard Worker     return true;
1133*8975f5c5SAndroid Build Coastguard Worker }
1134*8975f5c5SAndroid Build Coastguard Worker 
1135*8975f5c5SAndroid Build Coastguard Worker // This function checks to see if the node (for the expression) contains a scalar boolean expression
1136*8975f5c5SAndroid Build Coastguard Worker // or not.
checkIsScalarBool(const TSourceLoc & line,const TPublicType & pType)1137*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkIsScalarBool(const TSourceLoc &line, const TPublicType &pType)
1138*8975f5c5SAndroid Build Coastguard Worker {
1139*8975f5c5SAndroid Build Coastguard Worker     if (pType.getBasicType() != EbtBool || pType.isAggregate())
1140*8975f5c5SAndroid Build Coastguard Worker     {
1141*8975f5c5SAndroid Build Coastguard Worker         error(line, "boolean expression expected", "");
1142*8975f5c5SAndroid Build Coastguard Worker     }
1143*8975f5c5SAndroid Build Coastguard Worker }
1144*8975f5c5SAndroid Build Coastguard Worker 
checkIsNotOpaqueType(const TSourceLoc & line,const TTypeSpecifierNonArray & pType,const char * reason)1145*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkIsNotOpaqueType(const TSourceLoc &line,
1146*8975f5c5SAndroid Build Coastguard Worker                                          const TTypeSpecifierNonArray &pType,
1147*8975f5c5SAndroid Build Coastguard Worker                                          const char *reason)
1148*8975f5c5SAndroid Build Coastguard Worker {
1149*8975f5c5SAndroid Build Coastguard Worker     if (pType.type == EbtStruct)
1150*8975f5c5SAndroid Build Coastguard Worker     {
1151*8975f5c5SAndroid Build Coastguard Worker         if (ContainsOpaque<IsSamplerFunc>(pType.userDef))
1152*8975f5c5SAndroid Build Coastguard Worker         {
1153*8975f5c5SAndroid Build Coastguard Worker             std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
1154*8975f5c5SAndroid Build Coastguard Worker             reasonStream << reason << " (structure contains a sampler)";
1155*8975f5c5SAndroid Build Coastguard Worker             std::string reasonStr = reasonStream.str();
1156*8975f5c5SAndroid Build Coastguard Worker             error(line, reasonStr.c_str(), getBasicString(pType.type));
1157*8975f5c5SAndroid Build Coastguard Worker             return false;
1158*8975f5c5SAndroid Build Coastguard Worker         }
1159*8975f5c5SAndroid Build Coastguard Worker         // only samplers need to be checked from structs, since other opaque types can't be struct
1160*8975f5c5SAndroid Build Coastguard Worker         // members.
1161*8975f5c5SAndroid Build Coastguard Worker         return true;
1162*8975f5c5SAndroid Build Coastguard Worker     }
1163*8975f5c5SAndroid Build Coastguard Worker     else if (IsOpaqueType(pType.type))
1164*8975f5c5SAndroid Build Coastguard Worker     {
1165*8975f5c5SAndroid Build Coastguard Worker         error(line, reason, getBasicString(pType.type));
1166*8975f5c5SAndroid Build Coastguard Worker         return false;
1167*8975f5c5SAndroid Build Coastguard Worker     }
1168*8975f5c5SAndroid Build Coastguard Worker 
1169*8975f5c5SAndroid Build Coastguard Worker     return true;
1170*8975f5c5SAndroid Build Coastguard Worker }
1171*8975f5c5SAndroid Build Coastguard Worker 
checkDeclaratorLocationIsNotSpecified(const TSourceLoc & line,const TPublicType & pType)1172*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkDeclaratorLocationIsNotSpecified(const TSourceLoc &line,
1173*8975f5c5SAndroid Build Coastguard Worker                                                           const TPublicType &pType)
1174*8975f5c5SAndroid Build Coastguard Worker {
1175*8975f5c5SAndroid Build Coastguard Worker     if (pType.layoutQualifier.location != -1)
1176*8975f5c5SAndroid Build Coastguard Worker     {
1177*8975f5c5SAndroid Build Coastguard Worker         error(line, "location must only be specified for a single input or output variable",
1178*8975f5c5SAndroid Build Coastguard Worker               "location");
1179*8975f5c5SAndroid Build Coastguard Worker     }
1180*8975f5c5SAndroid Build Coastguard Worker }
1181*8975f5c5SAndroid Build Coastguard Worker 
checkLocationIsNotSpecified(const TSourceLoc & location,const TLayoutQualifier & layoutQualifier)1182*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkLocationIsNotSpecified(const TSourceLoc &location,
1183*8975f5c5SAndroid Build Coastguard Worker                                                 const TLayoutQualifier &layoutQualifier)
1184*8975f5c5SAndroid Build Coastguard Worker {
1185*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.location != -1)
1186*8975f5c5SAndroid Build Coastguard Worker     {
1187*8975f5c5SAndroid Build Coastguard Worker         const char *errorMsg = "invalid layout qualifier: only valid on program inputs and outputs";
1188*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion >= 310)
1189*8975f5c5SAndroid Build Coastguard Worker         {
1190*8975f5c5SAndroid Build Coastguard Worker             errorMsg =
1191*8975f5c5SAndroid Build Coastguard Worker                 "invalid layout qualifier: only valid on shader inputs, outputs, and uniforms";
1192*8975f5c5SAndroid Build Coastguard Worker         }
1193*8975f5c5SAndroid Build Coastguard Worker         error(location, errorMsg, "location");
1194*8975f5c5SAndroid Build Coastguard Worker     }
1195*8975f5c5SAndroid Build Coastguard Worker }
1196*8975f5c5SAndroid Build Coastguard Worker 
checkStd430IsForShaderStorageBlock(const TSourceLoc & location,const TLayoutBlockStorage & blockStorage,const TQualifier & qualifier)1197*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkStd430IsForShaderStorageBlock(const TSourceLoc &location,
1198*8975f5c5SAndroid Build Coastguard Worker                                                        const TLayoutBlockStorage &blockStorage,
1199*8975f5c5SAndroid Build Coastguard Worker                                                        const TQualifier &qualifier)
1200*8975f5c5SAndroid Build Coastguard Worker {
1201*8975f5c5SAndroid Build Coastguard Worker     if (blockStorage == EbsStd430 && qualifier != EvqBuffer)
1202*8975f5c5SAndroid Build Coastguard Worker     {
1203*8975f5c5SAndroid Build Coastguard Worker         error(location, "The std430 layout is supported only for shader storage blocks.", "std430");
1204*8975f5c5SAndroid Build Coastguard Worker     }
1205*8975f5c5SAndroid Build Coastguard Worker }
1206*8975f5c5SAndroid Build Coastguard Worker 
1207*8975f5c5SAndroid Build Coastguard Worker // Do size checking for an array type's size.
checkIsValidArraySize(const TSourceLoc & line,TIntermTyped * expr)1208*8975f5c5SAndroid Build Coastguard Worker unsigned int TParseContext::checkIsValidArraySize(const TSourceLoc &line, TIntermTyped *expr)
1209*8975f5c5SAndroid Build Coastguard Worker {
1210*8975f5c5SAndroid Build Coastguard Worker     TIntermConstantUnion *constant = expr->getAsConstantUnion();
1211*8975f5c5SAndroid Build Coastguard Worker 
1212*8975f5c5SAndroid Build Coastguard Worker     // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
1213*8975f5c5SAndroid Build Coastguard Worker     // safe against corner cases we still check for constant folding. Some interpretations of the
1214*8975f5c5SAndroid Build Coastguard Worker     // spec have allowed constant expressions with side effects - like array length() method on a
1215*8975f5c5SAndroid Build Coastguard Worker     // non-constant array.
1216*8975f5c5SAndroid Build Coastguard Worker     if (expr->getQualifier() != EvqConst || constant == nullptr || !constant->isScalarInt())
1217*8975f5c5SAndroid Build Coastguard Worker     {
1218*8975f5c5SAndroid Build Coastguard Worker         error(line, "array size must be a constant integer expression", "");
1219*8975f5c5SAndroid Build Coastguard Worker         return 1u;
1220*8975f5c5SAndroid Build Coastguard Worker     }
1221*8975f5c5SAndroid Build Coastguard Worker 
1222*8975f5c5SAndroid Build Coastguard Worker     unsigned int size = 0u;
1223*8975f5c5SAndroid Build Coastguard Worker 
1224*8975f5c5SAndroid Build Coastguard Worker     if (constant->getBasicType() == EbtUInt)
1225*8975f5c5SAndroid Build Coastguard Worker     {
1226*8975f5c5SAndroid Build Coastguard Worker         size = constant->getUConst(0);
1227*8975f5c5SAndroid Build Coastguard Worker     }
1228*8975f5c5SAndroid Build Coastguard Worker     else
1229*8975f5c5SAndroid Build Coastguard Worker     {
1230*8975f5c5SAndroid Build Coastguard Worker         int signedSize = constant->getIConst(0);
1231*8975f5c5SAndroid Build Coastguard Worker 
1232*8975f5c5SAndroid Build Coastguard Worker         if (signedSize < 0)
1233*8975f5c5SAndroid Build Coastguard Worker         {
1234*8975f5c5SAndroid Build Coastguard Worker             error(line, "array size must be non-negative", "");
1235*8975f5c5SAndroid Build Coastguard Worker             return 1u;
1236*8975f5c5SAndroid Build Coastguard Worker         }
1237*8975f5c5SAndroid Build Coastguard Worker 
1238*8975f5c5SAndroid Build Coastguard Worker         size = static_cast<unsigned int>(signedSize);
1239*8975f5c5SAndroid Build Coastguard Worker     }
1240*8975f5c5SAndroid Build Coastguard Worker 
1241*8975f5c5SAndroid Build Coastguard Worker     if (size == 0u)
1242*8975f5c5SAndroid Build Coastguard Worker     {
1243*8975f5c5SAndroid Build Coastguard Worker         error(line, "array size must be greater than zero", "");
1244*8975f5c5SAndroid Build Coastguard Worker         return 1u;
1245*8975f5c5SAndroid Build Coastguard Worker     }
1246*8975f5c5SAndroid Build Coastguard Worker 
1247*8975f5c5SAndroid Build Coastguard Worker     if (IsOutputHLSL(getOutputType()))
1248*8975f5c5SAndroid Build Coastguard Worker     {
1249*8975f5c5SAndroid Build Coastguard Worker         // The size of arrays is restricted here to prevent issues further down the
1250*8975f5c5SAndroid Build Coastguard Worker         // compiler/translator/driver stack. Shader Model 5 generation hardware is limited to
1251*8975f5c5SAndroid Build Coastguard Worker         // 4096 registers so this should be reasonable even for aggressively optimizable code.
1252*8975f5c5SAndroid Build Coastguard Worker         const unsigned int sizeLimit = 65536;
1253*8975f5c5SAndroid Build Coastguard Worker 
1254*8975f5c5SAndroid Build Coastguard Worker         if (size > sizeLimit)
1255*8975f5c5SAndroid Build Coastguard Worker         {
1256*8975f5c5SAndroid Build Coastguard Worker             error(line, "array size too large", "");
1257*8975f5c5SAndroid Build Coastguard Worker             return 1u;
1258*8975f5c5SAndroid Build Coastguard Worker         }
1259*8975f5c5SAndroid Build Coastguard Worker     }
1260*8975f5c5SAndroid Build Coastguard Worker 
1261*8975f5c5SAndroid Build Coastguard Worker     return size;
1262*8975f5c5SAndroid Build Coastguard Worker }
1263*8975f5c5SAndroid Build Coastguard Worker 
checkIsValidArrayDimension(const TSourceLoc & line,TVector<unsigned int> * arraySizes)1264*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkIsValidArrayDimension(const TSourceLoc &line,
1265*8975f5c5SAndroid Build Coastguard Worker                                                TVector<unsigned int> *arraySizes)
1266*8975f5c5SAndroid Build Coastguard Worker {
1267*8975f5c5SAndroid Build Coastguard Worker     if (arraySizes->size() > mMaxExpressionComplexity)
1268*8975f5c5SAndroid Build Coastguard Worker     {
1269*8975f5c5SAndroid Build Coastguard Worker         error(line, "array has too many dimensions", "");
1270*8975f5c5SAndroid Build Coastguard Worker         return false;
1271*8975f5c5SAndroid Build Coastguard Worker     }
1272*8975f5c5SAndroid Build Coastguard Worker     return true;
1273*8975f5c5SAndroid Build Coastguard Worker }
1274*8975f5c5SAndroid Build Coastguard Worker 
1275*8975f5c5SAndroid Build Coastguard Worker // See if this qualifier can be an array.
checkIsValidQualifierForArray(const TSourceLoc & line,const TPublicType & elementQualifier)1276*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkIsValidQualifierForArray(const TSourceLoc &line,
1277*8975f5c5SAndroid Build Coastguard Worker                                                   const TPublicType &elementQualifier)
1278*8975f5c5SAndroid Build Coastguard Worker {
1279*8975f5c5SAndroid Build Coastguard Worker     if ((elementQualifier.qualifier == EvqAttribute) ||
1280*8975f5c5SAndroid Build Coastguard Worker         (elementQualifier.qualifier == EvqVertexIn) ||
1281*8975f5c5SAndroid Build Coastguard Worker         (elementQualifier.qualifier == EvqConst && mShaderVersion < 300))
1282*8975f5c5SAndroid Build Coastguard Worker     {
1283*8975f5c5SAndroid Build Coastguard Worker         error(line, "cannot declare arrays of this qualifier",
1284*8975f5c5SAndroid Build Coastguard Worker               TType(elementQualifier).getQualifierString());
1285*8975f5c5SAndroid Build Coastguard Worker         return false;
1286*8975f5c5SAndroid Build Coastguard Worker     }
1287*8975f5c5SAndroid Build Coastguard Worker 
1288*8975f5c5SAndroid Build Coastguard Worker     return true;
1289*8975f5c5SAndroid Build Coastguard Worker }
1290*8975f5c5SAndroid Build Coastguard Worker 
1291*8975f5c5SAndroid Build Coastguard Worker // See if this element type can be formed into an array.
checkArrayElementIsNotArray(const TSourceLoc & line,const TPublicType & elementType)1292*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkArrayElementIsNotArray(const TSourceLoc &line,
1293*8975f5c5SAndroid Build Coastguard Worker                                                 const TPublicType &elementType)
1294*8975f5c5SAndroid Build Coastguard Worker {
1295*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion < 310 && elementType.isArray())
1296*8975f5c5SAndroid Build Coastguard Worker     {
1297*8975f5c5SAndroid Build Coastguard Worker         TInfoSinkBase typeString;
1298*8975f5c5SAndroid Build Coastguard Worker         typeString << TType(elementType);
1299*8975f5c5SAndroid Build Coastguard Worker         error(line, "cannot declare arrays of arrays", typeString.c_str());
1300*8975f5c5SAndroid Build Coastguard Worker         return false;
1301*8975f5c5SAndroid Build Coastguard Worker     }
1302*8975f5c5SAndroid Build Coastguard Worker     return true;
1303*8975f5c5SAndroid Build Coastguard Worker }
1304*8975f5c5SAndroid Build Coastguard Worker 
1305*8975f5c5SAndroid Build Coastguard Worker // Check for array-of-arrays being used as non-allowed shader inputs/outputs.
checkArrayOfArraysInOut(const TSourceLoc & line,const TPublicType & elementType,const TType & arrayType)1306*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkArrayOfArraysInOut(const TSourceLoc &line,
1307*8975f5c5SAndroid Build Coastguard Worker                                             const TPublicType &elementType,
1308*8975f5c5SAndroid Build Coastguard Worker                                             const TType &arrayType)
1309*8975f5c5SAndroid Build Coastguard Worker {
1310*8975f5c5SAndroid Build Coastguard Worker     if (arrayType.isArrayOfArrays())
1311*8975f5c5SAndroid Build Coastguard Worker     {
1312*8975f5c5SAndroid Build Coastguard Worker         if (elementType.qualifier == EvqVertexOut)
1313*8975f5c5SAndroid Build Coastguard Worker         {
1314*8975f5c5SAndroid Build Coastguard Worker             error(line, "vertex shader output cannot be an array of arrays",
1315*8975f5c5SAndroid Build Coastguard Worker                   TType(elementType).getQualifierString());
1316*8975f5c5SAndroid Build Coastguard Worker             return false;
1317*8975f5c5SAndroid Build Coastguard Worker         }
1318*8975f5c5SAndroid Build Coastguard Worker         if (elementType.qualifier == EvqFragmentIn)
1319*8975f5c5SAndroid Build Coastguard Worker         {
1320*8975f5c5SAndroid Build Coastguard Worker             error(line, "fragment shader input cannot be an array of arrays",
1321*8975f5c5SAndroid Build Coastguard Worker                   TType(elementType).getQualifierString());
1322*8975f5c5SAndroid Build Coastguard Worker             return false;
1323*8975f5c5SAndroid Build Coastguard Worker         }
1324*8975f5c5SAndroid Build Coastguard Worker         if (elementType.qualifier == EvqFragmentOut || elementType.qualifier == EvqFragmentInOut)
1325*8975f5c5SAndroid Build Coastguard Worker         {
1326*8975f5c5SAndroid Build Coastguard Worker             error(line, "fragment shader output cannot be an array of arrays",
1327*8975f5c5SAndroid Build Coastguard Worker                   TType(elementType).getQualifierString());
1328*8975f5c5SAndroid Build Coastguard Worker             return false;
1329*8975f5c5SAndroid Build Coastguard Worker         }
1330*8975f5c5SAndroid Build Coastguard Worker     }
1331*8975f5c5SAndroid Build Coastguard Worker     return true;
1332*8975f5c5SAndroid Build Coastguard Worker }
1333*8975f5c5SAndroid Build Coastguard Worker 
1334*8975f5c5SAndroid Build Coastguard Worker // Check if this qualified element type can be formed into an array. This is only called when array
1335*8975f5c5SAndroid Build Coastguard Worker // brackets are associated with an identifier in a declaration, like this:
1336*8975f5c5SAndroid Build Coastguard Worker //   float a[2];
1337*8975f5c5SAndroid Build Coastguard Worker // Similar checks are done in addFullySpecifiedType for array declarations where the array brackets
1338*8975f5c5SAndroid Build Coastguard Worker // are associated with the type, like this:
1339*8975f5c5SAndroid Build Coastguard Worker //   float[2] a;
checkIsValidTypeAndQualifierForArray(const TSourceLoc & indexLocation,const TPublicType & elementType)1340*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
1341*8975f5c5SAndroid Build Coastguard Worker                                                          const TPublicType &elementType)
1342*8975f5c5SAndroid Build Coastguard Worker {
1343*8975f5c5SAndroid Build Coastguard Worker     if (!checkArrayElementIsNotArray(indexLocation, elementType))
1344*8975f5c5SAndroid Build Coastguard Worker     {
1345*8975f5c5SAndroid Build Coastguard Worker         return false;
1346*8975f5c5SAndroid Build Coastguard Worker     }
1347*8975f5c5SAndroid Build Coastguard Worker     // In ESSL1.00 shaders, structs cannot be varying (section 4.3.5). This is checked elsewhere.
1348*8975f5c5SAndroid Build Coastguard Worker     // In ESSL3.00 shaders, struct inputs/outputs are allowed but not arrays of structs (section
1349*8975f5c5SAndroid Build Coastguard Worker     // 4.3.4).
1350*8975f5c5SAndroid Build Coastguard Worker     // Geometry shader requires each user-defined input be declared as arrays or inside input
1351*8975f5c5SAndroid Build Coastguard Worker     // blocks declared as arrays (GL_EXT_geometry_shader section 11.1gs.4.3). For the purposes of
1352*8975f5c5SAndroid Build Coastguard Worker     // interface matching, such variables and blocks are treated as though they were not declared
1353*8975f5c5SAndroid Build Coastguard Worker     // as arrays (GL_EXT_geometry_shader section 7.4.1).
1354*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion >= 300 && elementType.getBasicType() == EbtStruct &&
1355*8975f5c5SAndroid Build Coastguard Worker         sh::IsVarying(elementType.qualifier) &&
1356*8975f5c5SAndroid Build Coastguard Worker         !IsGeometryShaderInput(mShaderType, elementType.qualifier) &&
1357*8975f5c5SAndroid Build Coastguard Worker         !IsTessellationControlShaderInput(mShaderType, elementType.qualifier) &&
1358*8975f5c5SAndroid Build Coastguard Worker         !IsTessellationEvaluationShaderInput(mShaderType, elementType.qualifier) &&
1359*8975f5c5SAndroid Build Coastguard Worker         !IsTessellationControlShaderOutput(mShaderType, elementType.qualifier))
1360*8975f5c5SAndroid Build Coastguard Worker     {
1361*8975f5c5SAndroid Build Coastguard Worker         TInfoSinkBase typeString;
1362*8975f5c5SAndroid Build Coastguard Worker         typeString << TType(elementType);
1363*8975f5c5SAndroid Build Coastguard Worker         error(indexLocation, "cannot declare arrays of structs of this qualifier",
1364*8975f5c5SAndroid Build Coastguard Worker               typeString.c_str());
1365*8975f5c5SAndroid Build Coastguard Worker         return false;
1366*8975f5c5SAndroid Build Coastguard Worker     }
1367*8975f5c5SAndroid Build Coastguard Worker     return checkIsValidQualifierForArray(indexLocation, elementType);
1368*8975f5c5SAndroid Build Coastguard Worker }
1369*8975f5c5SAndroid Build Coastguard Worker 
checkNestingLevel(const TSourceLoc & line)1370*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkNestingLevel(const TSourceLoc &line)
1371*8975f5c5SAndroid Build Coastguard Worker {
1372*8975f5c5SAndroid Build Coastguard Worker     if (static_cast<size_t>(mLoopNestingLevel + mSwitchNestingLevel) > mMaxStatementDepth)
1373*8975f5c5SAndroid Build Coastguard Worker     {
1374*8975f5c5SAndroid Build Coastguard Worker         error(line, "statement is too deeply nested", "");
1375*8975f5c5SAndroid Build Coastguard Worker     }
1376*8975f5c5SAndroid Build Coastguard Worker }
1377*8975f5c5SAndroid Build Coastguard Worker 
1378*8975f5c5SAndroid Build Coastguard Worker // Enforce non-initializer type/qualifier rules.
checkCanBeDeclaredWithoutInitializer(const TSourceLoc & line,const ImmutableString & identifier,TType * type)1379*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkCanBeDeclaredWithoutInitializer(const TSourceLoc &line,
1380*8975f5c5SAndroid Build Coastguard Worker                                                          const ImmutableString &identifier,
1381*8975f5c5SAndroid Build Coastguard Worker                                                          TType *type)
1382*8975f5c5SAndroid Build Coastguard Worker {
1383*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type != nullptr);
1384*8975f5c5SAndroid Build Coastguard Worker     if (type->getQualifier() == EvqConst)
1385*8975f5c5SAndroid Build Coastguard Worker     {
1386*8975f5c5SAndroid Build Coastguard Worker         // Make the qualifier make sense.
1387*8975f5c5SAndroid Build Coastguard Worker         type->setQualifier(EvqTemporary);
1388*8975f5c5SAndroid Build Coastguard Worker 
1389*8975f5c5SAndroid Build Coastguard Worker         // Generate informative error messages for ESSL1.
1390*8975f5c5SAndroid Build Coastguard Worker         // In ESSL3 arrays and structures containing arrays can be constant.
1391*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 300 && type->isStructureContainingArrays())
1392*8975f5c5SAndroid Build Coastguard Worker         {
1393*8975f5c5SAndroid Build Coastguard Worker             error(line,
1394*8975f5c5SAndroid Build Coastguard Worker                   "structures containing arrays may not be declared constant since they cannot be "
1395*8975f5c5SAndroid Build Coastguard Worker                   "initialized",
1396*8975f5c5SAndroid Build Coastguard Worker                   identifier);
1397*8975f5c5SAndroid Build Coastguard Worker         }
1398*8975f5c5SAndroid Build Coastguard Worker         else
1399*8975f5c5SAndroid Build Coastguard Worker         {
1400*8975f5c5SAndroid Build Coastguard Worker             error(line, "variables with qualifier 'const' must be initialized", identifier);
1401*8975f5c5SAndroid Build Coastguard Worker         }
1402*8975f5c5SAndroid Build Coastguard Worker     }
1403*8975f5c5SAndroid Build Coastguard Worker }
1404*8975f5c5SAndroid Build Coastguard Worker 
checkDeclarationIsValidArraySize(const TSourceLoc & line,const ImmutableString & identifier,TType * type)1405*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkDeclarationIsValidArraySize(const TSourceLoc &line,
1406*8975f5c5SAndroid Build Coastguard Worker                                                      const ImmutableString &identifier,
1407*8975f5c5SAndroid Build Coastguard Worker                                                      TType *type)
1408*8975f5c5SAndroid Build Coastguard Worker {
1409*8975f5c5SAndroid Build Coastguard Worker 
1410*8975f5c5SAndroid Build Coastguard Worker     // Implicitly declared arrays are only allowed with tessellation or geometry shader inputs
1411*8975f5c5SAndroid Build Coastguard Worker     if (type->isUnsizedArray() &&
1412*8975f5c5SAndroid Build Coastguard Worker         ((mShaderType != GL_TESS_CONTROL_SHADER && mShaderType != GL_TESS_EVALUATION_SHADER &&
1413*8975f5c5SAndroid Build Coastguard Worker           mShaderType != GL_GEOMETRY_SHADER) ||
1414*8975f5c5SAndroid Build Coastguard Worker          (mShaderType == GL_GEOMETRY_SHADER && type->getQualifier() == EvqGeometryOut)))
1415*8975f5c5SAndroid Build Coastguard Worker     {
1416*8975f5c5SAndroid Build Coastguard Worker         error(line,
1417*8975f5c5SAndroid Build Coastguard Worker               "implicitly sized arrays only allowed for tessellation shaders "
1418*8975f5c5SAndroid Build Coastguard Worker               "or geometry shader inputs",
1419*8975f5c5SAndroid Build Coastguard Worker               identifier);
1420*8975f5c5SAndroid Build Coastguard Worker     }
1421*8975f5c5SAndroid Build Coastguard Worker }
1422*8975f5c5SAndroid Build Coastguard Worker 
1423*8975f5c5SAndroid Build Coastguard Worker // Do some simple checks that are shared between all variable declarations,
1424*8975f5c5SAndroid Build Coastguard Worker // and update the symbol table.
1425*8975f5c5SAndroid Build Coastguard Worker //
1426*8975f5c5SAndroid Build Coastguard Worker // Returns true if declaring the variable succeeded.
1427*8975f5c5SAndroid Build Coastguard Worker //
declareVariable(const TSourceLoc & line,const ImmutableString & identifier,const TType * type,TVariable ** variable)1428*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::declareVariable(const TSourceLoc &line,
1429*8975f5c5SAndroid Build Coastguard Worker                                     const ImmutableString &identifier,
1430*8975f5c5SAndroid Build Coastguard Worker                                     const TType *type,
1431*8975f5c5SAndroid Build Coastguard Worker                                     TVariable **variable)
1432*8975f5c5SAndroid Build Coastguard Worker {
1433*8975f5c5SAndroid Build Coastguard Worker     ASSERT((*variable) == nullptr);
1434*8975f5c5SAndroid Build Coastguard Worker 
1435*8975f5c5SAndroid Build Coastguard Worker     SymbolType symbolType = SymbolType::UserDefined;
1436*8975f5c5SAndroid Build Coastguard Worker     switch (type->getQualifier())
1437*8975f5c5SAndroid Build Coastguard Worker     {
1438*8975f5c5SAndroid Build Coastguard Worker         case EvqClipDistance:
1439*8975f5c5SAndroid Build Coastguard Worker         case EvqCullDistance:
1440*8975f5c5SAndroid Build Coastguard Worker         case EvqFragDepth:
1441*8975f5c5SAndroid Build Coastguard Worker         case EvqLastFragData:
1442*8975f5c5SAndroid Build Coastguard Worker         case EvqLastFragColor:
1443*8975f5c5SAndroid Build Coastguard Worker         case EvqLastFragDepth:
1444*8975f5c5SAndroid Build Coastguard Worker         case EvqLastFragStencil:
1445*8975f5c5SAndroid Build Coastguard Worker             symbolType = SymbolType::BuiltIn;
1446*8975f5c5SAndroid Build Coastguard Worker             break;
1447*8975f5c5SAndroid Build Coastguard Worker         default:
1448*8975f5c5SAndroid Build Coastguard Worker             break;
1449*8975f5c5SAndroid Build Coastguard Worker     }
1450*8975f5c5SAndroid Build Coastguard Worker 
1451*8975f5c5SAndroid Build Coastguard Worker     (*variable) = new TVariable(&symbolTable, identifier, type, symbolType);
1452*8975f5c5SAndroid Build Coastguard Worker 
1453*8975f5c5SAndroid Build Coastguard Worker     if (type->getQualifier() == EvqFragmentOut)
1454*8975f5c5SAndroid Build Coastguard Worker     {
1455*8975f5c5SAndroid Build Coastguard Worker         if (type->getLayoutQualifier().index != -1 && type->getLayoutQualifier().location == -1)
1456*8975f5c5SAndroid Build Coastguard Worker         {
1457*8975f5c5SAndroid Build Coastguard Worker             error(line,
1458*8975f5c5SAndroid Build Coastguard Worker                   "If index layout qualifier is specified for a fragment output, location must "
1459*8975f5c5SAndroid Build Coastguard Worker                   "also be specified.",
1460*8975f5c5SAndroid Build Coastguard Worker                   "index");
1461*8975f5c5SAndroid Build Coastguard Worker             return false;
1462*8975f5c5SAndroid Build Coastguard Worker         }
1463*8975f5c5SAndroid Build Coastguard Worker     }
1464*8975f5c5SAndroid Build Coastguard Worker     else
1465*8975f5c5SAndroid Build Coastguard Worker     {
1466*8975f5c5SAndroid Build Coastguard Worker         checkIndexIsNotSpecified(line, type->getLayoutQualifier().index);
1467*8975f5c5SAndroid Build Coastguard Worker     }
1468*8975f5c5SAndroid Build Coastguard Worker 
1469*8975f5c5SAndroid Build Coastguard Worker     if (!((identifier.beginsWith("gl_LastFragData") || type->getQualifier() == EvqFragmentInOut) &&
1470*8975f5c5SAndroid Build Coastguard Worker           (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) ||
1471*8975f5c5SAndroid Build Coastguard Worker            isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent))))
1472*8975f5c5SAndroid Build Coastguard Worker     {
1473*8975f5c5SAndroid Build Coastguard Worker         checkNoncoherentIsNotSpecified(line, type->getLayoutQualifier().noncoherent);
1474*8975f5c5SAndroid Build Coastguard Worker     }
1475*8975f5c5SAndroid Build Coastguard Worker     else if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent) &&
1476*8975f5c5SAndroid Build Coastguard Worker              !isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch))
1477*8975f5c5SAndroid Build Coastguard Worker     {
1478*8975f5c5SAndroid Build Coastguard Worker         checkNoncoherentIsSpecified(line, type->getLayoutQualifier().noncoherent);
1479*8975f5c5SAndroid Build Coastguard Worker     }
1480*8975f5c5SAndroid Build Coastguard Worker 
1481*8975f5c5SAndroid Build Coastguard Worker     checkBindingIsValid(line, *type);
1482*8975f5c5SAndroid Build Coastguard Worker 
1483*8975f5c5SAndroid Build Coastguard Worker     bool needsReservedCheck = true;
1484*8975f5c5SAndroid Build Coastguard Worker 
1485*8975f5c5SAndroid Build Coastguard Worker     // gl_LastFragData may be redeclared with a new precision qualifier
1486*8975f5c5SAndroid Build Coastguard Worker     if (type->isArray() && identifier.beginsWith("gl_LastFragData"))
1487*8975f5c5SAndroid Build Coastguard Worker     {
1488*8975f5c5SAndroid Build Coastguard Worker         const TVariable *maxDrawBuffers = static_cast<const TVariable *>(
1489*8975f5c5SAndroid Build Coastguard Worker             symbolTable.findBuiltIn(ImmutableString("gl_MaxDrawBuffers"), mShaderVersion));
1490*8975f5c5SAndroid Build Coastguard Worker         if (type->isArrayOfArrays())
1491*8975f5c5SAndroid Build Coastguard Worker         {
1492*8975f5c5SAndroid Build Coastguard Worker             error(line, "redeclaration of gl_LastFragData as an array of arrays", identifier);
1493*8975f5c5SAndroid Build Coastguard Worker             return false;
1494*8975f5c5SAndroid Build Coastguard Worker         }
1495*8975f5c5SAndroid Build Coastguard Worker         else if (static_cast<int>(type->getOutermostArraySize()) ==
1496*8975f5c5SAndroid Build Coastguard Worker                  maxDrawBuffers->getConstPointer()->getIConst())
1497*8975f5c5SAndroid Build Coastguard Worker         {
1498*8975f5c5SAndroid Build Coastguard Worker             if (const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
1499*8975f5c5SAndroid Build Coastguard Worker             {
1500*8975f5c5SAndroid Build Coastguard Worker                 needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
1501*8975f5c5SAndroid Build Coastguard Worker             }
1502*8975f5c5SAndroid Build Coastguard Worker         }
1503*8975f5c5SAndroid Build Coastguard Worker         else
1504*8975f5c5SAndroid Build Coastguard Worker         {
1505*8975f5c5SAndroid Build Coastguard Worker             error(line, "redeclaration of gl_LastFragData with size != gl_MaxDrawBuffers",
1506*8975f5c5SAndroid Build Coastguard Worker                   identifier);
1507*8975f5c5SAndroid Build Coastguard Worker             return false;
1508*8975f5c5SAndroid Build Coastguard Worker         }
1509*8975f5c5SAndroid Build Coastguard Worker     }
1510*8975f5c5SAndroid Build Coastguard Worker     else if (identifier.beginsWith("gl_LastFragColorARM") ||
1511*8975f5c5SAndroid Build Coastguard Worker              identifier.beginsWith("gl_LastFragDepthARM") ||
1512*8975f5c5SAndroid Build Coastguard Worker              identifier.beginsWith("gl_LastFragStencilARM"))
1513*8975f5c5SAndroid Build Coastguard Worker     {
1514*8975f5c5SAndroid Build Coastguard Worker         // gl_LastFrag{Color,Depth,Stencil}ARM may be redeclared with a new precision qualifier
1515*8975f5c5SAndroid Build Coastguard Worker         if (const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
1516*8975f5c5SAndroid Build Coastguard Worker         {
1517*8975f5c5SAndroid Build Coastguard Worker             needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
1518*8975f5c5SAndroid Build Coastguard Worker         }
1519*8975f5c5SAndroid Build Coastguard Worker     }
1520*8975f5c5SAndroid Build Coastguard Worker     else if (type->isArray() && identifier == "gl_ClipDistance")
1521*8975f5c5SAndroid Build Coastguard Worker     {
1522*8975f5c5SAndroid Build Coastguard Worker         // gl_ClipDistance can be redeclared with smaller size than gl_MaxClipDistances
1523*8975f5c5SAndroid Build Coastguard Worker         const TVariable *maxClipDistances = static_cast<const TVariable *>(
1524*8975f5c5SAndroid Build Coastguard Worker             symbolTable.findBuiltIn(ImmutableString("gl_MaxClipDistances"), mShaderVersion));
1525*8975f5c5SAndroid Build Coastguard Worker         if (!maxClipDistances)
1526*8975f5c5SAndroid Build Coastguard Worker         {
1527*8975f5c5SAndroid Build Coastguard Worker             // Unsupported extension
1528*8975f5c5SAndroid Build Coastguard Worker             needsReservedCheck = true;
1529*8975f5c5SAndroid Build Coastguard Worker         }
1530*8975f5c5SAndroid Build Coastguard Worker         else if (type->isArrayOfArrays())
1531*8975f5c5SAndroid Build Coastguard Worker         {
1532*8975f5c5SAndroid Build Coastguard Worker             error(line, "redeclaration of gl_ClipDistance as an array of arrays", identifier);
1533*8975f5c5SAndroid Build Coastguard Worker             return false;
1534*8975f5c5SAndroid Build Coastguard Worker         }
1535*8975f5c5SAndroid Build Coastguard Worker         else if (static_cast<int>(type->getOutermostArraySize()) <=
1536*8975f5c5SAndroid Build Coastguard Worker                  maxClipDistances->getConstPointer()->getIConst())
1537*8975f5c5SAndroid Build Coastguard Worker         {
1538*8975f5c5SAndroid Build Coastguard Worker             const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion);
1539*8975f5c5SAndroid Build Coastguard Worker             if (builtInSymbol)
1540*8975f5c5SAndroid Build Coastguard Worker             {
1541*8975f5c5SAndroid Build Coastguard Worker                 needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
1542*8975f5c5SAndroid Build Coastguard Worker             }
1543*8975f5c5SAndroid Build Coastguard Worker         }
1544*8975f5c5SAndroid Build Coastguard Worker         else
1545*8975f5c5SAndroid Build Coastguard Worker         {
1546*8975f5c5SAndroid Build Coastguard Worker             error(line, "redeclaration of gl_ClipDistance with size > gl_MaxClipDistances",
1547*8975f5c5SAndroid Build Coastguard Worker                   identifier);
1548*8975f5c5SAndroid Build Coastguard Worker             return false;
1549*8975f5c5SAndroid Build Coastguard Worker         }
1550*8975f5c5SAndroid Build Coastguard Worker     }
1551*8975f5c5SAndroid Build Coastguard Worker     else if (type->isArray() && identifier == "gl_CullDistance")
1552*8975f5c5SAndroid Build Coastguard Worker     {
1553*8975f5c5SAndroid Build Coastguard Worker         // gl_CullDistance can be redeclared with smaller size than gl_MaxCullDistances
1554*8975f5c5SAndroid Build Coastguard Worker         const TVariable *maxCullDistances = static_cast<const TVariable *>(
1555*8975f5c5SAndroid Build Coastguard Worker             symbolTable.findBuiltIn(ImmutableString("gl_MaxCullDistances"), mShaderVersion));
1556*8975f5c5SAndroid Build Coastguard Worker         if (!maxCullDistances)
1557*8975f5c5SAndroid Build Coastguard Worker         {
1558*8975f5c5SAndroid Build Coastguard Worker             // Unsupported extension
1559*8975f5c5SAndroid Build Coastguard Worker             needsReservedCheck = true;
1560*8975f5c5SAndroid Build Coastguard Worker         }
1561*8975f5c5SAndroid Build Coastguard Worker         else if (type->isArrayOfArrays())
1562*8975f5c5SAndroid Build Coastguard Worker         {
1563*8975f5c5SAndroid Build Coastguard Worker             error(line, "redeclaration of gl_CullDistance as an array of arrays", identifier);
1564*8975f5c5SAndroid Build Coastguard Worker             return false;
1565*8975f5c5SAndroid Build Coastguard Worker         }
1566*8975f5c5SAndroid Build Coastguard Worker         else if (static_cast<int>(type->getOutermostArraySize()) <=
1567*8975f5c5SAndroid Build Coastguard Worker                  maxCullDistances->getConstPointer()->getIConst())
1568*8975f5c5SAndroid Build Coastguard Worker         {
1569*8975f5c5SAndroid Build Coastguard Worker             if (const TSymbol *builtInSymbol = symbolTable.findBuiltIn(identifier, mShaderVersion))
1570*8975f5c5SAndroid Build Coastguard Worker             {
1571*8975f5c5SAndroid Build Coastguard Worker                 needsReservedCheck = !checkCanUseOneOfExtensions(line, builtInSymbol->extensions());
1572*8975f5c5SAndroid Build Coastguard Worker             }
1573*8975f5c5SAndroid Build Coastguard Worker         }
1574*8975f5c5SAndroid Build Coastguard Worker         else
1575*8975f5c5SAndroid Build Coastguard Worker         {
1576*8975f5c5SAndroid Build Coastguard Worker             error(line, "redeclaration of gl_CullDistance with size > gl_MaxCullDistances",
1577*8975f5c5SAndroid Build Coastguard Worker                   identifier);
1578*8975f5c5SAndroid Build Coastguard Worker             return false;
1579*8975f5c5SAndroid Build Coastguard Worker         }
1580*8975f5c5SAndroid Build Coastguard Worker     }
1581*8975f5c5SAndroid Build Coastguard Worker     else if (isExtensionEnabled(TExtension::EXT_conservative_depth) &&
1582*8975f5c5SAndroid Build Coastguard Worker              mShaderType == GL_FRAGMENT_SHADER && identifier == "gl_FragDepth")
1583*8975f5c5SAndroid Build Coastguard Worker     {
1584*8975f5c5SAndroid Build Coastguard Worker         if (type->getBasicType() != EbtFloat || type->getNominalSize() != 1 ||
1585*8975f5c5SAndroid Build Coastguard Worker             type->getSecondarySize() != 1 || type->isArray())
1586*8975f5c5SAndroid Build Coastguard Worker         {
1587*8975f5c5SAndroid Build Coastguard Worker             error(line, "gl_FragDepth can only be redeclared as float", identifier);
1588*8975f5c5SAndroid Build Coastguard Worker             return false;
1589*8975f5c5SAndroid Build Coastguard Worker         }
1590*8975f5c5SAndroid Build Coastguard Worker         needsReservedCheck = false;
1591*8975f5c5SAndroid Build Coastguard Worker     }
1592*8975f5c5SAndroid Build Coastguard Worker     else if (isExtensionEnabled(TExtension::EXT_separate_shader_objects) &&
1593*8975f5c5SAndroid Build Coastguard Worker              mShaderType == GL_VERTEX_SHADER)
1594*8975f5c5SAndroid Build Coastguard Worker     {
1595*8975f5c5SAndroid Build Coastguard Worker         bool isRedefiningPositionOrPointSize = false;
1596*8975f5c5SAndroid Build Coastguard Worker         if (identifier == "gl_Position")
1597*8975f5c5SAndroid Build Coastguard Worker         {
1598*8975f5c5SAndroid Build Coastguard Worker             if (type->getBasicType() != EbtFloat || type->getNominalSize() != 4 ||
1599*8975f5c5SAndroid Build Coastguard Worker                 type->getSecondarySize() != 1 || type->isArray())
1600*8975f5c5SAndroid Build Coastguard Worker             {
1601*8975f5c5SAndroid Build Coastguard Worker                 error(line, "gl_Position can only be redeclared as vec4", identifier);
1602*8975f5c5SAndroid Build Coastguard Worker                 return false;
1603*8975f5c5SAndroid Build Coastguard Worker             }
1604*8975f5c5SAndroid Build Coastguard Worker             needsReservedCheck                         = false;
1605*8975f5c5SAndroid Build Coastguard Worker             mPositionRedeclaredForSeparateShaderObject = true;
1606*8975f5c5SAndroid Build Coastguard Worker             isRedefiningPositionOrPointSize            = true;
1607*8975f5c5SAndroid Build Coastguard Worker         }
1608*8975f5c5SAndroid Build Coastguard Worker         else if (identifier == "gl_PointSize")
1609*8975f5c5SAndroid Build Coastguard Worker         {
1610*8975f5c5SAndroid Build Coastguard Worker             if (type->getBasicType() != EbtFloat || type->getNominalSize() != 1 ||
1611*8975f5c5SAndroid Build Coastguard Worker                 type->getSecondarySize() != 1 || type->isArray())
1612*8975f5c5SAndroid Build Coastguard Worker             {
1613*8975f5c5SAndroid Build Coastguard Worker                 error(line, "gl_PointSize can only be redeclared as float", identifier);
1614*8975f5c5SAndroid Build Coastguard Worker                 return false;
1615*8975f5c5SAndroid Build Coastguard Worker             }
1616*8975f5c5SAndroid Build Coastguard Worker             needsReservedCheck                          = false;
1617*8975f5c5SAndroid Build Coastguard Worker             mPointSizeRedeclaredForSeparateShaderObject = true;
1618*8975f5c5SAndroid Build Coastguard Worker             isRedefiningPositionOrPointSize             = true;
1619*8975f5c5SAndroid Build Coastguard Worker         }
1620*8975f5c5SAndroid Build Coastguard Worker         if (isRedefiningPositionOrPointSize && mPositionOrPointSizeUsedForSeparateShaderObject)
1621*8975f5c5SAndroid Build Coastguard Worker         {
1622*8975f5c5SAndroid Build Coastguard Worker             error(line,
1623*8975f5c5SAndroid Build Coastguard Worker                   "When EXT_separate_shader_objects is enabled, both gl_Position and "
1624*8975f5c5SAndroid Build Coastguard Worker                   "gl_PointSize must be redeclared before either is used",
1625*8975f5c5SAndroid Build Coastguard Worker                   identifier);
1626*8975f5c5SAndroid Build Coastguard Worker         }
1627*8975f5c5SAndroid Build Coastguard Worker     }
1628*8975f5c5SAndroid Build Coastguard Worker 
1629*8975f5c5SAndroid Build Coastguard Worker     if (needsReservedCheck && !checkIsNotReserved(line, identifier))
1630*8975f5c5SAndroid Build Coastguard Worker         return false;
1631*8975f5c5SAndroid Build Coastguard Worker 
1632*8975f5c5SAndroid Build Coastguard Worker     if (!symbolTable.declare(*variable))
1633*8975f5c5SAndroid Build Coastguard Worker     {
1634*8975f5c5SAndroid Build Coastguard Worker         error(line, "redefinition", identifier);
1635*8975f5c5SAndroid Build Coastguard Worker         return false;
1636*8975f5c5SAndroid Build Coastguard Worker     }
1637*8975f5c5SAndroid Build Coastguard Worker 
1638*8975f5c5SAndroid Build Coastguard Worker     if (!checkIsNonVoid(line, identifier, type->getBasicType()))
1639*8975f5c5SAndroid Build Coastguard Worker         return false;
1640*8975f5c5SAndroid Build Coastguard Worker 
1641*8975f5c5SAndroid Build Coastguard Worker     return true;
1642*8975f5c5SAndroid Build Coastguard Worker }
1643*8975f5c5SAndroid Build Coastguard Worker 
parseParameterQualifier(const TSourceLoc & line,const TTypeQualifierBuilder & typeQualifierBuilder,TPublicType & type)1644*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseParameterQualifier(const TSourceLoc &line,
1645*8975f5c5SAndroid Build Coastguard Worker                                             const TTypeQualifierBuilder &typeQualifierBuilder,
1646*8975f5c5SAndroid Build Coastguard Worker                                             TPublicType &type)
1647*8975f5c5SAndroid Build Coastguard Worker {
1648*8975f5c5SAndroid Build Coastguard Worker     // The only parameter qualifiers a parameter can have are in, out, inout or const.
1649*8975f5c5SAndroid Build Coastguard Worker     TTypeQualifier typeQualifier =
1650*8975f5c5SAndroid Build Coastguard Worker         typeQualifierBuilder.getParameterTypeQualifier(type.getBasicType(), mDiagnostics);
1651*8975f5c5SAndroid Build Coastguard Worker 
1652*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.qualifier == EvqParamOut || typeQualifier.qualifier == EvqParamInOut)
1653*8975f5c5SAndroid Build Coastguard Worker     {
1654*8975f5c5SAndroid Build Coastguard Worker         if (IsOpaqueType(type.getBasicType()))
1655*8975f5c5SAndroid Build Coastguard Worker         {
1656*8975f5c5SAndroid Build Coastguard Worker             error(line, "opaque types cannot be output parameters", type.getBasicString());
1657*8975f5c5SAndroid Build Coastguard Worker         }
1658*8975f5c5SAndroid Build Coastguard Worker     }
1659*8975f5c5SAndroid Build Coastguard Worker 
1660*8975f5c5SAndroid Build Coastguard Worker     if (!IsImage(type.getBasicType()))
1661*8975f5c5SAndroid Build Coastguard Worker     {
1662*8975f5c5SAndroid Build Coastguard Worker         checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, line);
1663*8975f5c5SAndroid Build Coastguard Worker     }
1664*8975f5c5SAndroid Build Coastguard Worker     else
1665*8975f5c5SAndroid Build Coastguard Worker     {
1666*8975f5c5SAndroid Build Coastguard Worker         type.setMemoryQualifier(typeQualifier.memoryQualifier);
1667*8975f5c5SAndroid Build Coastguard Worker     }
1668*8975f5c5SAndroid Build Coastguard Worker 
1669*8975f5c5SAndroid Build Coastguard Worker     type.setQualifier(typeQualifier.qualifier);
1670*8975f5c5SAndroid Build Coastguard Worker 
1671*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.precision != EbpUndefined)
1672*8975f5c5SAndroid Build Coastguard Worker     {
1673*8975f5c5SAndroid Build Coastguard Worker         type.setPrecision(typeQualifier.precision);
1674*8975f5c5SAndroid Build Coastguard Worker     }
1675*8975f5c5SAndroid Build Coastguard Worker 
1676*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.precise)
1677*8975f5c5SAndroid Build Coastguard Worker     {
1678*8975f5c5SAndroid Build Coastguard Worker         type.setPrecise(true);
1679*8975f5c5SAndroid Build Coastguard Worker     }
1680*8975f5c5SAndroid Build Coastguard Worker }
1681*8975f5c5SAndroid Build Coastguard Worker 
1682*8975f5c5SAndroid Build Coastguard Worker template <size_t size>
checkCanUseOneOfExtensions(const TSourceLoc & line,const std::array<TExtension,size> & extensions)1683*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkCanUseOneOfExtensions(const TSourceLoc &line,
1684*8975f5c5SAndroid Build Coastguard Worker                                                const std::array<TExtension, size> &extensions)
1685*8975f5c5SAndroid Build Coastguard Worker {
1686*8975f5c5SAndroid Build Coastguard Worker     ASSERT(!extensions.empty());
1687*8975f5c5SAndroid Build Coastguard Worker     const TExtensionBehavior &extBehavior = extensionBehavior();
1688*8975f5c5SAndroid Build Coastguard Worker 
1689*8975f5c5SAndroid Build Coastguard Worker     bool canUseWithWarning    = false;
1690*8975f5c5SAndroid Build Coastguard Worker     bool canUseWithoutWarning = false;
1691*8975f5c5SAndroid Build Coastguard Worker 
1692*8975f5c5SAndroid Build Coastguard Worker     const char *errorMsgString   = "";
1693*8975f5c5SAndroid Build Coastguard Worker     TExtension errorMsgExtension = TExtension::UNDEFINED;
1694*8975f5c5SAndroid Build Coastguard Worker 
1695*8975f5c5SAndroid Build Coastguard Worker     for (TExtension extension : extensions)
1696*8975f5c5SAndroid Build Coastguard Worker     {
1697*8975f5c5SAndroid Build Coastguard Worker         auto extIter = extBehavior.find(extension);
1698*8975f5c5SAndroid Build Coastguard Worker         if (canUseWithWarning)
1699*8975f5c5SAndroid Build Coastguard Worker         {
1700*8975f5c5SAndroid Build Coastguard Worker             // We already have an extension that we can use, but with a warning.
1701*8975f5c5SAndroid Build Coastguard Worker             // See if we can use the alternative extension without a warning.
1702*8975f5c5SAndroid Build Coastguard Worker             if (extIter == extBehavior.end())
1703*8975f5c5SAndroid Build Coastguard Worker             {
1704*8975f5c5SAndroid Build Coastguard Worker                 continue;
1705*8975f5c5SAndroid Build Coastguard Worker             }
1706*8975f5c5SAndroid Build Coastguard Worker             if (extIter->second == EBhEnable || extIter->second == EBhRequire)
1707*8975f5c5SAndroid Build Coastguard Worker             {
1708*8975f5c5SAndroid Build Coastguard Worker                 canUseWithoutWarning = true;
1709*8975f5c5SAndroid Build Coastguard Worker                 break;
1710*8975f5c5SAndroid Build Coastguard Worker             }
1711*8975f5c5SAndroid Build Coastguard Worker             continue;
1712*8975f5c5SAndroid Build Coastguard Worker         }
1713*8975f5c5SAndroid Build Coastguard Worker         if (extension == TExtension::UNDEFINED)
1714*8975f5c5SAndroid Build Coastguard Worker         {
1715*8975f5c5SAndroid Build Coastguard Worker             continue;
1716*8975f5c5SAndroid Build Coastguard Worker         }
1717*8975f5c5SAndroid Build Coastguard Worker         else if (extIter == extBehavior.end())
1718*8975f5c5SAndroid Build Coastguard Worker         {
1719*8975f5c5SAndroid Build Coastguard Worker             errorMsgString    = "extension is not supported";
1720*8975f5c5SAndroid Build Coastguard Worker             errorMsgExtension = extension;
1721*8975f5c5SAndroid Build Coastguard Worker         }
1722*8975f5c5SAndroid Build Coastguard Worker         else if (extIter->second == EBhUndefined || extIter->second == EBhDisable)
1723*8975f5c5SAndroid Build Coastguard Worker         {
1724*8975f5c5SAndroid Build Coastguard Worker             errorMsgString    = "extension is disabled";
1725*8975f5c5SAndroid Build Coastguard Worker             errorMsgExtension = extension;
1726*8975f5c5SAndroid Build Coastguard Worker         }
1727*8975f5c5SAndroid Build Coastguard Worker         else if (extIter->second == EBhWarn)
1728*8975f5c5SAndroid Build Coastguard Worker         {
1729*8975f5c5SAndroid Build Coastguard Worker             errorMsgExtension = extension;
1730*8975f5c5SAndroid Build Coastguard Worker             canUseWithWarning = true;
1731*8975f5c5SAndroid Build Coastguard Worker         }
1732*8975f5c5SAndroid Build Coastguard Worker         else
1733*8975f5c5SAndroid Build Coastguard Worker         {
1734*8975f5c5SAndroid Build Coastguard Worker             ASSERT(extIter->second == EBhEnable || extIter->second == EBhRequire);
1735*8975f5c5SAndroid Build Coastguard Worker             canUseWithoutWarning = true;
1736*8975f5c5SAndroid Build Coastguard Worker             break;
1737*8975f5c5SAndroid Build Coastguard Worker         }
1738*8975f5c5SAndroid Build Coastguard Worker     }
1739*8975f5c5SAndroid Build Coastguard Worker 
1740*8975f5c5SAndroid Build Coastguard Worker     if (canUseWithoutWarning)
1741*8975f5c5SAndroid Build Coastguard Worker     {
1742*8975f5c5SAndroid Build Coastguard Worker         return true;
1743*8975f5c5SAndroid Build Coastguard Worker     }
1744*8975f5c5SAndroid Build Coastguard Worker     if (canUseWithWarning)
1745*8975f5c5SAndroid Build Coastguard Worker     {
1746*8975f5c5SAndroid Build Coastguard Worker         warning(line, "extension is being used", GetExtensionNameString(errorMsgExtension));
1747*8975f5c5SAndroid Build Coastguard Worker         return true;
1748*8975f5c5SAndroid Build Coastguard Worker     }
1749*8975f5c5SAndroid Build Coastguard Worker     error(line, errorMsgString, GetExtensionNameString(errorMsgExtension));
1750*8975f5c5SAndroid Build Coastguard Worker     return false;
1751*8975f5c5SAndroid Build Coastguard Worker }
1752*8975f5c5SAndroid Build Coastguard Worker 
1753*8975f5c5SAndroid Build Coastguard Worker template bool TParseContext::checkCanUseOneOfExtensions(
1754*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &line,
1755*8975f5c5SAndroid Build Coastguard Worker     const std::array<TExtension, 1> &extensions);
1756*8975f5c5SAndroid Build Coastguard Worker template bool TParseContext::checkCanUseOneOfExtensions(
1757*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &line,
1758*8975f5c5SAndroid Build Coastguard Worker     const std::array<TExtension, 2> &extensions);
1759*8975f5c5SAndroid Build Coastguard Worker template bool TParseContext::checkCanUseOneOfExtensions(
1760*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &line,
1761*8975f5c5SAndroid Build Coastguard Worker     const std::array<TExtension, 3> &extensions);
1762*8975f5c5SAndroid Build Coastguard Worker 
checkCanUseExtension(const TSourceLoc & line,TExtension extension)1763*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkCanUseExtension(const TSourceLoc &line, TExtension extension)
1764*8975f5c5SAndroid Build Coastguard Worker {
1765*8975f5c5SAndroid Build Coastguard Worker     ASSERT(extension != TExtension::UNDEFINED);
1766*8975f5c5SAndroid Build Coastguard Worker     return checkCanUseOneOfExtensions(line, std::array<TExtension, 1u>{{extension}});
1767*8975f5c5SAndroid Build Coastguard Worker }
1768*8975f5c5SAndroid Build Coastguard Worker 
1769*8975f5c5SAndroid Build Coastguard Worker // ESSL 3.00.6 section 4.8 Empty Declarations: "The combinations of qualifiers that cause
1770*8975f5c5SAndroid Build Coastguard Worker // compile-time or link-time errors are the same whether or not the declaration is empty".
1771*8975f5c5SAndroid Build Coastguard Worker // This function implements all the checks that are done on qualifiers regardless of if the
1772*8975f5c5SAndroid Build Coastguard Worker // declaration is empty.
declarationQualifierErrorCheck(const sh::TQualifier qualifier,const sh::TLayoutQualifier & layoutQualifier,const TSourceLoc & location)1773*8975f5c5SAndroid Build Coastguard Worker void TParseContext::declarationQualifierErrorCheck(const sh::TQualifier qualifier,
1774*8975f5c5SAndroid Build Coastguard Worker                                                    const sh::TLayoutQualifier &layoutQualifier,
1775*8975f5c5SAndroid Build Coastguard Worker                                                    const TSourceLoc &location)
1776*8975f5c5SAndroid Build Coastguard Worker {
1777*8975f5c5SAndroid Build Coastguard Worker     if (qualifier == EvqShared && !layoutQualifier.isEmpty())
1778*8975f5c5SAndroid Build Coastguard Worker     {
1779*8975f5c5SAndroid Build Coastguard Worker         error(location, "Shared memory declarations cannot have layout specified", "layout");
1780*8975f5c5SAndroid Build Coastguard Worker     }
1781*8975f5c5SAndroid Build Coastguard Worker 
1782*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.matrixPacking != EmpUnspecified)
1783*8975f5c5SAndroid Build Coastguard Worker     {
1784*8975f5c5SAndroid Build Coastguard Worker         error(location, "layout qualifier only valid for interface blocks",
1785*8975f5c5SAndroid Build Coastguard Worker               getMatrixPackingString(layoutQualifier.matrixPacking));
1786*8975f5c5SAndroid Build Coastguard Worker         return;
1787*8975f5c5SAndroid Build Coastguard Worker     }
1788*8975f5c5SAndroid Build Coastguard Worker 
1789*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.blockStorage != EbsUnspecified)
1790*8975f5c5SAndroid Build Coastguard Worker     {
1791*8975f5c5SAndroid Build Coastguard Worker         error(location, "layout qualifier only valid for interface blocks",
1792*8975f5c5SAndroid Build Coastguard Worker               getBlockStorageString(layoutQualifier.blockStorage));
1793*8975f5c5SAndroid Build Coastguard Worker         return;
1794*8975f5c5SAndroid Build Coastguard Worker     }
1795*8975f5c5SAndroid Build Coastguard Worker 
1796*8975f5c5SAndroid Build Coastguard Worker     if (qualifier != EvqFragDepth)
1797*8975f5c5SAndroid Build Coastguard Worker     {
1798*8975f5c5SAndroid Build Coastguard Worker         checkDepthIsNotSpecified(location, layoutQualifier.depth);
1799*8975f5c5SAndroid Build Coastguard Worker     }
1800*8975f5c5SAndroid Build Coastguard Worker 
1801*8975f5c5SAndroid Build Coastguard Worker     if (qualifier == EvqFragmentOut)
1802*8975f5c5SAndroid Build Coastguard Worker     {
1803*8975f5c5SAndroid Build Coastguard Worker         if (layoutQualifier.location != -1 && layoutQualifier.yuv == true)
1804*8975f5c5SAndroid Build Coastguard Worker         {
1805*8975f5c5SAndroid Build Coastguard Worker             error(location, "invalid layout qualifier combination", "yuv");
1806*8975f5c5SAndroid Build Coastguard Worker             return;
1807*8975f5c5SAndroid Build Coastguard Worker         }
1808*8975f5c5SAndroid Build Coastguard Worker     }
1809*8975f5c5SAndroid Build Coastguard Worker     else
1810*8975f5c5SAndroid Build Coastguard Worker     {
1811*8975f5c5SAndroid Build Coastguard Worker         checkYuvIsNotSpecified(location, layoutQualifier.yuv);
1812*8975f5c5SAndroid Build Coastguard Worker     }
1813*8975f5c5SAndroid Build Coastguard Worker 
1814*8975f5c5SAndroid Build Coastguard Worker     if (qualifier != EvqFragmentIn)
1815*8975f5c5SAndroid Build Coastguard Worker     {
1816*8975f5c5SAndroid Build Coastguard Worker         checkEarlyFragmentTestsIsNotSpecified(location, layoutQualifier.earlyFragmentTests);
1817*8975f5c5SAndroid Build Coastguard Worker     }
1818*8975f5c5SAndroid Build Coastguard Worker 
1819*8975f5c5SAndroid Build Coastguard Worker     // If multiview extension is enabled, "in" qualifier is allowed in the vertex shader in previous
1820*8975f5c5SAndroid Build Coastguard Worker     // parsing steps. So it needs to be checked here.
1821*8975f5c5SAndroid Build Coastguard Worker     if (anyMultiviewExtensionAvailable() && mShaderVersion < 300 && qualifier == EvqVertexIn)
1822*8975f5c5SAndroid Build Coastguard Worker     {
1823*8975f5c5SAndroid Build Coastguard Worker         error(location, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
1824*8975f5c5SAndroid Build Coastguard Worker     }
1825*8975f5c5SAndroid Build Coastguard Worker 
1826*8975f5c5SAndroid Build Coastguard Worker     bool canHaveLocation = qualifier == EvqVertexIn || qualifier == EvqFragmentOut;
1827*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion >= 300 &&
1828*8975f5c5SAndroid Build Coastguard Worker         (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) ||
1829*8975f5c5SAndroid Build Coastguard Worker          isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent)))
1830*8975f5c5SAndroid Build Coastguard Worker     {
1831*8975f5c5SAndroid Build Coastguard Worker         // In the case of EXT_shader_framebuffer_fetch or EXT_shader_framebuffer_fetch_non_coherent
1832*8975f5c5SAndroid Build Coastguard Worker         // extension, the location of inout qualifier is used to set the input attachment index
1833*8975f5c5SAndroid Build Coastguard Worker         canHaveLocation = canHaveLocation || qualifier == EvqFragmentInOut;
1834*8975f5c5SAndroid Build Coastguard Worker     }
1835*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion >= 310)
1836*8975f5c5SAndroid Build Coastguard Worker     {
1837*8975f5c5SAndroid Build Coastguard Worker         canHaveLocation = canHaveLocation || qualifier == EvqUniform || IsVarying(qualifier);
1838*8975f5c5SAndroid Build Coastguard Worker         // We're not checking whether the uniform location is in range here since that depends on
1839*8975f5c5SAndroid Build Coastguard Worker         // the type of the variable.
1840*8975f5c5SAndroid Build Coastguard Worker         // The type can only be fully determined for non-empty declarations.
1841*8975f5c5SAndroid Build Coastguard Worker     }
1842*8975f5c5SAndroid Build Coastguard Worker     if (!canHaveLocation)
1843*8975f5c5SAndroid Build Coastguard Worker     {
1844*8975f5c5SAndroid Build Coastguard Worker         checkLocationIsNotSpecified(location, layoutQualifier);
1845*8975f5c5SAndroid Build Coastguard Worker     }
1846*8975f5c5SAndroid Build Coastguard Worker }
1847*8975f5c5SAndroid Build Coastguard Worker 
atomicCounterQualifierErrorCheck(const TPublicType & publicType,const TSourceLoc & location)1848*8975f5c5SAndroid Build Coastguard Worker void TParseContext::atomicCounterQualifierErrorCheck(const TPublicType &publicType,
1849*8975f5c5SAndroid Build Coastguard Worker                                                      const TSourceLoc &location)
1850*8975f5c5SAndroid Build Coastguard Worker {
1851*8975f5c5SAndroid Build Coastguard Worker     if (publicType.precision != EbpHigh)
1852*8975f5c5SAndroid Build Coastguard Worker     {
1853*8975f5c5SAndroid Build Coastguard Worker         error(location, "Can only be highp", "atomic counter");
1854*8975f5c5SAndroid Build Coastguard Worker     }
1855*8975f5c5SAndroid Build Coastguard Worker     // dEQP enforces compile error if location is specified. See uniform_location.test.
1856*8975f5c5SAndroid Build Coastguard Worker     if (publicType.layoutQualifier.location != -1)
1857*8975f5c5SAndroid Build Coastguard Worker     {
1858*8975f5c5SAndroid Build Coastguard Worker         error(location, "location must not be set for atomic_uint", "layout");
1859*8975f5c5SAndroid Build Coastguard Worker     }
1860*8975f5c5SAndroid Build Coastguard Worker     if (publicType.layoutQualifier.binding == -1)
1861*8975f5c5SAndroid Build Coastguard Worker     {
1862*8975f5c5SAndroid Build Coastguard Worker         error(location, "no binding specified", "atomic counter");
1863*8975f5c5SAndroid Build Coastguard Worker     }
1864*8975f5c5SAndroid Build Coastguard Worker }
1865*8975f5c5SAndroid Build Coastguard Worker 
emptyDeclarationErrorCheck(const TType & type,const TSourceLoc & location)1866*8975f5c5SAndroid Build Coastguard Worker void TParseContext::emptyDeclarationErrorCheck(const TType &type, const TSourceLoc &location)
1867*8975f5c5SAndroid Build Coastguard Worker {
1868*8975f5c5SAndroid Build Coastguard Worker     if (type.isUnsizedArray())
1869*8975f5c5SAndroid Build Coastguard Worker     {
1870*8975f5c5SAndroid Build Coastguard Worker         // ESSL3 spec section 4.1.9: Array declaration which leaves the size unspecified is an
1871*8975f5c5SAndroid Build Coastguard Worker         // error. It is assumed that this applies to empty declarations as well.
1872*8975f5c5SAndroid Build Coastguard Worker         error(location, "empty array declaration needs to specify a size", "");
1873*8975f5c5SAndroid Build Coastguard Worker     }
1874*8975f5c5SAndroid Build Coastguard Worker 
1875*8975f5c5SAndroid Build Coastguard Worker     if (type.getQualifier() != EvqFragmentOut)
1876*8975f5c5SAndroid Build Coastguard Worker     {
1877*8975f5c5SAndroid Build Coastguard Worker         checkIndexIsNotSpecified(location, type.getLayoutQualifier().index);
1878*8975f5c5SAndroid Build Coastguard Worker     }
1879*8975f5c5SAndroid Build Coastguard Worker }
1880*8975f5c5SAndroid Build Coastguard Worker 
1881*8975f5c5SAndroid Build Coastguard Worker // These checks are done for all declarations that are non-empty. They're done for non-empty
1882*8975f5c5SAndroid Build Coastguard Worker // declarations starting a declarator list, and declarators that follow an empty declaration.
nonEmptyDeclarationErrorCheck(const TPublicType & publicType,const TSourceLoc & identifierLocation)1883*8975f5c5SAndroid Build Coastguard Worker void TParseContext::nonEmptyDeclarationErrorCheck(const TPublicType &publicType,
1884*8975f5c5SAndroid Build Coastguard Worker                                                   const TSourceLoc &identifierLocation)
1885*8975f5c5SAndroid Build Coastguard Worker {
1886*8975f5c5SAndroid Build Coastguard Worker     switch (publicType.qualifier)
1887*8975f5c5SAndroid Build Coastguard Worker     {
1888*8975f5c5SAndroid Build Coastguard Worker         case EvqVaryingIn:
1889*8975f5c5SAndroid Build Coastguard Worker         case EvqVaryingOut:
1890*8975f5c5SAndroid Build Coastguard Worker         case EvqAttribute:
1891*8975f5c5SAndroid Build Coastguard Worker         case EvqVertexIn:
1892*8975f5c5SAndroid Build Coastguard Worker         case EvqFragmentOut:
1893*8975f5c5SAndroid Build Coastguard Worker         case EvqFragmentInOut:
1894*8975f5c5SAndroid Build Coastguard Worker         case EvqComputeIn:
1895*8975f5c5SAndroid Build Coastguard Worker             if (publicType.getBasicType() == EbtStruct)
1896*8975f5c5SAndroid Build Coastguard Worker             {
1897*8975f5c5SAndroid Build Coastguard Worker                 error(identifierLocation, "cannot be used with a structure",
1898*8975f5c5SAndroid Build Coastguard Worker                       getQualifierString(publicType.qualifier));
1899*8975f5c5SAndroid Build Coastguard Worker                 return;
1900*8975f5c5SAndroid Build Coastguard Worker             }
1901*8975f5c5SAndroid Build Coastguard Worker             break;
1902*8975f5c5SAndroid Build Coastguard Worker         case EvqBuffer:
1903*8975f5c5SAndroid Build Coastguard Worker             if (publicType.getBasicType() != EbtInterfaceBlock)
1904*8975f5c5SAndroid Build Coastguard Worker             {
1905*8975f5c5SAndroid Build Coastguard Worker                 error(identifierLocation,
1906*8975f5c5SAndroid Build Coastguard Worker                       "cannot declare buffer variables at global scope(outside a block)",
1907*8975f5c5SAndroid Build Coastguard Worker                       getQualifierString(publicType.qualifier));
1908*8975f5c5SAndroid Build Coastguard Worker                 return;
1909*8975f5c5SAndroid Build Coastguard Worker             }
1910*8975f5c5SAndroid Build Coastguard Worker             break;
1911*8975f5c5SAndroid Build Coastguard Worker         default:
1912*8975f5c5SAndroid Build Coastguard Worker             break;
1913*8975f5c5SAndroid Build Coastguard Worker     }
1914*8975f5c5SAndroid Build Coastguard Worker     std::string reason(getBasicString(publicType.getBasicType()));
1915*8975f5c5SAndroid Build Coastguard Worker     reason += "s must be uniform";
1916*8975f5c5SAndroid Build Coastguard Worker     if (publicType.qualifier != EvqUniform &&
1917*8975f5c5SAndroid Build Coastguard Worker         !checkIsNotOpaqueType(identifierLocation, publicType.typeSpecifierNonArray, reason.c_str()))
1918*8975f5c5SAndroid Build Coastguard Worker     {
1919*8975f5c5SAndroid Build Coastguard Worker         return;
1920*8975f5c5SAndroid Build Coastguard Worker     }
1921*8975f5c5SAndroid Build Coastguard Worker 
1922*8975f5c5SAndroid Build Coastguard Worker     if ((publicType.qualifier != EvqTemporary && publicType.qualifier != EvqGlobal &&
1923*8975f5c5SAndroid Build Coastguard Worker          publicType.qualifier != EvqConst) &&
1924*8975f5c5SAndroid Build Coastguard Worker         publicType.getBasicType() == EbtYuvCscStandardEXT)
1925*8975f5c5SAndroid Build Coastguard Worker     {
1926*8975f5c5SAndroid Build Coastguard Worker         error(identifierLocation, "cannot be used with a yuvCscStandardEXT",
1927*8975f5c5SAndroid Build Coastguard Worker               getQualifierString(publicType.qualifier));
1928*8975f5c5SAndroid Build Coastguard Worker         return;
1929*8975f5c5SAndroid Build Coastguard Worker     }
1930*8975f5c5SAndroid Build Coastguard Worker 
1931*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion >= 310 && publicType.qualifier == EvqUniform)
1932*8975f5c5SAndroid Build Coastguard Worker     {
1933*8975f5c5SAndroid Build Coastguard Worker         // Valid uniform declarations can't be unsized arrays since uniforms can't be initialized.
1934*8975f5c5SAndroid Build Coastguard Worker         // But invalid shaders may still reach here with an unsized array declaration.
1935*8975f5c5SAndroid Build Coastguard Worker         TType type(publicType);
1936*8975f5c5SAndroid Build Coastguard Worker         if (!type.isUnsizedArray())
1937*8975f5c5SAndroid Build Coastguard Worker         {
1938*8975f5c5SAndroid Build Coastguard Worker             checkUniformLocationInRange(identifierLocation, type.getLocationCount(),
1939*8975f5c5SAndroid Build Coastguard Worker                                         publicType.layoutQualifier);
1940*8975f5c5SAndroid Build Coastguard Worker         }
1941*8975f5c5SAndroid Build Coastguard Worker     }
1942*8975f5c5SAndroid Build Coastguard Worker 
1943*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion >= 300 && publicType.qualifier == EvqVertexIn)
1944*8975f5c5SAndroid Build Coastguard Worker     {
1945*8975f5c5SAndroid Build Coastguard Worker         // Valid vertex input declarations can't be unsized arrays since they can't be initialized.
1946*8975f5c5SAndroid Build Coastguard Worker         // But invalid shaders may still reach here with an unsized array declaration.
1947*8975f5c5SAndroid Build Coastguard Worker         TType type(publicType);
1948*8975f5c5SAndroid Build Coastguard Worker         if (!type.isUnsizedArray())
1949*8975f5c5SAndroid Build Coastguard Worker         {
1950*8975f5c5SAndroid Build Coastguard Worker             checkAttributeLocationInRange(identifierLocation, type.getLocationCount(),
1951*8975f5c5SAndroid Build Coastguard Worker                                           publicType.layoutQualifier);
1952*8975f5c5SAndroid Build Coastguard Worker         }
1953*8975f5c5SAndroid Build Coastguard Worker     }
1954*8975f5c5SAndroid Build Coastguard Worker 
1955*8975f5c5SAndroid Build Coastguard Worker     // check for layout qualifier issues
1956*8975f5c5SAndroid Build Coastguard Worker     const TLayoutQualifier layoutQualifier = publicType.layoutQualifier;
1957*8975f5c5SAndroid Build Coastguard Worker 
1958*8975f5c5SAndroid Build Coastguard Worker     if (IsImage(publicType.getBasicType()))
1959*8975f5c5SAndroid Build Coastguard Worker     {
1960*8975f5c5SAndroid Build Coastguard Worker 
1961*8975f5c5SAndroid Build Coastguard Worker         switch (layoutQualifier.imageInternalFormat)
1962*8975f5c5SAndroid Build Coastguard Worker         {
1963*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA32F:
1964*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA16F:
1965*8975f5c5SAndroid Build Coastguard Worker             case EiifR32F:
1966*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA8:
1967*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA8_SNORM:
1968*8975f5c5SAndroid Build Coastguard Worker                 if (!IsFloatImage(publicType.getBasicType()))
1969*8975f5c5SAndroid Build Coastguard Worker                 {
1970*8975f5c5SAndroid Build Coastguard Worker                     error(identifierLocation,
1971*8975f5c5SAndroid Build Coastguard Worker                           "internal image format requires a floating image type",
1972*8975f5c5SAndroid Build Coastguard Worker                           getBasicString(publicType.getBasicType()));
1973*8975f5c5SAndroid Build Coastguard Worker                     return;
1974*8975f5c5SAndroid Build Coastguard Worker                 }
1975*8975f5c5SAndroid Build Coastguard Worker                 break;
1976*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA32I:
1977*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA16I:
1978*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA8I:
1979*8975f5c5SAndroid Build Coastguard Worker             case EiifR32I:
1980*8975f5c5SAndroid Build Coastguard Worker                 if (!IsIntegerImage(publicType.getBasicType()))
1981*8975f5c5SAndroid Build Coastguard Worker                 {
1982*8975f5c5SAndroid Build Coastguard Worker                     error(identifierLocation,
1983*8975f5c5SAndroid Build Coastguard Worker                           "internal image format requires an integer image type",
1984*8975f5c5SAndroid Build Coastguard Worker                           getBasicString(publicType.getBasicType()));
1985*8975f5c5SAndroid Build Coastguard Worker                     return;
1986*8975f5c5SAndroid Build Coastguard Worker                 }
1987*8975f5c5SAndroid Build Coastguard Worker                 break;
1988*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA32UI:
1989*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA16UI:
1990*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA8UI:
1991*8975f5c5SAndroid Build Coastguard Worker             case EiifR32UI:
1992*8975f5c5SAndroid Build Coastguard Worker                 if (!IsUnsignedImage(publicType.getBasicType()))
1993*8975f5c5SAndroid Build Coastguard Worker                 {
1994*8975f5c5SAndroid Build Coastguard Worker                     error(identifierLocation,
1995*8975f5c5SAndroid Build Coastguard Worker                           "internal image format requires an unsigned image type",
1996*8975f5c5SAndroid Build Coastguard Worker                           getBasicString(publicType.getBasicType()));
1997*8975f5c5SAndroid Build Coastguard Worker                     return;
1998*8975f5c5SAndroid Build Coastguard Worker                 }
1999*8975f5c5SAndroid Build Coastguard Worker                 break;
2000*8975f5c5SAndroid Build Coastguard Worker             case EiifUnspecified:
2001*8975f5c5SAndroid Build Coastguard Worker                 error(identifierLocation, "layout qualifier", "No image internal format specified");
2002*8975f5c5SAndroid Build Coastguard Worker                 return;
2003*8975f5c5SAndroid Build Coastguard Worker             default:
2004*8975f5c5SAndroid Build Coastguard Worker                 error(identifierLocation, "layout qualifier", "unrecognized token");
2005*8975f5c5SAndroid Build Coastguard Worker                 return;
2006*8975f5c5SAndroid Build Coastguard Worker         }
2007*8975f5c5SAndroid Build Coastguard Worker 
2008*8975f5c5SAndroid Build Coastguard Worker         // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
2009*8975f5c5SAndroid Build Coastguard Worker         switch (layoutQualifier.imageInternalFormat)
2010*8975f5c5SAndroid Build Coastguard Worker         {
2011*8975f5c5SAndroid Build Coastguard Worker             case EiifR32F:
2012*8975f5c5SAndroid Build Coastguard Worker             case EiifR32I:
2013*8975f5c5SAndroid Build Coastguard Worker             case EiifR32UI:
2014*8975f5c5SAndroid Build Coastguard Worker                 break;
2015*8975f5c5SAndroid Build Coastguard Worker             default:
2016*8975f5c5SAndroid Build Coastguard Worker                 if (!publicType.memoryQualifier.readonly && !publicType.memoryQualifier.writeonly)
2017*8975f5c5SAndroid Build Coastguard Worker                 {
2018*8975f5c5SAndroid Build Coastguard Worker                     error(identifierLocation, "layout qualifier",
2019*8975f5c5SAndroid Build Coastguard Worker                           "Except for images with the r32f, r32i and r32ui format qualifiers, "
2020*8975f5c5SAndroid Build Coastguard Worker                           "image variables must be qualified readonly and/or writeonly");
2021*8975f5c5SAndroid Build Coastguard Worker                     return;
2022*8975f5c5SAndroid Build Coastguard Worker                 }
2023*8975f5c5SAndroid Build Coastguard Worker                 break;
2024*8975f5c5SAndroid Build Coastguard Worker         }
2025*8975f5c5SAndroid Build Coastguard Worker     }
2026*8975f5c5SAndroid Build Coastguard Worker     else if (IsPixelLocal(publicType.getBasicType()))
2027*8975f5c5SAndroid Build Coastguard Worker     {
2028*8975f5c5SAndroid Build Coastguard Worker         if (getShaderType() != GL_FRAGMENT_SHADER)
2029*8975f5c5SAndroid Build Coastguard Worker         {
2030*8975f5c5SAndroid Build Coastguard Worker             error(identifierLocation,
2031*8975f5c5SAndroid Build Coastguard Worker                   "undefined use of pixel local storage outside a fragment shader",
2032*8975f5c5SAndroid Build Coastguard Worker                   getBasicString(publicType.getBasicType()));
2033*8975f5c5SAndroid Build Coastguard Worker             return;
2034*8975f5c5SAndroid Build Coastguard Worker         }
2035*8975f5c5SAndroid Build Coastguard Worker         switch (layoutQualifier.imageInternalFormat)
2036*8975f5c5SAndroid Build Coastguard Worker         {
2037*8975f5c5SAndroid Build Coastguard Worker             case EiifR32F:
2038*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA8:
2039*8975f5c5SAndroid Build Coastguard Worker                 if (publicType.getBasicType() != EbtPixelLocalANGLE)
2040*8975f5c5SAndroid Build Coastguard Worker                 {
2041*8975f5c5SAndroid Build Coastguard Worker                     error(identifierLocation, "pixel local storage format requires pixelLocalANGLE",
2042*8975f5c5SAndroid Build Coastguard Worker                           getImageInternalFormatString(layoutQualifier.imageInternalFormat));
2043*8975f5c5SAndroid Build Coastguard Worker                 }
2044*8975f5c5SAndroid Build Coastguard Worker                 break;
2045*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA8I:
2046*8975f5c5SAndroid Build Coastguard Worker                 if (publicType.getBasicType() != EbtIPixelLocalANGLE)
2047*8975f5c5SAndroid Build Coastguard Worker                 {
2048*8975f5c5SAndroid Build Coastguard Worker                     error(identifierLocation,
2049*8975f5c5SAndroid Build Coastguard Worker                           "pixel local storage format requires ipixelLocalANGLE",
2050*8975f5c5SAndroid Build Coastguard Worker                           getImageInternalFormatString(layoutQualifier.imageInternalFormat));
2051*8975f5c5SAndroid Build Coastguard Worker                 }
2052*8975f5c5SAndroid Build Coastguard Worker                 break;
2053*8975f5c5SAndroid Build Coastguard Worker             case EiifR32UI:
2054*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA8UI:
2055*8975f5c5SAndroid Build Coastguard Worker                 if (publicType.getBasicType() != EbtUPixelLocalANGLE)
2056*8975f5c5SAndroid Build Coastguard Worker                 {
2057*8975f5c5SAndroid Build Coastguard Worker                     error(identifierLocation,
2058*8975f5c5SAndroid Build Coastguard Worker                           "pixel local storage format requires upixelLocalANGLE",
2059*8975f5c5SAndroid Build Coastguard Worker                           getImageInternalFormatString(layoutQualifier.imageInternalFormat));
2060*8975f5c5SAndroid Build Coastguard Worker                 }
2061*8975f5c5SAndroid Build Coastguard Worker                 break;
2062*8975f5c5SAndroid Build Coastguard Worker             case EiifR32I:
2063*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA8_SNORM:
2064*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA16F:
2065*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA32F:
2066*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA16I:
2067*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA32I:
2068*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA16UI:
2069*8975f5c5SAndroid Build Coastguard Worker             case EiifRGBA32UI:
2070*8975f5c5SAndroid Build Coastguard Worker             default:
2071*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(!IsValidWithPixelLocalStorage(layoutQualifier.imageInternalFormat));
2072*8975f5c5SAndroid Build Coastguard Worker                 error(identifierLocation, "illegal pixel local storage format",
2073*8975f5c5SAndroid Build Coastguard Worker                       getImageInternalFormatString(layoutQualifier.imageInternalFormat));
2074*8975f5c5SAndroid Build Coastguard Worker                 break;
2075*8975f5c5SAndroid Build Coastguard Worker             case EiifUnspecified:
2076*8975f5c5SAndroid Build Coastguard Worker                 error(identifierLocation, "pixel local storage requires a format specifier",
2077*8975f5c5SAndroid Build Coastguard Worker                       "layout qualifier");
2078*8975f5c5SAndroid Build Coastguard Worker                 break;
2079*8975f5c5SAndroid Build Coastguard Worker         }
2080*8975f5c5SAndroid Build Coastguard Worker         checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
2081*8975f5c5SAndroid Build Coastguard Worker         checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
2082*8975f5c5SAndroid Build Coastguard Worker     }
2083*8975f5c5SAndroid Build Coastguard Worker     else
2084*8975f5c5SAndroid Build Coastguard Worker     {
2085*8975f5c5SAndroid Build Coastguard Worker         checkInternalFormatIsNotSpecified(identifierLocation, layoutQualifier.imageInternalFormat);
2086*8975f5c5SAndroid Build Coastguard Worker         checkMemoryQualifierIsNotSpecified(publicType.memoryQualifier, identifierLocation);
2087*8975f5c5SAndroid Build Coastguard Worker     }
2088*8975f5c5SAndroid Build Coastguard Worker 
2089*8975f5c5SAndroid Build Coastguard Worker     if (IsAtomicCounter(publicType.getBasicType()))
2090*8975f5c5SAndroid Build Coastguard Worker     {
2091*8975f5c5SAndroid Build Coastguard Worker         atomicCounterQualifierErrorCheck(publicType, identifierLocation);
2092*8975f5c5SAndroid Build Coastguard Worker     }
2093*8975f5c5SAndroid Build Coastguard Worker     else
2094*8975f5c5SAndroid Build Coastguard Worker     {
2095*8975f5c5SAndroid Build Coastguard Worker         checkOffsetIsNotSpecified(identifierLocation, layoutQualifier.offset);
2096*8975f5c5SAndroid Build Coastguard Worker     }
2097*8975f5c5SAndroid Build Coastguard Worker }
2098*8975f5c5SAndroid Build Coastguard Worker 
checkBindingIsValid(const TSourceLoc & identifierLocation,const TType & type)2099*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkBindingIsValid(const TSourceLoc &identifierLocation, const TType &type)
2100*8975f5c5SAndroid Build Coastguard Worker {
2101*8975f5c5SAndroid Build Coastguard Worker     TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
2102*8975f5c5SAndroid Build Coastguard Worker     // Note that the ESSL 3.10 section 4.4.5 is not particularly clear on how the binding qualifier
2103*8975f5c5SAndroid Build Coastguard Worker     // on arrays of arrays should be handled. We interpret the spec so that the binding value is
2104*8975f5c5SAndroid Build Coastguard Worker     // incremented for each element of the innermost nested arrays. This is in line with how arrays
2105*8975f5c5SAndroid Build Coastguard Worker     // of arrays of blocks are specified to behave in GLSL 4.50 and a conservative interpretation
2106*8975f5c5SAndroid Build Coastguard Worker     // when it comes to which shaders are accepted by the compiler.
2107*8975f5c5SAndroid Build Coastguard Worker     int arrayTotalElementCount = type.getArraySizeProduct();
2108*8975f5c5SAndroid Build Coastguard Worker     if (IsPixelLocal(type.getBasicType()))
2109*8975f5c5SAndroid Build Coastguard Worker     {
2110*8975f5c5SAndroid Build Coastguard Worker         checkPixelLocalStorageBindingIsValid(identifierLocation, type);
2111*8975f5c5SAndroid Build Coastguard Worker     }
2112*8975f5c5SAndroid Build Coastguard Worker     else if (mShaderVersion < 310)
2113*8975f5c5SAndroid Build Coastguard Worker     {
2114*8975f5c5SAndroid Build Coastguard Worker         checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
2115*8975f5c5SAndroid Build Coastguard Worker     }
2116*8975f5c5SAndroid Build Coastguard Worker     else if (IsImage(type.getBasicType()))
2117*8975f5c5SAndroid Build Coastguard Worker     {
2118*8975f5c5SAndroid Build Coastguard Worker         checkImageBindingIsValid(identifierLocation, layoutQualifier.binding,
2119*8975f5c5SAndroid Build Coastguard Worker                                  arrayTotalElementCount);
2120*8975f5c5SAndroid Build Coastguard Worker     }
2121*8975f5c5SAndroid Build Coastguard Worker     else if (IsSampler(type.getBasicType()))
2122*8975f5c5SAndroid Build Coastguard Worker     {
2123*8975f5c5SAndroid Build Coastguard Worker         checkSamplerBindingIsValid(identifierLocation, layoutQualifier.binding,
2124*8975f5c5SAndroid Build Coastguard Worker                                    arrayTotalElementCount);
2125*8975f5c5SAndroid Build Coastguard Worker     }
2126*8975f5c5SAndroid Build Coastguard Worker     else if (IsAtomicCounter(type.getBasicType()))
2127*8975f5c5SAndroid Build Coastguard Worker     {
2128*8975f5c5SAndroid Build Coastguard Worker         checkAtomicCounterBindingIsValid(identifierLocation, layoutQualifier.binding);
2129*8975f5c5SAndroid Build Coastguard Worker     }
2130*8975f5c5SAndroid Build Coastguard Worker     else
2131*8975f5c5SAndroid Build Coastguard Worker     {
2132*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!IsOpaqueType(type.getBasicType()));
2133*8975f5c5SAndroid Build Coastguard Worker         checkBindingIsNotSpecified(identifierLocation, layoutQualifier.binding);
2134*8975f5c5SAndroid Build Coastguard Worker     }
2135*8975f5c5SAndroid Build Coastguard Worker }
2136*8975f5c5SAndroid Build Coastguard Worker 
checkCanUseLayoutQualifier(const TSourceLoc & location)2137*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkCanUseLayoutQualifier(const TSourceLoc &location)
2138*8975f5c5SAndroid Build Coastguard Worker {
2139*8975f5c5SAndroid Build Coastguard Worker     constexpr std::array<TExtension, 4u> extensions{
2140*8975f5c5SAndroid Build Coastguard Worker         {TExtension::EXT_shader_framebuffer_fetch,
2141*8975f5c5SAndroid Build Coastguard Worker          TExtension::EXT_shader_framebuffer_fetch_non_coherent,
2142*8975f5c5SAndroid Build Coastguard Worker          TExtension::KHR_blend_equation_advanced, TExtension::ANGLE_shader_pixel_local_storage}};
2143*8975f5c5SAndroid Build Coastguard Worker     if (getShaderVersion() < 300 && !checkCanUseOneOfExtensions(location, extensions))
2144*8975f5c5SAndroid Build Coastguard Worker     {
2145*8975f5c5SAndroid Build Coastguard Worker         error(location, "qualifier supported in GLSL ES 3.00 and above only", "layout");
2146*8975f5c5SAndroid Build Coastguard Worker     }
2147*8975f5c5SAndroid Build Coastguard Worker }
2148*8975f5c5SAndroid Build Coastguard Worker 
checkLayoutQualifierSupported(const TSourceLoc & location,const ImmutableString & layoutQualifierName,int versionRequired)2149*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkLayoutQualifierSupported(const TSourceLoc &location,
2150*8975f5c5SAndroid Build Coastguard Worker                                                   const ImmutableString &layoutQualifierName,
2151*8975f5c5SAndroid Build Coastguard Worker                                                   int versionRequired)
2152*8975f5c5SAndroid Build Coastguard Worker {
2153*8975f5c5SAndroid Build Coastguard Worker 
2154*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion < versionRequired)
2155*8975f5c5SAndroid Build Coastguard Worker     {
2156*8975f5c5SAndroid Build Coastguard Worker         error(location, "invalid layout qualifier: not supported", layoutQualifierName);
2157*8975f5c5SAndroid Build Coastguard Worker         return false;
2158*8975f5c5SAndroid Build Coastguard Worker     }
2159*8975f5c5SAndroid Build Coastguard Worker     return true;
2160*8975f5c5SAndroid Build Coastguard Worker }
2161*8975f5c5SAndroid Build Coastguard Worker 
checkWorkGroupSizeIsNotSpecified(const TSourceLoc & location,const TLayoutQualifier & layoutQualifier)2162*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkWorkGroupSizeIsNotSpecified(const TSourceLoc &location,
2163*8975f5c5SAndroid Build Coastguard Worker                                                      const TLayoutQualifier &layoutQualifier)
2164*8975f5c5SAndroid Build Coastguard Worker {
2165*8975f5c5SAndroid Build Coastguard Worker     const sh::WorkGroupSize &localSize = layoutQualifier.localSize;
2166*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0u; i < localSize.size(); ++i)
2167*8975f5c5SAndroid Build Coastguard Worker     {
2168*8975f5c5SAndroid Build Coastguard Worker         if (localSize[i] != -1)
2169*8975f5c5SAndroid Build Coastguard Worker         {
2170*8975f5c5SAndroid Build Coastguard Worker             error(location,
2171*8975f5c5SAndroid Build Coastguard Worker                   "invalid layout qualifier: only valid when used with 'in' in a compute shader "
2172*8975f5c5SAndroid Build Coastguard Worker                   "global layout declaration",
2173*8975f5c5SAndroid Build Coastguard Worker                   getWorkGroupSizeString(i));
2174*8975f5c5SAndroid Build Coastguard Worker             return false;
2175*8975f5c5SAndroid Build Coastguard Worker         }
2176*8975f5c5SAndroid Build Coastguard Worker     }
2177*8975f5c5SAndroid Build Coastguard Worker 
2178*8975f5c5SAndroid Build Coastguard Worker     return true;
2179*8975f5c5SAndroid Build Coastguard Worker }
2180*8975f5c5SAndroid Build Coastguard Worker 
checkInternalFormatIsNotSpecified(const TSourceLoc & location,TLayoutImageInternalFormat internalFormat)2181*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkInternalFormatIsNotSpecified(const TSourceLoc &location,
2182*8975f5c5SAndroid Build Coastguard Worker                                                       TLayoutImageInternalFormat internalFormat)
2183*8975f5c5SAndroid Build Coastguard Worker {
2184*8975f5c5SAndroid Build Coastguard Worker     if (internalFormat != EiifUnspecified)
2185*8975f5c5SAndroid Build Coastguard Worker     {
2186*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 310)
2187*8975f5c5SAndroid Build Coastguard Worker         {
2188*8975f5c5SAndroid Build Coastguard Worker             if (IsValidWithPixelLocalStorage(internalFormat))
2189*8975f5c5SAndroid Build Coastguard Worker             {
2190*8975f5c5SAndroid Build Coastguard Worker                 error(location,
2191*8975f5c5SAndroid Build Coastguard Worker                       "invalid layout qualifier: not supported before GLSL ES 3.10, except pixel "
2192*8975f5c5SAndroid Build Coastguard Worker                       "local storage",
2193*8975f5c5SAndroid Build Coastguard Worker                       getImageInternalFormatString(internalFormat));
2194*8975f5c5SAndroid Build Coastguard Worker             }
2195*8975f5c5SAndroid Build Coastguard Worker             else
2196*8975f5c5SAndroid Build Coastguard Worker             {
2197*8975f5c5SAndroid Build Coastguard Worker                 error(location, "invalid layout qualifier: not supported before GLSL ES 3.10",
2198*8975f5c5SAndroid Build Coastguard Worker                       getImageInternalFormatString(internalFormat));
2199*8975f5c5SAndroid Build Coastguard Worker             }
2200*8975f5c5SAndroid Build Coastguard Worker         }
2201*8975f5c5SAndroid Build Coastguard Worker         else
2202*8975f5c5SAndroid Build Coastguard Worker         {
2203*8975f5c5SAndroid Build Coastguard Worker             if (IsValidWithPixelLocalStorage(internalFormat))
2204*8975f5c5SAndroid Build Coastguard Worker             {
2205*8975f5c5SAndroid Build Coastguard Worker                 error(location,
2206*8975f5c5SAndroid Build Coastguard Worker                       "invalid layout qualifier: only valid when used with images or pixel local "
2207*8975f5c5SAndroid Build Coastguard Worker                       "storage ",
2208*8975f5c5SAndroid Build Coastguard Worker                       getImageInternalFormatString(internalFormat));
2209*8975f5c5SAndroid Build Coastguard Worker             }
2210*8975f5c5SAndroid Build Coastguard Worker             else
2211*8975f5c5SAndroid Build Coastguard Worker             {
2212*8975f5c5SAndroid Build Coastguard Worker                 error(location, "invalid layout qualifier: only valid when used with images",
2213*8975f5c5SAndroid Build Coastguard Worker                       getImageInternalFormatString(internalFormat));
2214*8975f5c5SAndroid Build Coastguard Worker             }
2215*8975f5c5SAndroid Build Coastguard Worker         }
2216*8975f5c5SAndroid Build Coastguard Worker     }
2217*8975f5c5SAndroid Build Coastguard Worker }
2218*8975f5c5SAndroid Build Coastguard Worker 
checkIndexIsNotSpecified(const TSourceLoc & location,int index)2219*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkIndexIsNotSpecified(const TSourceLoc &location, int index)
2220*8975f5c5SAndroid Build Coastguard Worker {
2221*8975f5c5SAndroid Build Coastguard Worker     if (index != -1)
2222*8975f5c5SAndroid Build Coastguard Worker     {
2223*8975f5c5SAndroid Build Coastguard Worker         error(location,
2224*8975f5c5SAndroid Build Coastguard Worker               "invalid layout qualifier: only valid when used with a fragment shader output in "
2225*8975f5c5SAndroid Build Coastguard Worker               "ESSL version >= 3.00 and EXT_blend_func_extended is enabled",
2226*8975f5c5SAndroid Build Coastguard Worker               "index");
2227*8975f5c5SAndroid Build Coastguard Worker     }
2228*8975f5c5SAndroid Build Coastguard Worker }
2229*8975f5c5SAndroid Build Coastguard Worker 
checkBindingIsNotSpecified(const TSourceLoc & location,int binding)2230*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkBindingIsNotSpecified(const TSourceLoc &location, int binding)
2231*8975f5c5SAndroid Build Coastguard Worker {
2232*8975f5c5SAndroid Build Coastguard Worker     if (binding != -1)
2233*8975f5c5SAndroid Build Coastguard Worker     {
2234*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 310)
2235*8975f5c5SAndroid Build Coastguard Worker         {
2236*8975f5c5SAndroid Build Coastguard Worker             error(location,
2237*8975f5c5SAndroid Build Coastguard Worker                   "invalid layout qualifier: only valid when used with pixel local storage",
2238*8975f5c5SAndroid Build Coastguard Worker                   "binding");
2239*8975f5c5SAndroid Build Coastguard Worker         }
2240*8975f5c5SAndroid Build Coastguard Worker         else
2241*8975f5c5SAndroid Build Coastguard Worker         {
2242*8975f5c5SAndroid Build Coastguard Worker             error(location,
2243*8975f5c5SAndroid Build Coastguard Worker                   "invalid layout qualifier: only valid when used with opaque types or blocks",
2244*8975f5c5SAndroid Build Coastguard Worker                   "binding");
2245*8975f5c5SAndroid Build Coastguard Worker         }
2246*8975f5c5SAndroid Build Coastguard Worker     }
2247*8975f5c5SAndroid Build Coastguard Worker }
2248*8975f5c5SAndroid Build Coastguard Worker 
checkOffsetIsNotSpecified(const TSourceLoc & location,int offset)2249*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkOffsetIsNotSpecified(const TSourceLoc &location, int offset)
2250*8975f5c5SAndroid Build Coastguard Worker {
2251*8975f5c5SAndroid Build Coastguard Worker     if (offset != -1)
2252*8975f5c5SAndroid Build Coastguard Worker     {
2253*8975f5c5SAndroid Build Coastguard Worker         error(location, "invalid layout qualifier: only valid when used with atomic counters",
2254*8975f5c5SAndroid Build Coastguard Worker               "offset");
2255*8975f5c5SAndroid Build Coastguard Worker     }
2256*8975f5c5SAndroid Build Coastguard Worker }
2257*8975f5c5SAndroid Build Coastguard Worker 
checkImageBindingIsValid(const TSourceLoc & location,int binding,int arrayTotalElementCount)2258*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkImageBindingIsValid(const TSourceLoc &location,
2259*8975f5c5SAndroid Build Coastguard Worker                                              int binding,
2260*8975f5c5SAndroid Build Coastguard Worker                                              int arrayTotalElementCount)
2261*8975f5c5SAndroid Build Coastguard Worker {
2262*8975f5c5SAndroid Build Coastguard Worker     // Expects arraySize to be 1 when setting binding for only a single variable.
2263*8975f5c5SAndroid Build Coastguard Worker     if (binding >= 0 && binding + arrayTotalElementCount > mMaxImageUnits)
2264*8975f5c5SAndroid Build Coastguard Worker     {
2265*8975f5c5SAndroid Build Coastguard Worker         error(location, "image binding greater than gl_MaxImageUnits", "binding");
2266*8975f5c5SAndroid Build Coastguard Worker     }
2267*8975f5c5SAndroid Build Coastguard Worker }
2268*8975f5c5SAndroid Build Coastguard Worker 
checkSamplerBindingIsValid(const TSourceLoc & location,int binding,int arrayTotalElementCount)2269*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkSamplerBindingIsValid(const TSourceLoc &location,
2270*8975f5c5SAndroid Build Coastguard Worker                                                int binding,
2271*8975f5c5SAndroid Build Coastguard Worker                                                int arrayTotalElementCount)
2272*8975f5c5SAndroid Build Coastguard Worker {
2273*8975f5c5SAndroid Build Coastguard Worker     // Expects arraySize to be 1 when setting binding for only a single variable.
2274*8975f5c5SAndroid Build Coastguard Worker     if (binding >= 0 && binding + arrayTotalElementCount > mMaxCombinedTextureImageUnits)
2275*8975f5c5SAndroid Build Coastguard Worker     {
2276*8975f5c5SAndroid Build Coastguard Worker         error(location, "sampler binding greater than maximum texture units", "binding");
2277*8975f5c5SAndroid Build Coastguard Worker     }
2278*8975f5c5SAndroid Build Coastguard Worker }
2279*8975f5c5SAndroid Build Coastguard Worker 
checkBlockBindingIsValid(const TSourceLoc & location,const TQualifier & qualifier,int binding,int arraySize)2280*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkBlockBindingIsValid(const TSourceLoc &location,
2281*8975f5c5SAndroid Build Coastguard Worker                                              const TQualifier &qualifier,
2282*8975f5c5SAndroid Build Coastguard Worker                                              int binding,
2283*8975f5c5SAndroid Build Coastguard Worker                                              int arraySize)
2284*8975f5c5SAndroid Build Coastguard Worker {
2285*8975f5c5SAndroid Build Coastguard Worker     int size = (arraySize == 0 ? 1 : arraySize);
2286*8975f5c5SAndroid Build Coastguard Worker     if (qualifier == EvqUniform)
2287*8975f5c5SAndroid Build Coastguard Worker     {
2288*8975f5c5SAndroid Build Coastguard Worker         if (binding + size > mMaxUniformBufferBindings)
2289*8975f5c5SAndroid Build Coastguard Worker         {
2290*8975f5c5SAndroid Build Coastguard Worker             error(location, "uniform block binding greater than MAX_UNIFORM_BUFFER_BINDINGS",
2291*8975f5c5SAndroid Build Coastguard Worker                   "binding");
2292*8975f5c5SAndroid Build Coastguard Worker         }
2293*8975f5c5SAndroid Build Coastguard Worker     }
2294*8975f5c5SAndroid Build Coastguard Worker     else if (qualifier == EvqBuffer)
2295*8975f5c5SAndroid Build Coastguard Worker     {
2296*8975f5c5SAndroid Build Coastguard Worker         if (binding + size > mMaxShaderStorageBufferBindings)
2297*8975f5c5SAndroid Build Coastguard Worker         {
2298*8975f5c5SAndroid Build Coastguard Worker             error(location,
2299*8975f5c5SAndroid Build Coastguard Worker                   "shader storage block binding greater than MAX_SHADER_STORAGE_BUFFER_BINDINGS",
2300*8975f5c5SAndroid Build Coastguard Worker                   "binding");
2301*8975f5c5SAndroid Build Coastguard Worker         }
2302*8975f5c5SAndroid Build Coastguard Worker     }
2303*8975f5c5SAndroid Build Coastguard Worker }
checkAtomicCounterBindingIsValid(const TSourceLoc & location,int binding)2304*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkAtomicCounterBindingIsValid(const TSourceLoc &location, int binding)
2305*8975f5c5SAndroid Build Coastguard Worker {
2306*8975f5c5SAndroid Build Coastguard Worker     if (binding >= mMaxAtomicCounterBindings)
2307*8975f5c5SAndroid Build Coastguard Worker     {
2308*8975f5c5SAndroid Build Coastguard Worker         error(location, "atomic counter binding greater than gl_MaxAtomicCounterBindings",
2309*8975f5c5SAndroid Build Coastguard Worker               "binding");
2310*8975f5c5SAndroid Build Coastguard Worker     }
2311*8975f5c5SAndroid Build Coastguard Worker }
2312*8975f5c5SAndroid Build Coastguard Worker 
checkPixelLocalStorageBindingIsValid(const TSourceLoc & location,const TType & type)2313*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkPixelLocalStorageBindingIsValid(const TSourceLoc &location,
2314*8975f5c5SAndroid Build Coastguard Worker                                                          const TType &type)
2315*8975f5c5SAndroid Build Coastguard Worker {
2316*8975f5c5SAndroid Build Coastguard Worker     TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
2317*8975f5c5SAndroid Build Coastguard Worker     if (type.isArray())
2318*8975f5c5SAndroid Build Coastguard Worker     {
2319*8975f5c5SAndroid Build Coastguard Worker         // PLS is not allowed in arrays.
2320*8975f5c5SAndroid Build Coastguard Worker         // TODO(anglebug.com/40096838): Consider allowing this once more backends are implemented.
2321*8975f5c5SAndroid Build Coastguard Worker         error(location, "pixel local storage handles cannot be aggregated in arrays", "array");
2322*8975f5c5SAndroid Build Coastguard Worker     }
2323*8975f5c5SAndroid Build Coastguard Worker     else if (layoutQualifier.binding < 0)
2324*8975f5c5SAndroid Build Coastguard Worker     {
2325*8975f5c5SAndroid Build Coastguard Worker         error(location, "pixel local storage requires a binding index", "layout qualifier");
2326*8975f5c5SAndroid Build Coastguard Worker     }
2327*8975f5c5SAndroid Build Coastguard Worker     // TODO(anglebug.com/40096838):
2328*8975f5c5SAndroid Build Coastguard Worker     else if (layoutQualifier.binding >= mMaxPixelLocalStoragePlanes)
2329*8975f5c5SAndroid Build Coastguard Worker     {
2330*8975f5c5SAndroid Build Coastguard Worker         error(location, "pixel local storage binding out of range", "layout qualifier");
2331*8975f5c5SAndroid Build Coastguard Worker     }
2332*8975f5c5SAndroid Build Coastguard Worker     else if (mPLSFormats.find(layoutQualifier.binding) != mPLSFormats.end())
2333*8975f5c5SAndroid Build Coastguard Worker     {
2334*8975f5c5SAndroid Build Coastguard Worker         error(location, "duplicate pixel local storage binding index",
2335*8975f5c5SAndroid Build Coastguard Worker               std::to_string(layoutQualifier.binding).c_str());
2336*8975f5c5SAndroid Build Coastguard Worker     }
2337*8975f5c5SAndroid Build Coastguard Worker     else
2338*8975f5c5SAndroid Build Coastguard Worker     {
2339*8975f5c5SAndroid Build Coastguard Worker         mPLSFormats[layoutQualifier.binding] =
2340*8975f5c5SAndroid Build Coastguard Worker             ImageFormatToPLSFormat(layoutQualifier.imageInternalFormat);
2341*8975f5c5SAndroid Build Coastguard Worker         // "mPLSFormats" is how we know whether any pixel local storage uniforms have been declared,
2342*8975f5c5SAndroid Build Coastguard Worker         // so flush the queue of potential errors once mPLSFormats isn't empty.
2343*8975f5c5SAndroid Build Coastguard Worker         if (!mPLSPotentialErrors.empty())
2344*8975f5c5SAndroid Build Coastguard Worker         {
2345*8975f5c5SAndroid Build Coastguard Worker             for (const auto &[loc, op] : mPLSPotentialErrors)
2346*8975f5c5SAndroid Build Coastguard Worker             {
2347*8975f5c5SAndroid Build Coastguard Worker                 errorIfPLSDeclared(loc, op);
2348*8975f5c5SAndroid Build Coastguard Worker             }
2349*8975f5c5SAndroid Build Coastguard Worker             mPLSPotentialErrors.clear();
2350*8975f5c5SAndroid Build Coastguard Worker         }
2351*8975f5c5SAndroid Build Coastguard Worker     }
2352*8975f5c5SAndroid Build Coastguard Worker }
2353*8975f5c5SAndroid Build Coastguard Worker 
checkUniformLocationInRange(const TSourceLoc & location,int objectLocationCount,const TLayoutQualifier & layoutQualifier)2354*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkUniformLocationInRange(const TSourceLoc &location,
2355*8975f5c5SAndroid Build Coastguard Worker                                                 int objectLocationCount,
2356*8975f5c5SAndroid Build Coastguard Worker                                                 const TLayoutQualifier &layoutQualifier)
2357*8975f5c5SAndroid Build Coastguard Worker {
2358*8975f5c5SAndroid Build Coastguard Worker     int loc = layoutQualifier.location;
2359*8975f5c5SAndroid Build Coastguard Worker     if (loc >= 0)  // Shader-specified location
2360*8975f5c5SAndroid Build Coastguard Worker     {
2361*8975f5c5SAndroid Build Coastguard Worker         if (loc >= mMaxUniformLocations || objectLocationCount > mMaxUniformLocations ||
2362*8975f5c5SAndroid Build Coastguard Worker             static_cast<unsigned int>(loc) + static_cast<unsigned int>(objectLocationCount) >
2363*8975f5c5SAndroid Build Coastguard Worker                 static_cast<unsigned int>(mMaxUniformLocations))
2364*8975f5c5SAndroid Build Coastguard Worker         {
2365*8975f5c5SAndroid Build Coastguard Worker             error(location, "Uniform location out of range", "location");
2366*8975f5c5SAndroid Build Coastguard Worker         }
2367*8975f5c5SAndroid Build Coastguard Worker     }
2368*8975f5c5SAndroid Build Coastguard Worker }
2369*8975f5c5SAndroid Build Coastguard Worker 
checkAttributeLocationInRange(const TSourceLoc & location,int objectLocationCount,const TLayoutQualifier & layoutQualifier)2370*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkAttributeLocationInRange(const TSourceLoc &location,
2371*8975f5c5SAndroid Build Coastguard Worker                                                   int objectLocationCount,
2372*8975f5c5SAndroid Build Coastguard Worker                                                   const TLayoutQualifier &layoutQualifier)
2373*8975f5c5SAndroid Build Coastguard Worker {
2374*8975f5c5SAndroid Build Coastguard Worker     int loc = layoutQualifier.location;
2375*8975f5c5SAndroid Build Coastguard Worker     if (loc >= 0)  // Shader-specified location
2376*8975f5c5SAndroid Build Coastguard Worker     {
2377*8975f5c5SAndroid Build Coastguard Worker         if (loc >= mMaxVertexAttribs || objectLocationCount > mMaxVertexAttribs ||
2378*8975f5c5SAndroid Build Coastguard Worker             static_cast<unsigned int>(loc) + static_cast<unsigned int>(objectLocationCount) >
2379*8975f5c5SAndroid Build Coastguard Worker                 static_cast<unsigned int>(mMaxVertexAttribs))
2380*8975f5c5SAndroid Build Coastguard Worker         {
2381*8975f5c5SAndroid Build Coastguard Worker             error(location, "Attribute location out of range", "location");
2382*8975f5c5SAndroid Build Coastguard Worker         }
2383*8975f5c5SAndroid Build Coastguard Worker     }
2384*8975f5c5SAndroid Build Coastguard Worker }
2385*8975f5c5SAndroid Build Coastguard Worker 
checkDepthIsNotSpecified(const TSourceLoc & location,TLayoutDepth depth)2386*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkDepthIsNotSpecified(const TSourceLoc &location, TLayoutDepth depth)
2387*8975f5c5SAndroid Build Coastguard Worker {
2388*8975f5c5SAndroid Build Coastguard Worker     if (depth != EdUnspecified)
2389*8975f5c5SAndroid Build Coastguard Worker     {
2390*8975f5c5SAndroid Build Coastguard Worker         error(location, "invalid layout qualifier: only valid on gl_FragDepth",
2391*8975f5c5SAndroid Build Coastguard Worker               getDepthString(depth));
2392*8975f5c5SAndroid Build Coastguard Worker     }
2393*8975f5c5SAndroid Build Coastguard Worker }
2394*8975f5c5SAndroid Build Coastguard Worker 
checkYuvIsNotSpecified(const TSourceLoc & location,bool yuv)2395*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkYuvIsNotSpecified(const TSourceLoc &location, bool yuv)
2396*8975f5c5SAndroid Build Coastguard Worker {
2397*8975f5c5SAndroid Build Coastguard Worker     if (yuv != false)
2398*8975f5c5SAndroid Build Coastguard Worker     {
2399*8975f5c5SAndroid Build Coastguard Worker         error(location, "invalid layout qualifier: only valid on program outputs", "yuv");
2400*8975f5c5SAndroid Build Coastguard Worker     }
2401*8975f5c5SAndroid Build Coastguard Worker }
2402*8975f5c5SAndroid Build Coastguard Worker 
checkEarlyFragmentTestsIsNotSpecified(const TSourceLoc & location,bool earlyFragmentTests)2403*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkEarlyFragmentTestsIsNotSpecified(const TSourceLoc &location,
2404*8975f5c5SAndroid Build Coastguard Worker                                                           bool earlyFragmentTests)
2405*8975f5c5SAndroid Build Coastguard Worker {
2406*8975f5c5SAndroid Build Coastguard Worker     if (earlyFragmentTests != false)
2407*8975f5c5SAndroid Build Coastguard Worker     {
2408*8975f5c5SAndroid Build Coastguard Worker         error(location,
2409*8975f5c5SAndroid Build Coastguard Worker               "invalid layout qualifier: only valid when used with 'in' in a fragment shader",
2410*8975f5c5SAndroid Build Coastguard Worker               "early_fragment_tests");
2411*8975f5c5SAndroid Build Coastguard Worker     }
2412*8975f5c5SAndroid Build Coastguard Worker }
2413*8975f5c5SAndroid Build Coastguard Worker 
checkNoncoherentIsSpecified(const TSourceLoc & location,bool noncoherent)2414*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkNoncoherentIsSpecified(const TSourceLoc &location, bool noncoherent)
2415*8975f5c5SAndroid Build Coastguard Worker {
2416*8975f5c5SAndroid Build Coastguard Worker     if (noncoherent == false)
2417*8975f5c5SAndroid Build Coastguard Worker     {
2418*8975f5c5SAndroid Build Coastguard Worker         error(location,
2419*8975f5c5SAndroid Build Coastguard Worker               "'noncoherent' qualifier must be used when "
2420*8975f5c5SAndroid Build Coastguard Worker               "GL_EXT_shader_framebuffer_fetch_non_coherent extension is used",
2421*8975f5c5SAndroid Build Coastguard Worker               "noncoherent");
2422*8975f5c5SAndroid Build Coastguard Worker     }
2423*8975f5c5SAndroid Build Coastguard Worker }
2424*8975f5c5SAndroid Build Coastguard Worker 
checkNoncoherentIsNotSpecified(const TSourceLoc & location,bool noncoherent)2425*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkNoncoherentIsNotSpecified(const TSourceLoc &location, bool noncoherent)
2426*8975f5c5SAndroid Build Coastguard Worker {
2427*8975f5c5SAndroid Build Coastguard Worker     if (noncoherent != false)
2428*8975f5c5SAndroid Build Coastguard Worker     {
2429*8975f5c5SAndroid Build Coastguard Worker         error(location,
2430*8975f5c5SAndroid Build Coastguard Worker               "invalid layout qualifier: only valid when used with 'gl_LastFragData' or the "
2431*8975f5c5SAndroid Build Coastguard Worker               "variable decorated with 'inout' in a fragment shader",
2432*8975f5c5SAndroid Build Coastguard Worker               "noncoherent");
2433*8975f5c5SAndroid Build Coastguard Worker     }
2434*8975f5c5SAndroid Build Coastguard Worker }
2435*8975f5c5SAndroid Build Coastguard Worker 
checkTCSOutVarIndexIsValid(TIntermBinary * binaryExpression,const TSourceLoc & location)2436*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkTCSOutVarIndexIsValid(TIntermBinary *binaryExpression,
2437*8975f5c5SAndroid Build Coastguard Worker                                                const TSourceLoc &location)
2438*8975f5c5SAndroid Build Coastguard Worker {
2439*8975f5c5SAndroid Build Coastguard Worker     ASSERT(binaryExpression->getOp() == EOpIndexIndirect ||
2440*8975f5c5SAndroid Build Coastguard Worker            binaryExpression->getOp() == EOpIndexDirect);
2441*8975f5c5SAndroid Build Coastguard Worker     const TIntermSymbol *intermSymbol = binaryExpression->getRight()->getAsSymbolNode();
2442*8975f5c5SAndroid Build Coastguard Worker     if ((intermSymbol == nullptr) || (intermSymbol->getName() != "gl_InvocationID"))
2443*8975f5c5SAndroid Build Coastguard Worker     {
2444*8975f5c5SAndroid Build Coastguard Worker         error(location,
2445*8975f5c5SAndroid Build Coastguard Worker               "tessellation-control per-vertex output l-value must be indexed with "
2446*8975f5c5SAndroid Build Coastguard Worker               "gl_InvocationID",
2447*8975f5c5SAndroid Build Coastguard Worker               "[");
2448*8975f5c5SAndroid Build Coastguard Worker     }
2449*8975f5c5SAndroid Build Coastguard Worker }
2450*8975f5c5SAndroid Build Coastguard Worker 
functionCallRValueLValueErrorCheck(const TFunction * fnCandidate,TIntermAggregate * fnCall)2451*8975f5c5SAndroid Build Coastguard Worker void TParseContext::functionCallRValueLValueErrorCheck(const TFunction *fnCandidate,
2452*8975f5c5SAndroid Build Coastguard Worker                                                        TIntermAggregate *fnCall)
2453*8975f5c5SAndroid Build Coastguard Worker {
2454*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < fnCandidate->getParamCount(); ++i)
2455*8975f5c5SAndroid Build Coastguard Worker     {
2456*8975f5c5SAndroid Build Coastguard Worker         TQualifier qual        = fnCandidate->getParam(i)->getType().getQualifier();
2457*8975f5c5SAndroid Build Coastguard Worker         TIntermTyped *argument = (*(fnCall->getSequence()))[i]->getAsTyped();
2458*8975f5c5SAndroid Build Coastguard Worker         bool argumentIsRead    = (IsQualifierUnspecified(qual) || qual == EvqParamIn ||
2459*8975f5c5SAndroid Build Coastguard Worker                                qual == EvqParamInOut || qual == EvqParamConst);
2460*8975f5c5SAndroid Build Coastguard Worker         if (argumentIsRead)
2461*8975f5c5SAndroid Build Coastguard Worker         {
2462*8975f5c5SAndroid Build Coastguard Worker             markStaticReadIfSymbol(argument);
2463*8975f5c5SAndroid Build Coastguard Worker             if (!IsImage(argument->getBasicType()))
2464*8975f5c5SAndroid Build Coastguard Worker             {
2465*8975f5c5SAndroid Build Coastguard Worker                 if (argument->getMemoryQualifier().writeonly)
2466*8975f5c5SAndroid Build Coastguard Worker                 {
2467*8975f5c5SAndroid Build Coastguard Worker                     error(argument->getLine(),
2468*8975f5c5SAndroid Build Coastguard Worker                           "Writeonly value cannot be passed for 'in' or 'inout' parameters.",
2469*8975f5c5SAndroid Build Coastguard Worker                           fnCall->functionName());
2470*8975f5c5SAndroid Build Coastguard Worker                     return;
2471*8975f5c5SAndroid Build Coastguard Worker                 }
2472*8975f5c5SAndroid Build Coastguard Worker             }
2473*8975f5c5SAndroid Build Coastguard Worker         }
2474*8975f5c5SAndroid Build Coastguard Worker         if (qual == EvqParamOut || qual == EvqParamInOut)
2475*8975f5c5SAndroid Build Coastguard Worker         {
2476*8975f5c5SAndroid Build Coastguard Worker             if (!checkCanBeLValue(argument->getLine(), "assign", argument))
2477*8975f5c5SAndroid Build Coastguard Worker             {
2478*8975f5c5SAndroid Build Coastguard Worker                 error(argument->getLine(),
2479*8975f5c5SAndroid Build Coastguard Worker                       "Constant value cannot be passed for 'out' or 'inout' parameters.",
2480*8975f5c5SAndroid Build Coastguard Worker                       fnCall->functionName());
2481*8975f5c5SAndroid Build Coastguard Worker                 return;
2482*8975f5c5SAndroid Build Coastguard Worker             }
2483*8975f5c5SAndroid Build Coastguard Worker         }
2484*8975f5c5SAndroid Build Coastguard Worker     }
2485*8975f5c5SAndroid Build Coastguard Worker }
2486*8975f5c5SAndroid Build Coastguard Worker 
checkInvariantVariableQualifier(bool invariant,const TQualifier qualifier,const TSourceLoc & invariantLocation)2487*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkInvariantVariableQualifier(bool invariant,
2488*8975f5c5SAndroid Build Coastguard Worker                                                     const TQualifier qualifier,
2489*8975f5c5SAndroid Build Coastguard Worker                                                     const TSourceLoc &invariantLocation)
2490*8975f5c5SAndroid Build Coastguard Worker {
2491*8975f5c5SAndroid Build Coastguard Worker     if (!invariant)
2492*8975f5c5SAndroid Build Coastguard Worker         return;
2493*8975f5c5SAndroid Build Coastguard Worker 
2494*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion < 300)
2495*8975f5c5SAndroid Build Coastguard Worker     {
2496*8975f5c5SAndroid Build Coastguard Worker         // input variables in the fragment shader can be also qualified as invariant
2497*8975f5c5SAndroid Build Coastguard Worker         if (!sh::CanBeInvariantESSL1(qualifier))
2498*8975f5c5SAndroid Build Coastguard Worker         {
2499*8975f5c5SAndroid Build Coastguard Worker             error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
2500*8975f5c5SAndroid Build Coastguard Worker         }
2501*8975f5c5SAndroid Build Coastguard Worker     }
2502*8975f5c5SAndroid Build Coastguard Worker     else
2503*8975f5c5SAndroid Build Coastguard Worker     {
2504*8975f5c5SAndroid Build Coastguard Worker         if (!sh::CanBeInvariantESSL3OrGreater(qualifier))
2505*8975f5c5SAndroid Build Coastguard Worker         {
2506*8975f5c5SAndroid Build Coastguard Worker             error(invariantLocation, "Cannot be qualified as invariant.", "invariant");
2507*8975f5c5SAndroid Build Coastguard Worker         }
2508*8975f5c5SAndroid Build Coastguard Worker     }
2509*8975f5c5SAndroid Build Coastguard Worker }
2510*8975f5c5SAndroid Build Coastguard Worker 
checkAdvancedBlendEquationsNotSpecified(const TSourceLoc & location,const AdvancedBlendEquations & advancedBlendEquations,const TQualifier & qualifier)2511*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkAdvancedBlendEquationsNotSpecified(
2512*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &location,
2513*8975f5c5SAndroid Build Coastguard Worker     const AdvancedBlendEquations &advancedBlendEquations,
2514*8975f5c5SAndroid Build Coastguard Worker     const TQualifier &qualifier)
2515*8975f5c5SAndroid Build Coastguard Worker {
2516*8975f5c5SAndroid Build Coastguard Worker     if (advancedBlendEquations.any() && qualifier != EvqFragmentOut)
2517*8975f5c5SAndroid Build Coastguard Worker     {
2518*8975f5c5SAndroid Build Coastguard Worker         error(location,
2519*8975f5c5SAndroid Build Coastguard Worker               "invalid layout qualifier: blending equation qualifiers are only permitted on the "
2520*8975f5c5SAndroid Build Coastguard Worker               "fragment 'out' qualifier ",
2521*8975f5c5SAndroid Build Coastguard Worker               "blend_support_qualifier");
2522*8975f5c5SAndroid Build Coastguard Worker     }
2523*8975f5c5SAndroid Build Coastguard Worker }
2524*8975f5c5SAndroid Build Coastguard Worker 
isExtensionEnabled(TExtension extension) const2525*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::isExtensionEnabled(TExtension extension) const
2526*8975f5c5SAndroid Build Coastguard Worker {
2527*8975f5c5SAndroid Build Coastguard Worker     return IsExtensionEnabled(extensionBehavior(), extension);
2528*8975f5c5SAndroid Build Coastguard Worker }
2529*8975f5c5SAndroid Build Coastguard Worker 
handleExtensionDirective(const TSourceLoc & loc,const char * extName,const char * behavior)2530*8975f5c5SAndroid Build Coastguard Worker void TParseContext::handleExtensionDirective(const TSourceLoc &loc,
2531*8975f5c5SAndroid Build Coastguard Worker                                              const char *extName,
2532*8975f5c5SAndroid Build Coastguard Worker                                              const char *behavior)
2533*8975f5c5SAndroid Build Coastguard Worker {
2534*8975f5c5SAndroid Build Coastguard Worker     angle::pp::SourceLocation srcLoc;
2535*8975f5c5SAndroid Build Coastguard Worker     srcLoc.file = loc.first_file;
2536*8975f5c5SAndroid Build Coastguard Worker     srcLoc.line = loc.first_line;
2537*8975f5c5SAndroid Build Coastguard Worker     mDirectiveHandler.handleExtension(srcLoc, extName, behavior);
2538*8975f5c5SAndroid Build Coastguard Worker }
2539*8975f5c5SAndroid Build Coastguard Worker 
handlePragmaDirective(const TSourceLoc & loc,const char * name,const char * value,bool stdgl)2540*8975f5c5SAndroid Build Coastguard Worker void TParseContext::handlePragmaDirective(const TSourceLoc &loc,
2541*8975f5c5SAndroid Build Coastguard Worker                                           const char *name,
2542*8975f5c5SAndroid Build Coastguard Worker                                           const char *value,
2543*8975f5c5SAndroid Build Coastguard Worker                                           bool stdgl)
2544*8975f5c5SAndroid Build Coastguard Worker {
2545*8975f5c5SAndroid Build Coastguard Worker     angle::pp::SourceLocation srcLoc;
2546*8975f5c5SAndroid Build Coastguard Worker     srcLoc.file = loc.first_file;
2547*8975f5c5SAndroid Build Coastguard Worker     srcLoc.line = loc.first_line;
2548*8975f5c5SAndroid Build Coastguard Worker     mDirectiveHandler.handlePragma(srcLoc, name, value, stdgl);
2549*8975f5c5SAndroid Build Coastguard Worker }
2550*8975f5c5SAndroid Build Coastguard Worker 
getComputeShaderLocalSize() const2551*8975f5c5SAndroid Build Coastguard Worker sh::WorkGroupSize TParseContext::getComputeShaderLocalSize() const
2552*8975f5c5SAndroid Build Coastguard Worker {
2553*8975f5c5SAndroid Build Coastguard Worker     sh::WorkGroupSize result(-1);
2554*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0u; i < result.size(); ++i)
2555*8975f5c5SAndroid Build Coastguard Worker     {
2556*8975f5c5SAndroid Build Coastguard Worker         if (mComputeShaderLocalSizeDeclared && mComputeShaderLocalSize[i] == -1)
2557*8975f5c5SAndroid Build Coastguard Worker         {
2558*8975f5c5SAndroid Build Coastguard Worker             result[i] = 1;
2559*8975f5c5SAndroid Build Coastguard Worker         }
2560*8975f5c5SAndroid Build Coastguard Worker         else
2561*8975f5c5SAndroid Build Coastguard Worker         {
2562*8975f5c5SAndroid Build Coastguard Worker             result[i] = mComputeShaderLocalSize[i];
2563*8975f5c5SAndroid Build Coastguard Worker         }
2564*8975f5c5SAndroid Build Coastguard Worker     }
2565*8975f5c5SAndroid Build Coastguard Worker     return result;
2566*8975f5c5SAndroid Build Coastguard Worker }
2567*8975f5c5SAndroid Build Coastguard Worker 
addScalarLiteral(const TConstantUnion * constantUnion,const TSourceLoc & line)2568*8975f5c5SAndroid Build Coastguard Worker TIntermConstantUnion *TParseContext::addScalarLiteral(const TConstantUnion *constantUnion,
2569*8975f5c5SAndroid Build Coastguard Worker                                                       const TSourceLoc &line)
2570*8975f5c5SAndroid Build Coastguard Worker {
2571*8975f5c5SAndroid Build Coastguard Worker     TIntermConstantUnion *node = new TIntermConstantUnion(
2572*8975f5c5SAndroid Build Coastguard Worker         constantUnion, TType(constantUnion->getType(), EbpUndefined, EvqConst));
2573*8975f5c5SAndroid Build Coastguard Worker     node->setLine(line);
2574*8975f5c5SAndroid Build Coastguard Worker     return node;
2575*8975f5c5SAndroid Build Coastguard Worker }
2576*8975f5c5SAndroid Build Coastguard Worker 
2577*8975f5c5SAndroid Build Coastguard Worker /////////////////////////////////////////////////////////////////////////////////
2578*8975f5c5SAndroid Build Coastguard Worker //
2579*8975f5c5SAndroid Build Coastguard Worker // Non-Errors.
2580*8975f5c5SAndroid Build Coastguard Worker //
2581*8975f5c5SAndroid Build Coastguard Worker /////////////////////////////////////////////////////////////////////////////////
2582*8975f5c5SAndroid Build Coastguard Worker 
getNamedVariable(const TSourceLoc & location,const ImmutableString & name,const TSymbol * symbol)2583*8975f5c5SAndroid Build Coastguard Worker const TVariable *TParseContext::getNamedVariable(const TSourceLoc &location,
2584*8975f5c5SAndroid Build Coastguard Worker                                                  const ImmutableString &name,
2585*8975f5c5SAndroid Build Coastguard Worker                                                  const TSymbol *symbol)
2586*8975f5c5SAndroid Build Coastguard Worker {
2587*8975f5c5SAndroid Build Coastguard Worker     if (!symbol)
2588*8975f5c5SAndroid Build Coastguard Worker     {
2589*8975f5c5SAndroid Build Coastguard Worker         error(location, "undeclared identifier", name);
2590*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
2591*8975f5c5SAndroid Build Coastguard Worker     }
2592*8975f5c5SAndroid Build Coastguard Worker 
2593*8975f5c5SAndroid Build Coastguard Worker     if (!symbol->isVariable())
2594*8975f5c5SAndroid Build Coastguard Worker     {
2595*8975f5c5SAndroid Build Coastguard Worker         error(location, "variable expected", name);
2596*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
2597*8975f5c5SAndroid Build Coastguard Worker     }
2598*8975f5c5SAndroid Build Coastguard Worker 
2599*8975f5c5SAndroid Build Coastguard Worker     const TVariable *variable = static_cast<const TVariable *>(symbol);
2600*8975f5c5SAndroid Build Coastguard Worker 
2601*8975f5c5SAndroid Build Coastguard Worker     if (!variable->extensions().empty() && variable->extensions()[0] != TExtension::UNDEFINED)
2602*8975f5c5SAndroid Build Coastguard Worker     {
2603*8975f5c5SAndroid Build Coastguard Worker         checkCanUseOneOfExtensions(location, variable->extensions());
2604*8975f5c5SAndroid Build Coastguard Worker     }
2605*8975f5c5SAndroid Build Coastguard Worker 
2606*8975f5c5SAndroid Build Coastguard Worker     // GLSL ES 3.1 Revision 4, 7.1.3 Compute Shader Special Variables
2607*8975f5c5SAndroid Build Coastguard Worker     if (getShaderType() == GL_COMPUTE_SHADER && !mComputeShaderLocalSizeDeclared &&
2608*8975f5c5SAndroid Build Coastguard Worker         variable->getType().getQualifier() == EvqWorkGroupSize)
2609*8975f5c5SAndroid Build Coastguard Worker     {
2610*8975f5c5SAndroid Build Coastguard Worker         error(location,
2611*8975f5c5SAndroid Build Coastguard Worker               "It is an error to use gl_WorkGroupSize before declaring the local group size",
2612*8975f5c5SAndroid Build Coastguard Worker               "gl_WorkGroupSize");
2613*8975f5c5SAndroid Build Coastguard Worker     }
2614*8975f5c5SAndroid Build Coastguard Worker 
2615*8975f5c5SAndroid Build Coastguard Worker     // If EXT_shader_framebuffer_fetch_non_coherent is used, gl_LastFragData should be decorated
2616*8975f5c5SAndroid Build Coastguard Worker     // with 'layout(noncoherent)' EXT_shader_framebuffer_fetch_non_coherent spec: "Unless the
2617*8975f5c5SAndroid Build Coastguard Worker     // GL_EXT_shader_framebuffer_fetch extension  has been enabled in addition, it's an error to use
2618*8975f5c5SAndroid Build Coastguard Worker     // gl_LastFragData if it hasn't been explicitly redeclared with layout(noncoherent)."
2619*8975f5c5SAndroid Build Coastguard Worker     if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent) &&
2620*8975f5c5SAndroid Build Coastguard Worker         !isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) &&
2621*8975f5c5SAndroid Build Coastguard Worker         variable->getType().getQualifier() == EvqLastFragData)
2622*8975f5c5SAndroid Build Coastguard Worker     {
2623*8975f5c5SAndroid Build Coastguard Worker         checkNoncoherentIsSpecified(location, variable->getType().getLayoutQualifier().noncoherent);
2624*8975f5c5SAndroid Build Coastguard Worker     }
2625*8975f5c5SAndroid Build Coastguard Worker 
2626*8975f5c5SAndroid Build Coastguard Worker     // When EXT_separate_shader_objects is enabled, gl_Position and gl_PointSize must both be
2627*8975f5c5SAndroid Build Coastguard Worker     // redeclared before either is accessed:
2628*8975f5c5SAndroid Build Coastguard Worker     //
2629*8975f5c5SAndroid Build Coastguard Worker     // > The following vertex shader outputs may be redeclared at global scope to
2630*8975f5c5SAndroid Build Coastguard Worker     // > specify a built-in output interface, with or without special qualifiers:
2631*8975f5c5SAndroid Build Coastguard Worker     // >
2632*8975f5c5SAndroid Build Coastguard Worker     // >     gl_Position
2633*8975f5c5SAndroid Build Coastguard Worker     // >     gl_PointSize
2634*8975f5c5SAndroid Build Coastguard Worker     // >
2635*8975f5c5SAndroid Build Coastguard Worker     // >   When compiling shaders using either of the above variables, both such
2636*8975f5c5SAndroid Build Coastguard Worker     // >   variables must be redeclared prior to use.  ((Note:  This restriction
2637*8975f5c5SAndroid Build Coastguard Worker     // >   applies only to shaders using version 300 that enable the
2638*8975f5c5SAndroid Build Coastguard Worker     // >   EXT_separate_shader_objects extension; shaders not enabling the
2639*8975f5c5SAndroid Build Coastguard Worker     // >   extension do not have this requirement.))
2640*8975f5c5SAndroid Build Coastguard Worker     //
2641*8975f5c5SAndroid Build Coastguard Worker     // However, there are dEQP tests that enable all extensions and don't actually redeclare these
2642*8975f5c5SAndroid Build Coastguard Worker     // variables.  Per https://gitlab.khronos.org/opengl/API/-/issues/169, there are drivers that do
2643*8975f5c5SAndroid Build Coastguard Worker     // enforce this, but they fail linking instead of compilation.
2644*8975f5c5SAndroid Build Coastguard Worker     //
2645*8975f5c5SAndroid Build Coastguard Worker     // In ANGLE, we make sure that they are both redeclared before use if any is redeclared, but if
2646*8975f5c5SAndroid Build Coastguard Worker     // neither are redeclared, we don't fail compilation.  Currently, linking also doesn't fail in
2647*8975f5c5SAndroid Build Coastguard Worker     // ANGLE (similarly to almost all other drivers).
2648*8975f5c5SAndroid Build Coastguard Worker     if (isExtensionEnabled(TExtension::EXT_separate_shader_objects) &&
2649*8975f5c5SAndroid Build Coastguard Worker         mShaderType == GL_VERTEX_SHADER)
2650*8975f5c5SAndroid Build Coastguard Worker     {
2651*8975f5c5SAndroid Build Coastguard Worker         if (variable->getType().getQualifier() == EvqPosition ||
2652*8975f5c5SAndroid Build Coastguard Worker             variable->getType().getQualifier() == EvqPointSize)
2653*8975f5c5SAndroid Build Coastguard Worker         {
2654*8975f5c5SAndroid Build Coastguard Worker             mPositionOrPointSizeUsedForSeparateShaderObject = true;
2655*8975f5c5SAndroid Build Coastguard Worker             const bool eitherIsRedeclared = mPositionRedeclaredForSeparateShaderObject ||
2656*8975f5c5SAndroid Build Coastguard Worker                                             mPointSizeRedeclaredForSeparateShaderObject;
2657*8975f5c5SAndroid Build Coastguard Worker             const bool bothAreRedeclared = mPositionRedeclaredForSeparateShaderObject &&
2658*8975f5c5SAndroid Build Coastguard Worker                                            mPointSizeRedeclaredForSeparateShaderObject;
2659*8975f5c5SAndroid Build Coastguard Worker 
2660*8975f5c5SAndroid Build Coastguard Worker             if (eitherIsRedeclared && !bothAreRedeclared)
2661*8975f5c5SAndroid Build Coastguard Worker             {
2662*8975f5c5SAndroid Build Coastguard Worker                 error(location,
2663*8975f5c5SAndroid Build Coastguard Worker                       "When EXT_separate_shader_objects is enabled, both gl_Position and "
2664*8975f5c5SAndroid Build Coastguard Worker                       "gl_PointSize must be redeclared before either is used",
2665*8975f5c5SAndroid Build Coastguard Worker                       name);
2666*8975f5c5SAndroid Build Coastguard Worker             }
2667*8975f5c5SAndroid Build Coastguard Worker         }
2668*8975f5c5SAndroid Build Coastguard Worker     }
2669*8975f5c5SAndroid Build Coastguard Worker 
2670*8975f5c5SAndroid Build Coastguard Worker     return variable;
2671*8975f5c5SAndroid Build Coastguard Worker }
2672*8975f5c5SAndroid Build Coastguard Worker 
parseVariableIdentifier(const TSourceLoc & location,const ImmutableString & name,const TSymbol * symbol)2673*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::parseVariableIdentifier(const TSourceLoc &location,
2674*8975f5c5SAndroid Build Coastguard Worker                                                      const ImmutableString &name,
2675*8975f5c5SAndroid Build Coastguard Worker                                                      const TSymbol *symbol)
2676*8975f5c5SAndroid Build Coastguard Worker {
2677*8975f5c5SAndroid Build Coastguard Worker     const TVariable *variable = getNamedVariable(location, name, symbol);
2678*8975f5c5SAndroid Build Coastguard Worker 
2679*8975f5c5SAndroid Build Coastguard Worker     if (!variable)
2680*8975f5c5SAndroid Build Coastguard Worker     {
2681*8975f5c5SAndroid Build Coastguard Worker         TIntermTyped *node = CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
2682*8975f5c5SAndroid Build Coastguard Worker         node->setLine(location);
2683*8975f5c5SAndroid Build Coastguard Worker         return node;
2684*8975f5c5SAndroid Build Coastguard Worker     }
2685*8975f5c5SAndroid Build Coastguard Worker 
2686*8975f5c5SAndroid Build Coastguard Worker     const TType &variableType = variable->getType();
2687*8975f5c5SAndroid Build Coastguard Worker     TIntermTyped *node        = nullptr;
2688*8975f5c5SAndroid Build Coastguard Worker 
2689*8975f5c5SAndroid Build Coastguard Worker     if (variable->getConstPointer() && variableType.canReplaceWithConstantUnion())
2690*8975f5c5SAndroid Build Coastguard Worker     {
2691*8975f5c5SAndroid Build Coastguard Worker         const TConstantUnion *constArray = variable->getConstPointer();
2692*8975f5c5SAndroid Build Coastguard Worker         node                             = new TIntermConstantUnion(constArray, variableType);
2693*8975f5c5SAndroid Build Coastguard Worker     }
2694*8975f5c5SAndroid Build Coastguard Worker     else if (variableType.getQualifier() == EvqWorkGroupSize && mComputeShaderLocalSizeDeclared)
2695*8975f5c5SAndroid Build Coastguard Worker     {
2696*8975f5c5SAndroid Build Coastguard Worker         // gl_WorkGroupSize can be used to size arrays according to the ESSL 3.10.4 spec, so it
2697*8975f5c5SAndroid Build Coastguard Worker         // needs to be added to the AST as a constant and not as a symbol.
2698*8975f5c5SAndroid Build Coastguard Worker         sh::WorkGroupSize workGroupSize = getComputeShaderLocalSize();
2699*8975f5c5SAndroid Build Coastguard Worker         TConstantUnion *constArray      = new TConstantUnion[3];
2700*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0; i < 3; ++i)
2701*8975f5c5SAndroid Build Coastguard Worker         {
2702*8975f5c5SAndroid Build Coastguard Worker             constArray[i].setUConst(static_cast<unsigned int>(workGroupSize[i]));
2703*8975f5c5SAndroid Build Coastguard Worker         }
2704*8975f5c5SAndroid Build Coastguard Worker 
2705*8975f5c5SAndroid Build Coastguard Worker         ASSERT(variableType.getBasicType() == EbtUInt);
2706*8975f5c5SAndroid Build Coastguard Worker         ASSERT(variableType.getObjectSize() == 3);
2707*8975f5c5SAndroid Build Coastguard Worker 
2708*8975f5c5SAndroid Build Coastguard Worker         TType type(variableType);
2709*8975f5c5SAndroid Build Coastguard Worker         type.setQualifier(EvqConst);
2710*8975f5c5SAndroid Build Coastguard Worker         node = new TIntermConstantUnion(constArray, type);
2711*8975f5c5SAndroid Build Coastguard Worker     }
2712*8975f5c5SAndroid Build Coastguard Worker     else if ((mGeometryShaderInputPrimitiveType != EptUndefined) &&
2713*8975f5c5SAndroid Build Coastguard Worker              (variableType.getQualifier() == EvqPerVertexIn))
2714*8975f5c5SAndroid Build Coastguard Worker     {
2715*8975f5c5SAndroid Build Coastguard Worker         ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
2716*8975f5c5SAndroid Build Coastguard Worker         node = new TIntermSymbol(symbolTable.getGlInVariableWithArraySize());
2717*8975f5c5SAndroid Build Coastguard Worker     }
2718*8975f5c5SAndroid Build Coastguard Worker     else
2719*8975f5c5SAndroid Build Coastguard Worker     {
2720*8975f5c5SAndroid Build Coastguard Worker         // gl_LastFragDepthARM and gl_LastFragStencilARM cannot be accessed if early_fragment_tests
2721*8975f5c5SAndroid Build Coastguard Worker         // is specified.
2722*8975f5c5SAndroid Build Coastguard Worker         if ((variableType.getQualifier() == EvqLastFragDepth ||
2723*8975f5c5SAndroid Build Coastguard Worker              variableType.getQualifier() == EvqLastFragStencil) &&
2724*8975f5c5SAndroid Build Coastguard Worker             isEarlyFragmentTestsSpecified())
2725*8975f5c5SAndroid Build Coastguard Worker         {
2726*8975f5c5SAndroid Build Coastguard Worker             error(location,
2727*8975f5c5SAndroid Build Coastguard Worker                   "gl_LastFragDepthARM and gl_LastFragStencilARM cannot be accessed because "
2728*8975f5c5SAndroid Build Coastguard Worker                   "early_fragment_tests is specified",
2729*8975f5c5SAndroid Build Coastguard Worker                   name);
2730*8975f5c5SAndroid Build Coastguard Worker         }
2731*8975f5c5SAndroid Build Coastguard Worker 
2732*8975f5c5SAndroid Build Coastguard Worker         node = new TIntermSymbol(variable);
2733*8975f5c5SAndroid Build Coastguard Worker     }
2734*8975f5c5SAndroid Build Coastguard Worker     ASSERT(node != nullptr);
2735*8975f5c5SAndroid Build Coastguard Worker     node->setLine(location);
2736*8975f5c5SAndroid Build Coastguard Worker     return node;
2737*8975f5c5SAndroid Build Coastguard Worker }
2738*8975f5c5SAndroid Build Coastguard Worker 
adjustRedeclaredBuiltInType(const TSourceLoc & line,const ImmutableString & identifier,TType * type)2739*8975f5c5SAndroid Build Coastguard Worker void TParseContext::adjustRedeclaredBuiltInType(const TSourceLoc &line,
2740*8975f5c5SAndroid Build Coastguard Worker                                                 const ImmutableString &identifier,
2741*8975f5c5SAndroid Build Coastguard Worker                                                 TType *type)
2742*8975f5c5SAndroid Build Coastguard Worker {
2743*8975f5c5SAndroid Build Coastguard Worker     if (identifier == "gl_ClipDistance")
2744*8975f5c5SAndroid Build Coastguard Worker     {
2745*8975f5c5SAndroid Build Coastguard Worker         const TQualifier qualifier = type->getQualifier();
2746*8975f5c5SAndroid Build Coastguard Worker         if ((mShaderType == GL_VERTEX_SHADER &&
2747*8975f5c5SAndroid Build Coastguard Worker              !(qualifier == EvqVertexOut || qualifier == EvqVaryingOut)) ||
2748*8975f5c5SAndroid Build Coastguard Worker             (mShaderType == GL_FRAGMENT_SHADER && qualifier != EvqFragmentIn))
2749*8975f5c5SAndroid Build Coastguard Worker         {
2750*8975f5c5SAndroid Build Coastguard Worker             error(line, "invalid or missing storage qualifier", identifier);
2751*8975f5c5SAndroid Build Coastguard Worker             return;
2752*8975f5c5SAndroid Build Coastguard Worker         }
2753*8975f5c5SAndroid Build Coastguard Worker 
2754*8975f5c5SAndroid Build Coastguard Worker         type->setQualifier(EvqClipDistance);
2755*8975f5c5SAndroid Build Coastguard Worker     }
2756*8975f5c5SAndroid Build Coastguard Worker     else if (identifier == "gl_CullDistance")
2757*8975f5c5SAndroid Build Coastguard Worker     {
2758*8975f5c5SAndroid Build Coastguard Worker         const TQualifier qualifier = type->getQualifier();
2759*8975f5c5SAndroid Build Coastguard Worker         if ((mShaderType == GL_VERTEX_SHADER && qualifier != EvqVertexOut) ||
2760*8975f5c5SAndroid Build Coastguard Worker             (mShaderType == GL_FRAGMENT_SHADER && qualifier != EvqFragmentIn))
2761*8975f5c5SAndroid Build Coastguard Worker         {
2762*8975f5c5SAndroid Build Coastguard Worker             error(line, "invalid or missing storage qualifier", identifier);
2763*8975f5c5SAndroid Build Coastguard Worker             return;
2764*8975f5c5SAndroid Build Coastguard Worker         }
2765*8975f5c5SAndroid Build Coastguard Worker 
2766*8975f5c5SAndroid Build Coastguard Worker         type->setQualifier(EvqCullDistance);
2767*8975f5c5SAndroid Build Coastguard Worker     }
2768*8975f5c5SAndroid Build Coastguard Worker     else if (identifier == "gl_LastFragData")
2769*8975f5c5SAndroid Build Coastguard Worker     {
2770*8975f5c5SAndroid Build Coastguard Worker         type->setQualifier(EvqLastFragData);
2771*8975f5c5SAndroid Build Coastguard Worker     }
2772*8975f5c5SAndroid Build Coastguard Worker     else if (identifier == "gl_LastFragColorARM")
2773*8975f5c5SAndroid Build Coastguard Worker     {
2774*8975f5c5SAndroid Build Coastguard Worker         type->setQualifier(EvqLastFragColor);
2775*8975f5c5SAndroid Build Coastguard Worker     }
2776*8975f5c5SAndroid Build Coastguard Worker     else if (identifier == "gl_LastFragDepthARM")
2777*8975f5c5SAndroid Build Coastguard Worker     {
2778*8975f5c5SAndroid Build Coastguard Worker         type->setQualifier(EvqLastFragDepth);
2779*8975f5c5SAndroid Build Coastguard Worker     }
2780*8975f5c5SAndroid Build Coastguard Worker     else if (identifier == "gl_LastFragStencilARM")
2781*8975f5c5SAndroid Build Coastguard Worker     {
2782*8975f5c5SAndroid Build Coastguard Worker         type->setQualifier(EvqLastFragStencil);
2783*8975f5c5SAndroid Build Coastguard Worker     }
2784*8975f5c5SAndroid Build Coastguard Worker     else if (identifier == "gl_Position")
2785*8975f5c5SAndroid Build Coastguard Worker     {
2786*8975f5c5SAndroid Build Coastguard Worker         type->setQualifier(EvqPosition);
2787*8975f5c5SAndroid Build Coastguard Worker     }
2788*8975f5c5SAndroid Build Coastguard Worker     else if (identifier == "gl_PointSize")
2789*8975f5c5SAndroid Build Coastguard Worker     {
2790*8975f5c5SAndroid Build Coastguard Worker         type->setQualifier(EvqPointSize);
2791*8975f5c5SAndroid Build Coastguard Worker     }
2792*8975f5c5SAndroid Build Coastguard Worker }
2793*8975f5c5SAndroid Build Coastguard Worker 
2794*8975f5c5SAndroid Build Coastguard Worker // Initializers show up in several places in the grammar.  Have one set of
2795*8975f5c5SAndroid Build Coastguard Worker // code to handle them here.
2796*8975f5c5SAndroid Build Coastguard Worker //
2797*8975f5c5SAndroid Build Coastguard Worker // Returns true on success.
executeInitializer(const TSourceLoc & line,const ImmutableString & identifier,TType * type,TIntermTyped * initializer,TIntermBinary ** initNode)2798*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::executeInitializer(const TSourceLoc &line,
2799*8975f5c5SAndroid Build Coastguard Worker                                        const ImmutableString &identifier,
2800*8975f5c5SAndroid Build Coastguard Worker                                        TType *type,
2801*8975f5c5SAndroid Build Coastguard Worker                                        TIntermTyped *initializer,
2802*8975f5c5SAndroid Build Coastguard Worker                                        TIntermBinary **initNode)
2803*8975f5c5SAndroid Build Coastguard Worker {
2804*8975f5c5SAndroid Build Coastguard Worker     ASSERT(initNode != nullptr);
2805*8975f5c5SAndroid Build Coastguard Worker     ASSERT(*initNode == nullptr);
2806*8975f5c5SAndroid Build Coastguard Worker 
2807*8975f5c5SAndroid Build Coastguard Worker     if (type->isUnsizedArray())
2808*8975f5c5SAndroid Build Coastguard Worker     {
2809*8975f5c5SAndroid Build Coastguard Worker         // In case initializer is not an array or type has more dimensions than initializer, this
2810*8975f5c5SAndroid Build Coastguard Worker         // will default to setting array sizes to 1. We have not checked yet whether the initializer
2811*8975f5c5SAndroid Build Coastguard Worker         // actually is an array or not. Having a non-array initializer for an unsized array will
2812*8975f5c5SAndroid Build Coastguard Worker         // result in an error later, so we don't generate an error message here.
2813*8975f5c5SAndroid Build Coastguard Worker         type->sizeUnsizedArrays(initializer->getType().getArraySizes());
2814*8975f5c5SAndroid Build Coastguard Worker     }
2815*8975f5c5SAndroid Build Coastguard Worker 
2816*8975f5c5SAndroid Build Coastguard Worker     const TQualifier qualifier = type->getQualifier();
2817*8975f5c5SAndroid Build Coastguard Worker 
2818*8975f5c5SAndroid Build Coastguard Worker     bool constError = false;
2819*8975f5c5SAndroid Build Coastguard Worker     if (qualifier == EvqConst)
2820*8975f5c5SAndroid Build Coastguard Worker     {
2821*8975f5c5SAndroid Build Coastguard Worker         if (EvqConst != initializer->getType().getQualifier())
2822*8975f5c5SAndroid Build Coastguard Worker         {
2823*8975f5c5SAndroid Build Coastguard Worker             TInfoSinkBase reasonStream;
2824*8975f5c5SAndroid Build Coastguard Worker             reasonStream << "assigning non-constant to '" << *type << "'";
2825*8975f5c5SAndroid Build Coastguard Worker             error(line, reasonStream.c_str(), "=");
2826*8975f5c5SAndroid Build Coastguard Worker 
2827*8975f5c5SAndroid Build Coastguard Worker             // We're still going to declare the variable to avoid extra error messages.
2828*8975f5c5SAndroid Build Coastguard Worker             type->setQualifier(EvqTemporary);
2829*8975f5c5SAndroid Build Coastguard Worker             constError = true;
2830*8975f5c5SAndroid Build Coastguard Worker         }
2831*8975f5c5SAndroid Build Coastguard Worker     }
2832*8975f5c5SAndroid Build Coastguard Worker 
2833*8975f5c5SAndroid Build Coastguard Worker     TVariable *variable = nullptr;
2834*8975f5c5SAndroid Build Coastguard Worker     if (!declareVariable(line, identifier, type, &variable))
2835*8975f5c5SAndroid Build Coastguard Worker     {
2836*8975f5c5SAndroid Build Coastguard Worker         return false;
2837*8975f5c5SAndroid Build Coastguard Worker     }
2838*8975f5c5SAndroid Build Coastguard Worker 
2839*8975f5c5SAndroid Build Coastguard Worker     if (constError)
2840*8975f5c5SAndroid Build Coastguard Worker     {
2841*8975f5c5SAndroid Build Coastguard Worker         return false;
2842*8975f5c5SAndroid Build Coastguard Worker     }
2843*8975f5c5SAndroid Build Coastguard Worker 
2844*8975f5c5SAndroid Build Coastguard Worker     bool nonConstGlobalInitializers =
2845*8975f5c5SAndroid Build Coastguard Worker         IsExtensionEnabled(mDirectiveHandler.extensionBehavior(),
2846*8975f5c5SAndroid Build Coastguard Worker                            TExtension::EXT_shader_non_constant_global_initializers);
2847*8975f5c5SAndroid Build Coastguard Worker     bool globalInitWarning = false;
2848*8975f5c5SAndroid Build Coastguard Worker     if (symbolTable.atGlobalLevel() &&
2849*8975f5c5SAndroid Build Coastguard Worker         !ValidateGlobalInitializer(initializer, mShaderVersion, sh::IsWebGLBasedSpec(mShaderSpec),
2850*8975f5c5SAndroid Build Coastguard Worker                                    nonConstGlobalInitializers, &globalInitWarning))
2851*8975f5c5SAndroid Build Coastguard Worker     {
2852*8975f5c5SAndroid Build Coastguard Worker         // Error message does not completely match behavior with ESSL 1.00, but
2853*8975f5c5SAndroid Build Coastguard Worker         // we want to steer developers towards only using constant expressions.
2854*8975f5c5SAndroid Build Coastguard Worker         error(line, "global variable initializers must be constant expressions", "=");
2855*8975f5c5SAndroid Build Coastguard Worker         return false;
2856*8975f5c5SAndroid Build Coastguard Worker     }
2857*8975f5c5SAndroid Build Coastguard Worker     if (globalInitWarning)
2858*8975f5c5SAndroid Build Coastguard Worker     {
2859*8975f5c5SAndroid Build Coastguard Worker         warning(
2860*8975f5c5SAndroid Build Coastguard Worker             line,
2861*8975f5c5SAndroid Build Coastguard Worker             "global variable initializers should be constant expressions "
2862*8975f5c5SAndroid Build Coastguard Worker             "(uniforms and globals are allowed in global initializers for legacy compatibility)",
2863*8975f5c5SAndroid Build Coastguard Worker             "=");
2864*8975f5c5SAndroid Build Coastguard Worker     }
2865*8975f5c5SAndroid Build Coastguard Worker 
2866*8975f5c5SAndroid Build Coastguard Worker     // identifier must be of type constant, a global, or a temporary
2867*8975f5c5SAndroid Build Coastguard Worker     if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal) && (qualifier != EvqConst))
2868*8975f5c5SAndroid Build Coastguard Worker     {
2869*8975f5c5SAndroid Build Coastguard Worker         error(line, " cannot initialize this type of qualifier ",
2870*8975f5c5SAndroid Build Coastguard Worker               variable->getType().getQualifierString());
2871*8975f5c5SAndroid Build Coastguard Worker         return false;
2872*8975f5c5SAndroid Build Coastguard Worker     }
2873*8975f5c5SAndroid Build Coastguard Worker 
2874*8975f5c5SAndroid Build Coastguard Worker     TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
2875*8975f5c5SAndroid Build Coastguard Worker     intermSymbol->setLine(line);
2876*8975f5c5SAndroid Build Coastguard Worker 
2877*8975f5c5SAndroid Build Coastguard Worker     if (!binaryOpCommonCheck(EOpInitialize, intermSymbol, initializer, line))
2878*8975f5c5SAndroid Build Coastguard Worker     {
2879*8975f5c5SAndroid Build Coastguard Worker         assignError(line, "=", variable->getType(), initializer->getType());
2880*8975f5c5SAndroid Build Coastguard Worker         return false;
2881*8975f5c5SAndroid Build Coastguard Worker     }
2882*8975f5c5SAndroid Build Coastguard Worker 
2883*8975f5c5SAndroid Build Coastguard Worker     if (qualifier == EvqConst)
2884*8975f5c5SAndroid Build Coastguard Worker     {
2885*8975f5c5SAndroid Build Coastguard Worker         // Save the constant folded value to the variable if possible.
2886*8975f5c5SAndroid Build Coastguard Worker         const TConstantUnion *constArray = initializer->getConstantValue();
2887*8975f5c5SAndroid Build Coastguard Worker         if (constArray)
2888*8975f5c5SAndroid Build Coastguard Worker         {
2889*8975f5c5SAndroid Build Coastguard Worker             variable->shareConstPointer(constArray);
2890*8975f5c5SAndroid Build Coastguard Worker             if (initializer->getType().canReplaceWithConstantUnion())
2891*8975f5c5SAndroid Build Coastguard Worker             {
2892*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(*initNode == nullptr);
2893*8975f5c5SAndroid Build Coastguard Worker                 return true;
2894*8975f5c5SAndroid Build Coastguard Worker             }
2895*8975f5c5SAndroid Build Coastguard Worker         }
2896*8975f5c5SAndroid Build Coastguard Worker     }
2897*8975f5c5SAndroid Build Coastguard Worker 
2898*8975f5c5SAndroid Build Coastguard Worker     *initNode = new TIntermBinary(EOpInitialize, intermSymbol, initializer);
2899*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(initializer);
2900*8975f5c5SAndroid Build Coastguard Worker     (*initNode)->setLine(line);
2901*8975f5c5SAndroid Build Coastguard Worker     return true;
2902*8975f5c5SAndroid Build Coastguard Worker }
2903*8975f5c5SAndroid Build Coastguard Worker 
addConditionInitializer(const TPublicType & pType,const ImmutableString & identifier,TIntermTyped * initializer,const TSourceLoc & loc)2904*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TParseContext::addConditionInitializer(const TPublicType &pType,
2905*8975f5c5SAndroid Build Coastguard Worker                                                     const ImmutableString &identifier,
2906*8975f5c5SAndroid Build Coastguard Worker                                                     TIntermTyped *initializer,
2907*8975f5c5SAndroid Build Coastguard Worker                                                     const TSourceLoc &loc)
2908*8975f5c5SAndroid Build Coastguard Worker {
2909*8975f5c5SAndroid Build Coastguard Worker     checkIsScalarBool(loc, pType);
2910*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *initNode = nullptr;
2911*8975f5c5SAndroid Build Coastguard Worker     TType *type             = new TType(pType);
2912*8975f5c5SAndroid Build Coastguard Worker     if (executeInitializer(loc, identifier, type, initializer, &initNode))
2913*8975f5c5SAndroid Build Coastguard Worker     {
2914*8975f5c5SAndroid Build Coastguard Worker         // The initializer is valid. The init condition needs to have a node - either the
2915*8975f5c5SAndroid Build Coastguard Worker         // initializer node, or a constant node in case the initialized variable is const and won't
2916*8975f5c5SAndroid Build Coastguard Worker         // be recorded in the AST.
2917*8975f5c5SAndroid Build Coastguard Worker         if (initNode == nullptr)
2918*8975f5c5SAndroid Build Coastguard Worker         {
2919*8975f5c5SAndroid Build Coastguard Worker             return initializer;
2920*8975f5c5SAndroid Build Coastguard Worker         }
2921*8975f5c5SAndroid Build Coastguard Worker         else
2922*8975f5c5SAndroid Build Coastguard Worker         {
2923*8975f5c5SAndroid Build Coastguard Worker             TIntermDeclaration *declaration = new TIntermDeclaration();
2924*8975f5c5SAndroid Build Coastguard Worker             declaration->appendDeclarator(initNode);
2925*8975f5c5SAndroid Build Coastguard Worker             return declaration;
2926*8975f5c5SAndroid Build Coastguard Worker         }
2927*8975f5c5SAndroid Build Coastguard Worker     }
2928*8975f5c5SAndroid Build Coastguard Worker     return nullptr;
2929*8975f5c5SAndroid Build Coastguard Worker }
2930*8975f5c5SAndroid Build Coastguard Worker 
addLoop(TLoopType type,TIntermNode * init,TIntermNode * cond,TIntermTyped * expr,TIntermNode * body,const TSourceLoc & line)2931*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TParseContext::addLoop(TLoopType type,
2932*8975f5c5SAndroid Build Coastguard Worker                                     TIntermNode *init,
2933*8975f5c5SAndroid Build Coastguard Worker                                     TIntermNode *cond,
2934*8975f5c5SAndroid Build Coastguard Worker                                     TIntermTyped *expr,
2935*8975f5c5SAndroid Build Coastguard Worker                                     TIntermNode *body,
2936*8975f5c5SAndroid Build Coastguard Worker                                     const TSourceLoc &line)
2937*8975f5c5SAndroid Build Coastguard Worker {
2938*8975f5c5SAndroid Build Coastguard Worker     TIntermNode *node       = nullptr;
2939*8975f5c5SAndroid Build Coastguard Worker     TIntermTyped *typedCond = nullptr;
2940*8975f5c5SAndroid Build Coastguard Worker     if (cond)
2941*8975f5c5SAndroid Build Coastguard Worker     {
2942*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(cond);
2943*8975f5c5SAndroid Build Coastguard Worker         typedCond = cond->getAsTyped();
2944*8975f5c5SAndroid Build Coastguard Worker     }
2945*8975f5c5SAndroid Build Coastguard Worker     if (expr)
2946*8975f5c5SAndroid Build Coastguard Worker     {
2947*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(expr);
2948*8975f5c5SAndroid Build Coastguard Worker     }
2949*8975f5c5SAndroid Build Coastguard Worker     // In case the loop body was not parsed as a block and contains a statement that simply refers
2950*8975f5c5SAndroid Build Coastguard Worker     // to a variable, we need to mark it as statically used.
2951*8975f5c5SAndroid Build Coastguard Worker     if (body)
2952*8975f5c5SAndroid Build Coastguard Worker     {
2953*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(body);
2954*8975f5c5SAndroid Build Coastguard Worker     }
2955*8975f5c5SAndroid Build Coastguard Worker     if (cond == nullptr || typedCond)
2956*8975f5c5SAndroid Build Coastguard Worker     {
2957*8975f5c5SAndroid Build Coastguard Worker         if (type == ELoopDoWhile && typedCond)
2958*8975f5c5SAndroid Build Coastguard Worker         {
2959*8975f5c5SAndroid Build Coastguard Worker             checkIsScalarBool(line, typedCond);
2960*8975f5c5SAndroid Build Coastguard Worker         }
2961*8975f5c5SAndroid Build Coastguard Worker         // In the case of other loops, it was checked before that the condition is a scalar boolean.
2962*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mDiagnostics->numErrors() > 0 || typedCond == nullptr ||
2963*8975f5c5SAndroid Build Coastguard Worker                (typedCond->getBasicType() == EbtBool && !typedCond->isArray() &&
2964*8975f5c5SAndroid Build Coastguard Worker                 !typedCond->isVector()));
2965*8975f5c5SAndroid Build Coastguard Worker 
2966*8975f5c5SAndroid Build Coastguard Worker         node = new TIntermLoop(type, init, typedCond, expr, EnsureLoopBodyBlock(body));
2967*8975f5c5SAndroid Build Coastguard Worker         node->setLine(line);
2968*8975f5c5SAndroid Build Coastguard Worker         return node;
2969*8975f5c5SAndroid Build Coastguard Worker     }
2970*8975f5c5SAndroid Build Coastguard Worker 
2971*8975f5c5SAndroid Build Coastguard Worker     ASSERT(type != ELoopDoWhile);
2972*8975f5c5SAndroid Build Coastguard Worker 
2973*8975f5c5SAndroid Build Coastguard Worker     TIntermDeclaration *declaration = cond->getAsDeclarationNode();
2974*8975f5c5SAndroid Build Coastguard Worker     ASSERT(declaration);
2975*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *declarator = declaration->getSequence()->front()->getAsBinaryNode();
2976*8975f5c5SAndroid Build Coastguard Worker     ASSERT(declarator->getLeft()->getAsSymbolNode());
2977*8975f5c5SAndroid Build Coastguard Worker 
2978*8975f5c5SAndroid Build Coastguard Worker     // The condition is a declaration. In the AST representation we don't support declarations as
2979*8975f5c5SAndroid Build Coastguard Worker     // loop conditions. Wrap the loop to a block that declares the condition variable and contains
2980*8975f5c5SAndroid Build Coastguard Worker     // the loop.
2981*8975f5c5SAndroid Build Coastguard Worker     TIntermBlock *block = new TIntermBlock();
2982*8975f5c5SAndroid Build Coastguard Worker 
2983*8975f5c5SAndroid Build Coastguard Worker     TIntermDeclaration *declareCondition = new TIntermDeclaration();
2984*8975f5c5SAndroid Build Coastguard Worker     declareCondition->appendDeclarator(declarator->getLeft()->deepCopy());
2985*8975f5c5SAndroid Build Coastguard Worker     block->appendStatement(declareCondition);
2986*8975f5c5SAndroid Build Coastguard Worker 
2987*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *conditionInit = new TIntermBinary(EOpAssign, declarator->getLeft()->deepCopy(),
2988*8975f5c5SAndroid Build Coastguard Worker                                                      declarator->getRight()->deepCopy());
2989*8975f5c5SAndroid Build Coastguard Worker     TIntermLoop *loop = new TIntermLoop(type, init, conditionInit, expr, EnsureLoopBodyBlock(body));
2990*8975f5c5SAndroid Build Coastguard Worker     block->appendStatement(loop);
2991*8975f5c5SAndroid Build Coastguard Worker     loop->setLine(line);
2992*8975f5c5SAndroid Build Coastguard Worker     block->setLine(line);
2993*8975f5c5SAndroid Build Coastguard Worker     return block;
2994*8975f5c5SAndroid Build Coastguard Worker }
2995*8975f5c5SAndroid Build Coastguard Worker 
addIfElse(TIntermTyped * cond,TIntermNodePair code,const TSourceLoc & loc)2996*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TParseContext::addIfElse(TIntermTyped *cond,
2997*8975f5c5SAndroid Build Coastguard Worker                                       TIntermNodePair code,
2998*8975f5c5SAndroid Build Coastguard Worker                                       const TSourceLoc &loc)
2999*8975f5c5SAndroid Build Coastguard Worker {
3000*8975f5c5SAndroid Build Coastguard Worker     bool isScalarBool = checkIsScalarBool(loc, cond);
3001*8975f5c5SAndroid Build Coastguard Worker     // In case the conditional statements were not parsed as blocks and contain a statement that
3002*8975f5c5SAndroid Build Coastguard Worker     // simply refers to a variable, we need to mark them as statically used.
3003*8975f5c5SAndroid Build Coastguard Worker     if (code.node1)
3004*8975f5c5SAndroid Build Coastguard Worker     {
3005*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(code.node1);
3006*8975f5c5SAndroid Build Coastguard Worker     }
3007*8975f5c5SAndroid Build Coastguard Worker     if (code.node2)
3008*8975f5c5SAndroid Build Coastguard Worker     {
3009*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(code.node2);
3010*8975f5c5SAndroid Build Coastguard Worker     }
3011*8975f5c5SAndroid Build Coastguard Worker 
3012*8975f5c5SAndroid Build Coastguard Worker     // For compile time constant conditions, prune the code now.
3013*8975f5c5SAndroid Build Coastguard Worker     if (isScalarBool && cond->getAsConstantUnion())
3014*8975f5c5SAndroid Build Coastguard Worker     {
3015*8975f5c5SAndroid Build Coastguard Worker         if (cond->getAsConstantUnion()->getBConst(0) == true)
3016*8975f5c5SAndroid Build Coastguard Worker         {
3017*8975f5c5SAndroid Build Coastguard Worker             return EnsureBlock(code.node1);
3018*8975f5c5SAndroid Build Coastguard Worker         }
3019*8975f5c5SAndroid Build Coastguard Worker         else
3020*8975f5c5SAndroid Build Coastguard Worker         {
3021*8975f5c5SAndroid Build Coastguard Worker             return EnsureBlock(code.node2);
3022*8975f5c5SAndroid Build Coastguard Worker         }
3023*8975f5c5SAndroid Build Coastguard Worker     }
3024*8975f5c5SAndroid Build Coastguard Worker 
3025*8975f5c5SAndroid Build Coastguard Worker     TIntermIfElse *node = new TIntermIfElse(cond, EnsureBlock(code.node1), EnsureBlock(code.node2));
3026*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(cond);
3027*8975f5c5SAndroid Build Coastguard Worker     node->setLine(loc);
3028*8975f5c5SAndroid Build Coastguard Worker 
3029*8975f5c5SAndroid Build Coastguard Worker     return node;
3030*8975f5c5SAndroid Build Coastguard Worker }
3031*8975f5c5SAndroid Build Coastguard Worker 
addFullySpecifiedType(TPublicType * typeSpecifier)3032*8975f5c5SAndroid Build Coastguard Worker void TParseContext::addFullySpecifiedType(TPublicType *typeSpecifier)
3033*8975f5c5SAndroid Build Coastguard Worker {
3034*8975f5c5SAndroid Build Coastguard Worker     checkPrecisionSpecified(typeSpecifier->getLine(), typeSpecifier->precision,
3035*8975f5c5SAndroid Build Coastguard Worker                             typeSpecifier->getBasicType());
3036*8975f5c5SAndroid Build Coastguard Worker 
3037*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion < 300 && typeSpecifier->isArray())
3038*8975f5c5SAndroid Build Coastguard Worker     {
3039*8975f5c5SAndroid Build Coastguard Worker         error(typeSpecifier->getLine(), "not supported", "first-class array");
3040*8975f5c5SAndroid Build Coastguard Worker         typeSpecifier->clearArrayness();
3041*8975f5c5SAndroid Build Coastguard Worker     }
3042*8975f5c5SAndroid Build Coastguard Worker }
3043*8975f5c5SAndroid Build Coastguard Worker 
addFullySpecifiedType(const TTypeQualifierBuilder & typeQualifierBuilder,const TPublicType & typeSpecifier)3044*8975f5c5SAndroid Build Coastguard Worker TPublicType TParseContext::addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
3045*8975f5c5SAndroid Build Coastguard Worker                                                  const TPublicType &typeSpecifier)
3046*8975f5c5SAndroid Build Coastguard Worker {
3047*8975f5c5SAndroid Build Coastguard Worker     TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
3048*8975f5c5SAndroid Build Coastguard Worker 
3049*8975f5c5SAndroid Build Coastguard Worker     TPublicType returnType     = typeSpecifier;
3050*8975f5c5SAndroid Build Coastguard Worker     returnType.qualifier       = typeQualifier.qualifier;
3051*8975f5c5SAndroid Build Coastguard Worker     returnType.invariant       = typeQualifier.invariant;
3052*8975f5c5SAndroid Build Coastguard Worker     returnType.precise         = typeQualifier.precise;
3053*8975f5c5SAndroid Build Coastguard Worker     returnType.layoutQualifier = typeQualifier.layoutQualifier;
3054*8975f5c5SAndroid Build Coastguard Worker     returnType.memoryQualifier = typeQualifier.memoryQualifier;
3055*8975f5c5SAndroid Build Coastguard Worker     returnType.precision       = typeSpecifier.precision;
3056*8975f5c5SAndroid Build Coastguard Worker 
3057*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.precision != EbpUndefined)
3058*8975f5c5SAndroid Build Coastguard Worker     {
3059*8975f5c5SAndroid Build Coastguard Worker         returnType.precision = typeQualifier.precision;
3060*8975f5c5SAndroid Build Coastguard Worker     }
3061*8975f5c5SAndroid Build Coastguard Worker 
3062*8975f5c5SAndroid Build Coastguard Worker     checkPrecisionSpecified(typeSpecifier.getLine(), returnType.precision,
3063*8975f5c5SAndroid Build Coastguard Worker                             typeSpecifier.getBasicType());
3064*8975f5c5SAndroid Build Coastguard Worker 
3065*8975f5c5SAndroid Build Coastguard Worker     checkInvariantVariableQualifier(returnType.invariant, returnType.qualifier,
3066*8975f5c5SAndroid Build Coastguard Worker                                     typeSpecifier.getLine());
3067*8975f5c5SAndroid Build Coastguard Worker 
3068*8975f5c5SAndroid Build Coastguard Worker     checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), returnType.layoutQualifier);
3069*8975f5c5SAndroid Build Coastguard Worker 
3070*8975f5c5SAndroid Build Coastguard Worker     checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(),
3071*8975f5c5SAndroid Build Coastguard Worker                                           returnType.layoutQualifier.earlyFragmentTests);
3072*8975f5c5SAndroid Build Coastguard Worker 
3073*8975f5c5SAndroid Build Coastguard Worker     if (returnType.qualifier == EvqSampleIn || returnType.qualifier == EvqSampleOut ||
3074*8975f5c5SAndroid Build Coastguard Worker         returnType.qualifier == EvqNoPerspectiveSampleIn ||
3075*8975f5c5SAndroid Build Coastguard Worker         returnType.qualifier == EvqNoPerspectiveSampleOut)
3076*8975f5c5SAndroid Build Coastguard Worker     {
3077*8975f5c5SAndroid Build Coastguard Worker         mSampleQualifierSpecified = true;
3078*8975f5c5SAndroid Build Coastguard Worker     }
3079*8975f5c5SAndroid Build Coastguard Worker 
3080*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion < 300)
3081*8975f5c5SAndroid Build Coastguard Worker     {
3082*8975f5c5SAndroid Build Coastguard Worker         if (typeSpecifier.isArray())
3083*8975f5c5SAndroid Build Coastguard Worker         {
3084*8975f5c5SAndroid Build Coastguard Worker             error(typeSpecifier.getLine(), "not supported", "first-class array");
3085*8975f5c5SAndroid Build Coastguard Worker             returnType.clearArrayness();
3086*8975f5c5SAndroid Build Coastguard Worker         }
3087*8975f5c5SAndroid Build Coastguard Worker 
3088*8975f5c5SAndroid Build Coastguard Worker         if (returnType.qualifier == EvqAttribute &&
3089*8975f5c5SAndroid Build Coastguard Worker             (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
3090*8975f5c5SAndroid Build Coastguard Worker         {
3091*8975f5c5SAndroid Build Coastguard Worker             error(typeSpecifier.getLine(), "cannot be bool or int",
3092*8975f5c5SAndroid Build Coastguard Worker                   getQualifierString(returnType.qualifier));
3093*8975f5c5SAndroid Build Coastguard Worker         }
3094*8975f5c5SAndroid Build Coastguard Worker 
3095*8975f5c5SAndroid Build Coastguard Worker         if ((returnType.qualifier == EvqVaryingIn || returnType.qualifier == EvqVaryingOut) &&
3096*8975f5c5SAndroid Build Coastguard Worker             (typeSpecifier.getBasicType() == EbtBool || typeSpecifier.getBasicType() == EbtInt))
3097*8975f5c5SAndroid Build Coastguard Worker         {
3098*8975f5c5SAndroid Build Coastguard Worker             error(typeSpecifier.getLine(), "cannot be bool or int",
3099*8975f5c5SAndroid Build Coastguard Worker                   getQualifierString(returnType.qualifier));
3100*8975f5c5SAndroid Build Coastguard Worker         }
3101*8975f5c5SAndroid Build Coastguard Worker     }
3102*8975f5c5SAndroid Build Coastguard Worker     else
3103*8975f5c5SAndroid Build Coastguard Worker     {
3104*8975f5c5SAndroid Build Coastguard Worker         if (!returnType.layoutQualifier.isEmpty())
3105*8975f5c5SAndroid Build Coastguard Worker         {
3106*8975f5c5SAndroid Build Coastguard Worker             checkIsAtGlobalLevel(typeSpecifier.getLine(), "layout");
3107*8975f5c5SAndroid Build Coastguard Worker         }
3108*8975f5c5SAndroid Build Coastguard Worker         if (sh::IsVarying(returnType.qualifier) || returnType.qualifier == EvqVertexIn ||
3109*8975f5c5SAndroid Build Coastguard Worker             returnType.qualifier == EvqFragmentOut || returnType.qualifier == EvqFragmentInOut)
3110*8975f5c5SAndroid Build Coastguard Worker         {
3111*8975f5c5SAndroid Build Coastguard Worker             checkInputOutputTypeIsValidES3(returnType.qualifier, typeSpecifier,
3112*8975f5c5SAndroid Build Coastguard Worker                                            typeSpecifier.getLine());
3113*8975f5c5SAndroid Build Coastguard Worker         }
3114*8975f5c5SAndroid Build Coastguard Worker         if (returnType.qualifier == EvqComputeIn)
3115*8975f5c5SAndroid Build Coastguard Worker         {
3116*8975f5c5SAndroid Build Coastguard Worker             error(typeSpecifier.getLine(), "'in' can be only used to specify the local group size",
3117*8975f5c5SAndroid Build Coastguard Worker                   "in");
3118*8975f5c5SAndroid Build Coastguard Worker         }
3119*8975f5c5SAndroid Build Coastguard Worker     }
3120*8975f5c5SAndroid Build Coastguard Worker 
3121*8975f5c5SAndroid Build Coastguard Worker     return returnType;
3122*8975f5c5SAndroid Build Coastguard Worker }
3123*8975f5c5SAndroid Build Coastguard Worker 
checkInputOutputTypeIsValidES3(const TQualifier qualifier,const TPublicType & type,const TSourceLoc & qualifierLocation)3124*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkInputOutputTypeIsValidES3(const TQualifier qualifier,
3125*8975f5c5SAndroid Build Coastguard Worker                                                    const TPublicType &type,
3126*8975f5c5SAndroid Build Coastguard Worker                                                    const TSourceLoc &qualifierLocation)
3127*8975f5c5SAndroid Build Coastguard Worker {
3128*8975f5c5SAndroid Build Coastguard Worker     // An input/output variable can never be bool or a sampler. Samplers are checked elsewhere.
3129*8975f5c5SAndroid Build Coastguard Worker     if (type.getBasicType() == EbtBool)
3130*8975f5c5SAndroid Build Coastguard Worker     {
3131*8975f5c5SAndroid Build Coastguard Worker         error(qualifierLocation, "cannot be bool", getQualifierString(qualifier));
3132*8975f5c5SAndroid Build Coastguard Worker     }
3133*8975f5c5SAndroid Build Coastguard Worker 
3134*8975f5c5SAndroid Build Coastguard Worker     // Specific restrictions apply for vertex shader inputs and fragment shader outputs.
3135*8975f5c5SAndroid Build Coastguard Worker     switch (qualifier)
3136*8975f5c5SAndroid Build Coastguard Worker     {
3137*8975f5c5SAndroid Build Coastguard Worker         case EvqVertexIn:
3138*8975f5c5SAndroid Build Coastguard Worker             // ESSL 3.00 section 4.3.4
3139*8975f5c5SAndroid Build Coastguard Worker             if (type.isArray())
3140*8975f5c5SAndroid Build Coastguard Worker             {
3141*8975f5c5SAndroid Build Coastguard Worker                 error(qualifierLocation, "cannot be array", getQualifierString(qualifier));
3142*8975f5c5SAndroid Build Coastguard Worker             }
3143*8975f5c5SAndroid Build Coastguard Worker             // Vertex inputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
3144*8975f5c5SAndroid Build Coastguard Worker             return;
3145*8975f5c5SAndroid Build Coastguard Worker         case EvqFragmentOut:
3146*8975f5c5SAndroid Build Coastguard Worker         case EvqFragmentInOut:
3147*8975f5c5SAndroid Build Coastguard Worker             // ESSL 3.00 section 4.3.6
3148*8975f5c5SAndroid Build Coastguard Worker             if (type.typeSpecifierNonArray.isMatrix())
3149*8975f5c5SAndroid Build Coastguard Worker             {
3150*8975f5c5SAndroid Build Coastguard Worker                 error(qualifierLocation, "cannot be matrix", getQualifierString(qualifier));
3151*8975f5c5SAndroid Build Coastguard Worker             }
3152*8975f5c5SAndroid Build Coastguard Worker             // Fragment outputs with a struct type are disallowed in nonEmptyDeclarationErrorCheck
3153*8975f5c5SAndroid Build Coastguard Worker             return;
3154*8975f5c5SAndroid Build Coastguard Worker         default:
3155*8975f5c5SAndroid Build Coastguard Worker             break;
3156*8975f5c5SAndroid Build Coastguard Worker     }
3157*8975f5c5SAndroid Build Coastguard Worker 
3158*8975f5c5SAndroid Build Coastguard Worker     // Vertex shader outputs / fragment shader inputs have a different, slightly more lenient set of
3159*8975f5c5SAndroid Build Coastguard Worker     // restrictions.
3160*8975f5c5SAndroid Build Coastguard Worker     bool typeContainsIntegers =
3161*8975f5c5SAndroid Build Coastguard Worker         (type.getBasicType() == EbtInt || type.getBasicType() == EbtUInt ||
3162*8975f5c5SAndroid Build Coastguard Worker          type.isStructureContainingType(EbtInt) || type.isStructureContainingType(EbtUInt));
3163*8975f5c5SAndroid Build Coastguard Worker     bool extendedShaderTypes = mShaderVersion >= 320 ||
3164*8975f5c5SAndroid Build Coastguard Worker                                isExtensionEnabled(TExtension::EXT_geometry_shader) ||
3165*8975f5c5SAndroid Build Coastguard Worker                                isExtensionEnabled(TExtension::OES_geometry_shader) ||
3166*8975f5c5SAndroid Build Coastguard Worker                                isExtensionEnabled(TExtension::EXT_tessellation_shader) ||
3167*8975f5c5SAndroid Build Coastguard Worker                                isExtensionEnabled(TExtension::OES_tessellation_shader);
3168*8975f5c5SAndroid Build Coastguard Worker     if (typeContainsIntegers && qualifier != EvqFlatIn && qualifier != EvqFlatOut &&
3169*8975f5c5SAndroid Build Coastguard Worker         (!extendedShaderTypes || mShaderType == GL_FRAGMENT_SHADER))
3170*8975f5c5SAndroid Build Coastguard Worker     {
3171*8975f5c5SAndroid Build Coastguard Worker         error(qualifierLocation, "must use 'flat' interpolation here",
3172*8975f5c5SAndroid Build Coastguard Worker               getQualifierString(qualifier));
3173*8975f5c5SAndroid Build Coastguard Worker     }
3174*8975f5c5SAndroid Build Coastguard Worker 
3175*8975f5c5SAndroid Build Coastguard Worker     if (type.getBasicType() == EbtStruct)
3176*8975f5c5SAndroid Build Coastguard Worker     {
3177*8975f5c5SAndroid Build Coastguard Worker         // ESSL 3.00 sections 4.3.4 and 4.3.6.
3178*8975f5c5SAndroid Build Coastguard Worker         // These restrictions are only implied by the ESSL 3.00 spec, but
3179*8975f5c5SAndroid Build Coastguard Worker         // the ESSL 3.10 spec lists these restrictions explicitly.
3180*8975f5c5SAndroid Build Coastguard Worker         if (type.isArray())
3181*8975f5c5SAndroid Build Coastguard Worker         {
3182*8975f5c5SAndroid Build Coastguard Worker             error(qualifierLocation, "cannot be an array of structures",
3183*8975f5c5SAndroid Build Coastguard Worker                   getQualifierString(qualifier));
3184*8975f5c5SAndroid Build Coastguard Worker         }
3185*8975f5c5SAndroid Build Coastguard Worker         if (type.isStructureContainingArrays())
3186*8975f5c5SAndroid Build Coastguard Worker         {
3187*8975f5c5SAndroid Build Coastguard Worker             error(qualifierLocation, "cannot be a structure containing an array",
3188*8975f5c5SAndroid Build Coastguard Worker                   getQualifierString(qualifier));
3189*8975f5c5SAndroid Build Coastguard Worker         }
3190*8975f5c5SAndroid Build Coastguard Worker         if (type.isStructureContainingType(EbtStruct))
3191*8975f5c5SAndroid Build Coastguard Worker         {
3192*8975f5c5SAndroid Build Coastguard Worker             error(qualifierLocation, "cannot be a structure containing a structure",
3193*8975f5c5SAndroid Build Coastguard Worker                   getQualifierString(qualifier));
3194*8975f5c5SAndroid Build Coastguard Worker         }
3195*8975f5c5SAndroid Build Coastguard Worker         if (type.isStructureContainingType(EbtBool))
3196*8975f5c5SAndroid Build Coastguard Worker         {
3197*8975f5c5SAndroid Build Coastguard Worker             error(qualifierLocation, "cannot be a structure containing a bool",
3198*8975f5c5SAndroid Build Coastguard Worker                   getQualifierString(qualifier));
3199*8975f5c5SAndroid Build Coastguard Worker         }
3200*8975f5c5SAndroid Build Coastguard Worker     }
3201*8975f5c5SAndroid Build Coastguard Worker }
3202*8975f5c5SAndroid Build Coastguard Worker 
checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase & qualifier)3203*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkLocalVariableConstStorageQualifier(const TQualifierWrapperBase &qualifier)
3204*8975f5c5SAndroid Build Coastguard Worker {
3205*8975f5c5SAndroid Build Coastguard Worker     if (qualifier.getType() == QtStorage)
3206*8975f5c5SAndroid Build Coastguard Worker     {
3207*8975f5c5SAndroid Build Coastguard Worker         const TStorageQualifierWrapper &storageQualifier =
3208*8975f5c5SAndroid Build Coastguard Worker             static_cast<const TStorageQualifierWrapper &>(qualifier);
3209*8975f5c5SAndroid Build Coastguard Worker         if (!declaringFunction() && storageQualifier.getQualifier() != EvqConst &&
3210*8975f5c5SAndroid Build Coastguard Worker             !symbolTable.atGlobalLevel())
3211*8975f5c5SAndroid Build Coastguard Worker         {
3212*8975f5c5SAndroid Build Coastguard Worker             error(storageQualifier.getLine(),
3213*8975f5c5SAndroid Build Coastguard Worker                   "Local variables can only use the const storage qualifier.",
3214*8975f5c5SAndroid Build Coastguard Worker                   storageQualifier.getQualifierString());
3215*8975f5c5SAndroid Build Coastguard Worker         }
3216*8975f5c5SAndroid Build Coastguard Worker     }
3217*8975f5c5SAndroid Build Coastguard Worker }
3218*8975f5c5SAndroid Build Coastguard Worker 
checkMemoryQualifierIsNotSpecified(const TMemoryQualifier & memoryQualifier,const TSourceLoc & location)3219*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkMemoryQualifierIsNotSpecified(const TMemoryQualifier &memoryQualifier,
3220*8975f5c5SAndroid Build Coastguard Worker                                                        const TSourceLoc &location)
3221*8975f5c5SAndroid Build Coastguard Worker {
3222*8975f5c5SAndroid Build Coastguard Worker     const std::string reason(
3223*8975f5c5SAndroid Build Coastguard Worker         "Only allowed with shader storage blocks, variables declared within shader storage blocks "
3224*8975f5c5SAndroid Build Coastguard Worker         "and variables declared as image types.");
3225*8975f5c5SAndroid Build Coastguard Worker     if (memoryQualifier.readonly)
3226*8975f5c5SAndroid Build Coastguard Worker     {
3227*8975f5c5SAndroid Build Coastguard Worker         error(location, reason.c_str(), "readonly");
3228*8975f5c5SAndroid Build Coastguard Worker     }
3229*8975f5c5SAndroid Build Coastguard Worker     if (memoryQualifier.writeonly)
3230*8975f5c5SAndroid Build Coastguard Worker     {
3231*8975f5c5SAndroid Build Coastguard Worker         error(location, reason.c_str(), "writeonly");
3232*8975f5c5SAndroid Build Coastguard Worker     }
3233*8975f5c5SAndroid Build Coastguard Worker     if (memoryQualifier.coherent)
3234*8975f5c5SAndroid Build Coastguard Worker     {
3235*8975f5c5SAndroid Build Coastguard Worker         error(location, reason.c_str(), "coherent");
3236*8975f5c5SAndroid Build Coastguard Worker     }
3237*8975f5c5SAndroid Build Coastguard Worker     if (memoryQualifier.restrictQualifier)
3238*8975f5c5SAndroid Build Coastguard Worker     {
3239*8975f5c5SAndroid Build Coastguard Worker         error(location, reason.c_str(), "restrict");
3240*8975f5c5SAndroid Build Coastguard Worker     }
3241*8975f5c5SAndroid Build Coastguard Worker     if (memoryQualifier.volatileQualifier)
3242*8975f5c5SAndroid Build Coastguard Worker     {
3243*8975f5c5SAndroid Build Coastguard Worker         error(location, reason.c_str(), "volatile");
3244*8975f5c5SAndroid Build Coastguard Worker     }
3245*8975f5c5SAndroid Build Coastguard Worker }
3246*8975f5c5SAndroid Build Coastguard Worker 
3247*8975f5c5SAndroid Build Coastguard Worker // Make sure there is no offset overlapping, and store the newly assigned offset to "type" in
3248*8975f5c5SAndroid Build Coastguard Worker // intermediate tree.
checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend,const TSourceLoc & loc,TType * type)3249*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkAtomicCounterOffsetDoesNotOverlap(bool forceAppend,
3250*8975f5c5SAndroid Build Coastguard Worker                                                            const TSourceLoc &loc,
3251*8975f5c5SAndroid Build Coastguard Worker                                                            TType *type)
3252*8975f5c5SAndroid Build Coastguard Worker {
3253*8975f5c5SAndroid Build Coastguard Worker     const size_t size = type->isArray() ? kAtomicCounterArrayStride * type->getArraySizeProduct()
3254*8975f5c5SAndroid Build Coastguard Worker                                         : kAtomicCounterSize;
3255*8975f5c5SAndroid Build Coastguard Worker     TLayoutQualifier layoutQualifier = type->getLayoutQualifier();
3256*8975f5c5SAndroid Build Coastguard Worker     auto &bindingState               = mAtomicCounterBindingStates[layoutQualifier.binding];
3257*8975f5c5SAndroid Build Coastguard Worker     int offset;
3258*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.offset == -1 || forceAppend)
3259*8975f5c5SAndroid Build Coastguard Worker     {
3260*8975f5c5SAndroid Build Coastguard Worker         offset = bindingState.appendSpan(size);
3261*8975f5c5SAndroid Build Coastguard Worker     }
3262*8975f5c5SAndroid Build Coastguard Worker     else
3263*8975f5c5SAndroid Build Coastguard Worker     {
3264*8975f5c5SAndroid Build Coastguard Worker         offset = bindingState.insertSpan(layoutQualifier.offset, size);
3265*8975f5c5SAndroid Build Coastguard Worker     }
3266*8975f5c5SAndroid Build Coastguard Worker     if (offset == -1)
3267*8975f5c5SAndroid Build Coastguard Worker     {
3268*8975f5c5SAndroid Build Coastguard Worker         error(loc, "Offset overlapping", "atomic counter");
3269*8975f5c5SAndroid Build Coastguard Worker         return;
3270*8975f5c5SAndroid Build Coastguard Worker     }
3271*8975f5c5SAndroid Build Coastguard Worker     layoutQualifier.offset = offset;
3272*8975f5c5SAndroid Build Coastguard Worker     type->setLayoutQualifier(layoutQualifier);
3273*8975f5c5SAndroid Build Coastguard Worker }
3274*8975f5c5SAndroid Build Coastguard Worker 
checkAtomicCounterOffsetAlignment(const TSourceLoc & location,const TType & type)3275*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkAtomicCounterOffsetAlignment(const TSourceLoc &location, const TType &type)
3276*8975f5c5SAndroid Build Coastguard Worker {
3277*8975f5c5SAndroid Build Coastguard Worker     TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
3278*8975f5c5SAndroid Build Coastguard Worker 
3279*8975f5c5SAndroid Build Coastguard Worker     // OpenGL ES 3.1 Table 6.5, Atomic counter offset must be a multiple of 4
3280*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.offset % 4 != 0)
3281*8975f5c5SAndroid Build Coastguard Worker     {
3282*8975f5c5SAndroid Build Coastguard Worker         error(location, "Offset must be multiple of 4", "atomic counter");
3283*8975f5c5SAndroid Build Coastguard Worker     }
3284*8975f5c5SAndroid Build Coastguard Worker }
3285*8975f5c5SAndroid Build Coastguard Worker 
checkAtomicCounterOffsetLimit(const TSourceLoc & location,const TType & type)3286*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkAtomicCounterOffsetLimit(const TSourceLoc &location, const TType &type)
3287*8975f5c5SAndroid Build Coastguard Worker {
3288*8975f5c5SAndroid Build Coastguard Worker     TLayoutQualifier layoutQualifier = type.getLayoutQualifier();
3289*8975f5c5SAndroid Build Coastguard Worker 
3290*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.offset >= mMaxAtomicCounterBufferSize)
3291*8975f5c5SAndroid Build Coastguard Worker     {
3292*8975f5c5SAndroid Build Coastguard Worker         error(location, "Offset must not exceed the maximum atomic counter buffer size",
3293*8975f5c5SAndroid Build Coastguard Worker               "atomic counter");
3294*8975f5c5SAndroid Build Coastguard Worker     }
3295*8975f5c5SAndroid Build Coastguard Worker }
3296*8975f5c5SAndroid Build Coastguard Worker 
checkAtomicCounterOffsetIsValid(bool forceAppend,const TSourceLoc & loc,TType * type)3297*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkAtomicCounterOffsetIsValid(bool forceAppend,
3298*8975f5c5SAndroid Build Coastguard Worker                                                     const TSourceLoc &loc,
3299*8975f5c5SAndroid Build Coastguard Worker                                                     TType *type)
3300*8975f5c5SAndroid Build Coastguard Worker {
3301*8975f5c5SAndroid Build Coastguard Worker     checkAtomicCounterOffsetDoesNotOverlap(forceAppend, loc, type);
3302*8975f5c5SAndroid Build Coastguard Worker     checkAtomicCounterOffsetAlignment(loc, *type);
3303*8975f5c5SAndroid Build Coastguard Worker     checkAtomicCounterOffsetLimit(loc, *type);
3304*8975f5c5SAndroid Build Coastguard Worker }
3305*8975f5c5SAndroid Build Coastguard Worker 
checkGeometryShaderInputAndSetArraySize(const TSourceLoc & location,const ImmutableString & token,TType * type)3306*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkGeometryShaderInputAndSetArraySize(const TSourceLoc &location,
3307*8975f5c5SAndroid Build Coastguard Worker                                                             const ImmutableString &token,
3308*8975f5c5SAndroid Build Coastguard Worker                                                             TType *type)
3309*8975f5c5SAndroid Build Coastguard Worker {
3310*8975f5c5SAndroid Build Coastguard Worker     if (IsGeometryShaderInput(mShaderType, type->getQualifier()))
3311*8975f5c5SAndroid Build Coastguard Worker     {
3312*8975f5c5SAndroid Build Coastguard Worker         if (type->isArray() && type->getOutermostArraySize() == 0u)
3313*8975f5c5SAndroid Build Coastguard Worker         {
3314*8975f5c5SAndroid Build Coastguard Worker             // Set size for the unsized geometry shader inputs if they are declared after a valid
3315*8975f5c5SAndroid Build Coastguard Worker             // input primitive declaration.
3316*8975f5c5SAndroid Build Coastguard Worker             if (mGeometryShaderInputPrimitiveType != EptUndefined)
3317*8975f5c5SAndroid Build Coastguard Worker             {
3318*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(symbolTable.getGlInVariableWithArraySize() != nullptr);
3319*8975f5c5SAndroid Build Coastguard Worker                 type->sizeOutermostUnsizedArray(
3320*8975f5c5SAndroid Build Coastguard Worker                     symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize());
3321*8975f5c5SAndroid Build Coastguard Worker             }
3322*8975f5c5SAndroid Build Coastguard Worker             else
3323*8975f5c5SAndroid Build Coastguard Worker             {
3324*8975f5c5SAndroid Build Coastguard Worker                 // [GLSL ES 3.2 SPEC Chapter 4.4.1.2]
3325*8975f5c5SAndroid Build Coastguard Worker                 // An input can be declared without an array size if there is a previous layout
3326*8975f5c5SAndroid Build Coastguard Worker                 // which specifies the size.
3327*8975f5c5SAndroid Build Coastguard Worker                 warning(location,
3328*8975f5c5SAndroid Build Coastguard Worker                         "Missing a valid input primitive declaration before declaring an unsized "
3329*8975f5c5SAndroid Build Coastguard Worker                         "array input",
3330*8975f5c5SAndroid Build Coastguard Worker                         "Deferred");
3331*8975f5c5SAndroid Build Coastguard Worker                 mDeferredArrayTypesToSize.push_back(type);
3332*8975f5c5SAndroid Build Coastguard Worker             }
3333*8975f5c5SAndroid Build Coastguard Worker         }
3334*8975f5c5SAndroid Build Coastguard Worker         else if (type->isArray())
3335*8975f5c5SAndroid Build Coastguard Worker         {
3336*8975f5c5SAndroid Build Coastguard Worker             setGeometryShaderInputArraySize(type->getOutermostArraySize(), location);
3337*8975f5c5SAndroid Build Coastguard Worker         }
3338*8975f5c5SAndroid Build Coastguard Worker         else
3339*8975f5c5SAndroid Build Coastguard Worker         {
3340*8975f5c5SAndroid Build Coastguard Worker             error(location, "Geometry shader input variable must be declared as an array", token);
3341*8975f5c5SAndroid Build Coastguard Worker         }
3342*8975f5c5SAndroid Build Coastguard Worker     }
3343*8975f5c5SAndroid Build Coastguard Worker }
3344*8975f5c5SAndroid Build Coastguard Worker 
checkTessellationShaderUnsizedArraysAndSetSize(const TSourceLoc & location,const ImmutableString & token,TType * type)3345*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkTessellationShaderUnsizedArraysAndSetSize(const TSourceLoc &location,
3346*8975f5c5SAndroid Build Coastguard Worker                                                                    const ImmutableString &token,
3347*8975f5c5SAndroid Build Coastguard Worker                                                                    TType *type)
3348*8975f5c5SAndroid Build Coastguard Worker {
3349*8975f5c5SAndroid Build Coastguard Worker     TQualifier qualifier = type->getQualifier();
3350*8975f5c5SAndroid Build Coastguard Worker     if (!IsTessellationControlShaderOutput(mShaderType, qualifier) &&
3351*8975f5c5SAndroid Build Coastguard Worker         !IsTessellationControlShaderInput(mShaderType, qualifier) &&
3352*8975f5c5SAndroid Build Coastguard Worker         !IsTessellationEvaluationShaderInput(mShaderType, qualifier))
3353*8975f5c5SAndroid Build Coastguard Worker     {
3354*8975f5c5SAndroid Build Coastguard Worker         return;
3355*8975f5c5SAndroid Build Coastguard Worker     }
3356*8975f5c5SAndroid Build Coastguard Worker 
3357*8975f5c5SAndroid Build Coastguard Worker     // Such variables must be declared as arrays or inside output blocks declared as arrays.
3358*8975f5c5SAndroid Build Coastguard Worker     if (!type->isArray())
3359*8975f5c5SAndroid Build Coastguard Worker     {
3360*8975f5c5SAndroid Build Coastguard Worker         error(location, "Tessellation interface variables must be declared as an array", token);
3361*8975f5c5SAndroid Build Coastguard Worker         return;
3362*8975f5c5SAndroid Build Coastguard Worker     }
3363*8975f5c5SAndroid Build Coastguard Worker 
3364*8975f5c5SAndroid Build Coastguard Worker     // If a size is specified, it must match the maximum patch size.
3365*8975f5c5SAndroid Build Coastguard Worker     unsigned int outermostSize = type->getOutermostArraySize();
3366*8975f5c5SAndroid Build Coastguard Worker     if (outermostSize == 0u)
3367*8975f5c5SAndroid Build Coastguard Worker     {
3368*8975f5c5SAndroid Build Coastguard Worker         switch (qualifier)
3369*8975f5c5SAndroid Build Coastguard Worker         {
3370*8975f5c5SAndroid Build Coastguard Worker             case EvqTessControlIn:
3371*8975f5c5SAndroid Build Coastguard Worker             case EvqTessEvaluationIn:
3372*8975f5c5SAndroid Build Coastguard Worker             case EvqSmoothIn:
3373*8975f5c5SAndroid Build Coastguard Worker             case EvqFlatIn:
3374*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveIn:
3375*8975f5c5SAndroid Build Coastguard Worker             case EvqCentroidIn:
3376*8975f5c5SAndroid Build Coastguard Worker             case EvqSampleIn:
3377*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveCentroidIn:
3378*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveSampleIn:
3379*8975f5c5SAndroid Build Coastguard Worker                 // Declaring an array size is optional. If no size is specified, it will be taken
3380*8975f5c5SAndroid Build Coastguard Worker                 // from the implementation-dependent maximum patch size (gl_MaxPatchVertices).
3381*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(mMaxPatchVertices > 0);
3382*8975f5c5SAndroid Build Coastguard Worker                 type->sizeOutermostUnsizedArray(mMaxPatchVertices);
3383*8975f5c5SAndroid Build Coastguard Worker                 break;
3384*8975f5c5SAndroid Build Coastguard Worker             case EvqTessControlOut:
3385*8975f5c5SAndroid Build Coastguard Worker             case EvqTessEvaluationOut:
3386*8975f5c5SAndroid Build Coastguard Worker             case EvqSmoothOut:
3387*8975f5c5SAndroid Build Coastguard Worker             case EvqFlatOut:
3388*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveOut:
3389*8975f5c5SAndroid Build Coastguard Worker             case EvqCentroidOut:
3390*8975f5c5SAndroid Build Coastguard Worker             case EvqSampleOut:
3391*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveCentroidOut:
3392*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveSampleOut:
3393*8975f5c5SAndroid Build Coastguard Worker                 // Declaring an array size is optional. If no size is specified, it will be taken
3394*8975f5c5SAndroid Build Coastguard Worker                 // from output patch size declared in the shader.  If the patch size is not yet
3395*8975f5c5SAndroid Build Coastguard Worker                 // declared, this is deferred until such time as it does.
3396*8975f5c5SAndroid Build Coastguard Worker                 if (mTessControlShaderOutputVertices == 0)
3397*8975f5c5SAndroid Build Coastguard Worker                 {
3398*8975f5c5SAndroid Build Coastguard Worker                     mDeferredArrayTypesToSize.push_back(type);
3399*8975f5c5SAndroid Build Coastguard Worker                 }
3400*8975f5c5SAndroid Build Coastguard Worker                 else
3401*8975f5c5SAndroid Build Coastguard Worker                 {
3402*8975f5c5SAndroid Build Coastguard Worker                     type->sizeOutermostUnsizedArray(mTessControlShaderOutputVertices);
3403*8975f5c5SAndroid Build Coastguard Worker                 }
3404*8975f5c5SAndroid Build Coastguard Worker                 break;
3405*8975f5c5SAndroid Build Coastguard Worker             default:
3406*8975f5c5SAndroid Build Coastguard Worker                 UNREACHABLE();
3407*8975f5c5SAndroid Build Coastguard Worker                 break;
3408*8975f5c5SAndroid Build Coastguard Worker         }
3409*8975f5c5SAndroid Build Coastguard Worker         return;
3410*8975f5c5SAndroid Build Coastguard Worker     }
3411*8975f5c5SAndroid Build Coastguard Worker 
3412*8975f5c5SAndroid Build Coastguard Worker     if (IsTessellationControlShaderInput(mShaderType, qualifier) ||
3413*8975f5c5SAndroid Build Coastguard Worker         IsTessellationEvaluationShaderInput(mShaderType, qualifier))
3414*8975f5c5SAndroid Build Coastguard Worker     {
3415*8975f5c5SAndroid Build Coastguard Worker         if (outermostSize != static_cast<unsigned int>(mMaxPatchVertices))
3416*8975f5c5SAndroid Build Coastguard Worker         {
3417*8975f5c5SAndroid Build Coastguard Worker             error(location,
3418*8975f5c5SAndroid Build Coastguard Worker                   "If a size is specified for a tessellation control or evaluation user-defined "
3419*8975f5c5SAndroid Build Coastguard Worker                   "input variable, it must match the maximum patch size (gl_MaxPatchVertices).",
3420*8975f5c5SAndroid Build Coastguard Worker                   token);
3421*8975f5c5SAndroid Build Coastguard Worker         }
3422*8975f5c5SAndroid Build Coastguard Worker     }
3423*8975f5c5SAndroid Build Coastguard Worker     else if (IsTessellationControlShaderOutput(mShaderType, qualifier))
3424*8975f5c5SAndroid Build Coastguard Worker     {
3425*8975f5c5SAndroid Build Coastguard Worker         if (outermostSize != static_cast<unsigned int>(mTessControlShaderOutputVertices) &&
3426*8975f5c5SAndroid Build Coastguard Worker             mTessControlShaderOutputVertices != 0)
3427*8975f5c5SAndroid Build Coastguard Worker         {
3428*8975f5c5SAndroid Build Coastguard Worker             error(location,
3429*8975f5c5SAndroid Build Coastguard Worker                   "If a size is specified for a tessellation control user-defined per-vertex "
3430*8975f5c5SAndroid Build Coastguard Worker                   "output variable, it must match the the number of vertices in the output "
3431*8975f5c5SAndroid Build Coastguard Worker                   "patch.",
3432*8975f5c5SAndroid Build Coastguard Worker                   token);
3433*8975f5c5SAndroid Build Coastguard Worker         }
3434*8975f5c5SAndroid Build Coastguard Worker     }
3435*8975f5c5SAndroid Build Coastguard Worker }
3436*8975f5c5SAndroid Build Coastguard Worker 
parseSingleDeclaration(TPublicType & publicType,const TSourceLoc & identifierOrTypeLocation,const ImmutableString & identifier)3437*8975f5c5SAndroid Build Coastguard Worker TIntermDeclaration *TParseContext::parseSingleDeclaration(
3438*8975f5c5SAndroid Build Coastguard Worker     TPublicType &publicType,
3439*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &identifierOrTypeLocation,
3440*8975f5c5SAndroid Build Coastguard Worker     const ImmutableString &identifier)
3441*8975f5c5SAndroid Build Coastguard Worker {
3442*8975f5c5SAndroid Build Coastguard Worker     TType *type = new TType(publicType);
3443*8975f5c5SAndroid Build Coastguard Worker     if (mCompileOptions.flattenPragmaSTDGLInvariantAll &&
3444*8975f5c5SAndroid Build Coastguard Worker         mDirectiveHandler.pragma().stdgl.invariantAll)
3445*8975f5c5SAndroid Build Coastguard Worker     {
3446*8975f5c5SAndroid Build Coastguard Worker         TQualifier qualifier = type->getQualifier();
3447*8975f5c5SAndroid Build Coastguard Worker 
3448*8975f5c5SAndroid Build Coastguard Worker         // The directive handler has already taken care of rejecting invalid uses of this pragma
3449*8975f5c5SAndroid Build Coastguard Worker         // (for example, in ESSL 3.00 fragment shaders), so at this point, flatten it into all
3450*8975f5c5SAndroid Build Coastguard Worker         // affected variable declarations:
3451*8975f5c5SAndroid Build Coastguard Worker         //
3452*8975f5c5SAndroid Build Coastguard Worker         // 1. Built-in special variables which are inputs to the fragment shader. (These are handled
3453*8975f5c5SAndroid Build Coastguard Worker         // elsewhere, in TranslatorGLSL.)
3454*8975f5c5SAndroid Build Coastguard Worker         //
3455*8975f5c5SAndroid Build Coastguard Worker         // 2. Outputs from vertex shaders in ESSL 1.00 and 3.00 (EvqVaryingOut and EvqVertexOut). It
3456*8975f5c5SAndroid Build Coastguard Worker         // is actually less likely that there will be bugs in the handling of ESSL 3.00 shaders, but
3457*8975f5c5SAndroid Build Coastguard Worker         // the way this is currently implemented we have to enable this compiler option before
3458*8975f5c5SAndroid Build Coastguard Worker         // parsing the shader and determining the shading language version it uses. If this were
3459*8975f5c5SAndroid Build Coastguard Worker         // implemented as a post-pass, the workaround could be more targeted.
3460*8975f5c5SAndroid Build Coastguard Worker         if (qualifier == EvqVaryingOut || qualifier == EvqVertexOut)
3461*8975f5c5SAndroid Build Coastguard Worker         {
3462*8975f5c5SAndroid Build Coastguard Worker             type->setInvariant(true);
3463*8975f5c5SAndroid Build Coastguard Worker         }
3464*8975f5c5SAndroid Build Coastguard Worker     }
3465*8975f5c5SAndroid Build Coastguard Worker 
3466*8975f5c5SAndroid Build Coastguard Worker     if (identifier == "gl_FragDepth")
3467*8975f5c5SAndroid Build Coastguard Worker     {
3468*8975f5c5SAndroid Build Coastguard Worker         if (type->getQualifier() == EvqFragmentOut)
3469*8975f5c5SAndroid Build Coastguard Worker         {
3470*8975f5c5SAndroid Build Coastguard Worker             type->setQualifier(EvqFragDepth);
3471*8975f5c5SAndroid Build Coastguard Worker         }
3472*8975f5c5SAndroid Build Coastguard Worker         else
3473*8975f5c5SAndroid Build Coastguard Worker         {
3474*8975f5c5SAndroid Build Coastguard Worker             error(identifierOrTypeLocation,
3475*8975f5c5SAndroid Build Coastguard Worker                   "gl_FragDepth can only be redeclared as fragment output", identifier);
3476*8975f5c5SAndroid Build Coastguard Worker         }
3477*8975f5c5SAndroid Build Coastguard Worker     }
3478*8975f5c5SAndroid Build Coastguard Worker 
3479*8975f5c5SAndroid Build Coastguard Worker     checkGeometryShaderInputAndSetArraySize(identifierOrTypeLocation, identifier, type);
3480*8975f5c5SAndroid Build Coastguard Worker     checkTessellationShaderUnsizedArraysAndSetSize(identifierOrTypeLocation, identifier, type);
3481*8975f5c5SAndroid Build Coastguard Worker 
3482*8975f5c5SAndroid Build Coastguard Worker     declarationQualifierErrorCheck(type->getQualifier(), publicType.layoutQualifier,
3483*8975f5c5SAndroid Build Coastguard Worker                                    identifierOrTypeLocation);
3484*8975f5c5SAndroid Build Coastguard Worker 
3485*8975f5c5SAndroid Build Coastguard Worker     bool emptyDeclaration                  = (identifier == "");
3486*8975f5c5SAndroid Build Coastguard Worker     mDeferredNonEmptyDeclarationErrorCheck = emptyDeclaration;
3487*8975f5c5SAndroid Build Coastguard Worker 
3488*8975f5c5SAndroid Build Coastguard Worker     TIntermSymbol *symbol = nullptr;
3489*8975f5c5SAndroid Build Coastguard Worker     if (emptyDeclaration)
3490*8975f5c5SAndroid Build Coastguard Worker     {
3491*8975f5c5SAndroid Build Coastguard Worker         emptyDeclarationErrorCheck(*type, identifierOrTypeLocation);
3492*8975f5c5SAndroid Build Coastguard Worker         // In most cases we don't need to create a symbol node for an empty declaration.
3493*8975f5c5SAndroid Build Coastguard Worker         // But if the empty declaration is declaring a struct type, the symbol node will store that.
3494*8975f5c5SAndroid Build Coastguard Worker         if (type->getBasicType() == EbtStruct)
3495*8975f5c5SAndroid Build Coastguard Worker         {
3496*8975f5c5SAndroid Build Coastguard Worker             TVariable *emptyVariable =
3497*8975f5c5SAndroid Build Coastguard Worker                 new TVariable(&symbolTable, kEmptyImmutableString, type, SymbolType::Empty);
3498*8975f5c5SAndroid Build Coastguard Worker             symbol = new TIntermSymbol(emptyVariable);
3499*8975f5c5SAndroid Build Coastguard Worker         }
3500*8975f5c5SAndroid Build Coastguard Worker         else if (IsAtomicCounter(publicType.getBasicType()))
3501*8975f5c5SAndroid Build Coastguard Worker         {
3502*8975f5c5SAndroid Build Coastguard Worker             setAtomicCounterBindingDefaultOffset(publicType, identifierOrTypeLocation);
3503*8975f5c5SAndroid Build Coastguard Worker         }
3504*8975f5c5SAndroid Build Coastguard Worker     }
3505*8975f5c5SAndroid Build Coastguard Worker     else
3506*8975f5c5SAndroid Build Coastguard Worker     {
3507*8975f5c5SAndroid Build Coastguard Worker         nonEmptyDeclarationErrorCheck(publicType, identifierOrTypeLocation);
3508*8975f5c5SAndroid Build Coastguard Worker 
3509*8975f5c5SAndroid Build Coastguard Worker         checkCanBeDeclaredWithoutInitializer(identifierOrTypeLocation, identifier, type);
3510*8975f5c5SAndroid Build Coastguard Worker         checkDeclarationIsValidArraySize(identifierOrTypeLocation, identifier, type);
3511*8975f5c5SAndroid Build Coastguard Worker 
3512*8975f5c5SAndroid Build Coastguard Worker         if (IsAtomicCounter(type->getBasicType()))
3513*8975f5c5SAndroid Build Coastguard Worker         {
3514*8975f5c5SAndroid Build Coastguard Worker             checkAtomicCounterOffsetIsValid(false, identifierOrTypeLocation, type);
3515*8975f5c5SAndroid Build Coastguard Worker         }
3516*8975f5c5SAndroid Build Coastguard Worker 
3517*8975f5c5SAndroid Build Coastguard Worker         TVariable *variable = nullptr;
3518*8975f5c5SAndroid Build Coastguard Worker         if (declareVariable(identifierOrTypeLocation, identifier, type, &variable))
3519*8975f5c5SAndroid Build Coastguard Worker         {
3520*8975f5c5SAndroid Build Coastguard Worker             symbol = new TIntermSymbol(variable);
3521*8975f5c5SAndroid Build Coastguard Worker         }
3522*8975f5c5SAndroid Build Coastguard Worker     }
3523*8975f5c5SAndroid Build Coastguard Worker 
3524*8975f5c5SAndroid Build Coastguard Worker     adjustRedeclaredBuiltInType(identifierOrTypeLocation, identifier, type);
3525*8975f5c5SAndroid Build Coastguard Worker 
3526*8975f5c5SAndroid Build Coastguard Worker     TIntermDeclaration *declaration = new TIntermDeclaration();
3527*8975f5c5SAndroid Build Coastguard Worker     declaration->setLine(identifierOrTypeLocation);
3528*8975f5c5SAndroid Build Coastguard Worker     if (symbol)
3529*8975f5c5SAndroid Build Coastguard Worker     {
3530*8975f5c5SAndroid Build Coastguard Worker         symbol->setLine(identifierOrTypeLocation);
3531*8975f5c5SAndroid Build Coastguard Worker         declaration->appendDeclarator(symbol);
3532*8975f5c5SAndroid Build Coastguard Worker     }
3533*8975f5c5SAndroid Build Coastguard Worker     return declaration;
3534*8975f5c5SAndroid Build Coastguard Worker }
3535*8975f5c5SAndroid Build Coastguard Worker 
parseSingleArrayDeclaration(TPublicType & elementType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & indexLocation,const TVector<unsigned int> & arraySizes)3536*8975f5c5SAndroid Build Coastguard Worker TIntermDeclaration *TParseContext::parseSingleArrayDeclaration(
3537*8975f5c5SAndroid Build Coastguard Worker     TPublicType &elementType,
3538*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &identifierLocation,
3539*8975f5c5SAndroid Build Coastguard Worker     const ImmutableString &identifier,
3540*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &indexLocation,
3541*8975f5c5SAndroid Build Coastguard Worker     const TVector<unsigned int> &arraySizes)
3542*8975f5c5SAndroid Build Coastguard Worker {
3543*8975f5c5SAndroid Build Coastguard Worker     mDeferredNonEmptyDeclarationErrorCheck = false;
3544*8975f5c5SAndroid Build Coastguard Worker 
3545*8975f5c5SAndroid Build Coastguard Worker     declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
3546*8975f5c5SAndroid Build Coastguard Worker                                    identifierLocation);
3547*8975f5c5SAndroid Build Coastguard Worker 
3548*8975f5c5SAndroid Build Coastguard Worker     nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
3549*8975f5c5SAndroid Build Coastguard Worker 
3550*8975f5c5SAndroid Build Coastguard Worker     checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
3551*8975f5c5SAndroid Build Coastguard Worker 
3552*8975f5c5SAndroid Build Coastguard Worker     TType *arrayType = new TType(elementType);
3553*8975f5c5SAndroid Build Coastguard Worker     arrayType->makeArrays(arraySizes);
3554*8975f5c5SAndroid Build Coastguard Worker 
3555*8975f5c5SAndroid Build Coastguard Worker     checkArrayOfArraysInOut(indexLocation, elementType, *arrayType);
3556*8975f5c5SAndroid Build Coastguard Worker 
3557*8975f5c5SAndroid Build Coastguard Worker     checkGeometryShaderInputAndSetArraySize(indexLocation, identifier, arrayType);
3558*8975f5c5SAndroid Build Coastguard Worker     checkTessellationShaderUnsizedArraysAndSetSize(indexLocation, identifier, arrayType);
3559*8975f5c5SAndroid Build Coastguard Worker 
3560*8975f5c5SAndroid Build Coastguard Worker     checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType);
3561*8975f5c5SAndroid Build Coastguard Worker     checkDeclarationIsValidArraySize(identifierLocation, identifier, arrayType);
3562*8975f5c5SAndroid Build Coastguard Worker 
3563*8975f5c5SAndroid Build Coastguard Worker     if (IsAtomicCounter(arrayType->getBasicType()))
3564*8975f5c5SAndroid Build Coastguard Worker     {
3565*8975f5c5SAndroid Build Coastguard Worker         checkAtomicCounterOffsetIsValid(false, identifierLocation, arrayType);
3566*8975f5c5SAndroid Build Coastguard Worker     }
3567*8975f5c5SAndroid Build Coastguard Worker 
3568*8975f5c5SAndroid Build Coastguard Worker     adjustRedeclaredBuiltInType(identifierLocation, identifier, arrayType);
3569*8975f5c5SAndroid Build Coastguard Worker 
3570*8975f5c5SAndroid Build Coastguard Worker     TIntermDeclaration *declaration = new TIntermDeclaration();
3571*8975f5c5SAndroid Build Coastguard Worker     declaration->setLine(identifierLocation);
3572*8975f5c5SAndroid Build Coastguard Worker 
3573*8975f5c5SAndroid Build Coastguard Worker     TVariable *variable = nullptr;
3574*8975f5c5SAndroid Build Coastguard Worker     if (declareVariable(identifierLocation, identifier, arrayType, &variable))
3575*8975f5c5SAndroid Build Coastguard Worker     {
3576*8975f5c5SAndroid Build Coastguard Worker         TIntermSymbol *symbol = new TIntermSymbol(variable);
3577*8975f5c5SAndroid Build Coastguard Worker         symbol->setLine(identifierLocation);
3578*8975f5c5SAndroid Build Coastguard Worker         declaration->appendDeclarator(symbol);
3579*8975f5c5SAndroid Build Coastguard Worker     }
3580*8975f5c5SAndroid Build Coastguard Worker 
3581*8975f5c5SAndroid Build Coastguard Worker     return declaration;
3582*8975f5c5SAndroid Build Coastguard Worker }
3583*8975f5c5SAndroid Build Coastguard Worker 
parseSingleInitDeclaration(const TPublicType & publicType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & initLocation,TIntermTyped * initializer)3584*8975f5c5SAndroid Build Coastguard Worker TIntermDeclaration *TParseContext::parseSingleInitDeclaration(const TPublicType &publicType,
3585*8975f5c5SAndroid Build Coastguard Worker                                                               const TSourceLoc &identifierLocation,
3586*8975f5c5SAndroid Build Coastguard Worker                                                               const ImmutableString &identifier,
3587*8975f5c5SAndroid Build Coastguard Worker                                                               const TSourceLoc &initLocation,
3588*8975f5c5SAndroid Build Coastguard Worker                                                               TIntermTyped *initializer)
3589*8975f5c5SAndroid Build Coastguard Worker {
3590*8975f5c5SAndroid Build Coastguard Worker     mDeferredNonEmptyDeclarationErrorCheck = false;
3591*8975f5c5SAndroid Build Coastguard Worker 
3592*8975f5c5SAndroid Build Coastguard Worker     declarationQualifierErrorCheck(publicType.qualifier, publicType.layoutQualifier,
3593*8975f5c5SAndroid Build Coastguard Worker                                    identifierLocation);
3594*8975f5c5SAndroid Build Coastguard Worker 
3595*8975f5c5SAndroid Build Coastguard Worker     nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
3596*8975f5c5SAndroid Build Coastguard Worker 
3597*8975f5c5SAndroid Build Coastguard Worker     TIntermDeclaration *declaration = new TIntermDeclaration();
3598*8975f5c5SAndroid Build Coastguard Worker     declaration->setLine(identifierLocation);
3599*8975f5c5SAndroid Build Coastguard Worker 
3600*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *initNode = nullptr;
3601*8975f5c5SAndroid Build Coastguard Worker     TType *type             = new TType(publicType);
3602*8975f5c5SAndroid Build Coastguard Worker     if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
3603*8975f5c5SAndroid Build Coastguard Worker     {
3604*8975f5c5SAndroid Build Coastguard Worker         if (initNode)
3605*8975f5c5SAndroid Build Coastguard Worker         {
3606*8975f5c5SAndroid Build Coastguard Worker             declaration->appendDeclarator(initNode);
3607*8975f5c5SAndroid Build Coastguard Worker         }
3608*8975f5c5SAndroid Build Coastguard Worker         else if (publicType.isStructSpecifier())
3609*8975f5c5SAndroid Build Coastguard Worker         {
3610*8975f5c5SAndroid Build Coastguard Worker             // The initialization got constant folded.  If it's a struct, declare the struct anyway.
3611*8975f5c5SAndroid Build Coastguard Worker             TVariable *emptyVariable =
3612*8975f5c5SAndroid Build Coastguard Worker                 new TVariable(&symbolTable, kEmptyImmutableString, type, SymbolType::Empty);
3613*8975f5c5SAndroid Build Coastguard Worker             TIntermSymbol *symbol = new TIntermSymbol(emptyVariable);
3614*8975f5c5SAndroid Build Coastguard Worker             symbol->setLine(publicType.getLine());
3615*8975f5c5SAndroid Build Coastguard Worker             declaration->appendDeclarator(symbol);
3616*8975f5c5SAndroid Build Coastguard Worker         }
3617*8975f5c5SAndroid Build Coastguard Worker     }
3618*8975f5c5SAndroid Build Coastguard Worker     return declaration;
3619*8975f5c5SAndroid Build Coastguard Worker }
3620*8975f5c5SAndroid Build Coastguard Worker 
parseSingleArrayInitDeclaration(TPublicType & elementType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & indexLocation,const TVector<unsigned int> & arraySizes,const TSourceLoc & initLocation,TIntermTyped * initializer)3621*8975f5c5SAndroid Build Coastguard Worker TIntermDeclaration *TParseContext::parseSingleArrayInitDeclaration(
3622*8975f5c5SAndroid Build Coastguard Worker     TPublicType &elementType,
3623*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &identifierLocation,
3624*8975f5c5SAndroid Build Coastguard Worker     const ImmutableString &identifier,
3625*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &indexLocation,
3626*8975f5c5SAndroid Build Coastguard Worker     const TVector<unsigned int> &arraySizes,
3627*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &initLocation,
3628*8975f5c5SAndroid Build Coastguard Worker     TIntermTyped *initializer)
3629*8975f5c5SAndroid Build Coastguard Worker {
3630*8975f5c5SAndroid Build Coastguard Worker     mDeferredNonEmptyDeclarationErrorCheck = false;
3631*8975f5c5SAndroid Build Coastguard Worker 
3632*8975f5c5SAndroid Build Coastguard Worker     declarationQualifierErrorCheck(elementType.qualifier, elementType.layoutQualifier,
3633*8975f5c5SAndroid Build Coastguard Worker                                    identifierLocation);
3634*8975f5c5SAndroid Build Coastguard Worker 
3635*8975f5c5SAndroid Build Coastguard Worker     nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
3636*8975f5c5SAndroid Build Coastguard Worker 
3637*8975f5c5SAndroid Build Coastguard Worker     checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
3638*8975f5c5SAndroid Build Coastguard Worker 
3639*8975f5c5SAndroid Build Coastguard Worker     TType *arrayType = new TType(elementType);
3640*8975f5c5SAndroid Build Coastguard Worker     arrayType->makeArrays(arraySizes);
3641*8975f5c5SAndroid Build Coastguard Worker 
3642*8975f5c5SAndroid Build Coastguard Worker     TIntermDeclaration *declaration = new TIntermDeclaration();
3643*8975f5c5SAndroid Build Coastguard Worker     declaration->setLine(identifierLocation);
3644*8975f5c5SAndroid Build Coastguard Worker 
3645*8975f5c5SAndroid Build Coastguard Worker     // initNode will correspond to the whole of "type b[n] = initializer".
3646*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *initNode = nullptr;
3647*8975f5c5SAndroid Build Coastguard Worker     if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
3648*8975f5c5SAndroid Build Coastguard Worker     {
3649*8975f5c5SAndroid Build Coastguard Worker         if (initNode)
3650*8975f5c5SAndroid Build Coastguard Worker         {
3651*8975f5c5SAndroid Build Coastguard Worker             declaration->appendDeclarator(initNode);
3652*8975f5c5SAndroid Build Coastguard Worker         }
3653*8975f5c5SAndroid Build Coastguard Worker     }
3654*8975f5c5SAndroid Build Coastguard Worker 
3655*8975f5c5SAndroid Build Coastguard Worker     return declaration;
3656*8975f5c5SAndroid Build Coastguard Worker }
3657*8975f5c5SAndroid Build Coastguard Worker 
parseGlobalQualifierDeclaration(const TTypeQualifierBuilder & typeQualifierBuilder,const TSourceLoc & identifierLoc,const ImmutableString & identifier,const TSymbol * symbol)3658*8975f5c5SAndroid Build Coastguard Worker TIntermGlobalQualifierDeclaration *TParseContext::parseGlobalQualifierDeclaration(
3659*8975f5c5SAndroid Build Coastguard Worker     const TTypeQualifierBuilder &typeQualifierBuilder,
3660*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &identifierLoc,
3661*8975f5c5SAndroid Build Coastguard Worker     const ImmutableString &identifier,
3662*8975f5c5SAndroid Build Coastguard Worker     const TSymbol *symbol)
3663*8975f5c5SAndroid Build Coastguard Worker {
3664*8975f5c5SAndroid Build Coastguard Worker     TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
3665*8975f5c5SAndroid Build Coastguard Worker 
3666*8975f5c5SAndroid Build Coastguard Worker     if (!typeQualifier.invariant && !typeQualifier.precise)
3667*8975f5c5SAndroid Build Coastguard Worker     {
3668*8975f5c5SAndroid Build Coastguard Worker         error(identifierLoc, "Expected invariant or precise", identifier);
3669*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
3670*8975f5c5SAndroid Build Coastguard Worker     }
3671*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.invariant && !checkIsAtGlobalLevel(identifierLoc, "invariant varying"))
3672*8975f5c5SAndroid Build Coastguard Worker     {
3673*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
3674*8975f5c5SAndroid Build Coastguard Worker     }
3675*8975f5c5SAndroid Build Coastguard Worker     if (!symbol)
3676*8975f5c5SAndroid Build Coastguard Worker     {
3677*8975f5c5SAndroid Build Coastguard Worker         error(identifierLoc, "undeclared identifier declared as invariant or precise", identifier);
3678*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
3679*8975f5c5SAndroid Build Coastguard Worker     }
3680*8975f5c5SAndroid Build Coastguard Worker     if (!IsQualifierUnspecified(typeQualifier.qualifier))
3681*8975f5c5SAndroid Build Coastguard Worker     {
3682*8975f5c5SAndroid Build Coastguard Worker         error(identifierLoc, "invariant or precise declaration specifies qualifier",
3683*8975f5c5SAndroid Build Coastguard Worker               getQualifierString(typeQualifier.qualifier));
3684*8975f5c5SAndroid Build Coastguard Worker     }
3685*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.precision != EbpUndefined)
3686*8975f5c5SAndroid Build Coastguard Worker     {
3687*8975f5c5SAndroid Build Coastguard Worker         error(identifierLoc, "invariant or precise declaration specifies precision",
3688*8975f5c5SAndroid Build Coastguard Worker               getPrecisionString(typeQualifier.precision));
3689*8975f5c5SAndroid Build Coastguard Worker     }
3690*8975f5c5SAndroid Build Coastguard Worker     if (!typeQualifier.layoutQualifier.isEmpty())
3691*8975f5c5SAndroid Build Coastguard Worker     {
3692*8975f5c5SAndroid Build Coastguard Worker         error(identifierLoc, "invariant or precise declaration specifies layout", "'layout'");
3693*8975f5c5SAndroid Build Coastguard Worker     }
3694*8975f5c5SAndroid Build Coastguard Worker 
3695*8975f5c5SAndroid Build Coastguard Worker     const TVariable *variable = getNamedVariable(identifierLoc, identifier, symbol);
3696*8975f5c5SAndroid Build Coastguard Worker     if (!variable)
3697*8975f5c5SAndroid Build Coastguard Worker     {
3698*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
3699*8975f5c5SAndroid Build Coastguard Worker     }
3700*8975f5c5SAndroid Build Coastguard Worker     const TType &type = variable->getType();
3701*8975f5c5SAndroid Build Coastguard Worker 
3702*8975f5c5SAndroid Build Coastguard Worker     checkInvariantVariableQualifier(typeQualifier.invariant, type.getQualifier(),
3703*8975f5c5SAndroid Build Coastguard Worker                                     typeQualifier.line);
3704*8975f5c5SAndroid Build Coastguard Worker     checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
3705*8975f5c5SAndroid Build Coastguard Worker 
3706*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.invariant)
3707*8975f5c5SAndroid Build Coastguard Worker     {
3708*8975f5c5SAndroid Build Coastguard Worker         symbolTable.addInvariantVarying(*variable);
3709*8975f5c5SAndroid Build Coastguard Worker     }
3710*8975f5c5SAndroid Build Coastguard Worker 
3711*8975f5c5SAndroid Build Coastguard Worker     TIntermSymbol *intermSymbol = new TIntermSymbol(variable);
3712*8975f5c5SAndroid Build Coastguard Worker     intermSymbol->setLine(identifierLoc);
3713*8975f5c5SAndroid Build Coastguard Worker 
3714*8975f5c5SAndroid Build Coastguard Worker     return new TIntermGlobalQualifierDeclaration(intermSymbol, typeQualifier.precise,
3715*8975f5c5SAndroid Build Coastguard Worker                                                  identifierLoc);
3716*8975f5c5SAndroid Build Coastguard Worker }
3717*8975f5c5SAndroid Build Coastguard Worker 
parseDeclarator(TPublicType & publicType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,TIntermDeclaration * declarationOut)3718*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseDeclarator(TPublicType &publicType,
3719*8975f5c5SAndroid Build Coastguard Worker                                     const TSourceLoc &identifierLocation,
3720*8975f5c5SAndroid Build Coastguard Worker                                     const ImmutableString &identifier,
3721*8975f5c5SAndroid Build Coastguard Worker                                     TIntermDeclaration *declarationOut)
3722*8975f5c5SAndroid Build Coastguard Worker {
3723*8975f5c5SAndroid Build Coastguard Worker     // If the declaration starting this declarator list was empty (example: int,), some checks were
3724*8975f5c5SAndroid Build Coastguard Worker     // not performed.
3725*8975f5c5SAndroid Build Coastguard Worker     if (mDeferredNonEmptyDeclarationErrorCheck)
3726*8975f5c5SAndroid Build Coastguard Worker     {
3727*8975f5c5SAndroid Build Coastguard Worker         nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
3728*8975f5c5SAndroid Build Coastguard Worker         mDeferredNonEmptyDeclarationErrorCheck = false;
3729*8975f5c5SAndroid Build Coastguard Worker     }
3730*8975f5c5SAndroid Build Coastguard Worker 
3731*8975f5c5SAndroid Build Coastguard Worker     checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
3732*8975f5c5SAndroid Build Coastguard Worker 
3733*8975f5c5SAndroid Build Coastguard Worker     TType *type = new TType(publicType);
3734*8975f5c5SAndroid Build Coastguard Worker 
3735*8975f5c5SAndroid Build Coastguard Worker     checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, type);
3736*8975f5c5SAndroid Build Coastguard Worker     checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, type);
3737*8975f5c5SAndroid Build Coastguard Worker 
3738*8975f5c5SAndroid Build Coastguard Worker     checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, type);
3739*8975f5c5SAndroid Build Coastguard Worker     checkDeclarationIsValidArraySize(identifierLocation, identifier, type);
3740*8975f5c5SAndroid Build Coastguard Worker 
3741*8975f5c5SAndroid Build Coastguard Worker     if (IsAtomicCounter(type->getBasicType()))
3742*8975f5c5SAndroid Build Coastguard Worker     {
3743*8975f5c5SAndroid Build Coastguard Worker         checkAtomicCounterOffsetIsValid(true, identifierLocation, type);
3744*8975f5c5SAndroid Build Coastguard Worker     }
3745*8975f5c5SAndroid Build Coastguard Worker 
3746*8975f5c5SAndroid Build Coastguard Worker     adjustRedeclaredBuiltInType(identifierLocation, identifier, type);
3747*8975f5c5SAndroid Build Coastguard Worker 
3748*8975f5c5SAndroid Build Coastguard Worker     TVariable *variable = nullptr;
3749*8975f5c5SAndroid Build Coastguard Worker     if (declareVariable(identifierLocation, identifier, type, &variable))
3750*8975f5c5SAndroid Build Coastguard Worker     {
3751*8975f5c5SAndroid Build Coastguard Worker         TIntermSymbol *symbol = new TIntermSymbol(variable);
3752*8975f5c5SAndroid Build Coastguard Worker         symbol->setLine(identifierLocation);
3753*8975f5c5SAndroid Build Coastguard Worker         declarationOut->appendDeclarator(symbol);
3754*8975f5c5SAndroid Build Coastguard Worker     }
3755*8975f5c5SAndroid Build Coastguard Worker }
3756*8975f5c5SAndroid Build Coastguard Worker 
parseArrayDeclarator(TPublicType & elementType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & arrayLocation,const TVector<unsigned int> & arraySizes,TIntermDeclaration * declarationOut)3757*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseArrayDeclarator(TPublicType &elementType,
3758*8975f5c5SAndroid Build Coastguard Worker                                          const TSourceLoc &identifierLocation,
3759*8975f5c5SAndroid Build Coastguard Worker                                          const ImmutableString &identifier,
3760*8975f5c5SAndroid Build Coastguard Worker                                          const TSourceLoc &arrayLocation,
3761*8975f5c5SAndroid Build Coastguard Worker                                          const TVector<unsigned int> &arraySizes,
3762*8975f5c5SAndroid Build Coastguard Worker                                          TIntermDeclaration *declarationOut)
3763*8975f5c5SAndroid Build Coastguard Worker {
3764*8975f5c5SAndroid Build Coastguard Worker     // If the declaration starting this declarator list was empty (example: int,), some checks were
3765*8975f5c5SAndroid Build Coastguard Worker     // not performed.
3766*8975f5c5SAndroid Build Coastguard Worker     if (mDeferredNonEmptyDeclarationErrorCheck)
3767*8975f5c5SAndroid Build Coastguard Worker     {
3768*8975f5c5SAndroid Build Coastguard Worker         nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
3769*8975f5c5SAndroid Build Coastguard Worker         mDeferredNonEmptyDeclarationErrorCheck = false;
3770*8975f5c5SAndroid Build Coastguard Worker     }
3771*8975f5c5SAndroid Build Coastguard Worker 
3772*8975f5c5SAndroid Build Coastguard Worker     checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);
3773*8975f5c5SAndroid Build Coastguard Worker 
3774*8975f5c5SAndroid Build Coastguard Worker     if (checkIsValidTypeAndQualifierForArray(arrayLocation, elementType))
3775*8975f5c5SAndroid Build Coastguard Worker     {
3776*8975f5c5SAndroid Build Coastguard Worker         TType *arrayType = new TType(elementType);
3777*8975f5c5SAndroid Build Coastguard Worker         arrayType->makeArrays(arraySizes);
3778*8975f5c5SAndroid Build Coastguard Worker 
3779*8975f5c5SAndroid Build Coastguard Worker         checkGeometryShaderInputAndSetArraySize(identifierLocation, identifier, arrayType);
3780*8975f5c5SAndroid Build Coastguard Worker         checkTessellationShaderUnsizedArraysAndSetSize(identifierLocation, identifier, arrayType);
3781*8975f5c5SAndroid Build Coastguard Worker 
3782*8975f5c5SAndroid Build Coastguard Worker         checkCanBeDeclaredWithoutInitializer(identifierLocation, identifier, arrayType);
3783*8975f5c5SAndroid Build Coastguard Worker         checkDeclarationIsValidArraySize(identifierLocation, identifier, arrayType);
3784*8975f5c5SAndroid Build Coastguard Worker 
3785*8975f5c5SAndroid Build Coastguard Worker         if (IsAtomicCounter(arrayType->getBasicType()))
3786*8975f5c5SAndroid Build Coastguard Worker         {
3787*8975f5c5SAndroid Build Coastguard Worker             checkAtomicCounterOffsetDoesNotOverlap(true, identifierLocation, arrayType);
3788*8975f5c5SAndroid Build Coastguard Worker 
3789*8975f5c5SAndroid Build Coastguard Worker             checkAtomicCounterOffsetAlignment(identifierLocation, *arrayType);
3790*8975f5c5SAndroid Build Coastguard Worker         }
3791*8975f5c5SAndroid Build Coastguard Worker 
3792*8975f5c5SAndroid Build Coastguard Worker         adjustRedeclaredBuiltInType(identifierLocation, identifier, arrayType);
3793*8975f5c5SAndroid Build Coastguard Worker 
3794*8975f5c5SAndroid Build Coastguard Worker         TVariable *variable = nullptr;
3795*8975f5c5SAndroid Build Coastguard Worker         if (declareVariable(identifierLocation, identifier, arrayType, &variable))
3796*8975f5c5SAndroid Build Coastguard Worker         {
3797*8975f5c5SAndroid Build Coastguard Worker             TIntermSymbol *symbol = new TIntermSymbol(variable);
3798*8975f5c5SAndroid Build Coastguard Worker             symbol->setLine(identifierLocation);
3799*8975f5c5SAndroid Build Coastguard Worker             declarationOut->appendDeclarator(symbol);
3800*8975f5c5SAndroid Build Coastguard Worker         }
3801*8975f5c5SAndroid Build Coastguard Worker     }
3802*8975f5c5SAndroid Build Coastguard Worker }
3803*8975f5c5SAndroid Build Coastguard Worker 
parseInitDeclarator(const TPublicType & publicType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & initLocation,TIntermTyped * initializer,TIntermDeclaration * declarationOut)3804*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseInitDeclarator(const TPublicType &publicType,
3805*8975f5c5SAndroid Build Coastguard Worker                                         const TSourceLoc &identifierLocation,
3806*8975f5c5SAndroid Build Coastguard Worker                                         const ImmutableString &identifier,
3807*8975f5c5SAndroid Build Coastguard Worker                                         const TSourceLoc &initLocation,
3808*8975f5c5SAndroid Build Coastguard Worker                                         TIntermTyped *initializer,
3809*8975f5c5SAndroid Build Coastguard Worker                                         TIntermDeclaration *declarationOut)
3810*8975f5c5SAndroid Build Coastguard Worker {
3811*8975f5c5SAndroid Build Coastguard Worker     // If the declaration starting this declarator list was empty (example: int,), some checks were
3812*8975f5c5SAndroid Build Coastguard Worker     // not performed.
3813*8975f5c5SAndroid Build Coastguard Worker     if (mDeferredNonEmptyDeclarationErrorCheck)
3814*8975f5c5SAndroid Build Coastguard Worker     {
3815*8975f5c5SAndroid Build Coastguard Worker         nonEmptyDeclarationErrorCheck(publicType, identifierLocation);
3816*8975f5c5SAndroid Build Coastguard Worker         mDeferredNonEmptyDeclarationErrorCheck = false;
3817*8975f5c5SAndroid Build Coastguard Worker     }
3818*8975f5c5SAndroid Build Coastguard Worker 
3819*8975f5c5SAndroid Build Coastguard Worker     checkDeclaratorLocationIsNotSpecified(identifierLocation, publicType);
3820*8975f5c5SAndroid Build Coastguard Worker 
3821*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *initNode = nullptr;
3822*8975f5c5SAndroid Build Coastguard Worker     TType *type             = new TType(publicType);
3823*8975f5c5SAndroid Build Coastguard Worker     if (executeInitializer(identifierLocation, identifier, type, initializer, &initNode))
3824*8975f5c5SAndroid Build Coastguard Worker     {
3825*8975f5c5SAndroid Build Coastguard Worker         //
3826*8975f5c5SAndroid Build Coastguard Worker         // build the intermediate representation
3827*8975f5c5SAndroid Build Coastguard Worker         //
3828*8975f5c5SAndroid Build Coastguard Worker         if (initNode)
3829*8975f5c5SAndroid Build Coastguard Worker         {
3830*8975f5c5SAndroid Build Coastguard Worker             declarationOut->appendDeclarator(initNode);
3831*8975f5c5SAndroid Build Coastguard Worker         }
3832*8975f5c5SAndroid Build Coastguard Worker     }
3833*8975f5c5SAndroid Build Coastguard Worker }
3834*8975f5c5SAndroid Build Coastguard Worker 
parseArrayInitDeclarator(const TPublicType & elementType,const TSourceLoc & identifierLocation,const ImmutableString & identifier,const TSourceLoc & indexLocation,const TVector<unsigned int> & arraySizes,const TSourceLoc & initLocation,TIntermTyped * initializer,TIntermDeclaration * declarationOut)3835*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseArrayInitDeclarator(const TPublicType &elementType,
3836*8975f5c5SAndroid Build Coastguard Worker                                              const TSourceLoc &identifierLocation,
3837*8975f5c5SAndroid Build Coastguard Worker                                              const ImmutableString &identifier,
3838*8975f5c5SAndroid Build Coastguard Worker                                              const TSourceLoc &indexLocation,
3839*8975f5c5SAndroid Build Coastguard Worker                                              const TVector<unsigned int> &arraySizes,
3840*8975f5c5SAndroid Build Coastguard Worker                                              const TSourceLoc &initLocation,
3841*8975f5c5SAndroid Build Coastguard Worker                                              TIntermTyped *initializer,
3842*8975f5c5SAndroid Build Coastguard Worker                                              TIntermDeclaration *declarationOut)
3843*8975f5c5SAndroid Build Coastguard Worker {
3844*8975f5c5SAndroid Build Coastguard Worker     // If the declaration starting this declarator list was empty (example: int,), some checks were
3845*8975f5c5SAndroid Build Coastguard Worker     // not performed.
3846*8975f5c5SAndroid Build Coastguard Worker     if (mDeferredNonEmptyDeclarationErrorCheck)
3847*8975f5c5SAndroid Build Coastguard Worker     {
3848*8975f5c5SAndroid Build Coastguard Worker         nonEmptyDeclarationErrorCheck(elementType, identifierLocation);
3849*8975f5c5SAndroid Build Coastguard Worker         mDeferredNonEmptyDeclarationErrorCheck = false;
3850*8975f5c5SAndroid Build Coastguard Worker     }
3851*8975f5c5SAndroid Build Coastguard Worker 
3852*8975f5c5SAndroid Build Coastguard Worker     checkDeclaratorLocationIsNotSpecified(identifierLocation, elementType);
3853*8975f5c5SAndroid Build Coastguard Worker 
3854*8975f5c5SAndroid Build Coastguard Worker     checkIsValidTypeAndQualifierForArray(indexLocation, elementType);
3855*8975f5c5SAndroid Build Coastguard Worker 
3856*8975f5c5SAndroid Build Coastguard Worker     TType *arrayType = new TType(elementType);
3857*8975f5c5SAndroid Build Coastguard Worker     arrayType->makeArrays(arraySizes);
3858*8975f5c5SAndroid Build Coastguard Worker 
3859*8975f5c5SAndroid Build Coastguard Worker     // initNode will correspond to the whole of "b[n] = initializer".
3860*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *initNode = nullptr;
3861*8975f5c5SAndroid Build Coastguard Worker     if (executeInitializer(identifierLocation, identifier, arrayType, initializer, &initNode))
3862*8975f5c5SAndroid Build Coastguard Worker     {
3863*8975f5c5SAndroid Build Coastguard Worker         if (initNode)
3864*8975f5c5SAndroid Build Coastguard Worker         {
3865*8975f5c5SAndroid Build Coastguard Worker             declarationOut->appendDeclarator(initNode);
3866*8975f5c5SAndroid Build Coastguard Worker         }
3867*8975f5c5SAndroid Build Coastguard Worker     }
3868*8975f5c5SAndroid Build Coastguard Worker }
3869*8975f5c5SAndroid Build Coastguard Worker 
addEmptyStatement(const TSourceLoc & location)3870*8975f5c5SAndroid Build Coastguard Worker TIntermNode *TParseContext::addEmptyStatement(const TSourceLoc &location)
3871*8975f5c5SAndroid Build Coastguard Worker {
3872*8975f5c5SAndroid Build Coastguard Worker     // It's simpler to parse an empty statement as a constant expression rather than having a
3873*8975f5c5SAndroid Build Coastguard Worker     // different type of node just for empty statements, that will be pruned from the AST anyway.
3874*8975f5c5SAndroid Build Coastguard Worker     TIntermNode *node = CreateZeroNode(TType(EbtInt, EbpMedium));
3875*8975f5c5SAndroid Build Coastguard Worker     node->setLine(location);
3876*8975f5c5SAndroid Build Coastguard Worker     return node;
3877*8975f5c5SAndroid Build Coastguard Worker }
3878*8975f5c5SAndroid Build Coastguard Worker 
setAtomicCounterBindingDefaultOffset(const TPublicType & publicType,const TSourceLoc & location)3879*8975f5c5SAndroid Build Coastguard Worker void TParseContext::setAtomicCounterBindingDefaultOffset(const TPublicType &publicType,
3880*8975f5c5SAndroid Build Coastguard Worker                                                          const TSourceLoc &location)
3881*8975f5c5SAndroid Build Coastguard Worker {
3882*8975f5c5SAndroid Build Coastguard Worker     const TLayoutQualifier &layoutQualifier = publicType.layoutQualifier;
3883*8975f5c5SAndroid Build Coastguard Worker     checkAtomicCounterBindingIsValid(location, layoutQualifier.binding);
3884*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.binding == -1 || layoutQualifier.offset == -1)
3885*8975f5c5SAndroid Build Coastguard Worker     {
3886*8975f5c5SAndroid Build Coastguard Worker         error(location, "Requires both binding and offset", "layout");
3887*8975f5c5SAndroid Build Coastguard Worker         return;
3888*8975f5c5SAndroid Build Coastguard Worker     }
3889*8975f5c5SAndroid Build Coastguard Worker     mAtomicCounterBindingStates[layoutQualifier.binding].setDefaultOffset(layoutQualifier.offset);
3890*8975f5c5SAndroid Build Coastguard Worker }
3891*8975f5c5SAndroid Build Coastguard Worker 
parseDefaultPrecisionQualifier(const TPrecision precision,const TPublicType & type,const TSourceLoc & loc)3892*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseDefaultPrecisionQualifier(const TPrecision precision,
3893*8975f5c5SAndroid Build Coastguard Worker                                                    const TPublicType &type,
3894*8975f5c5SAndroid Build Coastguard Worker                                                    const TSourceLoc &loc)
3895*8975f5c5SAndroid Build Coastguard Worker {
3896*8975f5c5SAndroid Build Coastguard Worker     if ((precision == EbpHigh) && (getShaderType() == GL_FRAGMENT_SHADER) &&
3897*8975f5c5SAndroid Build Coastguard Worker         !getFragmentPrecisionHigh())
3898*8975f5c5SAndroid Build Coastguard Worker     {
3899*8975f5c5SAndroid Build Coastguard Worker         error(loc, "precision is not supported in fragment shader", "highp");
3900*8975f5c5SAndroid Build Coastguard Worker     }
3901*8975f5c5SAndroid Build Coastguard Worker 
3902*8975f5c5SAndroid Build Coastguard Worker     if (!CanSetDefaultPrecisionOnType(type))
3903*8975f5c5SAndroid Build Coastguard Worker     {
3904*8975f5c5SAndroid Build Coastguard Worker         error(loc, "illegal type argument for default precision qualifier",
3905*8975f5c5SAndroid Build Coastguard Worker               getBasicString(type.getBasicType()));
3906*8975f5c5SAndroid Build Coastguard Worker         return;
3907*8975f5c5SAndroid Build Coastguard Worker     }
3908*8975f5c5SAndroid Build Coastguard Worker     symbolTable.setDefaultPrecision(type.getBasicType(), precision);
3909*8975f5c5SAndroid Build Coastguard Worker }
3910*8975f5c5SAndroid Build Coastguard Worker 
checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier & typeQualifier)3911*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkPrimitiveTypeMatchesTypeQualifier(const TTypeQualifier &typeQualifier)
3912*8975f5c5SAndroid Build Coastguard Worker {
3913*8975f5c5SAndroid Build Coastguard Worker     switch (typeQualifier.layoutQualifier.primitiveType)
3914*8975f5c5SAndroid Build Coastguard Worker     {
3915*8975f5c5SAndroid Build Coastguard Worker         case EptLines:
3916*8975f5c5SAndroid Build Coastguard Worker         case EptLinesAdjacency:
3917*8975f5c5SAndroid Build Coastguard Worker         case EptTriangles:
3918*8975f5c5SAndroid Build Coastguard Worker         case EptTrianglesAdjacency:
3919*8975f5c5SAndroid Build Coastguard Worker             return typeQualifier.qualifier == EvqGeometryIn;
3920*8975f5c5SAndroid Build Coastguard Worker 
3921*8975f5c5SAndroid Build Coastguard Worker         case EptLineStrip:
3922*8975f5c5SAndroid Build Coastguard Worker         case EptTriangleStrip:
3923*8975f5c5SAndroid Build Coastguard Worker             return typeQualifier.qualifier == EvqGeometryOut;
3924*8975f5c5SAndroid Build Coastguard Worker 
3925*8975f5c5SAndroid Build Coastguard Worker         case EptPoints:
3926*8975f5c5SAndroid Build Coastguard Worker             return true;
3927*8975f5c5SAndroid Build Coastguard Worker 
3928*8975f5c5SAndroid Build Coastguard Worker         default:
3929*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
3930*8975f5c5SAndroid Build Coastguard Worker             return false;
3931*8975f5c5SAndroid Build Coastguard Worker     }
3932*8975f5c5SAndroid Build Coastguard Worker }
3933*8975f5c5SAndroid Build Coastguard Worker 
setGeometryShaderInputArraySize(unsigned int inputArraySize,const TSourceLoc & line)3934*8975f5c5SAndroid Build Coastguard Worker void TParseContext::setGeometryShaderInputArraySize(unsigned int inputArraySize,
3935*8975f5c5SAndroid Build Coastguard Worker                                                     const TSourceLoc &line)
3936*8975f5c5SAndroid Build Coastguard Worker {
3937*8975f5c5SAndroid Build Coastguard Worker     if (!symbolTable.setGlInArraySize(inputArraySize))
3938*8975f5c5SAndroid Build Coastguard Worker     {
3939*8975f5c5SAndroid Build Coastguard Worker         error(line,
3940*8975f5c5SAndroid Build Coastguard Worker               "Array size or input primitive declaration doesn't match the size of earlier sized "
3941*8975f5c5SAndroid Build Coastguard Worker               "array inputs.",
3942*8975f5c5SAndroid Build Coastguard Worker               "layout");
3943*8975f5c5SAndroid Build Coastguard Worker     }
3944*8975f5c5SAndroid Build Coastguard Worker     mGeometryInputArraySize = inputArraySize;
3945*8975f5c5SAndroid Build Coastguard Worker }
3946*8975f5c5SAndroid Build Coastguard Worker 
parseGeometryShaderInputLayoutQualifier(const TTypeQualifier & typeQualifier)3947*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::parseGeometryShaderInputLayoutQualifier(const TTypeQualifier &typeQualifier)
3948*8975f5c5SAndroid Build Coastguard Worker {
3949*8975f5c5SAndroid Build Coastguard Worker     ASSERT(typeQualifier.qualifier == EvqGeometryIn);
3950*8975f5c5SAndroid Build Coastguard Worker 
3951*8975f5c5SAndroid Build Coastguard Worker     const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
3952*8975f5c5SAndroid Build Coastguard Worker 
3953*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.maxVertices != -1)
3954*8975f5c5SAndroid Build Coastguard Worker     {
3955*8975f5c5SAndroid Build Coastguard Worker         error(typeQualifier.line,
3956*8975f5c5SAndroid Build Coastguard Worker               "max_vertices can only be declared in 'out' layout in a geometry shader", "layout");
3957*8975f5c5SAndroid Build Coastguard Worker         return false;
3958*8975f5c5SAndroid Build Coastguard Worker     }
3959*8975f5c5SAndroid Build Coastguard Worker 
3960*8975f5c5SAndroid Build Coastguard Worker     // Set mGeometryInputPrimitiveType if exists
3961*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.primitiveType != EptUndefined)
3962*8975f5c5SAndroid Build Coastguard Worker     {
3963*8975f5c5SAndroid Build Coastguard Worker         if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
3964*8975f5c5SAndroid Build Coastguard Worker         {
3965*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "invalid primitive type for 'in' layout", "layout");
3966*8975f5c5SAndroid Build Coastguard Worker             return false;
3967*8975f5c5SAndroid Build Coastguard Worker         }
3968*8975f5c5SAndroid Build Coastguard Worker 
3969*8975f5c5SAndroid Build Coastguard Worker         if (mGeometryShaderInputPrimitiveType == EptUndefined)
3970*8975f5c5SAndroid Build Coastguard Worker         {
3971*8975f5c5SAndroid Build Coastguard Worker             mGeometryShaderInputPrimitiveType = layoutQualifier.primitiveType;
3972*8975f5c5SAndroid Build Coastguard Worker             setGeometryShaderInputArraySize(
3973*8975f5c5SAndroid Build Coastguard Worker                 GetGeometryShaderInputArraySize(mGeometryShaderInputPrimitiveType),
3974*8975f5c5SAndroid Build Coastguard Worker                 typeQualifier.line);
3975*8975f5c5SAndroid Build Coastguard Worker         }
3976*8975f5c5SAndroid Build Coastguard Worker         else if (mGeometryShaderInputPrimitiveType != layoutQualifier.primitiveType)
3977*8975f5c5SAndroid Build Coastguard Worker         {
3978*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "primitive doesn't match earlier input primitive declaration",
3979*8975f5c5SAndroid Build Coastguard Worker                   "layout");
3980*8975f5c5SAndroid Build Coastguard Worker             return false;
3981*8975f5c5SAndroid Build Coastguard Worker         }
3982*8975f5c5SAndroid Build Coastguard Worker 
3983*8975f5c5SAndroid Build Coastguard Worker         // Size any implicitly sized arrays that have already been declared.
3984*8975f5c5SAndroid Build Coastguard Worker         for (TType *type : mDeferredArrayTypesToSize)
3985*8975f5c5SAndroid Build Coastguard Worker         {
3986*8975f5c5SAndroid Build Coastguard Worker             type->sizeOutermostUnsizedArray(
3987*8975f5c5SAndroid Build Coastguard Worker                 symbolTable.getGlInVariableWithArraySize()->getType().getOutermostArraySize());
3988*8975f5c5SAndroid Build Coastguard Worker         }
3989*8975f5c5SAndroid Build Coastguard Worker         mDeferredArrayTypesToSize.clear();
3990*8975f5c5SAndroid Build Coastguard Worker     }
3991*8975f5c5SAndroid Build Coastguard Worker 
3992*8975f5c5SAndroid Build Coastguard Worker     // Set mGeometryInvocations if exists
3993*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.invocations > 0)
3994*8975f5c5SAndroid Build Coastguard Worker     {
3995*8975f5c5SAndroid Build Coastguard Worker         if (mGeometryShaderInvocations == 0)
3996*8975f5c5SAndroid Build Coastguard Worker         {
3997*8975f5c5SAndroid Build Coastguard Worker             mGeometryShaderInvocations = layoutQualifier.invocations;
3998*8975f5c5SAndroid Build Coastguard Worker         }
3999*8975f5c5SAndroid Build Coastguard Worker         else if (mGeometryShaderInvocations != layoutQualifier.invocations)
4000*8975f5c5SAndroid Build Coastguard Worker         {
4001*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "invocations contradicts to the earlier declaration",
4002*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4003*8975f5c5SAndroid Build Coastguard Worker             return false;
4004*8975f5c5SAndroid Build Coastguard Worker         }
4005*8975f5c5SAndroid Build Coastguard Worker     }
4006*8975f5c5SAndroid Build Coastguard Worker 
4007*8975f5c5SAndroid Build Coastguard Worker     return true;
4008*8975f5c5SAndroid Build Coastguard Worker }
4009*8975f5c5SAndroid Build Coastguard Worker 
parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier & typeQualifier)4010*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::parseGeometryShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier)
4011*8975f5c5SAndroid Build Coastguard Worker {
4012*8975f5c5SAndroid Build Coastguard Worker     ASSERT(typeQualifier.qualifier == EvqGeometryOut);
4013*8975f5c5SAndroid Build Coastguard Worker 
4014*8975f5c5SAndroid Build Coastguard Worker     const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
4015*8975f5c5SAndroid Build Coastguard Worker 
4016*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.invocations > 0)
4017*8975f5c5SAndroid Build Coastguard Worker     {
4018*8975f5c5SAndroid Build Coastguard Worker         error(typeQualifier.line,
4019*8975f5c5SAndroid Build Coastguard Worker               "invocations can only be declared in 'in' layout in a geometry shader", "layout");
4020*8975f5c5SAndroid Build Coastguard Worker         return false;
4021*8975f5c5SAndroid Build Coastguard Worker     }
4022*8975f5c5SAndroid Build Coastguard Worker 
4023*8975f5c5SAndroid Build Coastguard Worker     // Set mGeometryOutputPrimitiveType if exists
4024*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.primitiveType != EptUndefined)
4025*8975f5c5SAndroid Build Coastguard Worker     {
4026*8975f5c5SAndroid Build Coastguard Worker         if (!checkPrimitiveTypeMatchesTypeQualifier(typeQualifier))
4027*8975f5c5SAndroid Build Coastguard Worker         {
4028*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "invalid primitive type for 'out' layout", "layout");
4029*8975f5c5SAndroid Build Coastguard Worker             return false;
4030*8975f5c5SAndroid Build Coastguard Worker         }
4031*8975f5c5SAndroid Build Coastguard Worker 
4032*8975f5c5SAndroid Build Coastguard Worker         if (mGeometryShaderOutputPrimitiveType == EptUndefined)
4033*8975f5c5SAndroid Build Coastguard Worker         {
4034*8975f5c5SAndroid Build Coastguard Worker             mGeometryShaderOutputPrimitiveType = layoutQualifier.primitiveType;
4035*8975f5c5SAndroid Build Coastguard Worker         }
4036*8975f5c5SAndroid Build Coastguard Worker         else if (mGeometryShaderOutputPrimitiveType != layoutQualifier.primitiveType)
4037*8975f5c5SAndroid Build Coastguard Worker         {
4038*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line,
4039*8975f5c5SAndroid Build Coastguard Worker                   "primitive doesn't match earlier output primitive declaration", "layout");
4040*8975f5c5SAndroid Build Coastguard Worker             return false;
4041*8975f5c5SAndroid Build Coastguard Worker         }
4042*8975f5c5SAndroid Build Coastguard Worker     }
4043*8975f5c5SAndroid Build Coastguard Worker 
4044*8975f5c5SAndroid Build Coastguard Worker     // Set mGeometryMaxVertices if exists
4045*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.maxVertices > -1)
4046*8975f5c5SAndroid Build Coastguard Worker     {
4047*8975f5c5SAndroid Build Coastguard Worker         if (mGeometryShaderMaxVertices == -1)
4048*8975f5c5SAndroid Build Coastguard Worker         {
4049*8975f5c5SAndroid Build Coastguard Worker             mGeometryShaderMaxVertices = layoutQualifier.maxVertices;
4050*8975f5c5SAndroid Build Coastguard Worker         }
4051*8975f5c5SAndroid Build Coastguard Worker         else if (mGeometryShaderMaxVertices != layoutQualifier.maxVertices)
4052*8975f5c5SAndroid Build Coastguard Worker         {
4053*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "max_vertices contradicts to the earlier declaration",
4054*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4055*8975f5c5SAndroid Build Coastguard Worker             return false;
4056*8975f5c5SAndroid Build Coastguard Worker         }
4057*8975f5c5SAndroid Build Coastguard Worker     }
4058*8975f5c5SAndroid Build Coastguard Worker 
4059*8975f5c5SAndroid Build Coastguard Worker     return true;
4060*8975f5c5SAndroid Build Coastguard Worker }
4061*8975f5c5SAndroid Build Coastguard Worker 
parseTessControlShaderOutputLayoutQualifier(const TTypeQualifier & typeQualifier)4062*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::parseTessControlShaderOutputLayoutQualifier(const TTypeQualifier &typeQualifier)
4063*8975f5c5SAndroid Build Coastguard Worker {
4064*8975f5c5SAndroid Build Coastguard Worker     ASSERT(typeQualifier.qualifier == EvqTessControlOut);
4065*8975f5c5SAndroid Build Coastguard Worker 
4066*8975f5c5SAndroid Build Coastguard Worker     const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
4067*8975f5c5SAndroid Build Coastguard Worker 
4068*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.vertices == 0)
4069*8975f5c5SAndroid Build Coastguard Worker     {
4070*8975f5c5SAndroid Build Coastguard Worker         error(typeQualifier.line, "No vertices specified", "layout");
4071*8975f5c5SAndroid Build Coastguard Worker         return false;
4072*8975f5c5SAndroid Build Coastguard Worker     }
4073*8975f5c5SAndroid Build Coastguard Worker 
4074*8975f5c5SAndroid Build Coastguard Worker     // Set mTessControlShaderOutputVertices if exists
4075*8975f5c5SAndroid Build Coastguard Worker     if (mTessControlShaderOutputVertices == 0)
4076*8975f5c5SAndroid Build Coastguard Worker     {
4077*8975f5c5SAndroid Build Coastguard Worker         mTessControlShaderOutputVertices = layoutQualifier.vertices;
4078*8975f5c5SAndroid Build Coastguard Worker 
4079*8975f5c5SAndroid Build Coastguard Worker         // Size any implicitly sized arrays that have already been declared.
4080*8975f5c5SAndroid Build Coastguard Worker         for (TType *type : mDeferredArrayTypesToSize)
4081*8975f5c5SAndroid Build Coastguard Worker         {
4082*8975f5c5SAndroid Build Coastguard Worker             type->sizeOutermostUnsizedArray(mTessControlShaderOutputVertices);
4083*8975f5c5SAndroid Build Coastguard Worker         }
4084*8975f5c5SAndroid Build Coastguard Worker         mDeferredArrayTypesToSize.clear();
4085*8975f5c5SAndroid Build Coastguard Worker     }
4086*8975f5c5SAndroid Build Coastguard Worker     else
4087*8975f5c5SAndroid Build Coastguard Worker     {
4088*8975f5c5SAndroid Build Coastguard Worker         error(typeQualifier.line, "Duplicated vertices specified", "layout");
4089*8975f5c5SAndroid Build Coastguard Worker     }
4090*8975f5c5SAndroid Build Coastguard Worker     return true;
4091*8975f5c5SAndroid Build Coastguard Worker }
4092*8975f5c5SAndroid Build Coastguard Worker 
parseTessEvaluationShaderInputLayoutQualifier(const TTypeQualifier & typeQualifier)4093*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::parseTessEvaluationShaderInputLayoutQualifier(
4094*8975f5c5SAndroid Build Coastguard Worker     const TTypeQualifier &typeQualifier)
4095*8975f5c5SAndroid Build Coastguard Worker {
4096*8975f5c5SAndroid Build Coastguard Worker     ASSERT(typeQualifier.qualifier == EvqTessEvaluationIn);
4097*8975f5c5SAndroid Build Coastguard Worker 
4098*8975f5c5SAndroid Build Coastguard Worker     const TLayoutQualifier &layoutQualifier = typeQualifier.layoutQualifier;
4099*8975f5c5SAndroid Build Coastguard Worker 
4100*8975f5c5SAndroid Build Coastguard Worker     // Set mTessEvaluationShaderInputPrimitiveType if exists
4101*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.tesPrimitiveType != EtetUndefined)
4102*8975f5c5SAndroid Build Coastguard Worker     {
4103*8975f5c5SAndroid Build Coastguard Worker         if (mTessEvaluationShaderInputPrimitiveType == EtetUndefined)
4104*8975f5c5SAndroid Build Coastguard Worker         {
4105*8975f5c5SAndroid Build Coastguard Worker             mTessEvaluationShaderInputPrimitiveType = layoutQualifier.tesPrimitiveType;
4106*8975f5c5SAndroid Build Coastguard Worker         }
4107*8975f5c5SAndroid Build Coastguard Worker         else
4108*8975f5c5SAndroid Build Coastguard Worker         {
4109*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "Duplicated primitive type declaration", "layout");
4110*8975f5c5SAndroid Build Coastguard Worker         }
4111*8975f5c5SAndroid Build Coastguard Worker     }
4112*8975f5c5SAndroid Build Coastguard Worker     // Set mTessEvaluationShaderVertexSpacingType if exists
4113*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.tesVertexSpacingType != EtetUndefined)
4114*8975f5c5SAndroid Build Coastguard Worker     {
4115*8975f5c5SAndroid Build Coastguard Worker         if (mTessEvaluationShaderInputVertexSpacingType == EtetUndefined)
4116*8975f5c5SAndroid Build Coastguard Worker         {
4117*8975f5c5SAndroid Build Coastguard Worker             mTessEvaluationShaderInputVertexSpacingType = layoutQualifier.tesVertexSpacingType;
4118*8975f5c5SAndroid Build Coastguard Worker         }
4119*8975f5c5SAndroid Build Coastguard Worker         else
4120*8975f5c5SAndroid Build Coastguard Worker         {
4121*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "Duplicated vertex spacing declaration", "layout");
4122*8975f5c5SAndroid Build Coastguard Worker         }
4123*8975f5c5SAndroid Build Coastguard Worker     }
4124*8975f5c5SAndroid Build Coastguard Worker     // Set mTessEvaluationShaderInputOrderingType if exists
4125*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.tesOrderingType != EtetUndefined)
4126*8975f5c5SAndroid Build Coastguard Worker     {
4127*8975f5c5SAndroid Build Coastguard Worker         if (mTessEvaluationShaderInputOrderingType == EtetUndefined)
4128*8975f5c5SAndroid Build Coastguard Worker         {
4129*8975f5c5SAndroid Build Coastguard Worker             mTessEvaluationShaderInputOrderingType = layoutQualifier.tesOrderingType;
4130*8975f5c5SAndroid Build Coastguard Worker         }
4131*8975f5c5SAndroid Build Coastguard Worker         else
4132*8975f5c5SAndroid Build Coastguard Worker         {
4133*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "Duplicated ordering declaration", "layout");
4134*8975f5c5SAndroid Build Coastguard Worker         }
4135*8975f5c5SAndroid Build Coastguard Worker     }
4136*8975f5c5SAndroid Build Coastguard Worker     // Set mTessEvaluationShaderInputPointType if exists
4137*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.tesPointType != EtetUndefined)
4138*8975f5c5SAndroid Build Coastguard Worker     {
4139*8975f5c5SAndroid Build Coastguard Worker         if (mTessEvaluationShaderInputPointType == EtetUndefined)
4140*8975f5c5SAndroid Build Coastguard Worker         {
4141*8975f5c5SAndroid Build Coastguard Worker             mTessEvaluationShaderInputPointType = layoutQualifier.tesPointType;
4142*8975f5c5SAndroid Build Coastguard Worker         }
4143*8975f5c5SAndroid Build Coastguard Worker         else
4144*8975f5c5SAndroid Build Coastguard Worker         {
4145*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "Duplicated point type declaration", "layout");
4146*8975f5c5SAndroid Build Coastguard Worker         }
4147*8975f5c5SAndroid Build Coastguard Worker     }
4148*8975f5c5SAndroid Build Coastguard Worker 
4149*8975f5c5SAndroid Build Coastguard Worker     return true;
4150*8975f5c5SAndroid Build Coastguard Worker }
4151*8975f5c5SAndroid Build Coastguard Worker 
parseGlobalLayoutQualifier(const TTypeQualifierBuilder & typeQualifierBuilder)4152*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder)
4153*8975f5c5SAndroid Build Coastguard Worker {
4154*8975f5c5SAndroid Build Coastguard Worker     TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
4155*8975f5c5SAndroid Build Coastguard Worker     const TLayoutQualifier layoutQualifier = typeQualifier.layoutQualifier;
4156*8975f5c5SAndroid Build Coastguard Worker 
4157*8975f5c5SAndroid Build Coastguard Worker     checkInvariantVariableQualifier(typeQualifier.invariant, typeQualifier.qualifier,
4158*8975f5c5SAndroid Build Coastguard Worker                                     typeQualifier.line);
4159*8975f5c5SAndroid Build Coastguard Worker 
4160*8975f5c5SAndroid Build Coastguard Worker     // It should never be the case, but some strange parser errors can send us here.
4161*8975f5c5SAndroid Build Coastguard Worker     if (layoutQualifier.isEmpty())
4162*8975f5c5SAndroid Build Coastguard Worker     {
4163*8975f5c5SAndroid Build Coastguard Worker         error(typeQualifier.line, "Error during layout qualifier parsing.", "?");
4164*8975f5c5SAndroid Build Coastguard Worker         return;
4165*8975f5c5SAndroid Build Coastguard Worker     }
4166*8975f5c5SAndroid Build Coastguard Worker 
4167*8975f5c5SAndroid Build Coastguard Worker     if (!layoutQualifier.isCombinationValid())
4168*8975f5c5SAndroid Build Coastguard Worker     {
4169*8975f5c5SAndroid Build Coastguard Worker         error(typeQualifier.line, "invalid layout qualifier combination", "layout");
4170*8975f5c5SAndroid Build Coastguard Worker         return;
4171*8975f5c5SAndroid Build Coastguard Worker     }
4172*8975f5c5SAndroid Build Coastguard Worker 
4173*8975f5c5SAndroid Build Coastguard Worker     checkIndexIsNotSpecified(typeQualifier.line, layoutQualifier.index);
4174*8975f5c5SAndroid Build Coastguard Worker 
4175*8975f5c5SAndroid Build Coastguard Worker     checkBindingIsNotSpecified(typeQualifier.line, layoutQualifier.binding);
4176*8975f5c5SAndroid Build Coastguard Worker 
4177*8975f5c5SAndroid Build Coastguard Worker     checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
4178*8975f5c5SAndroid Build Coastguard Worker 
4179*8975f5c5SAndroid Build Coastguard Worker     checkInternalFormatIsNotSpecified(typeQualifier.line, layoutQualifier.imageInternalFormat);
4180*8975f5c5SAndroid Build Coastguard Worker 
4181*8975f5c5SAndroid Build Coastguard Worker     checkDepthIsNotSpecified(typeQualifier.line, layoutQualifier.depth);
4182*8975f5c5SAndroid Build Coastguard Worker 
4183*8975f5c5SAndroid Build Coastguard Worker     checkYuvIsNotSpecified(typeQualifier.line, layoutQualifier.yuv);
4184*8975f5c5SAndroid Build Coastguard Worker 
4185*8975f5c5SAndroid Build Coastguard Worker     checkOffsetIsNotSpecified(typeQualifier.line, layoutQualifier.offset);
4186*8975f5c5SAndroid Build Coastguard Worker 
4187*8975f5c5SAndroid Build Coastguard Worker     checkStd430IsForShaderStorageBlock(typeQualifier.line, layoutQualifier.blockStorage,
4188*8975f5c5SAndroid Build Coastguard Worker                                        typeQualifier.qualifier);
4189*8975f5c5SAndroid Build Coastguard Worker 
4190*8975f5c5SAndroid Build Coastguard Worker     checkAdvancedBlendEquationsNotSpecified(
4191*8975f5c5SAndroid Build Coastguard Worker         typeQualifier.line, layoutQualifier.advancedBlendEquations, typeQualifier.qualifier);
4192*8975f5c5SAndroid Build Coastguard Worker 
4193*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.qualifier != EvqFragmentIn)
4194*8975f5c5SAndroid Build Coastguard Worker     {
4195*8975f5c5SAndroid Build Coastguard Worker         checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line,
4196*8975f5c5SAndroid Build Coastguard Worker                                               layoutQualifier.earlyFragmentTests);
4197*8975f5c5SAndroid Build Coastguard Worker     }
4198*8975f5c5SAndroid Build Coastguard Worker 
4199*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.qualifier == EvqComputeIn)
4200*8975f5c5SAndroid Build Coastguard Worker     {
4201*8975f5c5SAndroid Build Coastguard Worker         if (mComputeShaderLocalSizeDeclared &&
4202*8975f5c5SAndroid Build Coastguard Worker             !layoutQualifier.isLocalSizeEqual(mComputeShaderLocalSize))
4203*8975f5c5SAndroid Build Coastguard Worker         {
4204*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "Work group size does not match the previous declaration",
4205*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4206*8975f5c5SAndroid Build Coastguard Worker             return;
4207*8975f5c5SAndroid Build Coastguard Worker         }
4208*8975f5c5SAndroid Build Coastguard Worker 
4209*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 310)
4210*8975f5c5SAndroid Build Coastguard Worker         {
4211*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
4212*8975f5c5SAndroid Build Coastguard Worker             return;
4213*8975f5c5SAndroid Build Coastguard Worker         }
4214*8975f5c5SAndroid Build Coastguard Worker 
4215*8975f5c5SAndroid Build Coastguard Worker         if (!layoutQualifier.localSize.isAnyValueSet())
4216*8975f5c5SAndroid Build Coastguard Worker         {
4217*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "No local work group size specified", "layout");
4218*8975f5c5SAndroid Build Coastguard Worker             return;
4219*8975f5c5SAndroid Build Coastguard Worker         }
4220*8975f5c5SAndroid Build Coastguard Worker 
4221*8975f5c5SAndroid Build Coastguard Worker         const TVariable *maxComputeWorkGroupSize = static_cast<const TVariable *>(
4222*8975f5c5SAndroid Build Coastguard Worker             symbolTable.findBuiltIn(ImmutableString("gl_MaxComputeWorkGroupSize"), mShaderVersion));
4223*8975f5c5SAndroid Build Coastguard Worker 
4224*8975f5c5SAndroid Build Coastguard Worker         const TConstantUnion *maxComputeWorkGroupSizeData =
4225*8975f5c5SAndroid Build Coastguard Worker             maxComputeWorkGroupSize->getConstPointer();
4226*8975f5c5SAndroid Build Coastguard Worker 
4227*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0u; i < layoutQualifier.localSize.size(); ++i)
4228*8975f5c5SAndroid Build Coastguard Worker         {
4229*8975f5c5SAndroid Build Coastguard Worker             if (layoutQualifier.localSize[i] != -1)
4230*8975f5c5SAndroid Build Coastguard Worker             {
4231*8975f5c5SAndroid Build Coastguard Worker                 mComputeShaderLocalSize[i]             = layoutQualifier.localSize[i];
4232*8975f5c5SAndroid Build Coastguard Worker                 const int maxComputeWorkGroupSizeValue = maxComputeWorkGroupSizeData[i].getIConst();
4233*8975f5c5SAndroid Build Coastguard Worker                 if (mComputeShaderLocalSize[i] < 1 ||
4234*8975f5c5SAndroid Build Coastguard Worker                     mComputeShaderLocalSize[i] > maxComputeWorkGroupSizeValue)
4235*8975f5c5SAndroid Build Coastguard Worker                 {
4236*8975f5c5SAndroid Build Coastguard Worker                     std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
4237*8975f5c5SAndroid Build Coastguard Worker                     reasonStream << "invalid value: Value must be at least 1 and no greater than "
4238*8975f5c5SAndroid Build Coastguard Worker                                  << maxComputeWorkGroupSizeValue;
4239*8975f5c5SAndroid Build Coastguard Worker                     const std::string &reason = reasonStream.str();
4240*8975f5c5SAndroid Build Coastguard Worker 
4241*8975f5c5SAndroid Build Coastguard Worker                     error(typeQualifier.line, reason.c_str(), getWorkGroupSizeString(i));
4242*8975f5c5SAndroid Build Coastguard Worker                     return;
4243*8975f5c5SAndroid Build Coastguard Worker                 }
4244*8975f5c5SAndroid Build Coastguard Worker             }
4245*8975f5c5SAndroid Build Coastguard Worker         }
4246*8975f5c5SAndroid Build Coastguard Worker 
4247*8975f5c5SAndroid Build Coastguard Worker         mComputeShaderLocalSizeDeclared = true;
4248*8975f5c5SAndroid Build Coastguard Worker     }
4249*8975f5c5SAndroid Build Coastguard Worker     else if (typeQualifier.qualifier == EvqGeometryIn)
4250*8975f5c5SAndroid Build Coastguard Worker     {
4251*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 310)
4252*8975f5c5SAndroid Build Coastguard Worker         {
4253*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 only", "layout");
4254*8975f5c5SAndroid Build Coastguard Worker             return;
4255*8975f5c5SAndroid Build Coastguard Worker         }
4256*8975f5c5SAndroid Build Coastguard Worker 
4257*8975f5c5SAndroid Build Coastguard Worker         if (!parseGeometryShaderInputLayoutQualifier(typeQualifier))
4258*8975f5c5SAndroid Build Coastguard Worker         {
4259*8975f5c5SAndroid Build Coastguard Worker             return;
4260*8975f5c5SAndroid Build Coastguard Worker         }
4261*8975f5c5SAndroid Build Coastguard Worker     }
4262*8975f5c5SAndroid Build Coastguard Worker     else if (typeQualifier.qualifier == EvqGeometryOut)
4263*8975f5c5SAndroid Build Coastguard Worker     {
4264*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 310)
4265*8975f5c5SAndroid Build Coastguard Worker         {
4266*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 only",
4267*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4268*8975f5c5SAndroid Build Coastguard Worker             return;
4269*8975f5c5SAndroid Build Coastguard Worker         }
4270*8975f5c5SAndroid Build Coastguard Worker 
4271*8975f5c5SAndroid Build Coastguard Worker         if (!parseGeometryShaderOutputLayoutQualifier(typeQualifier))
4272*8975f5c5SAndroid Build Coastguard Worker         {
4273*8975f5c5SAndroid Build Coastguard Worker             return;
4274*8975f5c5SAndroid Build Coastguard Worker         }
4275*8975f5c5SAndroid Build Coastguard Worker     }
4276*8975f5c5SAndroid Build Coastguard Worker     else if (anyMultiviewExtensionAvailable() && typeQualifier.qualifier == EvqVertexIn)
4277*8975f5c5SAndroid Build Coastguard Worker     {
4278*8975f5c5SAndroid Build Coastguard Worker         // This error is only specified in WebGL, but tightens unspecified behavior in the native
4279*8975f5c5SAndroid Build Coastguard Worker         // specification.
4280*8975f5c5SAndroid Build Coastguard Worker         if (mNumViews != -1 && layoutQualifier.numViews != mNumViews)
4281*8975f5c5SAndroid Build Coastguard Worker         {
4282*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "Number of views does not match the previous declaration",
4283*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4284*8975f5c5SAndroid Build Coastguard Worker             return;
4285*8975f5c5SAndroid Build Coastguard Worker         }
4286*8975f5c5SAndroid Build Coastguard Worker 
4287*8975f5c5SAndroid Build Coastguard Worker         if (layoutQualifier.numViews == -1)
4288*8975f5c5SAndroid Build Coastguard Worker         {
4289*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "No num_views specified", "layout");
4290*8975f5c5SAndroid Build Coastguard Worker             return;
4291*8975f5c5SAndroid Build Coastguard Worker         }
4292*8975f5c5SAndroid Build Coastguard Worker 
4293*8975f5c5SAndroid Build Coastguard Worker         if (layoutQualifier.numViews > mMaxNumViews)
4294*8975f5c5SAndroid Build Coastguard Worker         {
4295*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "num_views greater than the value of GL_MAX_VIEWS_OVR",
4296*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4297*8975f5c5SAndroid Build Coastguard Worker             return;
4298*8975f5c5SAndroid Build Coastguard Worker         }
4299*8975f5c5SAndroid Build Coastguard Worker 
4300*8975f5c5SAndroid Build Coastguard Worker         mNumViews = layoutQualifier.numViews;
4301*8975f5c5SAndroid Build Coastguard Worker     }
4302*8975f5c5SAndroid Build Coastguard Worker     else if (typeQualifier.qualifier == EvqFragmentIn)
4303*8975f5c5SAndroid Build Coastguard Worker     {
4304*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 310)
4305*8975f5c5SAndroid Build Coastguard Worker         {
4306*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line,
4307*8975f5c5SAndroid Build Coastguard Worker                   "in type qualifier without variable declaration supported in GLSL ES 3.10 and "
4308*8975f5c5SAndroid Build Coastguard Worker                   "after",
4309*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4310*8975f5c5SAndroid Build Coastguard Worker             return;
4311*8975f5c5SAndroid Build Coastguard Worker         }
4312*8975f5c5SAndroid Build Coastguard Worker 
4313*8975f5c5SAndroid Build Coastguard Worker         if (!layoutQualifier.earlyFragmentTests)
4314*8975f5c5SAndroid Build Coastguard Worker         {
4315*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line,
4316*8975f5c5SAndroid Build Coastguard Worker                   "only early_fragment_tests is allowed as layout qualifier when not declaring a "
4317*8975f5c5SAndroid Build Coastguard Worker                   "variable",
4318*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4319*8975f5c5SAndroid Build Coastguard Worker             return;
4320*8975f5c5SAndroid Build Coastguard Worker         }
4321*8975f5c5SAndroid Build Coastguard Worker 
4322*8975f5c5SAndroid Build Coastguard Worker         mEarlyFragmentTestsSpecified = true;
4323*8975f5c5SAndroid Build Coastguard Worker     }
4324*8975f5c5SAndroid Build Coastguard Worker     else if (typeQualifier.qualifier == EvqFragmentOut)
4325*8975f5c5SAndroid Build Coastguard Worker     {
4326*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 320 && !isExtensionEnabled(TExtension::KHR_blend_equation_advanced))
4327*8975f5c5SAndroid Build Coastguard Worker         {
4328*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line,
4329*8975f5c5SAndroid Build Coastguard Worker                   "out type qualifier without variable declaration is supported in GLSL ES 3.20,"
4330*8975f5c5SAndroid Build Coastguard Worker                   " or if GL_KHR_blend_equation_advanced is enabled",
4331*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4332*8975f5c5SAndroid Build Coastguard Worker             return;
4333*8975f5c5SAndroid Build Coastguard Worker         }
4334*8975f5c5SAndroid Build Coastguard Worker 
4335*8975f5c5SAndroid Build Coastguard Worker         if (!layoutQualifier.advancedBlendEquations.any())
4336*8975f5c5SAndroid Build Coastguard Worker         {
4337*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line,
4338*8975f5c5SAndroid Build Coastguard Worker                   "only blend equations are allowed as layout qualifier when not declaring a "
4339*8975f5c5SAndroid Build Coastguard Worker                   "variable",
4340*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4341*8975f5c5SAndroid Build Coastguard Worker             return;
4342*8975f5c5SAndroid Build Coastguard Worker         }
4343*8975f5c5SAndroid Build Coastguard Worker 
4344*8975f5c5SAndroid Build Coastguard Worker         errorIfPLSDeclared(typeQualifier.line, PLSIllegalOperations::EnableAdvancedBlendEquation);
4345*8975f5c5SAndroid Build Coastguard Worker         mAdvancedBlendEquations |= layoutQualifier.advancedBlendEquations;
4346*8975f5c5SAndroid Build Coastguard Worker     }
4347*8975f5c5SAndroid Build Coastguard Worker     else if (typeQualifier.qualifier == EvqTessControlOut)
4348*8975f5c5SAndroid Build Coastguard Worker     {
4349*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 310)
4350*8975f5c5SAndroid Build Coastguard Worker         {
4351*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "out type qualifier supported in GLSL ES 3.10 and after",
4352*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4353*8975f5c5SAndroid Build Coastguard Worker             return;
4354*8975f5c5SAndroid Build Coastguard Worker         }
4355*8975f5c5SAndroid Build Coastguard Worker 
4356*8975f5c5SAndroid Build Coastguard Worker         if (!parseTessControlShaderOutputLayoutQualifier(typeQualifier))
4357*8975f5c5SAndroid Build Coastguard Worker         {
4358*8975f5c5SAndroid Build Coastguard Worker             return;
4359*8975f5c5SAndroid Build Coastguard Worker         }
4360*8975f5c5SAndroid Build Coastguard Worker     }
4361*8975f5c5SAndroid Build Coastguard Worker     else if (typeQualifier.qualifier == EvqTessEvaluationIn)
4362*8975f5c5SAndroid Build Coastguard Worker     {
4363*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 310)
4364*8975f5c5SAndroid Build Coastguard Worker         {
4365*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "in type qualifier supported in GLSL ES 3.10 and after",
4366*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4367*8975f5c5SAndroid Build Coastguard Worker             return;
4368*8975f5c5SAndroid Build Coastguard Worker         }
4369*8975f5c5SAndroid Build Coastguard Worker 
4370*8975f5c5SAndroid Build Coastguard Worker         if (!parseTessEvaluationShaderInputLayoutQualifier(typeQualifier))
4371*8975f5c5SAndroid Build Coastguard Worker         {
4372*8975f5c5SAndroid Build Coastguard Worker             return;
4373*8975f5c5SAndroid Build Coastguard Worker         }
4374*8975f5c5SAndroid Build Coastguard Worker     }
4375*8975f5c5SAndroid Build Coastguard Worker     else
4376*8975f5c5SAndroid Build Coastguard Worker     {
4377*8975f5c5SAndroid Build Coastguard Worker         if (!checkWorkGroupSizeIsNotSpecified(typeQualifier.line, layoutQualifier))
4378*8975f5c5SAndroid Build Coastguard Worker         {
4379*8975f5c5SAndroid Build Coastguard Worker             return;
4380*8975f5c5SAndroid Build Coastguard Worker         }
4381*8975f5c5SAndroid Build Coastguard Worker 
4382*8975f5c5SAndroid Build Coastguard Worker         if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
4383*8975f5c5SAndroid Build Coastguard Worker         {
4384*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "invalid qualifier: global layout can only be set for blocks",
4385*8975f5c5SAndroid Build Coastguard Worker                   getQualifierString(typeQualifier.qualifier));
4386*8975f5c5SAndroid Build Coastguard Worker             return;
4387*8975f5c5SAndroid Build Coastguard Worker         }
4388*8975f5c5SAndroid Build Coastguard Worker 
4389*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 300)
4390*8975f5c5SAndroid Build Coastguard Worker         {
4391*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line, "layout qualifiers supported in GLSL ES 3.00 and after",
4392*8975f5c5SAndroid Build Coastguard Worker                   "layout");
4393*8975f5c5SAndroid Build Coastguard Worker             return;
4394*8975f5c5SAndroid Build Coastguard Worker         }
4395*8975f5c5SAndroid Build Coastguard Worker 
4396*8975f5c5SAndroid Build Coastguard Worker         checkLocationIsNotSpecified(typeQualifier.line, layoutQualifier);
4397*8975f5c5SAndroid Build Coastguard Worker 
4398*8975f5c5SAndroid Build Coastguard Worker         if (layoutQualifier.matrixPacking != EmpUnspecified)
4399*8975f5c5SAndroid Build Coastguard Worker         {
4400*8975f5c5SAndroid Build Coastguard Worker             if (typeQualifier.qualifier == EvqUniform)
4401*8975f5c5SAndroid Build Coastguard Worker             {
4402*8975f5c5SAndroid Build Coastguard Worker                 mDefaultUniformMatrixPacking = layoutQualifier.matrixPacking;
4403*8975f5c5SAndroid Build Coastguard Worker             }
4404*8975f5c5SAndroid Build Coastguard Worker             else if (typeQualifier.qualifier == EvqBuffer)
4405*8975f5c5SAndroid Build Coastguard Worker             {
4406*8975f5c5SAndroid Build Coastguard Worker                 mDefaultBufferMatrixPacking = layoutQualifier.matrixPacking;
4407*8975f5c5SAndroid Build Coastguard Worker             }
4408*8975f5c5SAndroid Build Coastguard Worker         }
4409*8975f5c5SAndroid Build Coastguard Worker 
4410*8975f5c5SAndroid Build Coastguard Worker         if (layoutQualifier.blockStorage != EbsUnspecified)
4411*8975f5c5SAndroid Build Coastguard Worker         {
4412*8975f5c5SAndroid Build Coastguard Worker             if (typeQualifier.qualifier == EvqUniform)
4413*8975f5c5SAndroid Build Coastguard Worker             {
4414*8975f5c5SAndroid Build Coastguard Worker                 mDefaultUniformBlockStorage = layoutQualifier.blockStorage;
4415*8975f5c5SAndroid Build Coastguard Worker             }
4416*8975f5c5SAndroid Build Coastguard Worker             else if (typeQualifier.qualifier == EvqBuffer)
4417*8975f5c5SAndroid Build Coastguard Worker             {
4418*8975f5c5SAndroid Build Coastguard Worker                 mDefaultBufferBlockStorage = layoutQualifier.blockStorage;
4419*8975f5c5SAndroid Build Coastguard Worker             }
4420*8975f5c5SAndroid Build Coastguard Worker         }
4421*8975f5c5SAndroid Build Coastguard Worker     }
4422*8975f5c5SAndroid Build Coastguard Worker }
4423*8975f5c5SAndroid Build Coastguard Worker 
createPrototypeNodeFromFunction(const TFunction & function,const TSourceLoc & location,bool insertParametersToSymbolTable)4424*8975f5c5SAndroid Build Coastguard Worker TIntermFunctionPrototype *TParseContext::createPrototypeNodeFromFunction(
4425*8975f5c5SAndroid Build Coastguard Worker     const TFunction &function,
4426*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &location,
4427*8975f5c5SAndroid Build Coastguard Worker     bool insertParametersToSymbolTable)
4428*8975f5c5SAndroid Build Coastguard Worker {
4429*8975f5c5SAndroid Build Coastguard Worker     checkIsNotReserved(location, function.name());
4430*8975f5c5SAndroid Build Coastguard Worker 
4431*8975f5c5SAndroid Build Coastguard Worker     TIntermFunctionPrototype *prototype = new TIntermFunctionPrototype(&function);
4432*8975f5c5SAndroid Build Coastguard Worker     prototype->setLine(location);
4433*8975f5c5SAndroid Build Coastguard Worker 
4434*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < function.getParamCount(); i++)
4435*8975f5c5SAndroid Build Coastguard Worker     {
4436*8975f5c5SAndroid Build Coastguard Worker         const TVariable *param = function.getParam(i);
4437*8975f5c5SAndroid Build Coastguard Worker 
4438*8975f5c5SAndroid Build Coastguard Worker         // If the parameter has no name, it's not an error, just don't add it to symbol table (could
4439*8975f5c5SAndroid Build Coastguard Worker         // be used for unused args).
4440*8975f5c5SAndroid Build Coastguard Worker         if (param->symbolType() != SymbolType::Empty)
4441*8975f5c5SAndroid Build Coastguard Worker         {
4442*8975f5c5SAndroid Build Coastguard Worker             if (insertParametersToSymbolTable)
4443*8975f5c5SAndroid Build Coastguard Worker             {
4444*8975f5c5SAndroid Build Coastguard Worker                 if (!symbolTable.declare(const_cast<TVariable *>(param)))
4445*8975f5c5SAndroid Build Coastguard Worker                 {
4446*8975f5c5SAndroid Build Coastguard Worker                     error(location, "redefinition", param->name());
4447*8975f5c5SAndroid Build Coastguard Worker                 }
4448*8975f5c5SAndroid Build Coastguard Worker             }
4449*8975f5c5SAndroid Build Coastguard Worker             // Unsized type of a named parameter should have already been checked and sanitized.
4450*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!param->getType().isUnsizedArray());
4451*8975f5c5SAndroid Build Coastguard Worker         }
4452*8975f5c5SAndroid Build Coastguard Worker     }
4453*8975f5c5SAndroid Build Coastguard Worker     return prototype;
4454*8975f5c5SAndroid Build Coastguard Worker }
4455*8975f5c5SAndroid Build Coastguard Worker 
addFunctionPrototypeDeclaration(const TFunction & parsedFunction,const TSourceLoc & location)4456*8975f5c5SAndroid Build Coastguard Worker TIntermFunctionPrototype *TParseContext::addFunctionPrototypeDeclaration(
4457*8975f5c5SAndroid Build Coastguard Worker     const TFunction &parsedFunction,
4458*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &location)
4459*8975f5c5SAndroid Build Coastguard Worker {
4460*8975f5c5SAndroid Build Coastguard Worker     // Note: function found from the symbol table could be the same as parsedFunction if this is the
4461*8975f5c5SAndroid Build Coastguard Worker     // first declaration. Either way the instance in the symbol table is used to track whether the
4462*8975f5c5SAndroid Build Coastguard Worker     // function is declared multiple times.
4463*8975f5c5SAndroid Build Coastguard Worker     bool hadPrototypeDeclaration = false;
4464*8975f5c5SAndroid Build Coastguard Worker     const TFunction *function    = symbolTable.markFunctionHasPrototypeDeclaration(
4465*8975f5c5SAndroid Build Coastguard Worker         parsedFunction.getMangledName(), &hadPrototypeDeclaration);
4466*8975f5c5SAndroid Build Coastguard Worker 
4467*8975f5c5SAndroid Build Coastguard Worker     if (hadPrototypeDeclaration && mShaderVersion == 100)
4468*8975f5c5SAndroid Build Coastguard Worker     {
4469*8975f5c5SAndroid Build Coastguard Worker         // ESSL 1.00.17 section 4.2.7.
4470*8975f5c5SAndroid Build Coastguard Worker         // Doesn't apply to ESSL 3.00.4: see section 4.2.3.
4471*8975f5c5SAndroid Build Coastguard Worker         error(location, "duplicate function prototype declarations are not allowed", "function");
4472*8975f5c5SAndroid Build Coastguard Worker     }
4473*8975f5c5SAndroid Build Coastguard Worker 
4474*8975f5c5SAndroid Build Coastguard Worker     TIntermFunctionPrototype *prototype =
4475*8975f5c5SAndroid Build Coastguard Worker         createPrototypeNodeFromFunction(*function, location, false);
4476*8975f5c5SAndroid Build Coastguard Worker 
4477*8975f5c5SAndroid Build Coastguard Worker     symbolTable.pop();
4478*8975f5c5SAndroid Build Coastguard Worker 
4479*8975f5c5SAndroid Build Coastguard Worker     if (!symbolTable.atGlobalLevel())
4480*8975f5c5SAndroid Build Coastguard Worker     {
4481*8975f5c5SAndroid Build Coastguard Worker         // ESSL 3.00.4 section 4.2.4.
4482*8975f5c5SAndroid Build Coastguard Worker         error(location, "local function prototype declarations are not allowed", "function");
4483*8975f5c5SAndroid Build Coastguard Worker     }
4484*8975f5c5SAndroid Build Coastguard Worker 
4485*8975f5c5SAndroid Build Coastguard Worker     return prototype;
4486*8975f5c5SAndroid Build Coastguard Worker }
4487*8975f5c5SAndroid Build Coastguard Worker 
addFunctionDefinition(TIntermFunctionPrototype * functionPrototype,TIntermBlock * functionBody,const TSourceLoc & location)4488*8975f5c5SAndroid Build Coastguard Worker TIntermFunctionDefinition *TParseContext::addFunctionDefinition(
4489*8975f5c5SAndroid Build Coastguard Worker     TIntermFunctionPrototype *functionPrototype,
4490*8975f5c5SAndroid Build Coastguard Worker     TIntermBlock *functionBody,
4491*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &location)
4492*8975f5c5SAndroid Build Coastguard Worker {
4493*8975f5c5SAndroid Build Coastguard Worker     // Undo push at end of parseFunctionDefinitionHeader() below for ESSL1.00 case
4494*8975f5c5SAndroid Build Coastguard Worker     if (mFunctionBodyNewScope)
4495*8975f5c5SAndroid Build Coastguard Worker     {
4496*8975f5c5SAndroid Build Coastguard Worker         mFunctionBodyNewScope = false;
4497*8975f5c5SAndroid Build Coastguard Worker         symbolTable.pop();
4498*8975f5c5SAndroid Build Coastguard Worker     }
4499*8975f5c5SAndroid Build Coastguard Worker 
4500*8975f5c5SAndroid Build Coastguard Worker     // Check that non-void functions have at least one return statement.
4501*8975f5c5SAndroid Build Coastguard Worker     if (mCurrentFunctionType->getBasicType() != EbtVoid && !mFunctionReturnsValue)
4502*8975f5c5SAndroid Build Coastguard Worker     {
4503*8975f5c5SAndroid Build Coastguard Worker         error(location,
4504*8975f5c5SAndroid Build Coastguard Worker               "function does not return a value:", functionPrototype->getFunction()->name());
4505*8975f5c5SAndroid Build Coastguard Worker     }
4506*8975f5c5SAndroid Build Coastguard Worker 
4507*8975f5c5SAndroid Build Coastguard Worker     if (functionBody == nullptr)
4508*8975f5c5SAndroid Build Coastguard Worker     {
4509*8975f5c5SAndroid Build Coastguard Worker         functionBody = new TIntermBlock();
4510*8975f5c5SAndroid Build Coastguard Worker         functionBody->setLine(location);
4511*8975f5c5SAndroid Build Coastguard Worker     }
4512*8975f5c5SAndroid Build Coastguard Worker     TIntermFunctionDefinition *functionNode =
4513*8975f5c5SAndroid Build Coastguard Worker         new TIntermFunctionDefinition(functionPrototype, functionBody);
4514*8975f5c5SAndroid Build Coastguard Worker     functionNode->setLine(location);
4515*8975f5c5SAndroid Build Coastguard Worker 
4516*8975f5c5SAndroid Build Coastguard Worker     symbolTable.pop();
4517*8975f5c5SAndroid Build Coastguard Worker     return functionNode;
4518*8975f5c5SAndroid Build Coastguard Worker }
4519*8975f5c5SAndroid Build Coastguard Worker 
parseFunctionDefinitionHeader(const TSourceLoc & location,const TFunction * function,TIntermFunctionPrototype ** prototypeOut)4520*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseFunctionDefinitionHeader(const TSourceLoc &location,
4521*8975f5c5SAndroid Build Coastguard Worker                                                   const TFunction *function,
4522*8975f5c5SAndroid Build Coastguard Worker                                                   TIntermFunctionPrototype **prototypeOut)
4523*8975f5c5SAndroid Build Coastguard Worker {
4524*8975f5c5SAndroid Build Coastguard Worker     ASSERT(function);
4525*8975f5c5SAndroid Build Coastguard Worker 
4526*8975f5c5SAndroid Build Coastguard Worker     bool wasDefined = false;
4527*8975f5c5SAndroid Build Coastguard Worker     function        = symbolTable.setFunctionParameterNamesFromDefinition(function, &wasDefined);
4528*8975f5c5SAndroid Build Coastguard Worker     if (wasDefined)
4529*8975f5c5SAndroid Build Coastguard Worker     {
4530*8975f5c5SAndroid Build Coastguard Worker         error(location, "function already has a body", function->name());
4531*8975f5c5SAndroid Build Coastguard Worker     }
4532*8975f5c5SAndroid Build Coastguard Worker 
4533*8975f5c5SAndroid Build Coastguard Worker     // Remember the return type for later checking for return statements.
4534*8975f5c5SAndroid Build Coastguard Worker     mCurrentFunctionType  = &(function->getReturnType());
4535*8975f5c5SAndroid Build Coastguard Worker     mFunctionReturnsValue = false;
4536*8975f5c5SAndroid Build Coastguard Worker 
4537*8975f5c5SAndroid Build Coastguard Worker     *prototypeOut = createPrototypeNodeFromFunction(*function, location, true);
4538*8975f5c5SAndroid Build Coastguard Worker     setLoopNestingLevel(0);
4539*8975f5c5SAndroid Build Coastguard Worker 
4540*8975f5c5SAndroid Build Coastguard Worker     // ESSL 1.00 spec allows for variable in function body to redefine parameter
4541*8975f5c5SAndroid Build Coastguard Worker     if (IsSpecWithFunctionBodyNewScope(mShaderSpec, mShaderVersion))
4542*8975f5c5SAndroid Build Coastguard Worker     {
4543*8975f5c5SAndroid Build Coastguard Worker         mFunctionBodyNewScope = true;
4544*8975f5c5SAndroid Build Coastguard Worker         symbolTable.push();
4545*8975f5c5SAndroid Build Coastguard Worker     }
4546*8975f5c5SAndroid Build Coastguard Worker }
4547*8975f5c5SAndroid Build Coastguard Worker 
parseFunctionDeclarator(const TSourceLoc & location,TFunction * function)4548*8975f5c5SAndroid Build Coastguard Worker TFunction *TParseContext::parseFunctionDeclarator(const TSourceLoc &location, TFunction *function)
4549*8975f5c5SAndroid Build Coastguard Worker {
4550*8975f5c5SAndroid Build Coastguard Worker     //
4551*8975f5c5SAndroid Build Coastguard Worker     // We don't know at this point whether this is a function definition or a prototype.
4552*8975f5c5SAndroid Build Coastguard Worker     // The definition production code will check for redefinitions.
4553*8975f5c5SAndroid Build Coastguard Worker     // In the case of ESSL 1.00 the prototype production code will also check for redeclarations.
4554*8975f5c5SAndroid Build Coastguard Worker     //
4555*8975f5c5SAndroid Build Coastguard Worker 
4556*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0u; i < function->getParamCount(); ++i)
4557*8975f5c5SAndroid Build Coastguard Worker     {
4558*8975f5c5SAndroid Build Coastguard Worker         const TVariable *param = function->getParam(i);
4559*8975f5c5SAndroid Build Coastguard Worker         const TType &paramType = param->getType();
4560*8975f5c5SAndroid Build Coastguard Worker 
4561*8975f5c5SAndroid Build Coastguard Worker         checkPrecisionSpecified(location, paramType.getPrecision(), paramType.getBasicType());
4562*8975f5c5SAndroid Build Coastguard Worker     }
4563*8975f5c5SAndroid Build Coastguard Worker 
4564*8975f5c5SAndroid Build Coastguard Worker     if (getShaderVersion() >= 300)
4565*8975f5c5SAndroid Build Coastguard Worker     {
4566*8975f5c5SAndroid Build Coastguard Worker         if (symbolTable.isUnmangledBuiltInName(function->name(), getShaderVersion(),
4567*8975f5c5SAndroid Build Coastguard Worker                                                extensionBehavior()))
4568*8975f5c5SAndroid Build Coastguard Worker         {
4569*8975f5c5SAndroid Build Coastguard Worker             // With ESSL 3.00 and above, names of built-in functions cannot be redeclared as
4570*8975f5c5SAndroid Build Coastguard Worker             // functions. Therefore overloading or redefining builtin functions is an error.
4571*8975f5c5SAndroid Build Coastguard Worker             error(location, "Name of a built-in function cannot be redeclared as function",
4572*8975f5c5SAndroid Build Coastguard Worker                   function->name());
4573*8975f5c5SAndroid Build Coastguard Worker         }
4574*8975f5c5SAndroid Build Coastguard Worker     }
4575*8975f5c5SAndroid Build Coastguard Worker     else
4576*8975f5c5SAndroid Build Coastguard Worker     {
4577*8975f5c5SAndroid Build Coastguard Worker         // ESSL 1.00.17 section 4.2.6: built-ins can be overloaded but not redefined. We assume that
4578*8975f5c5SAndroid Build Coastguard Worker         // this applies to redeclarations as well.
4579*8975f5c5SAndroid Build Coastguard Worker         const TSymbol *builtIn =
4580*8975f5c5SAndroid Build Coastguard Worker             symbolTable.findBuiltIn(function->getMangledName(), getShaderVersion());
4581*8975f5c5SAndroid Build Coastguard Worker         if (builtIn)
4582*8975f5c5SAndroid Build Coastguard Worker         {
4583*8975f5c5SAndroid Build Coastguard Worker             error(location, "built-in functions cannot be redefined", function->name());
4584*8975f5c5SAndroid Build Coastguard Worker         }
4585*8975f5c5SAndroid Build Coastguard Worker     }
4586*8975f5c5SAndroid Build Coastguard Worker 
4587*8975f5c5SAndroid Build Coastguard Worker     // Return types and parameter qualifiers must match in all redeclarations, so those are checked
4588*8975f5c5SAndroid Build Coastguard Worker     // here.
4589*8975f5c5SAndroid Build Coastguard Worker     const TFunction *prevDec =
4590*8975f5c5SAndroid Build Coastguard Worker         static_cast<const TFunction *>(symbolTable.findGlobal(function->getMangledName()));
4591*8975f5c5SAndroid Build Coastguard Worker     if (prevDec)
4592*8975f5c5SAndroid Build Coastguard Worker     {
4593*8975f5c5SAndroid Build Coastguard Worker         if (prevDec->getReturnType() != function->getReturnType())
4594*8975f5c5SAndroid Build Coastguard Worker         {
4595*8975f5c5SAndroid Build Coastguard Worker             error(location, "function must have the same return type in all of its declarations",
4596*8975f5c5SAndroid Build Coastguard Worker                   function->getReturnType().getBasicString());
4597*8975f5c5SAndroid Build Coastguard Worker         }
4598*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0; i < prevDec->getParamCount(); ++i)
4599*8975f5c5SAndroid Build Coastguard Worker         {
4600*8975f5c5SAndroid Build Coastguard Worker             if (prevDec->getParam(i)->getType().getQualifier() !=
4601*8975f5c5SAndroid Build Coastguard Worker                 function->getParam(i)->getType().getQualifier())
4602*8975f5c5SAndroid Build Coastguard Worker             {
4603*8975f5c5SAndroid Build Coastguard Worker                 error(location,
4604*8975f5c5SAndroid Build Coastguard Worker                       "function must have the same parameter qualifiers in all of its declarations",
4605*8975f5c5SAndroid Build Coastguard Worker                       function->getParam(i)->getType().getQualifierString());
4606*8975f5c5SAndroid Build Coastguard Worker             }
4607*8975f5c5SAndroid Build Coastguard Worker         }
4608*8975f5c5SAndroid Build Coastguard Worker     }
4609*8975f5c5SAndroid Build Coastguard Worker 
4610*8975f5c5SAndroid Build Coastguard Worker     // Check for previously declared variables using the same name.
4611*8975f5c5SAndroid Build Coastguard Worker     const TSymbol *prevSym   = symbolTable.find(function->name(), getShaderVersion());
4612*8975f5c5SAndroid Build Coastguard Worker     bool insertUnmangledName = true;
4613*8975f5c5SAndroid Build Coastguard Worker     if (prevSym)
4614*8975f5c5SAndroid Build Coastguard Worker     {
4615*8975f5c5SAndroid Build Coastguard Worker         if (!prevSym->isFunction())
4616*8975f5c5SAndroid Build Coastguard Worker         {
4617*8975f5c5SAndroid Build Coastguard Worker             error(location, "redefinition of a function", function->name());
4618*8975f5c5SAndroid Build Coastguard Worker         }
4619*8975f5c5SAndroid Build Coastguard Worker         insertUnmangledName = false;
4620*8975f5c5SAndroid Build Coastguard Worker     }
4621*8975f5c5SAndroid Build Coastguard Worker     // Parsing is at the inner scope level of the function's arguments and body statement at this
4622*8975f5c5SAndroid Build Coastguard Worker     // point, but declareUserDefinedFunction takes care of declaring the function at the global
4623*8975f5c5SAndroid Build Coastguard Worker     // scope.
4624*8975f5c5SAndroid Build Coastguard Worker     symbolTable.declareUserDefinedFunction(function, insertUnmangledName);
4625*8975f5c5SAndroid Build Coastguard Worker 
4626*8975f5c5SAndroid Build Coastguard Worker     // Raise error message if main function takes any parameters or return anything other than void
4627*8975f5c5SAndroid Build Coastguard Worker     if (function->isMain())
4628*8975f5c5SAndroid Build Coastguard Worker     {
4629*8975f5c5SAndroid Build Coastguard Worker         if (function->getParamCount() > 0)
4630*8975f5c5SAndroid Build Coastguard Worker         {
4631*8975f5c5SAndroid Build Coastguard Worker             error(location, "function cannot take any parameter(s)", "main");
4632*8975f5c5SAndroid Build Coastguard Worker         }
4633*8975f5c5SAndroid Build Coastguard Worker         if (function->getReturnType().getBasicType() != EbtVoid)
4634*8975f5c5SAndroid Build Coastguard Worker         {
4635*8975f5c5SAndroid Build Coastguard Worker             error(location, "main function cannot return a value",
4636*8975f5c5SAndroid Build Coastguard Worker                   function->getReturnType().getBasicString());
4637*8975f5c5SAndroid Build Coastguard Worker         }
4638*8975f5c5SAndroid Build Coastguard Worker     }
4639*8975f5c5SAndroid Build Coastguard Worker 
4640*8975f5c5SAndroid Build Coastguard Worker     mDeclaringMain = function->isMain();
4641*8975f5c5SAndroid Build Coastguard Worker 
4642*8975f5c5SAndroid Build Coastguard Worker     //
4643*8975f5c5SAndroid Build Coastguard Worker     // If this is a redeclaration, it could also be a definition, in which case, we want to use the
4644*8975f5c5SAndroid Build Coastguard Worker     // variable names from this one, and not the one that's
4645*8975f5c5SAndroid Build Coastguard Worker     // being redeclared.  So, pass back up this declaration, not the one in the symbol table.
4646*8975f5c5SAndroid Build Coastguard Worker     //
4647*8975f5c5SAndroid Build Coastguard Worker     return function;
4648*8975f5c5SAndroid Build Coastguard Worker }
4649*8975f5c5SAndroid Build Coastguard Worker 
parseFunctionHeader(const TPublicType & type,const ImmutableString & name,const TSourceLoc & location)4650*8975f5c5SAndroid Build Coastguard Worker TFunction *TParseContext::parseFunctionHeader(const TPublicType &type,
4651*8975f5c5SAndroid Build Coastguard Worker                                               const ImmutableString &name,
4652*8975f5c5SAndroid Build Coastguard Worker                                               const TSourceLoc &location)
4653*8975f5c5SAndroid Build Coastguard Worker {
4654*8975f5c5SAndroid Build Coastguard Worker     if (type.qualifier != EvqGlobal && type.qualifier != EvqTemporary)
4655*8975f5c5SAndroid Build Coastguard Worker     {
4656*8975f5c5SAndroid Build Coastguard Worker         error(location, "no qualifiers allowed for function return",
4657*8975f5c5SAndroid Build Coastguard Worker               getQualifierString(type.qualifier));
4658*8975f5c5SAndroid Build Coastguard Worker     }
4659*8975f5c5SAndroid Build Coastguard Worker     if (!type.layoutQualifier.isEmpty())
4660*8975f5c5SAndroid Build Coastguard Worker     {
4661*8975f5c5SAndroid Build Coastguard Worker         error(location, "no qualifiers allowed for function return", "layout");
4662*8975f5c5SAndroid Build Coastguard Worker     }
4663*8975f5c5SAndroid Build Coastguard Worker     // make sure an opaque type is not involved as well...
4664*8975f5c5SAndroid Build Coastguard Worker     std::string reason(getBasicString(type.getBasicType()));
4665*8975f5c5SAndroid Build Coastguard Worker     reason += "s can't be function return values";
4666*8975f5c5SAndroid Build Coastguard Worker     checkIsNotOpaqueType(location, type.typeSpecifierNonArray, reason.c_str());
4667*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion < 300)
4668*8975f5c5SAndroid Build Coastguard Worker     {
4669*8975f5c5SAndroid Build Coastguard Worker         // Array return values are forbidden, but there's also no valid syntax for declaring array
4670*8975f5c5SAndroid Build Coastguard Worker         // return values in ESSL 1.00.
4671*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!type.isArray() || mDiagnostics->numErrors() > 0);
4672*8975f5c5SAndroid Build Coastguard Worker 
4673*8975f5c5SAndroid Build Coastguard Worker         if (type.isStructureContainingArrays())
4674*8975f5c5SAndroid Build Coastguard Worker         {
4675*8975f5c5SAndroid Build Coastguard Worker             // ESSL 1.00.17 section 6.1 Function Definitions
4676*8975f5c5SAndroid Build Coastguard Worker             TInfoSinkBase typeString;
4677*8975f5c5SAndroid Build Coastguard Worker             typeString << TType(type);
4678*8975f5c5SAndroid Build Coastguard Worker             error(location, "structures containing arrays can't be function return values",
4679*8975f5c5SAndroid Build Coastguard Worker                   typeString.c_str());
4680*8975f5c5SAndroid Build Coastguard Worker         }
4681*8975f5c5SAndroid Build Coastguard Worker     }
4682*8975f5c5SAndroid Build Coastguard Worker 
4683*8975f5c5SAndroid Build Coastguard Worker     // Add the function as a prototype after parsing it (we do not support recursion)
4684*8975f5c5SAndroid Build Coastguard Worker     return new TFunction(&symbolTable, name, SymbolType::UserDefined, new TType(type), false);
4685*8975f5c5SAndroid Build Coastguard Worker }
4686*8975f5c5SAndroid Build Coastguard Worker 
addNonConstructorFunc(const ImmutableString & name,const TSymbol * symbol)4687*8975f5c5SAndroid Build Coastguard Worker TFunctionLookup *TParseContext::addNonConstructorFunc(const ImmutableString &name,
4688*8975f5c5SAndroid Build Coastguard Worker                                                       const TSymbol *symbol)
4689*8975f5c5SAndroid Build Coastguard Worker {
4690*8975f5c5SAndroid Build Coastguard Worker     return TFunctionLookup::CreateFunctionCall(name, symbol);
4691*8975f5c5SAndroid Build Coastguard Worker }
4692*8975f5c5SAndroid Build Coastguard Worker 
addConstructorFunc(const TPublicType & publicType)4693*8975f5c5SAndroid Build Coastguard Worker TFunctionLookup *TParseContext::addConstructorFunc(const TPublicType &publicType)
4694*8975f5c5SAndroid Build Coastguard Worker {
4695*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion < 300 && publicType.isArray())
4696*8975f5c5SAndroid Build Coastguard Worker     {
4697*8975f5c5SAndroid Build Coastguard Worker         error(publicType.getLine(), "array constructor supported in GLSL ES 3.00 and above only",
4698*8975f5c5SAndroid Build Coastguard Worker               "[]");
4699*8975f5c5SAndroid Build Coastguard Worker     }
4700*8975f5c5SAndroid Build Coastguard Worker     if (publicType.isStructSpecifier())
4701*8975f5c5SAndroid Build Coastguard Worker     {
4702*8975f5c5SAndroid Build Coastguard Worker         error(publicType.getLine(), "constructor can't be a structure definition",
4703*8975f5c5SAndroid Build Coastguard Worker               getBasicString(publicType.getBasicType()));
4704*8975f5c5SAndroid Build Coastguard Worker     }
4705*8975f5c5SAndroid Build Coastguard Worker 
4706*8975f5c5SAndroid Build Coastguard Worker     TType *type = new TType(publicType);
4707*8975f5c5SAndroid Build Coastguard Worker     if (!type->canBeConstructed())
4708*8975f5c5SAndroid Build Coastguard Worker     {
4709*8975f5c5SAndroid Build Coastguard Worker         error(publicType.getLine(), "cannot construct this type",
4710*8975f5c5SAndroid Build Coastguard Worker               getBasicString(publicType.getBasicType()));
4711*8975f5c5SAndroid Build Coastguard Worker         type->setBasicType(EbtFloat);
4712*8975f5c5SAndroid Build Coastguard Worker     }
4713*8975f5c5SAndroid Build Coastguard Worker     return TFunctionLookup::CreateConstructor(type);
4714*8975f5c5SAndroid Build Coastguard Worker }
4715*8975f5c5SAndroid Build Coastguard Worker 
checkIsNotUnsizedArray(const TSourceLoc & line,const char * errorMessage,const ImmutableString & token,TType * arrayType)4716*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkIsNotUnsizedArray(const TSourceLoc &line,
4717*8975f5c5SAndroid Build Coastguard Worker                                            const char *errorMessage,
4718*8975f5c5SAndroid Build Coastguard Worker                                            const ImmutableString &token,
4719*8975f5c5SAndroid Build Coastguard Worker                                            TType *arrayType)
4720*8975f5c5SAndroid Build Coastguard Worker {
4721*8975f5c5SAndroid Build Coastguard Worker     if (arrayType->isUnsizedArray())
4722*8975f5c5SAndroid Build Coastguard Worker     {
4723*8975f5c5SAndroid Build Coastguard Worker         error(line, errorMessage, token);
4724*8975f5c5SAndroid Build Coastguard Worker         arrayType->sizeUnsizedArrays(TSpan<const unsigned int>());
4725*8975f5c5SAndroid Build Coastguard Worker     }
4726*8975f5c5SAndroid Build Coastguard Worker }
4727*8975f5c5SAndroid Build Coastguard Worker 
parseParameterDeclarator(const TPublicType & type,const ImmutableString & name,const TSourceLoc & nameLoc)4728*8975f5c5SAndroid Build Coastguard Worker TParameter TParseContext::parseParameterDeclarator(const TPublicType &type,
4729*8975f5c5SAndroid Build Coastguard Worker                                                    const ImmutableString &name,
4730*8975f5c5SAndroid Build Coastguard Worker                                                    const TSourceLoc &nameLoc)
4731*8975f5c5SAndroid Build Coastguard Worker {
4732*8975f5c5SAndroid Build Coastguard Worker     if (!name.empty())
4733*8975f5c5SAndroid Build Coastguard Worker     {
4734*8975f5c5SAndroid Build Coastguard Worker         if (type.getBasicType() == EbtVoid)
4735*8975f5c5SAndroid Build Coastguard Worker         {
4736*8975f5c5SAndroid Build Coastguard Worker             error(nameLoc, "illegal use of type 'void'", name);
4737*8975f5c5SAndroid Build Coastguard Worker         }
4738*8975f5c5SAndroid Build Coastguard Worker     }
4739*8975f5c5SAndroid Build Coastguard Worker     if (type.isStructSpecifier())
4740*8975f5c5SAndroid Build Coastguard Worker     {
4741*8975f5c5SAndroid Build Coastguard Worker         // ESSL 3.00.6 section 12.10.
4742*8975f5c5SAndroid Build Coastguard Worker         error(nameLoc, "Function parameter type cannot be a structure definition", name);
4743*8975f5c5SAndroid Build Coastguard Worker     }
4744*8975f5c5SAndroid Build Coastguard Worker     checkIsNotReserved(nameLoc, name);
4745*8975f5c5SAndroid Build Coastguard Worker     TParameter param{name.data(), type};
4746*8975f5c5SAndroid Build Coastguard Worker     if (param.type.isUnsizedArray())
4747*8975f5c5SAndroid Build Coastguard Worker     {
4748*8975f5c5SAndroid Build Coastguard Worker         error(nameLoc, "function parameter array must specify a size", name);
4749*8975f5c5SAndroid Build Coastguard Worker         param.type.sizeUnsizedArrays();
4750*8975f5c5SAndroid Build Coastguard Worker     }
4751*8975f5c5SAndroid Build Coastguard Worker     return param;
4752*8975f5c5SAndroid Build Coastguard Worker }
4753*8975f5c5SAndroid Build Coastguard Worker 
parseParameterArrayDeclarator(const TPublicType & elementType,const ImmutableString & name,const TSourceLoc & nameLoc,TVector<unsigned int> * arraySizes,const TSourceLoc & arrayLoc)4754*8975f5c5SAndroid Build Coastguard Worker TParameter TParseContext::parseParameterArrayDeclarator(const TPublicType &elementType,
4755*8975f5c5SAndroid Build Coastguard Worker                                                         const ImmutableString &name,
4756*8975f5c5SAndroid Build Coastguard Worker                                                         const TSourceLoc &nameLoc,
4757*8975f5c5SAndroid Build Coastguard Worker                                                         TVector<unsigned int> *arraySizes,
4758*8975f5c5SAndroid Build Coastguard Worker                                                         const TSourceLoc &arrayLoc)
4759*8975f5c5SAndroid Build Coastguard Worker {
4760*8975f5c5SAndroid Build Coastguard Worker     checkArrayElementIsNotArray(arrayLoc, elementType);
4761*8975f5c5SAndroid Build Coastguard Worker     TPublicType arrayType{elementType};
4762*8975f5c5SAndroid Build Coastguard Worker     arrayType.makeArrays(arraySizes);
4763*8975f5c5SAndroid Build Coastguard Worker     return parseParameterDeclarator(arrayType, name, nameLoc);
4764*8975f5c5SAndroid Build Coastguard Worker }
4765*8975f5c5SAndroid Build Coastguard Worker 
checkUnsizedArrayConstructorArgumentDimensionality(const TIntermSequence & arguments,TType type,const TSourceLoc & line)4766*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::checkUnsizedArrayConstructorArgumentDimensionality(
4767*8975f5c5SAndroid Build Coastguard Worker     const TIntermSequence &arguments,
4768*8975f5c5SAndroid Build Coastguard Worker     TType type,
4769*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &line)
4770*8975f5c5SAndroid Build Coastguard Worker {
4771*8975f5c5SAndroid Build Coastguard Worker     if (arguments.empty())
4772*8975f5c5SAndroid Build Coastguard Worker     {
4773*8975f5c5SAndroid Build Coastguard Worker         error(line, "implicitly sized array constructor must have at least one argument", "[]");
4774*8975f5c5SAndroid Build Coastguard Worker         return false;
4775*8975f5c5SAndroid Build Coastguard Worker     }
4776*8975f5c5SAndroid Build Coastguard Worker     for (TIntermNode *arg : arguments)
4777*8975f5c5SAndroid Build Coastguard Worker     {
4778*8975f5c5SAndroid Build Coastguard Worker         const TIntermTyped *element = arg->getAsTyped();
4779*8975f5c5SAndroid Build Coastguard Worker         ASSERT(element);
4780*8975f5c5SAndroid Build Coastguard Worker         if (element->getType().isUnsizedArray())
4781*8975f5c5SAndroid Build Coastguard Worker         {
4782*8975f5c5SAndroid Build Coastguard Worker             error(line, "constructing from an unsized array", "constructor");
4783*8975f5c5SAndroid Build Coastguard Worker             return false;
4784*8975f5c5SAndroid Build Coastguard Worker         }
4785*8975f5c5SAndroid Build Coastguard Worker         size_t dimensionalityFromElement = element->getType().getNumArraySizes() + 1u;
4786*8975f5c5SAndroid Build Coastguard Worker         if (dimensionalityFromElement > type.getNumArraySizes())
4787*8975f5c5SAndroid Build Coastguard Worker         {
4788*8975f5c5SAndroid Build Coastguard Worker             error(line, "constructing from a non-dereferenced array", "constructor");
4789*8975f5c5SAndroid Build Coastguard Worker             return false;
4790*8975f5c5SAndroid Build Coastguard Worker         }
4791*8975f5c5SAndroid Build Coastguard Worker         else if (dimensionalityFromElement < type.getNumArraySizes())
4792*8975f5c5SAndroid Build Coastguard Worker         {
4793*8975f5c5SAndroid Build Coastguard Worker             if (dimensionalityFromElement == 1u)
4794*8975f5c5SAndroid Build Coastguard Worker             {
4795*8975f5c5SAndroid Build Coastguard Worker                 error(line, "implicitly sized array of arrays constructor argument is not an array",
4796*8975f5c5SAndroid Build Coastguard Worker                       "constructor");
4797*8975f5c5SAndroid Build Coastguard Worker             }
4798*8975f5c5SAndroid Build Coastguard Worker             else
4799*8975f5c5SAndroid Build Coastguard Worker             {
4800*8975f5c5SAndroid Build Coastguard Worker                 error(line,
4801*8975f5c5SAndroid Build Coastguard Worker                       "implicitly sized array of arrays constructor argument dimensionality is too "
4802*8975f5c5SAndroid Build Coastguard Worker                       "low",
4803*8975f5c5SAndroid Build Coastguard Worker                       "constructor");
4804*8975f5c5SAndroid Build Coastguard Worker             }
4805*8975f5c5SAndroid Build Coastguard Worker             return false;
4806*8975f5c5SAndroid Build Coastguard Worker         }
4807*8975f5c5SAndroid Build Coastguard Worker     }
4808*8975f5c5SAndroid Build Coastguard Worker     return true;
4809*8975f5c5SAndroid Build Coastguard Worker }
4810*8975f5c5SAndroid Build Coastguard Worker 
4811*8975f5c5SAndroid Build Coastguard Worker // This function is used to test for the correctness of the parameters passed to various constructor
4812*8975f5c5SAndroid Build Coastguard Worker // functions and also convert them to the right datatype if it is allowed and required.
4813*8975f5c5SAndroid Build Coastguard Worker //
4814*8975f5c5SAndroid Build Coastguard Worker // Returns a node to add to the tree regardless of if an error was generated or not.
4815*8975f5c5SAndroid Build Coastguard Worker //
addConstructor(TFunctionLookup * fnCall,const TSourceLoc & line)4816*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line)
4817*8975f5c5SAndroid Build Coastguard Worker {
4818*8975f5c5SAndroid Build Coastguard Worker     TType type                 = fnCall->constructorType();
4819*8975f5c5SAndroid Build Coastguard Worker     TIntermSequence &arguments = fnCall->arguments();
4820*8975f5c5SAndroid Build Coastguard Worker     if (type.isUnsizedArray())
4821*8975f5c5SAndroid Build Coastguard Worker     {
4822*8975f5c5SAndroid Build Coastguard Worker         if (!checkUnsizedArrayConstructorArgumentDimensionality(arguments, type, line))
4823*8975f5c5SAndroid Build Coastguard Worker         {
4824*8975f5c5SAndroid Build Coastguard Worker             type.sizeUnsizedArrays(TSpan<const unsigned int>());
4825*8975f5c5SAndroid Build Coastguard Worker             return CreateZeroNode(type);
4826*8975f5c5SAndroid Build Coastguard Worker         }
4827*8975f5c5SAndroid Build Coastguard Worker         TIntermTyped *firstElement = arguments.at(0)->getAsTyped();
4828*8975f5c5SAndroid Build Coastguard Worker         ASSERT(firstElement);
4829*8975f5c5SAndroid Build Coastguard Worker         if (type.getOutermostArraySize() == 0u)
4830*8975f5c5SAndroid Build Coastguard Worker         {
4831*8975f5c5SAndroid Build Coastguard Worker             type.sizeOutermostUnsizedArray(static_cast<unsigned int>(arguments.size()));
4832*8975f5c5SAndroid Build Coastguard Worker         }
4833*8975f5c5SAndroid Build Coastguard Worker         for (size_t i = 0; i < firstElement->getType().getNumArraySizes(); ++i)
4834*8975f5c5SAndroid Build Coastguard Worker         {
4835*8975f5c5SAndroid Build Coastguard Worker             if (type.getArraySizes()[i] == 0u)
4836*8975f5c5SAndroid Build Coastguard Worker             {
4837*8975f5c5SAndroid Build Coastguard Worker                 type.setArraySize(i, firstElement->getType().getArraySizes()[i]);
4838*8975f5c5SAndroid Build Coastguard Worker             }
4839*8975f5c5SAndroid Build Coastguard Worker         }
4840*8975f5c5SAndroid Build Coastguard Worker         ASSERT(!type.isUnsizedArray());
4841*8975f5c5SAndroid Build Coastguard Worker     }
4842*8975f5c5SAndroid Build Coastguard Worker 
4843*8975f5c5SAndroid Build Coastguard Worker     if (!checkConstructorArguments(line, arguments, type))
4844*8975f5c5SAndroid Build Coastguard Worker     {
4845*8975f5c5SAndroid Build Coastguard Worker         return CreateZeroNode(type);
4846*8975f5c5SAndroid Build Coastguard Worker     }
4847*8975f5c5SAndroid Build Coastguard Worker 
4848*8975f5c5SAndroid Build Coastguard Worker     TIntermAggregate *constructorNode = TIntermAggregate::CreateConstructor(type, &arguments);
4849*8975f5c5SAndroid Build Coastguard Worker     constructorNode->setLine(line);
4850*8975f5c5SAndroid Build Coastguard Worker 
4851*8975f5c5SAndroid Build Coastguard Worker     return constructorNode->fold(mDiagnostics);
4852*8975f5c5SAndroid Build Coastguard Worker }
4853*8975f5c5SAndroid Build Coastguard Worker 
4854*8975f5c5SAndroid Build Coastguard Worker //
4855*8975f5c5SAndroid Build Coastguard Worker // Interface/uniform blocks
addInterfaceBlock(const TTypeQualifierBuilder & typeQualifierBuilder,const TSourceLoc & nameLine,const ImmutableString & blockName,TFieldList * fieldList,const ImmutableString & instanceName,const TSourceLoc & instanceLine,const TVector<unsigned int> * arraySizes,const TSourceLoc & arraySizesLine)4856*8975f5c5SAndroid Build Coastguard Worker TIntermDeclaration *TParseContext::addInterfaceBlock(
4857*8975f5c5SAndroid Build Coastguard Worker     const TTypeQualifierBuilder &typeQualifierBuilder,
4858*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &nameLine,
4859*8975f5c5SAndroid Build Coastguard Worker     const ImmutableString &blockName,
4860*8975f5c5SAndroid Build Coastguard Worker     TFieldList *fieldList,
4861*8975f5c5SAndroid Build Coastguard Worker     const ImmutableString &instanceName,
4862*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &instanceLine,
4863*8975f5c5SAndroid Build Coastguard Worker     const TVector<unsigned int> *arraySizes,
4864*8975f5c5SAndroid Build Coastguard Worker     const TSourceLoc &arraySizesLine)
4865*8975f5c5SAndroid Build Coastguard Worker {
4866*8975f5c5SAndroid Build Coastguard Worker     checkDoesNotHaveTooManyFields(blockName, fieldList, nameLine);
4867*8975f5c5SAndroid Build Coastguard Worker 
4868*8975f5c5SAndroid Build Coastguard Worker     // Ensure there are no duplicate field names
4869*8975f5c5SAndroid Build Coastguard Worker     checkDoesNotHaveDuplicateFieldNames(fieldList, nameLine);
4870*8975f5c5SAndroid Build Coastguard Worker 
4871*8975f5c5SAndroid Build Coastguard Worker     const bool isGLPerVertex = blockName == "gl_PerVertex";
4872*8975f5c5SAndroid Build Coastguard Worker     // gl_PerVertex is allowed to be redefined and therefore not reserved
4873*8975f5c5SAndroid Build Coastguard Worker     if (!isGLPerVertex)
4874*8975f5c5SAndroid Build Coastguard Worker     {
4875*8975f5c5SAndroid Build Coastguard Worker         checkIsNotReserved(nameLine, blockName);
4876*8975f5c5SAndroid Build Coastguard Worker     }
4877*8975f5c5SAndroid Build Coastguard Worker 
4878*8975f5c5SAndroid Build Coastguard Worker     TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
4879*8975f5c5SAndroid Build Coastguard Worker 
4880*8975f5c5SAndroid Build Coastguard Worker     const bool isUniformOrBuffer =
4881*8975f5c5SAndroid Build Coastguard Worker         typeQualifier.qualifier == EvqUniform || typeQualifier.qualifier == EvqBuffer;
4882*8975f5c5SAndroid Build Coastguard Worker     const bool isShaderIoBlock = IsShaderIoBlock(typeQualifier.qualifier);
4883*8975f5c5SAndroid Build Coastguard Worker 
4884*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion < 310 && typeQualifier.qualifier != EvqUniform)
4885*8975f5c5SAndroid Build Coastguard Worker     {
4886*8975f5c5SAndroid Build Coastguard Worker         error(typeQualifier.line,
4887*8975f5c5SAndroid Build Coastguard Worker               "invalid qualifier: interface blocks must be uniform in version lower than GLSL ES "
4888*8975f5c5SAndroid Build Coastguard Worker               "3.10",
4889*8975f5c5SAndroid Build Coastguard Worker               getQualifierString(typeQualifier.qualifier));
4890*8975f5c5SAndroid Build Coastguard Worker     }
4891*8975f5c5SAndroid Build Coastguard Worker     else if (typeQualifier.qualifier == EvqPatchOut)
4892*8975f5c5SAndroid Build Coastguard Worker     {
4893*8975f5c5SAndroid Build Coastguard Worker         if ((!isExtensionEnabled(TExtension::EXT_tessellation_shader) &&
4894*8975f5c5SAndroid Build Coastguard Worker              !isExtensionEnabled(TExtension::OES_tessellation_shader) && mShaderVersion < 320) ||
4895*8975f5c5SAndroid Build Coastguard Worker             mShaderType != GL_TESS_CONTROL_SHADER)
4896*8975f5c5SAndroid Build Coastguard Worker         {
4897*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line,
4898*8975f5c5SAndroid Build Coastguard Worker                   "invalid qualifier: 'patch out' requires a tessellation control shader",
4899*8975f5c5SAndroid Build Coastguard Worker                   getQualifierString(typeQualifier.qualifier));
4900*8975f5c5SAndroid Build Coastguard Worker         }
4901*8975f5c5SAndroid Build Coastguard Worker     }
4902*8975f5c5SAndroid Build Coastguard Worker     else if (typeQualifier.qualifier == EvqPatchIn)
4903*8975f5c5SAndroid Build Coastguard Worker     {
4904*8975f5c5SAndroid Build Coastguard Worker         if ((!isExtensionEnabled(TExtension::EXT_tessellation_shader) &&
4905*8975f5c5SAndroid Build Coastguard Worker              !isExtensionEnabled(TExtension::OES_tessellation_shader) && mShaderVersion < 320) ||
4906*8975f5c5SAndroid Build Coastguard Worker             mShaderType != GL_TESS_EVALUATION_SHADER)
4907*8975f5c5SAndroid Build Coastguard Worker         {
4908*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line,
4909*8975f5c5SAndroid Build Coastguard Worker                   "invalid qualifier: 'patch in' requires a tessellation evaluation shader",
4910*8975f5c5SAndroid Build Coastguard Worker                   getQualifierString(typeQualifier.qualifier));
4911*8975f5c5SAndroid Build Coastguard Worker         }
4912*8975f5c5SAndroid Build Coastguard Worker     }
4913*8975f5c5SAndroid Build Coastguard Worker     else if (typeQualifier.qualifier != EvqUniform && typeQualifier.qualifier != EvqBuffer)
4914*8975f5c5SAndroid Build Coastguard Worker     {
4915*8975f5c5SAndroid Build Coastguard Worker         if (isShaderIoBlock)
4916*8975f5c5SAndroid Build Coastguard Worker         {
4917*8975f5c5SAndroid Build Coastguard Worker             if (!isExtensionEnabled(TExtension::OES_shader_io_blocks) &&
4918*8975f5c5SAndroid Build Coastguard Worker                 !isExtensionEnabled(TExtension::EXT_shader_io_blocks) &&
4919*8975f5c5SAndroid Build Coastguard Worker                 !isExtensionEnabled(TExtension::OES_geometry_shader) &&
4920*8975f5c5SAndroid Build Coastguard Worker                 !isExtensionEnabled(TExtension::EXT_geometry_shader) && mShaderVersion < 320)
4921*8975f5c5SAndroid Build Coastguard Worker             {
4922*8975f5c5SAndroid Build Coastguard Worker                 error(typeQualifier.line,
4923*8975f5c5SAndroid Build Coastguard Worker                       "invalid qualifier: shader IO blocks need shader io block extension",
4924*8975f5c5SAndroid Build Coastguard Worker                       getQualifierString(typeQualifier.qualifier));
4925*8975f5c5SAndroid Build Coastguard Worker             }
4926*8975f5c5SAndroid Build Coastguard Worker 
4927*8975f5c5SAndroid Build Coastguard Worker             // Both inputs and outputs of tessellation control shaders must be arrays.
4928*8975f5c5SAndroid Build Coastguard Worker             // For tessellation evaluation shaders, only inputs must necessarily be arrays.
4929*8975f5c5SAndroid Build Coastguard Worker             const bool isTCS = mShaderType == GL_TESS_CONTROL_SHADER;
4930*8975f5c5SAndroid Build Coastguard Worker             const bool isTESIn =
4931*8975f5c5SAndroid Build Coastguard Worker                 mShaderType == GL_TESS_EVALUATION_SHADER && IsShaderIn(typeQualifier.qualifier);
4932*8975f5c5SAndroid Build Coastguard Worker             if (arraySizes == nullptr && (isTCS || isTESIn))
4933*8975f5c5SAndroid Build Coastguard Worker             {
4934*8975f5c5SAndroid Build Coastguard Worker                 error(typeQualifier.line, "type must be an array", blockName);
4935*8975f5c5SAndroid Build Coastguard Worker             }
4936*8975f5c5SAndroid Build Coastguard Worker         }
4937*8975f5c5SAndroid Build Coastguard Worker         else
4938*8975f5c5SAndroid Build Coastguard Worker         {
4939*8975f5c5SAndroid Build Coastguard Worker             error(typeQualifier.line,
4940*8975f5c5SAndroid Build Coastguard Worker                   "invalid qualifier: interface blocks must be uniform or buffer",
4941*8975f5c5SAndroid Build Coastguard Worker                   getQualifierString(typeQualifier.qualifier));
4942*8975f5c5SAndroid Build Coastguard Worker         }
4943*8975f5c5SAndroid Build Coastguard Worker     }
4944*8975f5c5SAndroid Build Coastguard Worker 
4945*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.invariant)
4946*8975f5c5SAndroid Build Coastguard Worker     {
4947*8975f5c5SAndroid Build Coastguard Worker         error(typeQualifier.line, "invalid qualifier on interface block", "invariant");
4948*8975f5c5SAndroid Build Coastguard Worker     }
4949*8975f5c5SAndroid Build Coastguard Worker 
4950*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.qualifier != EvqBuffer)
4951*8975f5c5SAndroid Build Coastguard Worker     {
4952*8975f5c5SAndroid Build Coastguard Worker         checkMemoryQualifierIsNotSpecified(typeQualifier.memoryQualifier, typeQualifier.line);
4953*8975f5c5SAndroid Build Coastguard Worker     }
4954*8975f5c5SAndroid Build Coastguard Worker 
4955*8975f5c5SAndroid Build Coastguard Worker     // Verify array sizes
4956*8975f5c5SAndroid Build Coastguard Worker     if (arraySizes)
4957*8975f5c5SAndroid Build Coastguard Worker     {
4958*8975f5c5SAndroid Build Coastguard Worker         if (isUniformOrBuffer)
4959*8975f5c5SAndroid Build Coastguard Worker         {
4960*8975f5c5SAndroid Build Coastguard Worker             if (arraySizes->size() == 0)
4961*8975f5c5SAndroid Build Coastguard Worker             {
4962*8975f5c5SAndroid Build Coastguard Worker                 error(arraySizesLine, "unsized arrays are not allowed with interface blocks", "");
4963*8975f5c5SAndroid Build Coastguard Worker             }
4964*8975f5c5SAndroid Build Coastguard Worker             if (arraySizes->size() > 1)
4965*8975f5c5SAndroid Build Coastguard Worker             {
4966*8975f5c5SAndroid Build Coastguard Worker                 error(arraySizesLine, "array of arrays are not allowed with interface blocks", "");
4967*8975f5c5SAndroid Build Coastguard Worker             }
4968*8975f5c5SAndroid Build Coastguard Worker         }
4969*8975f5c5SAndroid Build Coastguard Worker         else if (isShaderIoBlock)
4970*8975f5c5SAndroid Build Coastguard Worker         {
4971*8975f5c5SAndroid Build Coastguard Worker             size_t arrayDimensions = arraySizes->size();
4972*8975f5c5SAndroid Build Coastguard Worker 
4973*8975f5c5SAndroid Build Coastguard Worker             // Geometry shader inputs have a level arrayness that must be ignored.
4974*8975f5c5SAndroid Build Coastguard Worker             if (mShaderType == GL_GEOMETRY_SHADER_EXT && IsVaryingIn(typeQualifier.qualifier))
4975*8975f5c5SAndroid Build Coastguard Worker             {
4976*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(arrayDimensions > 0);
4977*8975f5c5SAndroid Build Coastguard Worker                 --arrayDimensions;
4978*8975f5c5SAndroid Build Coastguard Worker 
4979*8975f5c5SAndroid Build Coastguard Worker                 // Validate that the array size of input matches the geometry layout
4980*8975f5c5SAndroid Build Coastguard Worker                 // declaration, if not automatic (specified as []).
4981*8975f5c5SAndroid Build Coastguard Worker                 const unsigned int geometryDim = arraySizes->back();
4982*8975f5c5SAndroid Build Coastguard Worker                 if (geometryDim > 0 && geometryDim != mGeometryInputArraySize)
4983*8975f5c5SAndroid Build Coastguard Worker                 {
4984*8975f5c5SAndroid Build Coastguard Worker                     error(arraySizesLine,
4985*8975f5c5SAndroid Build Coastguard Worker                           "geometry shader input block array size inconsistent "
4986*8975f5c5SAndroid Build Coastguard Worker                           "with primitive",
4987*8975f5c5SAndroid Build Coastguard Worker                           "");
4988*8975f5c5SAndroid Build Coastguard Worker                 }
4989*8975f5c5SAndroid Build Coastguard Worker             }
4990*8975f5c5SAndroid Build Coastguard Worker 
4991*8975f5c5SAndroid Build Coastguard Worker             if (arrayDimensions > 1)
4992*8975f5c5SAndroid Build Coastguard Worker             {
4993*8975f5c5SAndroid Build Coastguard Worker                 error(arraySizesLine, "array of arrays are not allowed with I/O blocks", "");
4994*8975f5c5SAndroid Build Coastguard Worker             }
4995*8975f5c5SAndroid Build Coastguard Worker         }
4996*8975f5c5SAndroid Build Coastguard Worker     }
4997*8975f5c5SAndroid Build Coastguard Worker     else if (isShaderIoBlock && mShaderType == GL_GEOMETRY_SHADER_EXT &&
4998*8975f5c5SAndroid Build Coastguard Worker              IsVaryingIn(typeQualifier.qualifier))
4999*8975f5c5SAndroid Build Coastguard Worker     {
5000*8975f5c5SAndroid Build Coastguard Worker         error(arraySizesLine, "geometry shader input blocks must be an array", "");
5001*8975f5c5SAndroid Build Coastguard Worker     }
5002*8975f5c5SAndroid Build Coastguard Worker 
5003*8975f5c5SAndroid Build Coastguard Worker     checkIndexIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.index);
5004*8975f5c5SAndroid Build Coastguard Worker 
5005*8975f5c5SAndroid Build Coastguard Worker     if (mShaderVersion < 310)
5006*8975f5c5SAndroid Build Coastguard Worker     {
5007*8975f5c5SAndroid Build Coastguard Worker         checkBindingIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.binding);
5008*8975f5c5SAndroid Build Coastguard Worker     }
5009*8975f5c5SAndroid Build Coastguard Worker     else
5010*8975f5c5SAndroid Build Coastguard Worker     {
5011*8975f5c5SAndroid Build Coastguard Worker         unsigned int arraySize =
5012*8975f5c5SAndroid Build Coastguard Worker             arraySizes == nullptr || arraySizes->empty() ? 0 : (*arraySizes)[0];
5013*8975f5c5SAndroid Build Coastguard Worker         checkBlockBindingIsValid(typeQualifier.line, typeQualifier.qualifier,
5014*8975f5c5SAndroid Build Coastguard Worker                                  typeQualifier.layoutQualifier.binding, arraySize);
5015*8975f5c5SAndroid Build Coastguard Worker     }
5016*8975f5c5SAndroid Build Coastguard Worker 
5017*8975f5c5SAndroid Build Coastguard Worker     checkDepthIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.depth);
5018*8975f5c5SAndroid Build Coastguard Worker     checkYuvIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.yuv);
5019*8975f5c5SAndroid Build Coastguard Worker     checkEarlyFragmentTestsIsNotSpecified(typeQualifier.line,
5020*8975f5c5SAndroid Build Coastguard Worker                                           typeQualifier.layoutQualifier.earlyFragmentTests);
5021*8975f5c5SAndroid Build Coastguard Worker     checkNoncoherentIsNotSpecified(typeQualifier.line, typeQualifier.layoutQualifier.noncoherent);
5022*8975f5c5SAndroid Build Coastguard Worker 
5023*8975f5c5SAndroid Build Coastguard Worker     TLayoutQualifier blockLayoutQualifier = typeQualifier.layoutQualifier;
5024*8975f5c5SAndroid Build Coastguard Worker     if (!IsShaderIoBlock(typeQualifier.qualifier) && typeQualifier.qualifier != EvqPatchIn &&
5025*8975f5c5SAndroid Build Coastguard Worker         typeQualifier.qualifier != EvqPatchOut)
5026*8975f5c5SAndroid Build Coastguard Worker     {
5027*8975f5c5SAndroid Build Coastguard Worker         checkLocationIsNotSpecified(typeQualifier.line, blockLayoutQualifier);
5028*8975f5c5SAndroid Build Coastguard Worker     }
5029*8975f5c5SAndroid Build Coastguard Worker     checkStd430IsForShaderStorageBlock(typeQualifier.line, blockLayoutQualifier.blockStorage,
5030*8975f5c5SAndroid Build Coastguard Worker                                        typeQualifier.qualifier);
5031*8975f5c5SAndroid Build Coastguard Worker 
5032*8975f5c5SAndroid Build Coastguard Worker     if (blockLayoutQualifier.matrixPacking == EmpUnspecified)
5033*8975f5c5SAndroid Build Coastguard Worker     {
5034*8975f5c5SAndroid Build Coastguard Worker         if (typeQualifier.qualifier == EvqUniform)
5035*8975f5c5SAndroid Build Coastguard Worker         {
5036*8975f5c5SAndroid Build Coastguard Worker             blockLayoutQualifier.matrixPacking = mDefaultUniformMatrixPacking;
5037*8975f5c5SAndroid Build Coastguard Worker         }
5038*8975f5c5SAndroid Build Coastguard Worker         else if (typeQualifier.qualifier == EvqBuffer)
5039*8975f5c5SAndroid Build Coastguard Worker         {
5040*8975f5c5SAndroid Build Coastguard Worker             blockLayoutQualifier.matrixPacking = mDefaultBufferMatrixPacking;
5041*8975f5c5SAndroid Build Coastguard Worker         }
5042*8975f5c5SAndroid Build Coastguard Worker     }
5043*8975f5c5SAndroid Build Coastguard Worker 
5044*8975f5c5SAndroid Build Coastguard Worker     if (blockLayoutQualifier.blockStorage == EbsUnspecified)
5045*8975f5c5SAndroid Build Coastguard Worker     {
5046*8975f5c5SAndroid Build Coastguard Worker         if (typeQualifier.qualifier == EvqUniform)
5047*8975f5c5SAndroid Build Coastguard Worker         {
5048*8975f5c5SAndroid Build Coastguard Worker             blockLayoutQualifier.blockStorage = mDefaultUniformBlockStorage;
5049*8975f5c5SAndroid Build Coastguard Worker         }
5050*8975f5c5SAndroid Build Coastguard Worker         else if (typeQualifier.qualifier == EvqBuffer)
5051*8975f5c5SAndroid Build Coastguard Worker         {
5052*8975f5c5SAndroid Build Coastguard Worker             blockLayoutQualifier.blockStorage = mDefaultBufferBlockStorage;
5053*8975f5c5SAndroid Build Coastguard Worker         }
5054*8975f5c5SAndroid Build Coastguard Worker     }
5055*8975f5c5SAndroid Build Coastguard Worker 
5056*8975f5c5SAndroid Build Coastguard Worker     checkWorkGroupSizeIsNotSpecified(nameLine, blockLayoutQualifier);
5057*8975f5c5SAndroid Build Coastguard Worker 
5058*8975f5c5SAndroid Build Coastguard Worker     checkInternalFormatIsNotSpecified(nameLine, blockLayoutQualifier.imageInternalFormat);
5059*8975f5c5SAndroid Build Coastguard Worker 
5060*8975f5c5SAndroid Build Coastguard Worker     // check for sampler types and apply layout qualifiers
5061*8975f5c5SAndroid Build Coastguard Worker     for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
5062*8975f5c5SAndroid Build Coastguard Worker     {
5063*8975f5c5SAndroid Build Coastguard Worker         TField *field    = (*fieldList)[memberIndex];
5064*8975f5c5SAndroid Build Coastguard Worker         TType *fieldType = field->type();
5065*8975f5c5SAndroid Build Coastguard Worker         if (ContainsOpaque<IsOpaqueFunc>(*fieldType))
5066*8975f5c5SAndroid Build Coastguard Worker         {
5067*8975f5c5SAndroid Build Coastguard Worker             error(field->line(), "Opaque types are not allowed in interface blocks", blockName);
5068*8975f5c5SAndroid Build Coastguard Worker         }
5069*8975f5c5SAndroid Build Coastguard Worker 
5070*8975f5c5SAndroid Build Coastguard Worker         const TQualifier qualifier = fieldType->getQualifier();
5071*8975f5c5SAndroid Build Coastguard Worker         switch (qualifier)
5072*8975f5c5SAndroid Build Coastguard Worker         {
5073*8975f5c5SAndroid Build Coastguard Worker             case EvqGlobal:
5074*8975f5c5SAndroid Build Coastguard Worker                 break;
5075*8975f5c5SAndroid Build Coastguard Worker             case EvqUniform:
5076*8975f5c5SAndroid Build Coastguard Worker                 if (typeQualifier.qualifier == EvqBuffer)
5077*8975f5c5SAndroid Build Coastguard Worker                 {
5078*8975f5c5SAndroid Build Coastguard Worker                     error(field->line(), "invalid qualifier on shader storage block member",
5079*8975f5c5SAndroid Build Coastguard Worker                           getQualifierString(qualifier));
5080*8975f5c5SAndroid Build Coastguard Worker                 }
5081*8975f5c5SAndroid Build Coastguard Worker                 break;
5082*8975f5c5SAndroid Build Coastguard Worker             case EvqBuffer:
5083*8975f5c5SAndroid Build Coastguard Worker                 if (typeQualifier.qualifier == EvqUniform)
5084*8975f5c5SAndroid Build Coastguard Worker                 {
5085*8975f5c5SAndroid Build Coastguard Worker                     error(field->line(), "invalid qualifier on uniform block member",
5086*8975f5c5SAndroid Build Coastguard Worker                           getQualifierString(qualifier));
5087*8975f5c5SAndroid Build Coastguard Worker                 }
5088*8975f5c5SAndroid Build Coastguard Worker                 break;
5089*8975f5c5SAndroid Build Coastguard Worker             // a member variable in io block may have different interpolation.
5090*8975f5c5SAndroid Build Coastguard Worker             case EvqSmoothIn:
5091*8975f5c5SAndroid Build Coastguard Worker             case EvqSmoothOut:
5092*8975f5c5SAndroid Build Coastguard Worker             case EvqFlatIn:
5093*8975f5c5SAndroid Build Coastguard Worker             case EvqFlatOut:
5094*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveIn:
5095*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveOut:
5096*8975f5c5SAndroid Build Coastguard Worker             case EvqCentroidIn:
5097*8975f5c5SAndroid Build Coastguard Worker             case EvqCentroidOut:
5098*8975f5c5SAndroid Build Coastguard Worker             case EvqSampleIn:
5099*8975f5c5SAndroid Build Coastguard Worker             case EvqSampleOut:
5100*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveCentroidIn:
5101*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveCentroidOut:
5102*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveSampleIn:
5103*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveSampleOut:
5104*8975f5c5SAndroid Build Coastguard Worker                 break;
5105*8975f5c5SAndroid Build Coastguard Worker             // a member variable can have an incomplete qualifier because shader io block has either
5106*8975f5c5SAndroid Build Coastguard Worker             // in or out.
5107*8975f5c5SAndroid Build Coastguard Worker             case EvqSmooth:
5108*8975f5c5SAndroid Build Coastguard Worker             case EvqFlat:
5109*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspective:
5110*8975f5c5SAndroid Build Coastguard Worker             case EvqCentroid:
5111*8975f5c5SAndroid Build Coastguard Worker             case EvqSample:
5112*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveCentroid:
5113*8975f5c5SAndroid Build Coastguard Worker             case EvqNoPerspectiveSample:
5114*8975f5c5SAndroid Build Coastguard Worker             case EvqGeometryIn:
5115*8975f5c5SAndroid Build Coastguard Worker             case EvqGeometryOut:
5116*8975f5c5SAndroid Build Coastguard Worker                 if (!IsShaderIoBlock(typeQualifier.qualifier) &&
5117*8975f5c5SAndroid Build Coastguard Worker                     typeQualifier.qualifier != EvqPatchIn &&
5118*8975f5c5SAndroid Build Coastguard Worker                     typeQualifier.qualifier != EvqPatchOut &&
5119*8975f5c5SAndroid Build Coastguard Worker                     typeQualifier.qualifier != EvqGeometryIn &&
5120*8975f5c5SAndroid Build Coastguard Worker                     typeQualifier.qualifier != EvqGeometryOut)
5121*8975f5c5SAndroid Build Coastguard Worker                 {
5122*8975f5c5SAndroid Build Coastguard Worker                     error(field->line(), "invalid qualifier on interface block member",
5123*8975f5c5SAndroid Build Coastguard Worker                           getQualifierString(qualifier));
5124*8975f5c5SAndroid Build Coastguard Worker                 }
5125*8975f5c5SAndroid Build Coastguard Worker                 break;
5126*8975f5c5SAndroid Build Coastguard Worker             default:
5127*8975f5c5SAndroid Build Coastguard Worker                 error(field->line(), "invalid qualifier on interface block member",
5128*8975f5c5SAndroid Build Coastguard Worker                       getQualifierString(qualifier));
5129*8975f5c5SAndroid Build Coastguard Worker                 break;
5130*8975f5c5SAndroid Build Coastguard Worker         }
5131*8975f5c5SAndroid Build Coastguard Worker 
5132*8975f5c5SAndroid Build Coastguard Worker         // On interface block members, invariant is only applicable to output I/O blocks.
5133*8975f5c5SAndroid Build Coastguard Worker         const bool isOutputShaderIoBlock = isShaderIoBlock && IsShaderOut(typeQualifier.qualifier);
5134*8975f5c5SAndroid Build Coastguard Worker         if (fieldType->isInvariant() && !isOutputShaderIoBlock)
5135*8975f5c5SAndroid Build Coastguard Worker         {
5136*8975f5c5SAndroid Build Coastguard Worker             error(field->line(), "invalid qualifier on interface block member", "invariant");
5137*8975f5c5SAndroid Build Coastguard Worker         }
5138*8975f5c5SAndroid Build Coastguard Worker 
5139*8975f5c5SAndroid Build Coastguard Worker         // check layout qualifiers
5140*8975f5c5SAndroid Build Coastguard Worker         TLayoutQualifier fieldLayoutQualifier = fieldType->getLayoutQualifier();
5141*8975f5c5SAndroid Build Coastguard Worker         checkIndexIsNotSpecified(field->line(), fieldLayoutQualifier.index);
5142*8975f5c5SAndroid Build Coastguard Worker         checkBindingIsNotSpecified(field->line(), fieldLayoutQualifier.binding);
5143*8975f5c5SAndroid Build Coastguard Worker 
5144*8975f5c5SAndroid Build Coastguard Worker         if (fieldLayoutQualifier.blockStorage != EbsUnspecified)
5145*8975f5c5SAndroid Build Coastguard Worker         {
5146*8975f5c5SAndroid Build Coastguard Worker             error(field->line(), "invalid layout qualifier: cannot be used here",
5147*8975f5c5SAndroid Build Coastguard Worker                   getBlockStorageString(fieldLayoutQualifier.blockStorage));
5148*8975f5c5SAndroid Build Coastguard Worker         }
5149*8975f5c5SAndroid Build Coastguard Worker 
5150*8975f5c5SAndroid Build Coastguard Worker         if (fieldLayoutQualifier.matrixPacking == EmpUnspecified)
5151*8975f5c5SAndroid Build Coastguard Worker         {
5152*8975f5c5SAndroid Build Coastguard Worker             fieldLayoutQualifier.matrixPacking = blockLayoutQualifier.matrixPacking;
5153*8975f5c5SAndroid Build Coastguard Worker         }
5154*8975f5c5SAndroid Build Coastguard Worker         else if (!fieldType->isMatrix() && fieldType->getBasicType() != EbtStruct)
5155*8975f5c5SAndroid Build Coastguard Worker         {
5156*8975f5c5SAndroid Build Coastguard Worker             warning(field->line(),
5157*8975f5c5SAndroid Build Coastguard Worker                     "extraneous layout qualifier: only has an effect on matrix types",
5158*8975f5c5SAndroid Build Coastguard Worker                     getMatrixPackingString(fieldLayoutQualifier.matrixPacking));
5159*8975f5c5SAndroid Build Coastguard Worker         }
5160*8975f5c5SAndroid Build Coastguard Worker 
5161*8975f5c5SAndroid Build Coastguard Worker         fieldType->setLayoutQualifier(fieldLayoutQualifier);
5162*8975f5c5SAndroid Build Coastguard Worker 
5163*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 310 || memberIndex != fieldList->size() - 1u ||
5164*8975f5c5SAndroid Build Coastguard Worker             typeQualifier.qualifier != EvqBuffer)
5165*8975f5c5SAndroid Build Coastguard Worker         {
5166*8975f5c5SAndroid Build Coastguard Worker             // ESSL 3.10 spec section 4.1.9 allows for runtime-sized arrays.
5167*8975f5c5SAndroid Build Coastguard Worker             checkIsNotUnsizedArray(field->line(),
5168*8975f5c5SAndroid Build Coastguard Worker                                    "array members of interface blocks must specify a size",
5169*8975f5c5SAndroid Build Coastguard Worker                                    field->name(), field->type());
5170*8975f5c5SAndroid Build Coastguard Worker         }
5171*8975f5c5SAndroid Build Coastguard Worker 
5172*8975f5c5SAndroid Build Coastguard Worker         if (typeQualifier.qualifier == EvqBuffer)
5173*8975f5c5SAndroid Build Coastguard Worker         {
5174*8975f5c5SAndroid Build Coastguard Worker             // set memory qualifiers
5175*8975f5c5SAndroid Build Coastguard Worker             // GLSL ES 3.10 session 4.9 [Memory Access Qualifiers]. When a block declaration is
5176*8975f5c5SAndroid Build Coastguard Worker             // qualified with a memory qualifier, it is as if all of its members were declared with
5177*8975f5c5SAndroid Build Coastguard Worker             // the same memory qualifier.
5178*8975f5c5SAndroid Build Coastguard Worker             const TMemoryQualifier &blockMemoryQualifier = typeQualifier.memoryQualifier;
5179*8975f5c5SAndroid Build Coastguard Worker             TMemoryQualifier fieldMemoryQualifier        = fieldType->getMemoryQualifier();
5180*8975f5c5SAndroid Build Coastguard Worker             fieldMemoryQualifier.readonly |= blockMemoryQualifier.readonly;
5181*8975f5c5SAndroid Build Coastguard Worker             fieldMemoryQualifier.writeonly |= blockMemoryQualifier.writeonly;
5182*8975f5c5SAndroid Build Coastguard Worker             fieldMemoryQualifier.coherent |= blockMemoryQualifier.coherent;
5183*8975f5c5SAndroid Build Coastguard Worker             fieldMemoryQualifier.restrictQualifier |= blockMemoryQualifier.restrictQualifier;
5184*8975f5c5SAndroid Build Coastguard Worker             fieldMemoryQualifier.volatileQualifier |= blockMemoryQualifier.volatileQualifier;
5185*8975f5c5SAndroid Build Coastguard Worker             // TODO([email protected]): Decide whether if readonly and writeonly buffer variable
5186*8975f5c5SAndroid Build Coastguard Worker             // is legal. See bug https://github.com/KhronosGroup/OpenGL-API/issues/7
5187*8975f5c5SAndroid Build Coastguard Worker             fieldType->setMemoryQualifier(fieldMemoryQualifier);
5188*8975f5c5SAndroid Build Coastguard Worker         }
5189*8975f5c5SAndroid Build Coastguard Worker     }
5190*8975f5c5SAndroid Build Coastguard Worker 
5191*8975f5c5SAndroid Build Coastguard Worker     SymbolType instanceSymbolType = SymbolType::UserDefined;
5192*8975f5c5SAndroid Build Coastguard Worker     if (isGLPerVertex)
5193*8975f5c5SAndroid Build Coastguard Worker     {
5194*8975f5c5SAndroid Build Coastguard Worker         instanceSymbolType = SymbolType::BuiltIn;
5195*8975f5c5SAndroid Build Coastguard Worker     }
5196*8975f5c5SAndroid Build Coastguard Worker     TInterfaceBlock *interfaceBlock = new TInterfaceBlock(&symbolTable, blockName, fieldList,
5197*8975f5c5SAndroid Build Coastguard Worker                                                           blockLayoutQualifier, instanceSymbolType);
5198*8975f5c5SAndroid Build Coastguard Worker     if (!symbolTable.declare(interfaceBlock) && isUniformOrBuffer)
5199*8975f5c5SAndroid Build Coastguard Worker     {
5200*8975f5c5SAndroid Build Coastguard Worker         error(nameLine, "redefinition of an interface block name", blockName);
5201*8975f5c5SAndroid Build Coastguard Worker     }
5202*8975f5c5SAndroid Build Coastguard Worker 
5203*8975f5c5SAndroid Build Coastguard Worker     TType *interfaceBlockType =
5204*8975f5c5SAndroid Build Coastguard Worker         new TType(interfaceBlock, typeQualifier.qualifier, blockLayoutQualifier);
5205*8975f5c5SAndroid Build Coastguard Worker     if (arraySizes)
5206*8975f5c5SAndroid Build Coastguard Worker     {
5207*8975f5c5SAndroid Build Coastguard Worker         interfaceBlockType->makeArrays(*arraySizes);
5208*8975f5c5SAndroid Build Coastguard Worker         checkGeometryShaderInputAndSetArraySize(instanceLine, instanceName, interfaceBlockType);
5209*8975f5c5SAndroid Build Coastguard Worker         checkTessellationShaderUnsizedArraysAndSetSize(instanceLine, instanceName,
5210*8975f5c5SAndroid Build Coastguard Worker                                                        interfaceBlockType);
5211*8975f5c5SAndroid Build Coastguard Worker         checkDeclarationIsValidArraySize(instanceLine, instanceName, interfaceBlockType);
5212*8975f5c5SAndroid Build Coastguard Worker     }
5213*8975f5c5SAndroid Build Coastguard Worker 
5214*8975f5c5SAndroid Build Coastguard Worker     // The instance variable gets created to refer to the interface block type from the AST
5215*8975f5c5SAndroid Build Coastguard Worker     // regardless of if there's an instance name. It's created as an empty symbol if there is no
5216*8975f5c5SAndroid Build Coastguard Worker     // instance name.
5217*8975f5c5SAndroid Build Coastguard Worker     TVariable *instanceVariable =
5218*8975f5c5SAndroid Build Coastguard Worker         new TVariable(&symbolTable, instanceName, interfaceBlockType,
5219*8975f5c5SAndroid Build Coastguard Worker                       instanceName.empty() ? SymbolType::Empty : SymbolType::UserDefined);
5220*8975f5c5SAndroid Build Coastguard Worker 
5221*8975f5c5SAndroid Build Coastguard Worker     if (instanceVariable->symbolType() == SymbolType::Empty)
5222*8975f5c5SAndroid Build Coastguard Worker     {
5223*8975f5c5SAndroid Build Coastguard Worker         // define symbols for the members of the interface block
5224*8975f5c5SAndroid Build Coastguard Worker         for (size_t memberIndex = 0; memberIndex < fieldList->size(); ++memberIndex)
5225*8975f5c5SAndroid Build Coastguard Worker         {
5226*8975f5c5SAndroid Build Coastguard Worker             TField *field    = (*fieldList)[memberIndex];
5227*8975f5c5SAndroid Build Coastguard Worker             TType *fieldType = new TType(*field->type());
5228*8975f5c5SAndroid Build Coastguard Worker 
5229*8975f5c5SAndroid Build Coastguard Worker             // set parent pointer of the field variable
5230*8975f5c5SAndroid Build Coastguard Worker             fieldType->setInterfaceBlockField(interfaceBlock, memberIndex);
5231*8975f5c5SAndroid Build Coastguard Worker 
5232*8975f5c5SAndroid Build Coastguard Worker             fieldType->setQualifier(typeQualifier.qualifier);
5233*8975f5c5SAndroid Build Coastguard Worker 
5234*8975f5c5SAndroid Build Coastguard Worker             SymbolType symbolType = SymbolType::UserDefined;
5235*8975f5c5SAndroid Build Coastguard Worker             if (field->name() == "gl_Position" || field->name() == "gl_PointSize" ||
5236*8975f5c5SAndroid Build Coastguard Worker                 field->name() == "gl_ClipDistance" || field->name() == "gl_CullDistance")
5237*8975f5c5SAndroid Build Coastguard Worker             {
5238*8975f5c5SAndroid Build Coastguard Worker                 // These builtins can be redefined only when used within a redefined gl_PerVertex
5239*8975f5c5SAndroid Build Coastguard Worker                 // block
5240*8975f5c5SAndroid Build Coastguard Worker                 if (interfaceBlock->name() != "gl_PerVertex")
5241*8975f5c5SAndroid Build Coastguard Worker                 {
5242*8975f5c5SAndroid Build Coastguard Worker                     error(field->line(), "redefinition in an invalid interface block",
5243*8975f5c5SAndroid Build Coastguard Worker                           field->name());
5244*8975f5c5SAndroid Build Coastguard Worker                 }
5245*8975f5c5SAndroid Build Coastguard Worker                 symbolType = SymbolType::BuiltIn;
5246*8975f5c5SAndroid Build Coastguard Worker             }
5247*8975f5c5SAndroid Build Coastguard Worker             TVariable *fieldVariable =
5248*8975f5c5SAndroid Build Coastguard Worker                 new TVariable(&symbolTable, field->name(), fieldType, symbolType);
5249*8975f5c5SAndroid Build Coastguard Worker             if (!symbolTable.declare(fieldVariable))
5250*8975f5c5SAndroid Build Coastguard Worker             {
5251*8975f5c5SAndroid Build Coastguard Worker                 error(field->line(), "redefinition of an interface block member name",
5252*8975f5c5SAndroid Build Coastguard Worker                       field->name());
5253*8975f5c5SAndroid Build Coastguard Worker             }
5254*8975f5c5SAndroid Build Coastguard Worker         }
5255*8975f5c5SAndroid Build Coastguard Worker     }
5256*8975f5c5SAndroid Build Coastguard Worker     else
5257*8975f5c5SAndroid Build Coastguard Worker     {
5258*8975f5c5SAndroid Build Coastguard Worker         checkIsNotReserved(instanceLine, instanceName);
5259*8975f5c5SAndroid Build Coastguard Worker 
5260*8975f5c5SAndroid Build Coastguard Worker         // add a symbol for this interface block
5261*8975f5c5SAndroid Build Coastguard Worker         if (!symbolTable.declare(instanceVariable))
5262*8975f5c5SAndroid Build Coastguard Worker         {
5263*8975f5c5SAndroid Build Coastguard Worker             error(instanceLine, "redefinition of an interface block instance name", instanceName);
5264*8975f5c5SAndroid Build Coastguard Worker         }
5265*8975f5c5SAndroid Build Coastguard Worker     }
5266*8975f5c5SAndroid Build Coastguard Worker 
5267*8975f5c5SAndroid Build Coastguard Worker     TIntermSymbol *blockSymbol = new TIntermSymbol(instanceVariable);
5268*8975f5c5SAndroid Build Coastguard Worker     blockSymbol->setLine(typeQualifier.line);
5269*8975f5c5SAndroid Build Coastguard Worker     TIntermDeclaration *declaration = new TIntermDeclaration();
5270*8975f5c5SAndroid Build Coastguard Worker     declaration->appendDeclarator(blockSymbol);
5271*8975f5c5SAndroid Build Coastguard Worker     declaration->setLine(nameLine);
5272*8975f5c5SAndroid Build Coastguard Worker 
5273*8975f5c5SAndroid Build Coastguard Worker     exitStructDeclaration();
5274*8975f5c5SAndroid Build Coastguard Worker     return declaration;
5275*8975f5c5SAndroid Build Coastguard Worker }
5276*8975f5c5SAndroid Build Coastguard Worker 
enterStructDeclaration(const TSourceLoc & line,const ImmutableString & identifier)5277*8975f5c5SAndroid Build Coastguard Worker void TParseContext::enterStructDeclaration(const TSourceLoc &line,
5278*8975f5c5SAndroid Build Coastguard Worker                                            const ImmutableString &identifier)
5279*8975f5c5SAndroid Build Coastguard Worker {
5280*8975f5c5SAndroid Build Coastguard Worker     ++mStructNestingLevel;
5281*8975f5c5SAndroid Build Coastguard Worker 
5282*8975f5c5SAndroid Build Coastguard Worker     // Embedded structure definitions are not supported per GLSL ES spec.
5283*8975f5c5SAndroid Build Coastguard Worker     // ESSL 1.00.17 section 10.9. ESSL 3.00.6 section 12.11.
5284*8975f5c5SAndroid Build Coastguard Worker     if (mStructNestingLevel > 1)
5285*8975f5c5SAndroid Build Coastguard Worker     {
5286*8975f5c5SAndroid Build Coastguard Worker         error(line, "Embedded struct definitions are not allowed", "struct");
5287*8975f5c5SAndroid Build Coastguard Worker     }
5288*8975f5c5SAndroid Build Coastguard Worker }
5289*8975f5c5SAndroid Build Coastguard Worker 
exitStructDeclaration()5290*8975f5c5SAndroid Build Coastguard Worker void TParseContext::exitStructDeclaration()
5291*8975f5c5SAndroid Build Coastguard Worker {
5292*8975f5c5SAndroid Build Coastguard Worker     --mStructNestingLevel;
5293*8975f5c5SAndroid Build Coastguard Worker }
5294*8975f5c5SAndroid Build Coastguard Worker 
checkIsBelowStructNestingLimit(const TSourceLoc & line,const TField & field)5295*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkIsBelowStructNestingLimit(const TSourceLoc &line, const TField &field)
5296*8975f5c5SAndroid Build Coastguard Worker {
5297*8975f5c5SAndroid Build Coastguard Worker     if (!sh::IsWebGLBasedSpec(mShaderSpec))
5298*8975f5c5SAndroid Build Coastguard Worker     {
5299*8975f5c5SAndroid Build Coastguard Worker         return;
5300*8975f5c5SAndroid Build Coastguard Worker     }
5301*8975f5c5SAndroid Build Coastguard Worker 
5302*8975f5c5SAndroid Build Coastguard Worker     if (field.type()->getBasicType() != EbtStruct)
5303*8975f5c5SAndroid Build Coastguard Worker     {
5304*8975f5c5SAndroid Build Coastguard Worker         return;
5305*8975f5c5SAndroid Build Coastguard Worker     }
5306*8975f5c5SAndroid Build Coastguard Worker 
5307*8975f5c5SAndroid Build Coastguard Worker     // We're already inside a structure definition at this point, so add
5308*8975f5c5SAndroid Build Coastguard Worker     // one to the field's struct nesting.
5309*8975f5c5SAndroid Build Coastguard Worker     if (1 + field.type()->getDeepestStructNesting() > kWebGLMaxStructNesting)
5310*8975f5c5SAndroid Build Coastguard Worker     {
5311*8975f5c5SAndroid Build Coastguard Worker         std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
5312*8975f5c5SAndroid Build Coastguard Worker         if (field.type()->getStruct()->symbolType() == SymbolType::Empty)
5313*8975f5c5SAndroid Build Coastguard Worker         {
5314*8975f5c5SAndroid Build Coastguard Worker             // This may happen in case there are nested struct definitions. While they are also
5315*8975f5c5SAndroid Build Coastguard Worker             // invalid GLSL, they don't cause a syntax error.
5316*8975f5c5SAndroid Build Coastguard Worker             reasonStream << "Struct nesting";
5317*8975f5c5SAndroid Build Coastguard Worker         }
5318*8975f5c5SAndroid Build Coastguard Worker         else
5319*8975f5c5SAndroid Build Coastguard Worker         {
5320*8975f5c5SAndroid Build Coastguard Worker             reasonStream << "Reference of struct type " << field.type()->getStruct()->name();
5321*8975f5c5SAndroid Build Coastguard Worker         }
5322*8975f5c5SAndroid Build Coastguard Worker         reasonStream << " exceeds maximum allowed nesting level of " << kWebGLMaxStructNesting;
5323*8975f5c5SAndroid Build Coastguard Worker         std::string reason = reasonStream.str();
5324*8975f5c5SAndroid Build Coastguard Worker         error(line, reason.c_str(), field.name());
5325*8975f5c5SAndroid Build Coastguard Worker         return;
5326*8975f5c5SAndroid Build Coastguard Worker     }
5327*8975f5c5SAndroid Build Coastguard Worker }
5328*8975f5c5SAndroid Build Coastguard Worker 
5329*8975f5c5SAndroid Build Coastguard Worker //
5330*8975f5c5SAndroid Build Coastguard Worker // Parse an array index expression
5331*8975f5c5SAndroid Build Coastguard Worker //
addIndexExpression(TIntermTyped * baseExpression,const TSourceLoc & location,TIntermTyped * indexExpression)5332*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addIndexExpression(TIntermTyped *baseExpression,
5333*8975f5c5SAndroid Build Coastguard Worker                                                 const TSourceLoc &location,
5334*8975f5c5SAndroid Build Coastguard Worker                                                 TIntermTyped *indexExpression)
5335*8975f5c5SAndroid Build Coastguard Worker {
5336*8975f5c5SAndroid Build Coastguard Worker     if (!baseExpression->isArray() && !baseExpression->isMatrix() && !baseExpression->isVector())
5337*8975f5c5SAndroid Build Coastguard Worker     {
5338*8975f5c5SAndroid Build Coastguard Worker         if (baseExpression->getAsSymbolNode())
5339*8975f5c5SAndroid Build Coastguard Worker         {
5340*8975f5c5SAndroid Build Coastguard Worker             error(location, " left of '[' is not of type array, matrix, or vector ",
5341*8975f5c5SAndroid Build Coastguard Worker                   baseExpression->getAsSymbolNode()->getName());
5342*8975f5c5SAndroid Build Coastguard Worker         }
5343*8975f5c5SAndroid Build Coastguard Worker         else
5344*8975f5c5SAndroid Build Coastguard Worker         {
5345*8975f5c5SAndroid Build Coastguard Worker             error(location, " left of '[' is not of type array, matrix, or vector ", "expression");
5346*8975f5c5SAndroid Build Coastguard Worker         }
5347*8975f5c5SAndroid Build Coastguard Worker 
5348*8975f5c5SAndroid Build Coastguard Worker         return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
5349*8975f5c5SAndroid Build Coastguard Worker     }
5350*8975f5c5SAndroid Build Coastguard Worker 
5351*8975f5c5SAndroid Build Coastguard Worker     if (baseExpression->getQualifier() == EvqPerVertexIn)
5352*8975f5c5SAndroid Build Coastguard Worker     {
5353*8975f5c5SAndroid Build Coastguard Worker         if (mGeometryShaderInputPrimitiveType == EptUndefined &&
5354*8975f5c5SAndroid Build Coastguard Worker             mShaderType == GL_GEOMETRY_SHADER_EXT)
5355*8975f5c5SAndroid Build Coastguard Worker         {
5356*8975f5c5SAndroid Build Coastguard Worker             error(location, "missing input primitive declaration before indexing gl_in.", "[");
5357*8975f5c5SAndroid Build Coastguard Worker             return CreateZeroNode(TType(EbtFloat, EbpHigh, EvqConst));
5358*8975f5c5SAndroid Build Coastguard Worker         }
5359*8975f5c5SAndroid Build Coastguard Worker     }
5360*8975f5c5SAndroid Build Coastguard Worker 
5361*8975f5c5SAndroid Build Coastguard Worker     TIntermConstantUnion *indexConstantUnion = indexExpression->getAsConstantUnion();
5362*8975f5c5SAndroid Build Coastguard Worker 
5363*8975f5c5SAndroid Build Coastguard Worker     // ES3.2 or ES3.1's EXT_gpu_shader5 allow dynamically uniform expressions to be used as indices
5364*8975f5c5SAndroid Build Coastguard Worker     // of opaque types (samplers and atomic counters) as well as UBOs, but not SSBOs and images.
5365*8975f5c5SAndroid Build Coastguard Worker     bool allowUniformIndices = mShaderVersion >= 320 ||
5366*8975f5c5SAndroid Build Coastguard Worker                                isExtensionEnabled(TExtension::EXT_gpu_shader5) ||
5367*8975f5c5SAndroid Build Coastguard Worker                                isExtensionEnabled(TExtension::OES_gpu_shader5);
5368*8975f5c5SAndroid Build Coastguard Worker 
5369*8975f5c5SAndroid Build Coastguard Worker     // ANGLE should be able to fold any constant expressions resulting in an integer - but to be
5370*8975f5c5SAndroid Build Coastguard Worker     // safe we don't treat "EvqConst" that's evaluated according to the spec as being sufficient
5371*8975f5c5SAndroid Build Coastguard Worker     // for constness. Some interpretations of the spec have allowed constant expressions with side
5372*8975f5c5SAndroid Build Coastguard Worker     // effects - like array length() method on a non-constant array.
5373*8975f5c5SAndroid Build Coastguard Worker     if (indexExpression->getQualifier() != EvqConst || indexConstantUnion == nullptr)
5374*8975f5c5SAndroid Build Coastguard Worker     {
5375*8975f5c5SAndroid Build Coastguard Worker         if (baseExpression->isInterfaceBlock())
5376*8975f5c5SAndroid Build Coastguard Worker         {
5377*8975f5c5SAndroid Build Coastguard Worker             switch (baseExpression->getQualifier())
5378*8975f5c5SAndroid Build Coastguard Worker             {
5379*8975f5c5SAndroid Build Coastguard Worker                 case EvqPerVertexIn:
5380*8975f5c5SAndroid Build Coastguard Worker                     break;
5381*8975f5c5SAndroid Build Coastguard Worker                 case EvqUniform:
5382*8975f5c5SAndroid Build Coastguard Worker                     if (!allowUniformIndices)
5383*8975f5c5SAndroid Build Coastguard Worker                     {
5384*8975f5c5SAndroid Build Coastguard Worker                         error(location,
5385*8975f5c5SAndroid Build Coastguard Worker                               "array indexes for uniform block arrays must be constant integral "
5386*8975f5c5SAndroid Build Coastguard Worker                               "expressions",
5387*8975f5c5SAndroid Build Coastguard Worker                               "[");
5388*8975f5c5SAndroid Build Coastguard Worker                     }
5389*8975f5c5SAndroid Build Coastguard Worker                     break;
5390*8975f5c5SAndroid Build Coastguard Worker                 case EvqBuffer:
5391*8975f5c5SAndroid Build Coastguard Worker                     error(location,
5392*8975f5c5SAndroid Build Coastguard Worker                           "array indexes for shader storage block arrays must be constant integral "
5393*8975f5c5SAndroid Build Coastguard Worker                           "expressions",
5394*8975f5c5SAndroid Build Coastguard Worker                           "[");
5395*8975f5c5SAndroid Build Coastguard Worker                     break;
5396*8975f5c5SAndroid Build Coastguard Worker                 default:
5397*8975f5c5SAndroid Build Coastguard Worker                     // It's ok for shader I/O blocks to be dynamically indexed
5398*8975f5c5SAndroid Build Coastguard Worker                     if (!IsShaderIoBlock(baseExpression->getQualifier()) &&
5399*8975f5c5SAndroid Build Coastguard Worker                         baseExpression->getQualifier() != EvqPatchIn &&
5400*8975f5c5SAndroid Build Coastguard Worker                         baseExpression->getQualifier() != EvqPatchOut)
5401*8975f5c5SAndroid Build Coastguard Worker                     {
5402*8975f5c5SAndroid Build Coastguard Worker                         // We can reach here only in error cases.
5403*8975f5c5SAndroid Build Coastguard Worker                         ASSERT(mDiagnostics->numErrors() > 0);
5404*8975f5c5SAndroid Build Coastguard Worker                     }
5405*8975f5c5SAndroid Build Coastguard Worker                     break;
5406*8975f5c5SAndroid Build Coastguard Worker             }
5407*8975f5c5SAndroid Build Coastguard Worker         }
5408*8975f5c5SAndroid Build Coastguard Worker         else if (baseExpression->getQualifier() == EvqFragmentOut ||
5409*8975f5c5SAndroid Build Coastguard Worker                  baseExpression->getQualifier() == EvqFragmentInOut)
5410*8975f5c5SAndroid Build Coastguard Worker         {
5411*8975f5c5SAndroid Build Coastguard Worker             error(location,
5412*8975f5c5SAndroid Build Coastguard Worker                   "array indexes for fragment outputs must be constant integral expressions", "[");
5413*8975f5c5SAndroid Build Coastguard Worker         }
5414*8975f5c5SAndroid Build Coastguard Worker         else if (baseExpression->getQualifier() == EvqLastFragData)
5415*8975f5c5SAndroid Build Coastguard Worker         {
5416*8975f5c5SAndroid Build Coastguard Worker             error(location,
5417*8975f5c5SAndroid Build Coastguard Worker                   "array indexes for gl_LastFragData must be constant integral expressions", "[");
5418*8975f5c5SAndroid Build Coastguard Worker         }
5419*8975f5c5SAndroid Build Coastguard Worker         else if (mShaderSpec == SH_WEBGL2_SPEC && baseExpression->getQualifier() == EvqFragData)
5420*8975f5c5SAndroid Build Coastguard Worker         {
5421*8975f5c5SAndroid Build Coastguard Worker             error(location, "array index for gl_FragData must be constant zero", "[");
5422*8975f5c5SAndroid Build Coastguard Worker         }
5423*8975f5c5SAndroid Build Coastguard Worker         else if (mShaderSpec == SH_WEBGL2_SPEC &&
5424*8975f5c5SAndroid Build Coastguard Worker                  baseExpression->getQualifier() == EvqSecondaryFragDataEXT)
5425*8975f5c5SAndroid Build Coastguard Worker         {
5426*8975f5c5SAndroid Build Coastguard Worker             error(location, "array index for gl_SecondaryFragDataEXT must be constant zero", "[");
5427*8975f5c5SAndroid Build Coastguard Worker         }
5428*8975f5c5SAndroid Build Coastguard Worker         else if (baseExpression->isArray())
5429*8975f5c5SAndroid Build Coastguard Worker         {
5430*8975f5c5SAndroid Build Coastguard Worker             TBasicType elementType = baseExpression->getType().getBasicType();
5431*8975f5c5SAndroid Build Coastguard Worker 
5432*8975f5c5SAndroid Build Coastguard Worker             // Note: In Section 12.30 of the ESSL 3.00 spec on p143-144:
5433*8975f5c5SAndroid Build Coastguard Worker             //
5434*8975f5c5SAndroid Build Coastguard Worker             //   Indexing of arrays of samplers by constant-index-expressions is
5435*8975f5c5SAndroid Build Coastguard Worker             //   supported in GLSL ES 1.00. A constant-index-expression is an
5436*8975f5c5SAndroid Build Coastguard Worker             //   expression formed from constant-expressions and certain loop indices,
5437*8975f5c5SAndroid Build Coastguard Worker             //   defined for a subset of loop constructs. Should this functionality be
5438*8975f5c5SAndroid Build Coastguard Worker             //   included in GLSL ES 3.00?
5439*8975f5c5SAndroid Build Coastguard Worker             //
5440*8975f5c5SAndroid Build Coastguard Worker             //   RESOLUTION: No. Arrays of samplers may only be indexed by constant-
5441*8975f5c5SAndroid Build Coastguard Worker             //   integral-expressions.
5442*8975f5c5SAndroid Build Coastguard Worker             if (IsSampler(elementType) && !allowUniformIndices && mShaderVersion > 100)
5443*8975f5c5SAndroid Build Coastguard Worker             {
5444*8975f5c5SAndroid Build Coastguard Worker                 error(location, "array index for samplers must be constant integral expressions",
5445*8975f5c5SAndroid Build Coastguard Worker                       "[");
5446*8975f5c5SAndroid Build Coastguard Worker             }
5447*8975f5c5SAndroid Build Coastguard Worker             else if (IsImage(elementType))
5448*8975f5c5SAndroid Build Coastguard Worker             {
5449*8975f5c5SAndroid Build Coastguard Worker                 error(location,
5450*8975f5c5SAndroid Build Coastguard Worker                       "array indexes for image arrays must be constant integral expressions", "[");
5451*8975f5c5SAndroid Build Coastguard Worker             }
5452*8975f5c5SAndroid Build Coastguard Worker         }
5453*8975f5c5SAndroid Build Coastguard Worker     }
5454*8975f5c5SAndroid Build Coastguard Worker 
5455*8975f5c5SAndroid Build Coastguard Worker     if (indexConstantUnion)
5456*8975f5c5SAndroid Build Coastguard Worker     {
5457*8975f5c5SAndroid Build Coastguard Worker         // If an out-of-range index is not qualified as constant, the behavior in the spec is
5458*8975f5c5SAndroid Build Coastguard Worker         // undefined. This applies even if ANGLE has been able to constant fold it (ANGLE may
5459*8975f5c5SAndroid Build Coastguard Worker         // constant fold expressions that are not constant expressions). The most compatible way to
5460*8975f5c5SAndroid Build Coastguard Worker         // handle this case is to report a warning instead of an error and force the index to be in
5461*8975f5c5SAndroid Build Coastguard Worker         // the correct range.
5462*8975f5c5SAndroid Build Coastguard Worker         bool outOfRangeIndexIsError = indexExpression->getQualifier() == EvqConst;
5463*8975f5c5SAndroid Build Coastguard Worker         int index                   = 0;
5464*8975f5c5SAndroid Build Coastguard Worker         if (indexConstantUnion->getBasicType() == EbtInt)
5465*8975f5c5SAndroid Build Coastguard Worker         {
5466*8975f5c5SAndroid Build Coastguard Worker             index = indexConstantUnion->getIConst(0);
5467*8975f5c5SAndroid Build Coastguard Worker         }
5468*8975f5c5SAndroid Build Coastguard Worker         else if (indexConstantUnion->getBasicType() == EbtUInt)
5469*8975f5c5SAndroid Build Coastguard Worker         {
5470*8975f5c5SAndroid Build Coastguard Worker             index = static_cast<int>(indexConstantUnion->getUConst(0));
5471*8975f5c5SAndroid Build Coastguard Worker         }
5472*8975f5c5SAndroid Build Coastguard Worker 
5473*8975f5c5SAndroid Build Coastguard Worker         int safeIndex = -1;
5474*8975f5c5SAndroid Build Coastguard Worker 
5475*8975f5c5SAndroid Build Coastguard Worker         if (index < 0)
5476*8975f5c5SAndroid Build Coastguard Worker         {
5477*8975f5c5SAndroid Build Coastguard Worker             outOfRangeError(outOfRangeIndexIsError, location, "index expression is negative", "[]");
5478*8975f5c5SAndroid Build Coastguard Worker             safeIndex = 0;
5479*8975f5c5SAndroid Build Coastguard Worker         }
5480*8975f5c5SAndroid Build Coastguard Worker 
5481*8975f5c5SAndroid Build Coastguard Worker         if (!baseExpression->getType().isUnsizedArray())
5482*8975f5c5SAndroid Build Coastguard Worker         {
5483*8975f5c5SAndroid Build Coastguard Worker             if (baseExpression->isArray())
5484*8975f5c5SAndroid Build Coastguard Worker             {
5485*8975f5c5SAndroid Build Coastguard Worker                 if (baseExpression->getQualifier() == EvqFragData && index > 0)
5486*8975f5c5SAndroid Build Coastguard Worker                 {
5487*8975f5c5SAndroid Build Coastguard Worker                     if (!isExtensionEnabled(TExtension::EXT_draw_buffers))
5488*8975f5c5SAndroid Build Coastguard Worker                     {
5489*8975f5c5SAndroid Build Coastguard Worker                         outOfRangeError(outOfRangeIndexIsError, location,
5490*8975f5c5SAndroid Build Coastguard Worker                                         "array index for gl_FragData must be zero when "
5491*8975f5c5SAndroid Build Coastguard Worker                                         "GL_EXT_draw_buffers is disabled",
5492*8975f5c5SAndroid Build Coastguard Worker                                         "[]");
5493*8975f5c5SAndroid Build Coastguard Worker                         safeIndex = 0;
5494*8975f5c5SAndroid Build Coastguard Worker                     }
5495*8975f5c5SAndroid Build Coastguard Worker                 }
5496*8975f5c5SAndroid Build Coastguard Worker             }
5497*8975f5c5SAndroid Build Coastguard Worker             // Only do generic out-of-range check if similar error hasn't already been reported.
5498*8975f5c5SAndroid Build Coastguard Worker             if (safeIndex < 0)
5499*8975f5c5SAndroid Build Coastguard Worker             {
5500*8975f5c5SAndroid Build Coastguard Worker                 if (baseExpression->isArray())
5501*8975f5c5SAndroid Build Coastguard Worker                 {
5502*8975f5c5SAndroid Build Coastguard Worker                     safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
5503*8975f5c5SAndroid Build Coastguard Worker                                                    baseExpression->getOutermostArraySize(),
5504*8975f5c5SAndroid Build Coastguard Worker                                                    "array index out of range");
5505*8975f5c5SAndroid Build Coastguard Worker                 }
5506*8975f5c5SAndroid Build Coastguard Worker                 else if (baseExpression->isMatrix())
5507*8975f5c5SAndroid Build Coastguard Worker                 {
5508*8975f5c5SAndroid Build Coastguard Worker                     safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
5509*8975f5c5SAndroid Build Coastguard Worker                                                    baseExpression->getType().getCols(),
5510*8975f5c5SAndroid Build Coastguard Worker                                                    "matrix field selection out of range");
5511*8975f5c5SAndroid Build Coastguard Worker                 }
5512*8975f5c5SAndroid Build Coastguard Worker                 else
5513*8975f5c5SAndroid Build Coastguard Worker                 {
5514*8975f5c5SAndroid Build Coastguard Worker                     ASSERT(baseExpression->isVector());
5515*8975f5c5SAndroid Build Coastguard Worker                     safeIndex = checkIndexLessThan(outOfRangeIndexIsError, location, index,
5516*8975f5c5SAndroid Build Coastguard Worker                                                    baseExpression->getType().getNominalSize(),
5517*8975f5c5SAndroid Build Coastguard Worker                                                    "vector field selection out of range");
5518*8975f5c5SAndroid Build Coastguard Worker                 }
5519*8975f5c5SAndroid Build Coastguard Worker             }
5520*8975f5c5SAndroid Build Coastguard Worker 
5521*8975f5c5SAndroid Build Coastguard Worker             ASSERT(safeIndex >= 0);
5522*8975f5c5SAndroid Build Coastguard Worker             // Data of constant unions can't be changed, because it may be shared with other
5523*8975f5c5SAndroid Build Coastguard Worker             // constant unions or even builtins, like gl_MaxDrawBuffers. Instead use a new
5524*8975f5c5SAndroid Build Coastguard Worker             // sanitized object.
5525*8975f5c5SAndroid Build Coastguard Worker             if (safeIndex != index || indexConstantUnion->getBasicType() != EbtInt)
5526*8975f5c5SAndroid Build Coastguard Worker             {
5527*8975f5c5SAndroid Build Coastguard Worker                 TConstantUnion *safeConstantUnion = new TConstantUnion();
5528*8975f5c5SAndroid Build Coastguard Worker                 safeConstantUnion->setIConst(safeIndex);
5529*8975f5c5SAndroid Build Coastguard Worker                 indexExpression =
5530*8975f5c5SAndroid Build Coastguard Worker                     new TIntermConstantUnion(safeConstantUnion, TType(indexExpression->getType()));
5531*8975f5c5SAndroid Build Coastguard Worker             }
5532*8975f5c5SAndroid Build Coastguard Worker 
5533*8975f5c5SAndroid Build Coastguard Worker             TIntermBinary *node =
5534*8975f5c5SAndroid Build Coastguard Worker                 new TIntermBinary(EOpIndexDirect, baseExpression, indexExpression);
5535*8975f5c5SAndroid Build Coastguard Worker             node->setLine(location);
5536*8975f5c5SAndroid Build Coastguard Worker             return expressionOrFoldedResult(node);
5537*8975f5c5SAndroid Build Coastguard Worker         }
5538*8975f5c5SAndroid Build Coastguard Worker     }
5539*8975f5c5SAndroid Build Coastguard Worker 
5540*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(indexExpression);
5541*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *node = new TIntermBinary(EOpIndexIndirect, baseExpression, indexExpression);
5542*8975f5c5SAndroid Build Coastguard Worker     node->setLine(location);
5543*8975f5c5SAndroid Build Coastguard Worker     // Indirect indexing can never be constant folded.
5544*8975f5c5SAndroid Build Coastguard Worker     return node;
5545*8975f5c5SAndroid Build Coastguard Worker }
5546*8975f5c5SAndroid Build Coastguard Worker 
checkIndexLessThan(bool outOfRangeIndexIsError,const TSourceLoc & location,int index,unsigned int arraySize,const char * reason)5547*8975f5c5SAndroid Build Coastguard Worker int TParseContext::checkIndexLessThan(bool outOfRangeIndexIsError,
5548*8975f5c5SAndroid Build Coastguard Worker                                       const TSourceLoc &location,
5549*8975f5c5SAndroid Build Coastguard Worker                                       int index,
5550*8975f5c5SAndroid Build Coastguard Worker                                       unsigned int arraySize,
5551*8975f5c5SAndroid Build Coastguard Worker                                       const char *reason)
5552*8975f5c5SAndroid Build Coastguard Worker {
5553*8975f5c5SAndroid Build Coastguard Worker     // A negative index should already have been checked.
5554*8975f5c5SAndroid Build Coastguard Worker     ASSERT(index >= 0);
5555*8975f5c5SAndroid Build Coastguard Worker     if (static_cast<unsigned int>(index) >= arraySize)
5556*8975f5c5SAndroid Build Coastguard Worker     {
5557*8975f5c5SAndroid Build Coastguard Worker         std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
5558*8975f5c5SAndroid Build Coastguard Worker         reasonStream << reason << " '" << index << "'";
5559*8975f5c5SAndroid Build Coastguard Worker         std::string token = reasonStream.str();
5560*8975f5c5SAndroid Build Coastguard Worker         outOfRangeError(outOfRangeIndexIsError, location, reason, "[]");
5561*8975f5c5SAndroid Build Coastguard Worker         return arraySize - 1;
5562*8975f5c5SAndroid Build Coastguard Worker     }
5563*8975f5c5SAndroid Build Coastguard Worker     return index;
5564*8975f5c5SAndroid Build Coastguard Worker }
5565*8975f5c5SAndroid Build Coastguard Worker 
addFieldSelectionExpression(TIntermTyped * baseExpression,const TSourceLoc & dotLocation,const ImmutableString & fieldString,const TSourceLoc & fieldLocation)5566*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addFieldSelectionExpression(TIntermTyped *baseExpression,
5567*8975f5c5SAndroid Build Coastguard Worker                                                          const TSourceLoc &dotLocation,
5568*8975f5c5SAndroid Build Coastguard Worker                                                          const ImmutableString &fieldString,
5569*8975f5c5SAndroid Build Coastguard Worker                                                          const TSourceLoc &fieldLocation)
5570*8975f5c5SAndroid Build Coastguard Worker {
5571*8975f5c5SAndroid Build Coastguard Worker     if (baseExpression->isArray())
5572*8975f5c5SAndroid Build Coastguard Worker     {
5573*8975f5c5SAndroid Build Coastguard Worker         error(fieldLocation, "cannot apply dot operator to an array", ".");
5574*8975f5c5SAndroid Build Coastguard Worker         return baseExpression;
5575*8975f5c5SAndroid Build Coastguard Worker     }
5576*8975f5c5SAndroid Build Coastguard Worker 
5577*8975f5c5SAndroid Build Coastguard Worker     if (baseExpression->isVector())
5578*8975f5c5SAndroid Build Coastguard Worker     {
5579*8975f5c5SAndroid Build Coastguard Worker         TVector<int> fieldOffsets;
5580*8975f5c5SAndroid Build Coastguard Worker         if (!parseVectorFields(fieldLocation, fieldString, baseExpression->getNominalSize(),
5581*8975f5c5SAndroid Build Coastguard Worker                                &fieldOffsets))
5582*8975f5c5SAndroid Build Coastguard Worker         {
5583*8975f5c5SAndroid Build Coastguard Worker             fieldOffsets.resize(1);
5584*8975f5c5SAndroid Build Coastguard Worker             fieldOffsets[0] = 0;
5585*8975f5c5SAndroid Build Coastguard Worker         }
5586*8975f5c5SAndroid Build Coastguard Worker         TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldOffsets);
5587*8975f5c5SAndroid Build Coastguard Worker         node->setLine(dotLocation);
5588*8975f5c5SAndroid Build Coastguard Worker 
5589*8975f5c5SAndroid Build Coastguard Worker         return node->fold(mDiagnostics);
5590*8975f5c5SAndroid Build Coastguard Worker     }
5591*8975f5c5SAndroid Build Coastguard Worker     else if (baseExpression->getBasicType() == EbtStruct)
5592*8975f5c5SAndroid Build Coastguard Worker     {
5593*8975f5c5SAndroid Build Coastguard Worker         const TFieldList &fields = baseExpression->getType().getStruct()->fields();
5594*8975f5c5SAndroid Build Coastguard Worker         if (fields.empty())
5595*8975f5c5SAndroid Build Coastguard Worker         {
5596*8975f5c5SAndroid Build Coastguard Worker             error(dotLocation, "structure has no fields", "Internal Error");
5597*8975f5c5SAndroid Build Coastguard Worker             return baseExpression;
5598*8975f5c5SAndroid Build Coastguard Worker         }
5599*8975f5c5SAndroid Build Coastguard Worker         else
5600*8975f5c5SAndroid Build Coastguard Worker         {
5601*8975f5c5SAndroid Build Coastguard Worker             bool fieldFound = false;
5602*8975f5c5SAndroid Build Coastguard Worker             unsigned int i;
5603*8975f5c5SAndroid Build Coastguard Worker             for (i = 0; i < fields.size(); ++i)
5604*8975f5c5SAndroid Build Coastguard Worker             {
5605*8975f5c5SAndroid Build Coastguard Worker                 if (fields[i]->name() == fieldString)
5606*8975f5c5SAndroid Build Coastguard Worker                 {
5607*8975f5c5SAndroid Build Coastguard Worker                     fieldFound = true;
5608*8975f5c5SAndroid Build Coastguard Worker                     break;
5609*8975f5c5SAndroid Build Coastguard Worker                 }
5610*8975f5c5SAndroid Build Coastguard Worker             }
5611*8975f5c5SAndroid Build Coastguard Worker             if (fieldFound)
5612*8975f5c5SAndroid Build Coastguard Worker             {
5613*8975f5c5SAndroid Build Coastguard Worker                 TIntermTyped *index = CreateIndexNode(i);
5614*8975f5c5SAndroid Build Coastguard Worker                 index->setLine(fieldLocation);
5615*8975f5c5SAndroid Build Coastguard Worker                 TIntermBinary *node =
5616*8975f5c5SAndroid Build Coastguard Worker                     new TIntermBinary(EOpIndexDirectStruct, baseExpression, index);
5617*8975f5c5SAndroid Build Coastguard Worker                 node->setLine(dotLocation);
5618*8975f5c5SAndroid Build Coastguard Worker                 return expressionOrFoldedResult(node);
5619*8975f5c5SAndroid Build Coastguard Worker             }
5620*8975f5c5SAndroid Build Coastguard Worker             else
5621*8975f5c5SAndroid Build Coastguard Worker             {
5622*8975f5c5SAndroid Build Coastguard Worker                 error(dotLocation, " no such field in structure", fieldString);
5623*8975f5c5SAndroid Build Coastguard Worker                 return baseExpression;
5624*8975f5c5SAndroid Build Coastguard Worker             }
5625*8975f5c5SAndroid Build Coastguard Worker         }
5626*8975f5c5SAndroid Build Coastguard Worker     }
5627*8975f5c5SAndroid Build Coastguard Worker     else if (baseExpression->isInterfaceBlock())
5628*8975f5c5SAndroid Build Coastguard Worker     {
5629*8975f5c5SAndroid Build Coastguard Worker         const TFieldList &fields = baseExpression->getType().getInterfaceBlock()->fields();
5630*8975f5c5SAndroid Build Coastguard Worker         if (fields.empty())
5631*8975f5c5SAndroid Build Coastguard Worker         {
5632*8975f5c5SAndroid Build Coastguard Worker             error(dotLocation, "interface block has no fields", "Internal Error");
5633*8975f5c5SAndroid Build Coastguard Worker             return baseExpression;
5634*8975f5c5SAndroid Build Coastguard Worker         }
5635*8975f5c5SAndroid Build Coastguard Worker         else
5636*8975f5c5SAndroid Build Coastguard Worker         {
5637*8975f5c5SAndroid Build Coastguard Worker             bool fieldFound = false;
5638*8975f5c5SAndroid Build Coastguard Worker             unsigned int i;
5639*8975f5c5SAndroid Build Coastguard Worker             for (i = 0; i < fields.size(); ++i)
5640*8975f5c5SAndroid Build Coastguard Worker             {
5641*8975f5c5SAndroid Build Coastguard Worker                 if (fields[i]->name() == fieldString)
5642*8975f5c5SAndroid Build Coastguard Worker                 {
5643*8975f5c5SAndroid Build Coastguard Worker                     fieldFound = true;
5644*8975f5c5SAndroid Build Coastguard Worker                     break;
5645*8975f5c5SAndroid Build Coastguard Worker                 }
5646*8975f5c5SAndroid Build Coastguard Worker             }
5647*8975f5c5SAndroid Build Coastguard Worker             if (fieldFound)
5648*8975f5c5SAndroid Build Coastguard Worker             {
5649*8975f5c5SAndroid Build Coastguard Worker                 TIntermTyped *index = CreateIndexNode(i);
5650*8975f5c5SAndroid Build Coastguard Worker                 index->setLine(fieldLocation);
5651*8975f5c5SAndroid Build Coastguard Worker                 TIntermBinary *node =
5652*8975f5c5SAndroid Build Coastguard Worker                     new TIntermBinary(EOpIndexDirectInterfaceBlock, baseExpression, index);
5653*8975f5c5SAndroid Build Coastguard Worker                 node->setLine(dotLocation);
5654*8975f5c5SAndroid Build Coastguard Worker                 // Indexing interface blocks can never be constant folded.
5655*8975f5c5SAndroid Build Coastguard Worker                 return node;
5656*8975f5c5SAndroid Build Coastguard Worker             }
5657*8975f5c5SAndroid Build Coastguard Worker             else
5658*8975f5c5SAndroid Build Coastguard Worker             {
5659*8975f5c5SAndroid Build Coastguard Worker                 error(dotLocation, " no such field in interface block", fieldString);
5660*8975f5c5SAndroid Build Coastguard Worker                 return baseExpression;
5661*8975f5c5SAndroid Build Coastguard Worker             }
5662*8975f5c5SAndroid Build Coastguard Worker         }
5663*8975f5c5SAndroid Build Coastguard Worker     }
5664*8975f5c5SAndroid Build Coastguard Worker     else
5665*8975f5c5SAndroid Build Coastguard Worker     {
5666*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 300)
5667*8975f5c5SAndroid Build Coastguard Worker         {
5668*8975f5c5SAndroid Build Coastguard Worker             error(dotLocation, " field selection requires structure or vector on left hand side",
5669*8975f5c5SAndroid Build Coastguard Worker                   fieldString);
5670*8975f5c5SAndroid Build Coastguard Worker         }
5671*8975f5c5SAndroid Build Coastguard Worker         else
5672*8975f5c5SAndroid Build Coastguard Worker         {
5673*8975f5c5SAndroid Build Coastguard Worker             error(dotLocation,
5674*8975f5c5SAndroid Build Coastguard Worker                   " field selection requires structure, vector, or interface block on left hand "
5675*8975f5c5SAndroid Build Coastguard Worker                   "side",
5676*8975f5c5SAndroid Build Coastguard Worker                   fieldString);
5677*8975f5c5SAndroid Build Coastguard Worker         }
5678*8975f5c5SAndroid Build Coastguard Worker         return baseExpression;
5679*8975f5c5SAndroid Build Coastguard Worker     }
5680*8975f5c5SAndroid Build Coastguard Worker }
5681*8975f5c5SAndroid Build Coastguard Worker 
parseLayoutQualifier(const ImmutableString & qualifierType,const TSourceLoc & qualifierTypeLine)5682*8975f5c5SAndroid Build Coastguard Worker TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType,
5683*8975f5c5SAndroid Build Coastguard Worker                                                      const TSourceLoc &qualifierTypeLine)
5684*8975f5c5SAndroid Build Coastguard Worker {
5685*8975f5c5SAndroid Build Coastguard Worker     TLayoutQualifier qualifier = TLayoutQualifier::Create();
5686*8975f5c5SAndroid Build Coastguard Worker 
5687*8975f5c5SAndroid Build Coastguard Worker     if (qualifierType == "shared")
5688*8975f5c5SAndroid Build Coastguard Worker     {
5689*8975f5c5SAndroid Build Coastguard Worker         if (sh::IsWebGLBasedSpec(mShaderSpec))
5690*8975f5c5SAndroid Build Coastguard Worker         {
5691*8975f5c5SAndroid Build Coastguard Worker             error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "shared");
5692*8975f5c5SAndroid Build Coastguard Worker         }
5693*8975f5c5SAndroid Build Coastguard Worker         qualifier.blockStorage = EbsShared;
5694*8975f5c5SAndroid Build Coastguard Worker     }
5695*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "packed")
5696*8975f5c5SAndroid Build Coastguard Worker     {
5697*8975f5c5SAndroid Build Coastguard Worker         if (sh::IsWebGLBasedSpec(mShaderSpec))
5698*8975f5c5SAndroid Build Coastguard Worker         {
5699*8975f5c5SAndroid Build Coastguard Worker             error(qualifierTypeLine, "Only std140 layout is allowed in WebGL", "packed");
5700*8975f5c5SAndroid Build Coastguard Worker         }
5701*8975f5c5SAndroid Build Coastguard Worker         qualifier.blockStorage = EbsPacked;
5702*8975f5c5SAndroid Build Coastguard Worker     }
5703*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "std430")
5704*8975f5c5SAndroid Build Coastguard Worker     {
5705*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5706*8975f5c5SAndroid Build Coastguard Worker         qualifier.blockStorage = EbsStd430;
5707*8975f5c5SAndroid Build Coastguard Worker     }
5708*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "std140")
5709*8975f5c5SAndroid Build Coastguard Worker     {
5710*8975f5c5SAndroid Build Coastguard Worker         qualifier.blockStorage = EbsStd140;
5711*8975f5c5SAndroid Build Coastguard Worker     }
5712*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "row_major")
5713*8975f5c5SAndroid Build Coastguard Worker     {
5714*8975f5c5SAndroid Build Coastguard Worker         qualifier.matrixPacking = EmpRowMajor;
5715*8975f5c5SAndroid Build Coastguard Worker     }
5716*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "column_major")
5717*8975f5c5SAndroid Build Coastguard Worker     {
5718*8975f5c5SAndroid Build Coastguard Worker         qualifier.matrixPacking = EmpColumnMajor;
5719*8975f5c5SAndroid Build Coastguard Worker     }
5720*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "location")
5721*8975f5c5SAndroid Build Coastguard Worker     {
5722*8975f5c5SAndroid Build Coastguard Worker         error(qualifierTypeLine, "invalid layout qualifier: location requires an argument",
5723*8975f5c5SAndroid Build Coastguard Worker               qualifierType);
5724*8975f5c5SAndroid Build Coastguard Worker     }
5725*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "yuv" && mShaderType == GL_FRAGMENT_SHADER)
5726*8975f5c5SAndroid Build Coastguard Worker     {
5727*8975f5c5SAndroid Build Coastguard Worker         if (checkCanUseExtension(qualifierTypeLine, TExtension::EXT_YUV_target))
5728*8975f5c5SAndroid Build Coastguard Worker         {
5729*8975f5c5SAndroid Build Coastguard Worker             qualifier.yuv = true;
5730*8975f5c5SAndroid Build Coastguard Worker         }
5731*8975f5c5SAndroid Build Coastguard Worker     }
5732*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "early_fragment_tests")
5733*8975f5c5SAndroid Build Coastguard Worker     {
5734*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5735*8975f5c5SAndroid Build Coastguard Worker         qualifier.earlyFragmentTests = true;
5736*8975f5c5SAndroid Build Coastguard Worker     }
5737*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "rgba32f")
5738*8975f5c5SAndroid Build Coastguard Worker     {
5739*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5740*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifRGBA32F;
5741*8975f5c5SAndroid Build Coastguard Worker     }
5742*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "rgba16f")
5743*8975f5c5SAndroid Build Coastguard Worker     {
5744*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5745*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifRGBA16F;
5746*8975f5c5SAndroid Build Coastguard Worker     }
5747*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "r32f")
5748*8975f5c5SAndroid Build Coastguard Worker     {
5749*8975f5c5SAndroid Build Coastguard Worker         if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
5750*8975f5c5SAndroid Build Coastguard Worker         {
5751*8975f5c5SAndroid Build Coastguard Worker             checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5752*8975f5c5SAndroid Build Coastguard Worker         }
5753*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifR32F;
5754*8975f5c5SAndroid Build Coastguard Worker     }
5755*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "rgba8")
5756*8975f5c5SAndroid Build Coastguard Worker     {
5757*8975f5c5SAndroid Build Coastguard Worker         if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
5758*8975f5c5SAndroid Build Coastguard Worker         {
5759*8975f5c5SAndroid Build Coastguard Worker             checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5760*8975f5c5SAndroid Build Coastguard Worker         }
5761*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifRGBA8;
5762*8975f5c5SAndroid Build Coastguard Worker     }
5763*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "rgba8_snorm")
5764*8975f5c5SAndroid Build Coastguard Worker     {
5765*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5766*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifRGBA8_SNORM;
5767*8975f5c5SAndroid Build Coastguard Worker     }
5768*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "rgba32i")
5769*8975f5c5SAndroid Build Coastguard Worker     {
5770*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5771*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifRGBA32I;
5772*8975f5c5SAndroid Build Coastguard Worker     }
5773*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "rgba16i")
5774*8975f5c5SAndroid Build Coastguard Worker     {
5775*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5776*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifRGBA16I;
5777*8975f5c5SAndroid Build Coastguard Worker     }
5778*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "rgba8i")
5779*8975f5c5SAndroid Build Coastguard Worker     {
5780*8975f5c5SAndroid Build Coastguard Worker         if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
5781*8975f5c5SAndroid Build Coastguard Worker         {
5782*8975f5c5SAndroid Build Coastguard Worker             checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5783*8975f5c5SAndroid Build Coastguard Worker         }
5784*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifRGBA8I;
5785*8975f5c5SAndroid Build Coastguard Worker     }
5786*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "r32i")
5787*8975f5c5SAndroid Build Coastguard Worker     {
5788*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5789*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifR32I;
5790*8975f5c5SAndroid Build Coastguard Worker     }
5791*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "rgba32ui")
5792*8975f5c5SAndroid Build Coastguard Worker     {
5793*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5794*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifRGBA32UI;
5795*8975f5c5SAndroid Build Coastguard Worker     }
5796*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "rgba16ui")
5797*8975f5c5SAndroid Build Coastguard Worker     {
5798*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5799*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifRGBA16UI;
5800*8975f5c5SAndroid Build Coastguard Worker     }
5801*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "rgba8ui")
5802*8975f5c5SAndroid Build Coastguard Worker     {
5803*8975f5c5SAndroid Build Coastguard Worker         if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
5804*8975f5c5SAndroid Build Coastguard Worker         {
5805*8975f5c5SAndroid Build Coastguard Worker             checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5806*8975f5c5SAndroid Build Coastguard Worker         }
5807*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifRGBA8UI;
5808*8975f5c5SAndroid Build Coastguard Worker     }
5809*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "r32ui")
5810*8975f5c5SAndroid Build Coastguard Worker     {
5811*8975f5c5SAndroid Build Coastguard Worker         if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
5812*8975f5c5SAndroid Build Coastguard Worker         {
5813*8975f5c5SAndroid Build Coastguard Worker             checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
5814*8975f5c5SAndroid Build Coastguard Worker         }
5815*8975f5c5SAndroid Build Coastguard Worker         qualifier.imageInternalFormat = EiifR32UI;
5816*8975f5c5SAndroid Build Coastguard Worker     }
5817*8975f5c5SAndroid Build Coastguard Worker     else if (mShaderType == GL_GEOMETRY_SHADER_EXT &&
5818*8975f5c5SAndroid Build Coastguard Worker              (mShaderVersion >= 320 ||
5819*8975f5c5SAndroid Build Coastguard Worker               (checkCanUseOneOfExtensions(
5820*8975f5c5SAndroid Build Coastguard Worker                    qualifierTypeLine,
5821*8975f5c5SAndroid Build Coastguard Worker                    std::array<TExtension, 2u>{
5822*8975f5c5SAndroid Build Coastguard Worker                        {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}}) &&
5823*8975f5c5SAndroid Build Coastguard Worker                checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310))))
5824*8975f5c5SAndroid Build Coastguard Worker     {
5825*8975f5c5SAndroid Build Coastguard Worker         if (qualifierType == "points")
5826*8975f5c5SAndroid Build Coastguard Worker         {
5827*8975f5c5SAndroid Build Coastguard Worker             qualifier.primitiveType = EptPoints;
5828*8975f5c5SAndroid Build Coastguard Worker         }
5829*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "lines")
5830*8975f5c5SAndroid Build Coastguard Worker         {
5831*8975f5c5SAndroid Build Coastguard Worker             qualifier.primitiveType = EptLines;
5832*8975f5c5SAndroid Build Coastguard Worker         }
5833*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "lines_adjacency")
5834*8975f5c5SAndroid Build Coastguard Worker         {
5835*8975f5c5SAndroid Build Coastguard Worker             qualifier.primitiveType = EptLinesAdjacency;
5836*8975f5c5SAndroid Build Coastguard Worker         }
5837*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "triangles")
5838*8975f5c5SAndroid Build Coastguard Worker         {
5839*8975f5c5SAndroid Build Coastguard Worker             qualifier.primitiveType = EptTriangles;
5840*8975f5c5SAndroid Build Coastguard Worker         }
5841*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "triangles_adjacency")
5842*8975f5c5SAndroid Build Coastguard Worker         {
5843*8975f5c5SAndroid Build Coastguard Worker             qualifier.primitiveType = EptTrianglesAdjacency;
5844*8975f5c5SAndroid Build Coastguard Worker         }
5845*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "line_strip")
5846*8975f5c5SAndroid Build Coastguard Worker         {
5847*8975f5c5SAndroid Build Coastguard Worker             qualifier.primitiveType = EptLineStrip;
5848*8975f5c5SAndroid Build Coastguard Worker         }
5849*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "triangle_strip")
5850*8975f5c5SAndroid Build Coastguard Worker         {
5851*8975f5c5SAndroid Build Coastguard Worker             qualifier.primitiveType = EptTriangleStrip;
5852*8975f5c5SAndroid Build Coastguard Worker         }
5853*8975f5c5SAndroid Build Coastguard Worker         else
5854*8975f5c5SAndroid Build Coastguard Worker         {
5855*8975f5c5SAndroid Build Coastguard Worker             error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
5856*8975f5c5SAndroid Build Coastguard Worker         }
5857*8975f5c5SAndroid Build Coastguard Worker     }
5858*8975f5c5SAndroid Build Coastguard Worker     else if (mShaderType == GL_TESS_EVALUATION_SHADER_EXT &&
5859*8975f5c5SAndroid Build Coastguard Worker              (mShaderVersion >= 320 ||
5860*8975f5c5SAndroid Build Coastguard Worker               (checkCanUseOneOfExtensions(
5861*8975f5c5SAndroid Build Coastguard Worker                    qualifierTypeLine,
5862*8975f5c5SAndroid Build Coastguard Worker                    std::array<TExtension, 2u>{{TExtension::EXT_tessellation_shader,
5863*8975f5c5SAndroid Build Coastguard Worker                                                TExtension::OES_tessellation_shader}}) &&
5864*8975f5c5SAndroid Build Coastguard Worker                checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310))))
5865*8975f5c5SAndroid Build Coastguard Worker     {
5866*8975f5c5SAndroid Build Coastguard Worker         if (qualifierType == "triangles")
5867*8975f5c5SAndroid Build Coastguard Worker         {
5868*8975f5c5SAndroid Build Coastguard Worker             qualifier.tesPrimitiveType = EtetTriangles;
5869*8975f5c5SAndroid Build Coastguard Worker         }
5870*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "quads")
5871*8975f5c5SAndroid Build Coastguard Worker         {
5872*8975f5c5SAndroid Build Coastguard Worker             qualifier.tesPrimitiveType = EtetQuads;
5873*8975f5c5SAndroid Build Coastguard Worker         }
5874*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "isolines")
5875*8975f5c5SAndroid Build Coastguard Worker         {
5876*8975f5c5SAndroid Build Coastguard Worker             qualifier.tesPrimitiveType = EtetIsolines;
5877*8975f5c5SAndroid Build Coastguard Worker         }
5878*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "equal_spacing")
5879*8975f5c5SAndroid Build Coastguard Worker         {
5880*8975f5c5SAndroid Build Coastguard Worker             qualifier.tesVertexSpacingType = EtetEqualSpacing;
5881*8975f5c5SAndroid Build Coastguard Worker         }
5882*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "fractional_even_spacing")
5883*8975f5c5SAndroid Build Coastguard Worker         {
5884*8975f5c5SAndroid Build Coastguard Worker             qualifier.tesVertexSpacingType = EtetFractionalEvenSpacing;
5885*8975f5c5SAndroid Build Coastguard Worker         }
5886*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "fractional_odd_spacing")
5887*8975f5c5SAndroid Build Coastguard Worker         {
5888*8975f5c5SAndroid Build Coastguard Worker             qualifier.tesVertexSpacingType = EtetFractionalOddSpacing;
5889*8975f5c5SAndroid Build Coastguard Worker         }
5890*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "cw")
5891*8975f5c5SAndroid Build Coastguard Worker         {
5892*8975f5c5SAndroid Build Coastguard Worker             qualifier.tesOrderingType = EtetCw;
5893*8975f5c5SAndroid Build Coastguard Worker         }
5894*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "ccw")
5895*8975f5c5SAndroid Build Coastguard Worker         {
5896*8975f5c5SAndroid Build Coastguard Worker             qualifier.tesOrderingType = EtetCcw;
5897*8975f5c5SAndroid Build Coastguard Worker         }
5898*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "point_mode")
5899*8975f5c5SAndroid Build Coastguard Worker         {
5900*8975f5c5SAndroid Build Coastguard Worker             qualifier.tesPointType = EtetPointMode;
5901*8975f5c5SAndroid Build Coastguard Worker         }
5902*8975f5c5SAndroid Build Coastguard Worker         else
5903*8975f5c5SAndroid Build Coastguard Worker         {
5904*8975f5c5SAndroid Build Coastguard Worker             error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
5905*8975f5c5SAndroid Build Coastguard Worker         }
5906*8975f5c5SAndroid Build Coastguard Worker     }
5907*8975f5c5SAndroid Build Coastguard Worker     else if (mShaderType == GL_FRAGMENT_SHADER)
5908*8975f5c5SAndroid Build Coastguard Worker     {
5909*8975f5c5SAndroid Build Coastguard Worker         if (qualifierType == "noncoherent")
5910*8975f5c5SAndroid Build Coastguard Worker         {
5911*8975f5c5SAndroid Build Coastguard Worker             if (checkCanUseOneOfExtensions(
5912*8975f5c5SAndroid Build Coastguard Worker                     qualifierTypeLine,
5913*8975f5c5SAndroid Build Coastguard Worker                     std::array<TExtension, 2u>{
5914*8975f5c5SAndroid Build Coastguard Worker                         {TExtension::EXT_shader_framebuffer_fetch,
5915*8975f5c5SAndroid Build Coastguard Worker                          TExtension::EXT_shader_framebuffer_fetch_non_coherent}}))
5916*8975f5c5SAndroid Build Coastguard Worker             {
5917*8975f5c5SAndroid Build Coastguard Worker                 checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 100);
5918*8975f5c5SAndroid Build Coastguard Worker                 qualifier.noncoherent = true;
5919*8975f5c5SAndroid Build Coastguard Worker             }
5920*8975f5c5SAndroid Build Coastguard Worker         }
5921*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_multiply")
5922*8975f5c5SAndroid Build Coastguard Worker         {
5923*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Multiply, &qualifier);
5924*8975f5c5SAndroid Build Coastguard Worker         }
5925*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_screen")
5926*8975f5c5SAndroid Build Coastguard Worker         {
5927*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Screen, &qualifier);
5928*8975f5c5SAndroid Build Coastguard Worker         }
5929*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_overlay")
5930*8975f5c5SAndroid Build Coastguard Worker         {
5931*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Overlay, &qualifier);
5932*8975f5c5SAndroid Build Coastguard Worker         }
5933*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_darken")
5934*8975f5c5SAndroid Build Coastguard Worker         {
5935*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Darken, &qualifier);
5936*8975f5c5SAndroid Build Coastguard Worker         }
5937*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_lighten")
5938*8975f5c5SAndroid Build Coastguard Worker         {
5939*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Lighten, &qualifier);
5940*8975f5c5SAndroid Build Coastguard Worker         }
5941*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_colordodge")
5942*8975f5c5SAndroid Build Coastguard Worker         {
5943*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Colordodge, &qualifier);
5944*8975f5c5SAndroid Build Coastguard Worker         }
5945*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_colorburn")
5946*8975f5c5SAndroid Build Coastguard Worker         {
5947*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Colorburn, &qualifier);
5948*8975f5c5SAndroid Build Coastguard Worker         }
5949*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_hardlight")
5950*8975f5c5SAndroid Build Coastguard Worker         {
5951*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Hardlight, &qualifier);
5952*8975f5c5SAndroid Build Coastguard Worker         }
5953*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_softlight")
5954*8975f5c5SAndroid Build Coastguard Worker         {
5955*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Softlight, &qualifier);
5956*8975f5c5SAndroid Build Coastguard Worker         }
5957*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_difference")
5958*8975f5c5SAndroid Build Coastguard Worker         {
5959*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Difference, &qualifier);
5960*8975f5c5SAndroid Build Coastguard Worker         }
5961*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_exclusion")
5962*8975f5c5SAndroid Build Coastguard Worker         {
5963*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::Exclusion, &qualifier);
5964*8975f5c5SAndroid Build Coastguard Worker         }
5965*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_hsl_hue")
5966*8975f5c5SAndroid Build Coastguard Worker         {
5967*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::HslHue, &qualifier);
5968*8975f5c5SAndroid Build Coastguard Worker         }
5969*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_hsl_saturation")
5970*8975f5c5SAndroid Build Coastguard Worker         {
5971*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::HslSaturation, &qualifier);
5972*8975f5c5SAndroid Build Coastguard Worker         }
5973*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_hsl_color")
5974*8975f5c5SAndroid Build Coastguard Worker         {
5975*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::HslColor, &qualifier);
5976*8975f5c5SAndroid Build Coastguard Worker         }
5977*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_hsl_luminosity")
5978*8975f5c5SAndroid Build Coastguard Worker         {
5979*8975f5c5SAndroid Build Coastguard Worker             AddAdvancedBlendEquation(gl::BlendEquationType::HslLuminosity, &qualifier);
5980*8975f5c5SAndroid Build Coastguard Worker         }
5981*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "blend_support_all_equations")
5982*8975f5c5SAndroid Build Coastguard Worker         {
5983*8975f5c5SAndroid Build Coastguard Worker             qualifier.advancedBlendEquations.setAll();
5984*8975f5c5SAndroid Build Coastguard Worker         }
5985*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "depth_any")
5986*8975f5c5SAndroid Build Coastguard Worker         {
5987*8975f5c5SAndroid Build Coastguard Worker             qualifier.depth = EdAny;
5988*8975f5c5SAndroid Build Coastguard Worker         }
5989*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "depth_greater")
5990*8975f5c5SAndroid Build Coastguard Worker         {
5991*8975f5c5SAndroid Build Coastguard Worker             qualifier.depth = EdGreater;
5992*8975f5c5SAndroid Build Coastguard Worker         }
5993*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "depth_less")
5994*8975f5c5SAndroid Build Coastguard Worker         {
5995*8975f5c5SAndroid Build Coastguard Worker             qualifier.depth = EdLess;
5996*8975f5c5SAndroid Build Coastguard Worker         }
5997*8975f5c5SAndroid Build Coastguard Worker         else if (qualifierType == "depth_unchanged" && !sh::IsWebGLBasedSpec(mShaderSpec))
5998*8975f5c5SAndroid Build Coastguard Worker         {
5999*8975f5c5SAndroid Build Coastguard Worker             qualifier.depth = EdUnchanged;
6000*8975f5c5SAndroid Build Coastguard Worker         }
6001*8975f5c5SAndroid Build Coastguard Worker         else
6002*8975f5c5SAndroid Build Coastguard Worker         {
6003*8975f5c5SAndroid Build Coastguard Worker             error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
6004*8975f5c5SAndroid Build Coastguard Worker         }
6005*8975f5c5SAndroid Build Coastguard Worker 
6006*8975f5c5SAndroid Build Coastguard Worker         if (qualifier.advancedBlendEquations.any() && mShaderVersion < 320)
6007*8975f5c5SAndroid Build Coastguard Worker         {
6008*8975f5c5SAndroid Build Coastguard Worker             if (!checkCanUseExtension(qualifierTypeLine, TExtension::KHR_blend_equation_advanced))
6009*8975f5c5SAndroid Build Coastguard Worker             {
6010*8975f5c5SAndroid Build Coastguard Worker                 qualifier.advancedBlendEquations.reset();
6011*8975f5c5SAndroid Build Coastguard Worker             }
6012*8975f5c5SAndroid Build Coastguard Worker         }
6013*8975f5c5SAndroid Build Coastguard Worker     }
6014*8975f5c5SAndroid Build Coastguard Worker     else
6015*8975f5c5SAndroid Build Coastguard Worker     {
6016*8975f5c5SAndroid Build Coastguard Worker         error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
6017*8975f5c5SAndroid Build Coastguard Worker     }
6018*8975f5c5SAndroid Build Coastguard Worker 
6019*8975f5c5SAndroid Build Coastguard Worker     return qualifier;
6020*8975f5c5SAndroid Build Coastguard Worker }
6021*8975f5c5SAndroid Build Coastguard Worker 
parseLocalSize(const ImmutableString & qualifierType,const TSourceLoc & qualifierTypeLine,int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,size_t index,sh::WorkGroupSize * localSize)6022*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseLocalSize(const ImmutableString &qualifierType,
6023*8975f5c5SAndroid Build Coastguard Worker                                    const TSourceLoc &qualifierTypeLine,
6024*8975f5c5SAndroid Build Coastguard Worker                                    int intValue,
6025*8975f5c5SAndroid Build Coastguard Worker                                    const TSourceLoc &intValueLine,
6026*8975f5c5SAndroid Build Coastguard Worker                                    const std::string &intValueString,
6027*8975f5c5SAndroid Build Coastguard Worker                                    size_t index,
6028*8975f5c5SAndroid Build Coastguard Worker                                    sh::WorkGroupSize *localSize)
6029*8975f5c5SAndroid Build Coastguard Worker {
6030*8975f5c5SAndroid Build Coastguard Worker     checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
6031*8975f5c5SAndroid Build Coastguard Worker     if (intValue < 1)
6032*8975f5c5SAndroid Build Coastguard Worker     {
6033*8975f5c5SAndroid Build Coastguard Worker         std::stringstream reasonStream = sh::InitializeStream<std::stringstream>();
6034*8975f5c5SAndroid Build Coastguard Worker         reasonStream << "out of range: " << getWorkGroupSizeString(index) << " must be positive";
6035*8975f5c5SAndroid Build Coastguard Worker         std::string reason = reasonStream.str();
6036*8975f5c5SAndroid Build Coastguard Worker         error(intValueLine, reason.c_str(), intValueString.c_str());
6037*8975f5c5SAndroid Build Coastguard Worker     }
6038*8975f5c5SAndroid Build Coastguard Worker     (*localSize)[index] = intValue;
6039*8975f5c5SAndroid Build Coastguard Worker }
6040*8975f5c5SAndroid Build Coastguard Worker 
parseNumViews(int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,int * numViews)6041*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseNumViews(int intValue,
6042*8975f5c5SAndroid Build Coastguard Worker                                   const TSourceLoc &intValueLine,
6043*8975f5c5SAndroid Build Coastguard Worker                                   const std::string &intValueString,
6044*8975f5c5SAndroid Build Coastguard Worker                                   int *numViews)
6045*8975f5c5SAndroid Build Coastguard Worker {
6046*8975f5c5SAndroid Build Coastguard Worker     // This error is only specified in WebGL, but tightens unspecified behavior in the native
6047*8975f5c5SAndroid Build Coastguard Worker     // specification.
6048*8975f5c5SAndroid Build Coastguard Worker     if (intValue < 1)
6049*8975f5c5SAndroid Build Coastguard Worker     {
6050*8975f5c5SAndroid Build Coastguard Worker         error(intValueLine, "out of range: num_views must be positive", intValueString.c_str());
6051*8975f5c5SAndroid Build Coastguard Worker     }
6052*8975f5c5SAndroid Build Coastguard Worker     *numViews = intValue;
6053*8975f5c5SAndroid Build Coastguard Worker }
6054*8975f5c5SAndroid Build Coastguard Worker 
parseInvocations(int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,int * numInvocations)6055*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseInvocations(int intValue,
6056*8975f5c5SAndroid Build Coastguard Worker                                      const TSourceLoc &intValueLine,
6057*8975f5c5SAndroid Build Coastguard Worker                                      const std::string &intValueString,
6058*8975f5c5SAndroid Build Coastguard Worker                                      int *numInvocations)
6059*8975f5c5SAndroid Build Coastguard Worker {
6060*8975f5c5SAndroid Build Coastguard Worker     // Although SPEC isn't clear whether invocations can be less than 1, we add this limit because
6061*8975f5c5SAndroid Build Coastguard Worker     // it doesn't make sense to accept invocations <= 0.
6062*8975f5c5SAndroid Build Coastguard Worker     if (intValue < 1 || intValue > mMaxGeometryShaderInvocations)
6063*8975f5c5SAndroid Build Coastguard Worker     {
6064*8975f5c5SAndroid Build Coastguard Worker         error(intValueLine,
6065*8975f5c5SAndroid Build Coastguard Worker               "out of range: invocations must be in the range of [1, "
6066*8975f5c5SAndroid Build Coastguard Worker               "MAX_GEOMETRY_SHADER_INVOCATIONS_OES]",
6067*8975f5c5SAndroid Build Coastguard Worker               intValueString.c_str());
6068*8975f5c5SAndroid Build Coastguard Worker     }
6069*8975f5c5SAndroid Build Coastguard Worker     else
6070*8975f5c5SAndroid Build Coastguard Worker     {
6071*8975f5c5SAndroid Build Coastguard Worker         *numInvocations = intValue;
6072*8975f5c5SAndroid Build Coastguard Worker     }
6073*8975f5c5SAndroid Build Coastguard Worker }
6074*8975f5c5SAndroid Build Coastguard Worker 
parseMaxVertices(int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,int * maxVertices)6075*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseMaxVertices(int intValue,
6076*8975f5c5SAndroid Build Coastguard Worker                                      const TSourceLoc &intValueLine,
6077*8975f5c5SAndroid Build Coastguard Worker                                      const std::string &intValueString,
6078*8975f5c5SAndroid Build Coastguard Worker                                      int *maxVertices)
6079*8975f5c5SAndroid Build Coastguard Worker {
6080*8975f5c5SAndroid Build Coastguard Worker     // Although SPEC isn't clear whether max_vertices can be less than 0, we add this limit because
6081*8975f5c5SAndroid Build Coastguard Worker     // it doesn't make sense to accept max_vertices < 0.
6082*8975f5c5SAndroid Build Coastguard Worker     if (intValue < 0 || intValue > mMaxGeometryShaderMaxVertices)
6083*8975f5c5SAndroid Build Coastguard Worker     {
6084*8975f5c5SAndroid Build Coastguard Worker         error(
6085*8975f5c5SAndroid Build Coastguard Worker             intValueLine,
6086*8975f5c5SAndroid Build Coastguard Worker             "out of range: max_vertices must be in the range of [0, gl_MaxGeometryOutputVertices]",
6087*8975f5c5SAndroid Build Coastguard Worker             intValueString.c_str());
6088*8975f5c5SAndroid Build Coastguard Worker     }
6089*8975f5c5SAndroid Build Coastguard Worker     else
6090*8975f5c5SAndroid Build Coastguard Worker     {
6091*8975f5c5SAndroid Build Coastguard Worker         *maxVertices = intValue;
6092*8975f5c5SAndroid Build Coastguard Worker     }
6093*8975f5c5SAndroid Build Coastguard Worker }
6094*8975f5c5SAndroid Build Coastguard Worker 
parseVertices(int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,int * vertices)6095*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseVertices(int intValue,
6096*8975f5c5SAndroid Build Coastguard Worker                                   const TSourceLoc &intValueLine,
6097*8975f5c5SAndroid Build Coastguard Worker                                   const std::string &intValueString,
6098*8975f5c5SAndroid Build Coastguard Worker                                   int *vertices)
6099*8975f5c5SAndroid Build Coastguard Worker {
6100*8975f5c5SAndroid Build Coastguard Worker     if (intValue < 1 || intValue > mMaxPatchVertices)
6101*8975f5c5SAndroid Build Coastguard Worker     {
6102*8975f5c5SAndroid Build Coastguard Worker         error(intValueLine,
6103*8975f5c5SAndroid Build Coastguard Worker               "out of range : vertices must be in the range of [1, gl_MaxPatchVertices]",
6104*8975f5c5SAndroid Build Coastguard Worker               intValueString.c_str());
6105*8975f5c5SAndroid Build Coastguard Worker     }
6106*8975f5c5SAndroid Build Coastguard Worker     else
6107*8975f5c5SAndroid Build Coastguard Worker     {
6108*8975f5c5SAndroid Build Coastguard Worker         *vertices = intValue;
6109*8975f5c5SAndroid Build Coastguard Worker     }
6110*8975f5c5SAndroid Build Coastguard Worker }
6111*8975f5c5SAndroid Build Coastguard Worker 
parseIndexLayoutQualifier(int intValue,const TSourceLoc & intValueLine,const std::string & intValueString,int * index)6112*8975f5c5SAndroid Build Coastguard Worker void TParseContext::parseIndexLayoutQualifier(int intValue,
6113*8975f5c5SAndroid Build Coastguard Worker                                               const TSourceLoc &intValueLine,
6114*8975f5c5SAndroid Build Coastguard Worker                                               const std::string &intValueString,
6115*8975f5c5SAndroid Build Coastguard Worker                                               int *index)
6116*8975f5c5SAndroid Build Coastguard Worker {
6117*8975f5c5SAndroid Build Coastguard Worker     // EXT_blend_func_extended specifies that most validation should happen at link time, but since
6118*8975f5c5SAndroid Build Coastguard Worker     // we're validating output variable locations at compile time, it makes sense to validate that
6119*8975f5c5SAndroid Build Coastguard Worker     // index is 0 or 1 also at compile time. Also since we use "-1" as a placeholder for unspecified
6120*8975f5c5SAndroid Build Coastguard Worker     // index, we can't accept it here.
6121*8975f5c5SAndroid Build Coastguard Worker     if (intValue < 0 || intValue > 1)
6122*8975f5c5SAndroid Build Coastguard Worker     {
6123*8975f5c5SAndroid Build Coastguard Worker         error(intValueLine, "out of range: index layout qualifier can only be 0 or 1",
6124*8975f5c5SAndroid Build Coastguard Worker               intValueString.c_str());
6125*8975f5c5SAndroid Build Coastguard Worker     }
6126*8975f5c5SAndroid Build Coastguard Worker     else
6127*8975f5c5SAndroid Build Coastguard Worker     {
6128*8975f5c5SAndroid Build Coastguard Worker         *index = intValue;
6129*8975f5c5SAndroid Build Coastguard Worker     }
6130*8975f5c5SAndroid Build Coastguard Worker }
6131*8975f5c5SAndroid Build Coastguard Worker 
parseLayoutQualifier(const ImmutableString & qualifierType,const TSourceLoc & qualifierTypeLine,int intValue,const TSourceLoc & intValueLine)6132*8975f5c5SAndroid Build Coastguard Worker TLayoutQualifier TParseContext::parseLayoutQualifier(const ImmutableString &qualifierType,
6133*8975f5c5SAndroid Build Coastguard Worker                                                      const TSourceLoc &qualifierTypeLine,
6134*8975f5c5SAndroid Build Coastguard Worker                                                      int intValue,
6135*8975f5c5SAndroid Build Coastguard Worker                                                      const TSourceLoc &intValueLine)
6136*8975f5c5SAndroid Build Coastguard Worker {
6137*8975f5c5SAndroid Build Coastguard Worker     TLayoutQualifier qualifier = TLayoutQualifier::Create();
6138*8975f5c5SAndroid Build Coastguard Worker 
6139*8975f5c5SAndroid Build Coastguard Worker     std::string intValueString = Str(intValue);
6140*8975f5c5SAndroid Build Coastguard Worker 
6141*8975f5c5SAndroid Build Coastguard Worker     if (qualifierType == "location")
6142*8975f5c5SAndroid Build Coastguard Worker     {
6143*8975f5c5SAndroid Build Coastguard Worker         // must check that location is non-negative
6144*8975f5c5SAndroid Build Coastguard Worker         if (intValue < 0)
6145*8975f5c5SAndroid Build Coastguard Worker         {
6146*8975f5c5SAndroid Build Coastguard Worker             error(intValueLine, "out of range: location must be non-negative",
6147*8975f5c5SAndroid Build Coastguard Worker                   intValueString.c_str());
6148*8975f5c5SAndroid Build Coastguard Worker         }
6149*8975f5c5SAndroid Build Coastguard Worker         else
6150*8975f5c5SAndroid Build Coastguard Worker         {
6151*8975f5c5SAndroid Build Coastguard Worker             qualifier.location           = intValue;
6152*8975f5c5SAndroid Build Coastguard Worker             qualifier.locationsSpecified = 1;
6153*8975f5c5SAndroid Build Coastguard Worker         }
6154*8975f5c5SAndroid Build Coastguard Worker     }
6155*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "binding")
6156*8975f5c5SAndroid Build Coastguard Worker     {
6157*8975f5c5SAndroid Build Coastguard Worker         if (!isExtensionEnabled(TExtension::ANGLE_shader_pixel_local_storage))
6158*8975f5c5SAndroid Build Coastguard Worker         {
6159*8975f5c5SAndroid Build Coastguard Worker             checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
6160*8975f5c5SAndroid Build Coastguard Worker         }
6161*8975f5c5SAndroid Build Coastguard Worker         if (intValue < 0)
6162*8975f5c5SAndroid Build Coastguard Worker         {
6163*8975f5c5SAndroid Build Coastguard Worker             error(intValueLine, "out of range: binding must be non-negative",
6164*8975f5c5SAndroid Build Coastguard Worker                   intValueString.c_str());
6165*8975f5c5SAndroid Build Coastguard Worker         }
6166*8975f5c5SAndroid Build Coastguard Worker         else
6167*8975f5c5SAndroid Build Coastguard Worker         {
6168*8975f5c5SAndroid Build Coastguard Worker             qualifier.binding = intValue;
6169*8975f5c5SAndroid Build Coastguard Worker         }
6170*8975f5c5SAndroid Build Coastguard Worker     }
6171*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "offset")
6172*8975f5c5SAndroid Build Coastguard Worker     {
6173*8975f5c5SAndroid Build Coastguard Worker         checkLayoutQualifierSupported(qualifierTypeLine, qualifierType, 310);
6174*8975f5c5SAndroid Build Coastguard Worker         if (intValue < 0)
6175*8975f5c5SAndroid Build Coastguard Worker         {
6176*8975f5c5SAndroid Build Coastguard Worker             error(intValueLine, "out of range: offset must be non-negative",
6177*8975f5c5SAndroid Build Coastguard Worker                   intValueString.c_str());
6178*8975f5c5SAndroid Build Coastguard Worker         }
6179*8975f5c5SAndroid Build Coastguard Worker         else
6180*8975f5c5SAndroid Build Coastguard Worker         {
6181*8975f5c5SAndroid Build Coastguard Worker             qualifier.offset = intValue;
6182*8975f5c5SAndroid Build Coastguard Worker         }
6183*8975f5c5SAndroid Build Coastguard Worker     }
6184*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "local_size_x")
6185*8975f5c5SAndroid Build Coastguard Worker     {
6186*8975f5c5SAndroid Build Coastguard Worker         parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 0u,
6187*8975f5c5SAndroid Build Coastguard Worker                        &qualifier.localSize);
6188*8975f5c5SAndroid Build Coastguard Worker     }
6189*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "local_size_y")
6190*8975f5c5SAndroid Build Coastguard Worker     {
6191*8975f5c5SAndroid Build Coastguard Worker         parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 1u,
6192*8975f5c5SAndroid Build Coastguard Worker                        &qualifier.localSize);
6193*8975f5c5SAndroid Build Coastguard Worker     }
6194*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "local_size_z")
6195*8975f5c5SAndroid Build Coastguard Worker     {
6196*8975f5c5SAndroid Build Coastguard Worker         parseLocalSize(qualifierType, qualifierTypeLine, intValue, intValueLine, intValueString, 2u,
6197*8975f5c5SAndroid Build Coastguard Worker                        &qualifier.localSize);
6198*8975f5c5SAndroid Build Coastguard Worker     }
6199*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "num_views" && mShaderType == GL_VERTEX_SHADER)
6200*8975f5c5SAndroid Build Coastguard Worker     {
6201*8975f5c5SAndroid Build Coastguard Worker         if (checkCanUseOneOfExtensions(
6202*8975f5c5SAndroid Build Coastguard Worker                 qualifierTypeLine, std::array<TExtension, 2u>{
6203*8975f5c5SAndroid Build Coastguard Worker                                        {TExtension::OVR_multiview, TExtension::OVR_multiview2}}))
6204*8975f5c5SAndroid Build Coastguard Worker         {
6205*8975f5c5SAndroid Build Coastguard Worker             parseNumViews(intValue, intValueLine, intValueString, &qualifier.numViews);
6206*8975f5c5SAndroid Build Coastguard Worker         }
6207*8975f5c5SAndroid Build Coastguard Worker     }
6208*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "invocations" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
6209*8975f5c5SAndroid Build Coastguard Worker              (mShaderVersion >= 320 ||
6210*8975f5c5SAndroid Build Coastguard Worker               checkCanUseOneOfExtensions(
6211*8975f5c5SAndroid Build Coastguard Worker                   qualifierTypeLine,
6212*8975f5c5SAndroid Build Coastguard Worker                   std::array<TExtension, 2u>{
6213*8975f5c5SAndroid Build Coastguard Worker                       {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}})))
6214*8975f5c5SAndroid Build Coastguard Worker     {
6215*8975f5c5SAndroid Build Coastguard Worker         parseInvocations(intValue, intValueLine, intValueString, &qualifier.invocations);
6216*8975f5c5SAndroid Build Coastguard Worker     }
6217*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "max_vertices" && mShaderType == GL_GEOMETRY_SHADER_EXT &&
6218*8975f5c5SAndroid Build Coastguard Worker              (mShaderVersion >= 320 ||
6219*8975f5c5SAndroid Build Coastguard Worker               checkCanUseOneOfExtensions(
6220*8975f5c5SAndroid Build Coastguard Worker                   qualifierTypeLine,
6221*8975f5c5SAndroid Build Coastguard Worker                   std::array<TExtension, 2u>{
6222*8975f5c5SAndroid Build Coastguard Worker                       {TExtension::EXT_geometry_shader, TExtension::OES_geometry_shader}})))
6223*8975f5c5SAndroid Build Coastguard Worker     {
6224*8975f5c5SAndroid Build Coastguard Worker         parseMaxVertices(intValue, intValueLine, intValueString, &qualifier.maxVertices);
6225*8975f5c5SAndroid Build Coastguard Worker     }
6226*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "index" && mShaderType == GL_FRAGMENT_SHADER &&
6227*8975f5c5SAndroid Build Coastguard Worker              checkCanUseExtension(qualifierTypeLine, TExtension::EXT_blend_func_extended))
6228*8975f5c5SAndroid Build Coastguard Worker     {
6229*8975f5c5SAndroid Build Coastguard Worker         parseIndexLayoutQualifier(intValue, intValueLine, intValueString, &qualifier.index);
6230*8975f5c5SAndroid Build Coastguard Worker         if (intValue != 0)
6231*8975f5c5SAndroid Build Coastguard Worker         {
6232*8975f5c5SAndroid Build Coastguard Worker             errorIfPLSDeclared(qualifierTypeLine, PLSIllegalOperations::FragDataIndexNonzero);
6233*8975f5c5SAndroid Build Coastguard Worker         }
6234*8975f5c5SAndroid Build Coastguard Worker     }
6235*8975f5c5SAndroid Build Coastguard Worker     else if (qualifierType == "vertices" && mShaderType == GL_TESS_CONTROL_SHADER_EXT &&
6236*8975f5c5SAndroid Build Coastguard Worker              (mShaderVersion >= 320 ||
6237*8975f5c5SAndroid Build Coastguard Worker               checkCanUseOneOfExtensions(
6238*8975f5c5SAndroid Build Coastguard Worker                   qualifierTypeLine,
6239*8975f5c5SAndroid Build Coastguard Worker                   std::array<TExtension, 2u>{
6240*8975f5c5SAndroid Build Coastguard Worker                       {TExtension::EXT_tessellation_shader, TExtension::OES_tessellation_shader}})))
6241*8975f5c5SAndroid Build Coastguard Worker     {
6242*8975f5c5SAndroid Build Coastguard Worker         parseVertices(intValue, intValueLine, intValueString, &qualifier.vertices);
6243*8975f5c5SAndroid Build Coastguard Worker     }
6244*8975f5c5SAndroid Build Coastguard Worker     else
6245*8975f5c5SAndroid Build Coastguard Worker     {
6246*8975f5c5SAndroid Build Coastguard Worker         error(qualifierTypeLine, "invalid layout qualifier", qualifierType);
6247*8975f5c5SAndroid Build Coastguard Worker     }
6248*8975f5c5SAndroid Build Coastguard Worker 
6249*8975f5c5SAndroid Build Coastguard Worker     return qualifier;
6250*8975f5c5SAndroid Build Coastguard Worker }
6251*8975f5c5SAndroid Build Coastguard Worker 
createTypeQualifierBuilder(const TSourceLoc & loc)6252*8975f5c5SAndroid Build Coastguard Worker TTypeQualifierBuilder *TParseContext::createTypeQualifierBuilder(const TSourceLoc &loc)
6253*8975f5c5SAndroid Build Coastguard Worker {
6254*8975f5c5SAndroid Build Coastguard Worker     return new TTypeQualifierBuilder(
6255*8975f5c5SAndroid Build Coastguard Worker         new TStorageQualifierWrapper(symbolTable.atGlobalLevel() ? EvqGlobal : EvqTemporary, loc),
6256*8975f5c5SAndroid Build Coastguard Worker         mShaderVersion);
6257*8975f5c5SAndroid Build Coastguard Worker }
6258*8975f5c5SAndroid Build Coastguard Worker 
parseGlobalStorageQualifier(TQualifier qualifier,const TSourceLoc & loc)6259*8975f5c5SAndroid Build Coastguard Worker TStorageQualifierWrapper *TParseContext::parseGlobalStorageQualifier(TQualifier qualifier,
6260*8975f5c5SAndroid Build Coastguard Worker                                                                      const TSourceLoc &loc)
6261*8975f5c5SAndroid Build Coastguard Worker {
6262*8975f5c5SAndroid Build Coastguard Worker     checkIsAtGlobalLevel(loc, getQualifierString(qualifier));
6263*8975f5c5SAndroid Build Coastguard Worker     return new TStorageQualifierWrapper(qualifier, loc);
6264*8975f5c5SAndroid Build Coastguard Worker }
6265*8975f5c5SAndroid Build Coastguard Worker 
parseVaryingQualifier(const TSourceLoc & loc)6266*8975f5c5SAndroid Build Coastguard Worker TStorageQualifierWrapper *TParseContext::parseVaryingQualifier(const TSourceLoc &loc)
6267*8975f5c5SAndroid Build Coastguard Worker {
6268*8975f5c5SAndroid Build Coastguard Worker     if (getShaderType() == GL_VERTEX_SHADER)
6269*8975f5c5SAndroid Build Coastguard Worker     {
6270*8975f5c5SAndroid Build Coastguard Worker         return parseGlobalStorageQualifier(EvqVaryingOut, loc);
6271*8975f5c5SAndroid Build Coastguard Worker     }
6272*8975f5c5SAndroid Build Coastguard Worker     return parseGlobalStorageQualifier(EvqVaryingIn, loc);
6273*8975f5c5SAndroid Build Coastguard Worker }
6274*8975f5c5SAndroid Build Coastguard Worker 
parseInQualifier(const TSourceLoc & loc)6275*8975f5c5SAndroid Build Coastguard Worker TStorageQualifierWrapper *TParseContext::parseInQualifier(const TSourceLoc &loc)
6276*8975f5c5SAndroid Build Coastguard Worker {
6277*8975f5c5SAndroid Build Coastguard Worker     if (declaringFunction())
6278*8975f5c5SAndroid Build Coastguard Worker     {
6279*8975f5c5SAndroid Build Coastguard Worker         return new TStorageQualifierWrapper(EvqParamIn, loc);
6280*8975f5c5SAndroid Build Coastguard Worker     }
6281*8975f5c5SAndroid Build Coastguard Worker 
6282*8975f5c5SAndroid Build Coastguard Worker     switch (getShaderType())
6283*8975f5c5SAndroid Build Coastguard Worker     {
6284*8975f5c5SAndroid Build Coastguard Worker         case GL_VERTEX_SHADER:
6285*8975f5c5SAndroid Build Coastguard Worker         {
6286*8975f5c5SAndroid Build Coastguard Worker             if (mShaderVersion < 300 && !anyMultiviewExtensionAvailable())
6287*8975f5c5SAndroid Build Coastguard Worker             {
6288*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
6289*8975f5c5SAndroid Build Coastguard Worker             }
6290*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqVertexIn, loc);
6291*8975f5c5SAndroid Build Coastguard Worker         }
6292*8975f5c5SAndroid Build Coastguard Worker         case GL_FRAGMENT_SHADER:
6293*8975f5c5SAndroid Build Coastguard Worker         {
6294*8975f5c5SAndroid Build Coastguard Worker             if (mShaderVersion < 300)
6295*8975f5c5SAndroid Build Coastguard Worker             {
6296*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "in");
6297*8975f5c5SAndroid Build Coastguard Worker             }
6298*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqFragmentIn, loc);
6299*8975f5c5SAndroid Build Coastguard Worker         }
6300*8975f5c5SAndroid Build Coastguard Worker         case GL_COMPUTE_SHADER:
6301*8975f5c5SAndroid Build Coastguard Worker         {
6302*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqComputeIn, loc);
6303*8975f5c5SAndroid Build Coastguard Worker         }
6304*8975f5c5SAndroid Build Coastguard Worker         case GL_GEOMETRY_SHADER:
6305*8975f5c5SAndroid Build Coastguard Worker         {
6306*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqGeometryIn, loc);
6307*8975f5c5SAndroid Build Coastguard Worker         }
6308*8975f5c5SAndroid Build Coastguard Worker         case GL_TESS_CONTROL_SHADER:
6309*8975f5c5SAndroid Build Coastguard Worker         {
6310*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqTessControlIn, loc);
6311*8975f5c5SAndroid Build Coastguard Worker         }
6312*8975f5c5SAndroid Build Coastguard Worker         case GL_TESS_EVALUATION_SHADER:
6313*8975f5c5SAndroid Build Coastguard Worker         {
6314*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqTessEvaluationIn, loc);
6315*8975f5c5SAndroid Build Coastguard Worker         }
6316*8975f5c5SAndroid Build Coastguard Worker         default:
6317*8975f5c5SAndroid Build Coastguard Worker         {
6318*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
6319*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqLast, loc);
6320*8975f5c5SAndroid Build Coastguard Worker         }
6321*8975f5c5SAndroid Build Coastguard Worker     }
6322*8975f5c5SAndroid Build Coastguard Worker }
6323*8975f5c5SAndroid Build Coastguard Worker 
parseOutQualifier(const TSourceLoc & loc)6324*8975f5c5SAndroid Build Coastguard Worker TStorageQualifierWrapper *TParseContext::parseOutQualifier(const TSourceLoc &loc)
6325*8975f5c5SAndroid Build Coastguard Worker {
6326*8975f5c5SAndroid Build Coastguard Worker     if (declaringFunction())
6327*8975f5c5SAndroid Build Coastguard Worker     {
6328*8975f5c5SAndroid Build Coastguard Worker         return new TStorageQualifierWrapper(EvqParamOut, loc);
6329*8975f5c5SAndroid Build Coastguard Worker     }
6330*8975f5c5SAndroid Build Coastguard Worker     switch (getShaderType())
6331*8975f5c5SAndroid Build Coastguard Worker     {
6332*8975f5c5SAndroid Build Coastguard Worker         case GL_VERTEX_SHADER:
6333*8975f5c5SAndroid Build Coastguard Worker         {
6334*8975f5c5SAndroid Build Coastguard Worker             if (mShaderVersion < 300)
6335*8975f5c5SAndroid Build Coastguard Worker             {
6336*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
6337*8975f5c5SAndroid Build Coastguard Worker             }
6338*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqVertexOut, loc);
6339*8975f5c5SAndroid Build Coastguard Worker         }
6340*8975f5c5SAndroid Build Coastguard Worker         case GL_FRAGMENT_SHADER:
6341*8975f5c5SAndroid Build Coastguard Worker         {
6342*8975f5c5SAndroid Build Coastguard Worker             if (mShaderVersion < 300)
6343*8975f5c5SAndroid Build Coastguard Worker             {
6344*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "out");
6345*8975f5c5SAndroid Build Coastguard Worker             }
6346*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqFragmentOut, loc);
6347*8975f5c5SAndroid Build Coastguard Worker         }
6348*8975f5c5SAndroid Build Coastguard Worker         case GL_COMPUTE_SHADER:
6349*8975f5c5SAndroid Build Coastguard Worker         {
6350*8975f5c5SAndroid Build Coastguard Worker             error(loc, "storage qualifier isn't supported in compute shaders", "out");
6351*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqParamOut, loc);
6352*8975f5c5SAndroid Build Coastguard Worker         }
6353*8975f5c5SAndroid Build Coastguard Worker         case GL_GEOMETRY_SHADER_EXT:
6354*8975f5c5SAndroid Build Coastguard Worker         {
6355*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqGeometryOut, loc);
6356*8975f5c5SAndroid Build Coastguard Worker         }
6357*8975f5c5SAndroid Build Coastguard Worker         case GL_TESS_CONTROL_SHADER_EXT:
6358*8975f5c5SAndroid Build Coastguard Worker         {
6359*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqTessControlOut, loc);
6360*8975f5c5SAndroid Build Coastguard Worker         }
6361*8975f5c5SAndroid Build Coastguard Worker         case GL_TESS_EVALUATION_SHADER_EXT:
6362*8975f5c5SAndroid Build Coastguard Worker         {
6363*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqTessEvaluationOut, loc);
6364*8975f5c5SAndroid Build Coastguard Worker         }
6365*8975f5c5SAndroid Build Coastguard Worker         default:
6366*8975f5c5SAndroid Build Coastguard Worker         {
6367*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
6368*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqLast, loc);
6369*8975f5c5SAndroid Build Coastguard Worker         }
6370*8975f5c5SAndroid Build Coastguard Worker     }
6371*8975f5c5SAndroid Build Coastguard Worker }
6372*8975f5c5SAndroid Build Coastguard Worker 
parseInOutQualifier(const TSourceLoc & loc)6373*8975f5c5SAndroid Build Coastguard Worker TStorageQualifierWrapper *TParseContext::parseInOutQualifier(const TSourceLoc &loc)
6374*8975f5c5SAndroid Build Coastguard Worker {
6375*8975f5c5SAndroid Build Coastguard Worker     if (!declaringFunction())
6376*8975f5c5SAndroid Build Coastguard Worker     {
6377*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 300)
6378*8975f5c5SAndroid Build Coastguard Worker         {
6379*8975f5c5SAndroid Build Coastguard Worker             error(loc, "storage qualifier supported in GLSL ES 3.00 and above only", "inout");
6380*8975f5c5SAndroid Build Coastguard Worker         }
6381*8975f5c5SAndroid Build Coastguard Worker 
6382*8975f5c5SAndroid Build Coastguard Worker         if (getShaderType() != GL_FRAGMENT_SHADER)
6383*8975f5c5SAndroid Build Coastguard Worker         {
6384*8975f5c5SAndroid Build Coastguard Worker             error(loc, "storage qualifier isn't supported in non-fragment shaders", "inout");
6385*8975f5c5SAndroid Build Coastguard Worker         }
6386*8975f5c5SAndroid Build Coastguard Worker 
6387*8975f5c5SAndroid Build Coastguard Worker         if (isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch) ||
6388*8975f5c5SAndroid Build Coastguard Worker             isExtensionEnabled(TExtension::EXT_shader_framebuffer_fetch_non_coherent))
6389*8975f5c5SAndroid Build Coastguard Worker         {
6390*8975f5c5SAndroid Build Coastguard Worker             return new TStorageQualifierWrapper(EvqFragmentInOut, loc);
6391*8975f5c5SAndroid Build Coastguard Worker         }
6392*8975f5c5SAndroid Build Coastguard Worker 
6393*8975f5c5SAndroid Build Coastguard Worker         error(loc,
6394*8975f5c5SAndroid Build Coastguard Worker               "invalid qualifier: can be used with either function parameters or the variables for "
6395*8975f5c5SAndroid Build Coastguard Worker               "fetching input attachment data",
6396*8975f5c5SAndroid Build Coastguard Worker               "inout");
6397*8975f5c5SAndroid Build Coastguard Worker     }
6398*8975f5c5SAndroid Build Coastguard Worker     return new TStorageQualifierWrapper(EvqParamInOut, loc);
6399*8975f5c5SAndroid Build Coastguard Worker }
6400*8975f5c5SAndroid Build Coastguard Worker 
joinLayoutQualifiers(TLayoutQualifier leftQualifier,TLayoutQualifier rightQualifier,const TSourceLoc & rightQualifierLocation)6401*8975f5c5SAndroid Build Coastguard Worker TLayoutQualifier TParseContext::joinLayoutQualifiers(TLayoutQualifier leftQualifier,
6402*8975f5c5SAndroid Build Coastguard Worker                                                      TLayoutQualifier rightQualifier,
6403*8975f5c5SAndroid Build Coastguard Worker                                                      const TSourceLoc &rightQualifierLocation)
6404*8975f5c5SAndroid Build Coastguard Worker {
6405*8975f5c5SAndroid Build Coastguard Worker     return sh::JoinLayoutQualifiers(leftQualifier, rightQualifier, rightQualifierLocation,
6406*8975f5c5SAndroid Build Coastguard Worker                                     mDiagnostics);
6407*8975f5c5SAndroid Build Coastguard Worker }
6408*8975f5c5SAndroid Build Coastguard Worker 
parseStructDeclarator(const ImmutableString & identifier,const TSourceLoc & loc)6409*8975f5c5SAndroid Build Coastguard Worker TDeclarator *TParseContext::parseStructDeclarator(const ImmutableString &identifier,
6410*8975f5c5SAndroid Build Coastguard Worker                                                   const TSourceLoc &loc)
6411*8975f5c5SAndroid Build Coastguard Worker {
6412*8975f5c5SAndroid Build Coastguard Worker     return new TDeclarator(identifier, loc);
6413*8975f5c5SAndroid Build Coastguard Worker }
6414*8975f5c5SAndroid Build Coastguard Worker 
parseStructArrayDeclarator(const ImmutableString & identifier,const TSourceLoc & loc,const TVector<unsigned int> * arraySizes)6415*8975f5c5SAndroid Build Coastguard Worker TDeclarator *TParseContext::parseStructArrayDeclarator(const ImmutableString &identifier,
6416*8975f5c5SAndroid Build Coastguard Worker                                                        const TSourceLoc &loc,
6417*8975f5c5SAndroid Build Coastguard Worker                                                        const TVector<unsigned int> *arraySizes)
6418*8975f5c5SAndroid Build Coastguard Worker {
6419*8975f5c5SAndroid Build Coastguard Worker     return new TDeclarator(identifier, arraySizes, loc);
6420*8975f5c5SAndroid Build Coastguard Worker }
6421*8975f5c5SAndroid Build Coastguard Worker 
checkDoesNotHaveDuplicateFieldNames(const TFieldList * fields,const TSourceLoc & location)6422*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkDoesNotHaveDuplicateFieldNames(const TFieldList *fields,
6423*8975f5c5SAndroid Build Coastguard Worker                                                         const TSourceLoc &location)
6424*8975f5c5SAndroid Build Coastguard Worker {
6425*8975f5c5SAndroid Build Coastguard Worker     TUnorderedMap<ImmutableString, uint32_t, ImmutableString::FowlerNollVoHash<sizeof(size_t)>>
6426*8975f5c5SAndroid Build Coastguard Worker         fieldNames;
6427*8975f5c5SAndroid Build Coastguard Worker     for (TField *field : *fields)
6428*8975f5c5SAndroid Build Coastguard Worker     {
6429*8975f5c5SAndroid Build Coastguard Worker         // Note: operator[] adds this name to the map if it doesn't already exist, and initializes
6430*8975f5c5SAndroid Build Coastguard Worker         // its value to 0.
6431*8975f5c5SAndroid Build Coastguard Worker         uint32_t count = ++fieldNames[field->name()];
6432*8975f5c5SAndroid Build Coastguard Worker         if (count != 1)
6433*8975f5c5SAndroid Build Coastguard Worker         {
6434*8975f5c5SAndroid Build Coastguard Worker             error(location, "Duplicate field name in structure", field->name());
6435*8975f5c5SAndroid Build Coastguard Worker         }
6436*8975f5c5SAndroid Build Coastguard Worker     }
6437*8975f5c5SAndroid Build Coastguard Worker }
6438*8975f5c5SAndroid Build Coastguard Worker 
checkDoesNotHaveTooManyFields(const ImmutableString & name,const TFieldList * fields,const TSourceLoc & location)6439*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkDoesNotHaveTooManyFields(const ImmutableString &name,
6440*8975f5c5SAndroid Build Coastguard Worker                                                   const TFieldList *fields,
6441*8975f5c5SAndroid Build Coastguard Worker                                                   const TSourceLoc &location)
6442*8975f5c5SAndroid Build Coastguard Worker {
6443*8975f5c5SAndroid Build Coastguard Worker     // Check that there are not too many fields.  SPIR-V has a limit of 16383 fields, and it would
6444*8975f5c5SAndroid Build Coastguard Worker     // be reasonable to apply that limit to all outputs.  For example, it was observed that 32768
6445*8975f5c5SAndroid Build Coastguard Worker     // fields cause the Nvidia GL driver to fail compilation, so such a limit is not too specific to
6446*8975f5c5SAndroid Build Coastguard Worker     // SPIR-V.
6447*8975f5c5SAndroid Build Coastguard Worker     constexpr size_t kMaxFieldCount = 16383;
6448*8975f5c5SAndroid Build Coastguard Worker     if (fields->size() > kMaxFieldCount)
6449*8975f5c5SAndroid Build Coastguard Worker     {
6450*8975f5c5SAndroid Build Coastguard Worker         error(location, "Too many fields in the struct (limit is 16383)", name);
6451*8975f5c5SAndroid Build Coastguard Worker     }
6452*8975f5c5SAndroid Build Coastguard Worker }
6453*8975f5c5SAndroid Build Coastguard Worker 
addStructFieldList(TFieldList * fields,const TSourceLoc & location)6454*8975f5c5SAndroid Build Coastguard Worker TFieldList *TParseContext::addStructFieldList(TFieldList *fields, const TSourceLoc &location)
6455*8975f5c5SAndroid Build Coastguard Worker {
6456*8975f5c5SAndroid Build Coastguard Worker     return fields;
6457*8975f5c5SAndroid Build Coastguard Worker }
6458*8975f5c5SAndroid Build Coastguard Worker 
combineStructFieldLists(TFieldList * processedFields,const TFieldList * newlyAddedFields,const TSourceLoc & location)6459*8975f5c5SAndroid Build Coastguard Worker TFieldList *TParseContext::combineStructFieldLists(TFieldList *processedFields,
6460*8975f5c5SAndroid Build Coastguard Worker                                                    const TFieldList *newlyAddedFields,
6461*8975f5c5SAndroid Build Coastguard Worker                                                    const TSourceLoc &location)
6462*8975f5c5SAndroid Build Coastguard Worker {
6463*8975f5c5SAndroid Build Coastguard Worker     processedFields->insert(processedFields->end(), newlyAddedFields->begin(),
6464*8975f5c5SAndroid Build Coastguard Worker                             newlyAddedFields->end());
6465*8975f5c5SAndroid Build Coastguard Worker     return processedFields;
6466*8975f5c5SAndroid Build Coastguard Worker }
6467*8975f5c5SAndroid Build Coastguard Worker 
addStructDeclaratorListWithQualifiers(const TTypeQualifierBuilder & typeQualifierBuilder,TPublicType * typeSpecifier,const TDeclaratorList * declaratorList)6468*8975f5c5SAndroid Build Coastguard Worker TFieldList *TParseContext::addStructDeclaratorListWithQualifiers(
6469*8975f5c5SAndroid Build Coastguard Worker     const TTypeQualifierBuilder &typeQualifierBuilder,
6470*8975f5c5SAndroid Build Coastguard Worker     TPublicType *typeSpecifier,
6471*8975f5c5SAndroid Build Coastguard Worker     const TDeclaratorList *declaratorList)
6472*8975f5c5SAndroid Build Coastguard Worker {
6473*8975f5c5SAndroid Build Coastguard Worker     TTypeQualifier typeQualifier = typeQualifierBuilder.getVariableTypeQualifier(mDiagnostics);
6474*8975f5c5SAndroid Build Coastguard Worker 
6475*8975f5c5SAndroid Build Coastguard Worker     typeSpecifier->qualifier       = typeQualifier.qualifier;
6476*8975f5c5SAndroid Build Coastguard Worker     typeSpecifier->layoutQualifier = typeQualifier.layoutQualifier;
6477*8975f5c5SAndroid Build Coastguard Worker     typeSpecifier->memoryQualifier = typeQualifier.memoryQualifier;
6478*8975f5c5SAndroid Build Coastguard Worker     typeSpecifier->invariant       = typeQualifier.invariant;
6479*8975f5c5SAndroid Build Coastguard Worker     typeSpecifier->precise         = typeQualifier.precise;
6480*8975f5c5SAndroid Build Coastguard Worker     if (typeQualifier.precision != EbpUndefined)
6481*8975f5c5SAndroid Build Coastguard Worker     {
6482*8975f5c5SAndroid Build Coastguard Worker         typeSpecifier->precision = typeQualifier.precision;
6483*8975f5c5SAndroid Build Coastguard Worker     }
6484*8975f5c5SAndroid Build Coastguard Worker     return addStructDeclaratorList(*typeSpecifier, declaratorList);
6485*8975f5c5SAndroid Build Coastguard Worker }
6486*8975f5c5SAndroid Build Coastguard Worker 
addStructDeclaratorList(const TPublicType & typeSpecifier,const TDeclaratorList * declaratorList)6487*8975f5c5SAndroid Build Coastguard Worker TFieldList *TParseContext::addStructDeclaratorList(const TPublicType &typeSpecifier,
6488*8975f5c5SAndroid Build Coastguard Worker                                                    const TDeclaratorList *declaratorList)
6489*8975f5c5SAndroid Build Coastguard Worker {
6490*8975f5c5SAndroid Build Coastguard Worker     checkPrecisionSpecified(typeSpecifier.getLine(), typeSpecifier.precision,
6491*8975f5c5SAndroid Build Coastguard Worker                             typeSpecifier.getBasicType());
6492*8975f5c5SAndroid Build Coastguard Worker 
6493*8975f5c5SAndroid Build Coastguard Worker     checkIsNonVoid(typeSpecifier.getLine(), (*declaratorList)[0]->name(),
6494*8975f5c5SAndroid Build Coastguard Worker                    typeSpecifier.getBasicType());
6495*8975f5c5SAndroid Build Coastguard Worker 
6496*8975f5c5SAndroid Build Coastguard Worker     checkWorkGroupSizeIsNotSpecified(typeSpecifier.getLine(), typeSpecifier.layoutQualifier);
6497*8975f5c5SAndroid Build Coastguard Worker     checkEarlyFragmentTestsIsNotSpecified(typeSpecifier.getLine(),
6498*8975f5c5SAndroid Build Coastguard Worker                                           typeSpecifier.layoutQualifier.earlyFragmentTests);
6499*8975f5c5SAndroid Build Coastguard Worker     checkNoncoherentIsNotSpecified(typeSpecifier.getLine(),
6500*8975f5c5SAndroid Build Coastguard Worker                                    typeSpecifier.layoutQualifier.noncoherent);
6501*8975f5c5SAndroid Build Coastguard Worker 
6502*8975f5c5SAndroid Build Coastguard Worker     TFieldList *fieldList = new TFieldList();
6503*8975f5c5SAndroid Build Coastguard Worker 
6504*8975f5c5SAndroid Build Coastguard Worker     for (const TDeclarator *declarator : *declaratorList)
6505*8975f5c5SAndroid Build Coastguard Worker     {
6506*8975f5c5SAndroid Build Coastguard Worker         TType *type = new TType(typeSpecifier);
6507*8975f5c5SAndroid Build Coastguard Worker         if (declarator->isArray())
6508*8975f5c5SAndroid Build Coastguard Worker         {
6509*8975f5c5SAndroid Build Coastguard Worker             // Don't allow arrays of arrays in ESSL < 3.10.
6510*8975f5c5SAndroid Build Coastguard Worker             checkArrayElementIsNotArray(typeSpecifier.getLine(), typeSpecifier);
6511*8975f5c5SAndroid Build Coastguard Worker             type->makeArrays(*declarator->arraySizes());
6512*8975f5c5SAndroid Build Coastguard Worker         }
6513*8975f5c5SAndroid Build Coastguard Worker 
6514*8975f5c5SAndroid Build Coastguard Worker         SymbolType symbolType = SymbolType::UserDefined;
6515*8975f5c5SAndroid Build Coastguard Worker         if (declarator->name() == "gl_Position" || declarator->name() == "gl_PointSize" ||
6516*8975f5c5SAndroid Build Coastguard Worker             declarator->name() == "gl_ClipDistance" || declarator->name() == "gl_CullDistance")
6517*8975f5c5SAndroid Build Coastguard Worker         {
6518*8975f5c5SAndroid Build Coastguard Worker             symbolType = SymbolType::BuiltIn;
6519*8975f5c5SAndroid Build Coastguard Worker         }
6520*8975f5c5SAndroid Build Coastguard Worker         else
6521*8975f5c5SAndroid Build Coastguard Worker         {
6522*8975f5c5SAndroid Build Coastguard Worker             checkIsNotReserved(typeSpecifier.getLine(), declarator->name());
6523*8975f5c5SAndroid Build Coastguard Worker         }
6524*8975f5c5SAndroid Build Coastguard Worker         TField *field = new TField(type, declarator->name(), declarator->line(), symbolType);
6525*8975f5c5SAndroid Build Coastguard Worker         checkIsBelowStructNestingLimit(typeSpecifier.getLine(), *field);
6526*8975f5c5SAndroid Build Coastguard Worker         fieldList->push_back(field);
6527*8975f5c5SAndroid Build Coastguard Worker     }
6528*8975f5c5SAndroid Build Coastguard Worker 
6529*8975f5c5SAndroid Build Coastguard Worker     return fieldList;
6530*8975f5c5SAndroid Build Coastguard Worker }
6531*8975f5c5SAndroid Build Coastguard Worker 
addStructure(const TSourceLoc & structLine,const TSourceLoc & nameLine,const ImmutableString & structName,TFieldList * fieldList)6532*8975f5c5SAndroid Build Coastguard Worker TTypeSpecifierNonArray TParseContext::addStructure(const TSourceLoc &structLine,
6533*8975f5c5SAndroid Build Coastguard Worker                                                    const TSourceLoc &nameLine,
6534*8975f5c5SAndroid Build Coastguard Worker                                                    const ImmutableString &structName,
6535*8975f5c5SAndroid Build Coastguard Worker                                                    TFieldList *fieldList)
6536*8975f5c5SAndroid Build Coastguard Worker {
6537*8975f5c5SAndroid Build Coastguard Worker     SymbolType structSymbolType = SymbolType::UserDefined;
6538*8975f5c5SAndroid Build Coastguard Worker     if (structName.empty())
6539*8975f5c5SAndroid Build Coastguard Worker     {
6540*8975f5c5SAndroid Build Coastguard Worker         structSymbolType = SymbolType::Empty;
6541*8975f5c5SAndroid Build Coastguard Worker     }
6542*8975f5c5SAndroid Build Coastguard Worker 
6543*8975f5c5SAndroid Build Coastguard Worker     // To simplify pulling samplers out of structs, reorder the struct fields to put the samplers at
6544*8975f5c5SAndroid Build Coastguard Worker     // the end.
6545*8975f5c5SAndroid Build Coastguard Worker     TFieldList *reorderedFields = new TFieldList;
6546*8975f5c5SAndroid Build Coastguard Worker     for (TField *field : *fieldList)
6547*8975f5c5SAndroid Build Coastguard Worker     {
6548*8975f5c5SAndroid Build Coastguard Worker         if (!IsSampler(field->type()->getBasicType()))
6549*8975f5c5SAndroid Build Coastguard Worker         {
6550*8975f5c5SAndroid Build Coastguard Worker             reorderedFields->push_back(field);
6551*8975f5c5SAndroid Build Coastguard Worker         }
6552*8975f5c5SAndroid Build Coastguard Worker     }
6553*8975f5c5SAndroid Build Coastguard Worker     for (TField *field : *fieldList)
6554*8975f5c5SAndroid Build Coastguard Worker     {
6555*8975f5c5SAndroid Build Coastguard Worker         if (IsSampler(field->type()->getBasicType()))
6556*8975f5c5SAndroid Build Coastguard Worker         {
6557*8975f5c5SAndroid Build Coastguard Worker             reorderedFields->push_back(field);
6558*8975f5c5SAndroid Build Coastguard Worker         }
6559*8975f5c5SAndroid Build Coastguard Worker     }
6560*8975f5c5SAndroid Build Coastguard Worker 
6561*8975f5c5SAndroid Build Coastguard Worker     TStructure *structure =
6562*8975f5c5SAndroid Build Coastguard Worker         new TStructure(&symbolTable, structName, reorderedFields, structSymbolType);
6563*8975f5c5SAndroid Build Coastguard Worker 
6564*8975f5c5SAndroid Build Coastguard Worker     // Store a bool in the struct if we're at global scope, to allow us to
6565*8975f5c5SAndroid Build Coastguard Worker     // skip the local struct scoping workaround in HLSL.
6566*8975f5c5SAndroid Build Coastguard Worker     structure->setAtGlobalScope(symbolTable.atGlobalLevel());
6567*8975f5c5SAndroid Build Coastguard Worker 
6568*8975f5c5SAndroid Build Coastguard Worker     if (structSymbolType != SymbolType::Empty)
6569*8975f5c5SAndroid Build Coastguard Worker     {
6570*8975f5c5SAndroid Build Coastguard Worker         checkIsNotReserved(nameLine, structName);
6571*8975f5c5SAndroid Build Coastguard Worker         if (!symbolTable.declare(structure))
6572*8975f5c5SAndroid Build Coastguard Worker         {
6573*8975f5c5SAndroid Build Coastguard Worker             error(nameLine, "redefinition of a struct", structName);
6574*8975f5c5SAndroid Build Coastguard Worker         }
6575*8975f5c5SAndroid Build Coastguard Worker     }
6576*8975f5c5SAndroid Build Coastguard Worker 
6577*8975f5c5SAndroid Build Coastguard Worker     checkDoesNotHaveTooManyFields(structName, fieldList, structLine);
6578*8975f5c5SAndroid Build Coastguard Worker 
6579*8975f5c5SAndroid Build Coastguard Worker     // Ensure there are no duplicate field names
6580*8975f5c5SAndroid Build Coastguard Worker     checkDoesNotHaveDuplicateFieldNames(fieldList, structLine);
6581*8975f5c5SAndroid Build Coastguard Worker 
6582*8975f5c5SAndroid Build Coastguard Worker     // Ensure we do not specify any storage qualifiers on the struct members
6583*8975f5c5SAndroid Build Coastguard Worker     for (unsigned int typeListIndex = 0; typeListIndex < fieldList->size(); typeListIndex++)
6584*8975f5c5SAndroid Build Coastguard Worker     {
6585*8975f5c5SAndroid Build Coastguard Worker         TField &field              = *(*fieldList)[typeListIndex];
6586*8975f5c5SAndroid Build Coastguard Worker         const TQualifier qualifier = field.type()->getQualifier();
6587*8975f5c5SAndroid Build Coastguard Worker         switch (qualifier)
6588*8975f5c5SAndroid Build Coastguard Worker         {
6589*8975f5c5SAndroid Build Coastguard Worker             case EvqGlobal:
6590*8975f5c5SAndroid Build Coastguard Worker             case EvqTemporary:
6591*8975f5c5SAndroid Build Coastguard Worker                 break;
6592*8975f5c5SAndroid Build Coastguard Worker             default:
6593*8975f5c5SAndroid Build Coastguard Worker                 error(field.line(), "invalid qualifier on struct member",
6594*8975f5c5SAndroid Build Coastguard Worker                       getQualifierString(qualifier));
6595*8975f5c5SAndroid Build Coastguard Worker                 break;
6596*8975f5c5SAndroid Build Coastguard Worker         }
6597*8975f5c5SAndroid Build Coastguard Worker         if (field.type()->isInvariant())
6598*8975f5c5SAndroid Build Coastguard Worker         {
6599*8975f5c5SAndroid Build Coastguard Worker             error(field.line(), "invalid qualifier on struct member", "invariant");
6600*8975f5c5SAndroid Build Coastguard Worker         }
6601*8975f5c5SAndroid Build Coastguard Worker 
6602*8975f5c5SAndroid Build Coastguard Worker         const TLayoutQualifier layoutQualifier = field.type()->getLayoutQualifier();
6603*8975f5c5SAndroid Build Coastguard Worker         if (!layoutQualifier.isEmpty())
6604*8975f5c5SAndroid Build Coastguard Worker         {
6605*8975f5c5SAndroid Build Coastguard Worker             error(field.line(), "invalid layout qualifier on struct member", "layout");
6606*8975f5c5SAndroid Build Coastguard Worker         }
6607*8975f5c5SAndroid Build Coastguard Worker 
6608*8975f5c5SAndroid Build Coastguard Worker         const TMemoryQualifier memoryQualifier = field.type()->getMemoryQualifier();
6609*8975f5c5SAndroid Build Coastguard Worker         if (!memoryQualifier.isEmpty())
6610*8975f5c5SAndroid Build Coastguard Worker         {
6611*8975f5c5SAndroid Build Coastguard Worker             error(field.line(), "invalid memory qualifier on struct member",
6612*8975f5c5SAndroid Build Coastguard Worker                   memoryQualifier.getAnyQualifierString());
6613*8975f5c5SAndroid Build Coastguard Worker         }
6614*8975f5c5SAndroid Build Coastguard Worker 
6615*8975f5c5SAndroid Build Coastguard Worker         if (field.type()->isPrecise())
6616*8975f5c5SAndroid Build Coastguard Worker         {
6617*8975f5c5SAndroid Build Coastguard Worker             error(field.line(), "invalid precise qualifier on struct member", "precise");
6618*8975f5c5SAndroid Build Coastguard Worker         }
6619*8975f5c5SAndroid Build Coastguard Worker 
6620*8975f5c5SAndroid Build Coastguard Worker         // ESSL 3.10 section 4.1.8 -- atomic_uint or images are not allowed as structure member.
6621*8975f5c5SAndroid Build Coastguard Worker         // ANGLE_shader_pixel_local_storage also disallows PLS as struct members.
6622*8975f5c5SAndroid Build Coastguard Worker         if (IsImage(field.type()->getBasicType()) ||
6623*8975f5c5SAndroid Build Coastguard Worker             IsAtomicCounter(field.type()->getBasicType()) ||
6624*8975f5c5SAndroid Build Coastguard Worker             IsPixelLocal(field.type()->getBasicType()))
6625*8975f5c5SAndroid Build Coastguard Worker         {
6626*8975f5c5SAndroid Build Coastguard Worker             error(field.line(), "disallowed type in struct", field.type()->getBasicString());
6627*8975f5c5SAndroid Build Coastguard Worker         }
6628*8975f5c5SAndroid Build Coastguard Worker 
6629*8975f5c5SAndroid Build Coastguard Worker         checkIsNotUnsizedArray(field.line(), "array members of structs must specify a size",
6630*8975f5c5SAndroid Build Coastguard Worker                                field.name(), field.type());
6631*8975f5c5SAndroid Build Coastguard Worker 
6632*8975f5c5SAndroid Build Coastguard Worker         checkMemoryQualifierIsNotSpecified(field.type()->getMemoryQualifier(), field.line());
6633*8975f5c5SAndroid Build Coastguard Worker 
6634*8975f5c5SAndroid Build Coastguard Worker         checkIndexIsNotSpecified(field.line(), field.type()->getLayoutQualifier().index);
6635*8975f5c5SAndroid Build Coastguard Worker 
6636*8975f5c5SAndroid Build Coastguard Worker         checkBindingIsNotSpecified(field.line(), field.type()->getLayoutQualifier().binding);
6637*8975f5c5SAndroid Build Coastguard Worker 
6638*8975f5c5SAndroid Build Coastguard Worker         checkLocationIsNotSpecified(field.line(), field.type()->getLayoutQualifier());
6639*8975f5c5SAndroid Build Coastguard Worker     }
6640*8975f5c5SAndroid Build Coastguard Worker 
6641*8975f5c5SAndroid Build Coastguard Worker     TTypeSpecifierNonArray typeSpecifierNonArray;
6642*8975f5c5SAndroid Build Coastguard Worker     typeSpecifierNonArray.initializeStruct(structure, true, structLine);
6643*8975f5c5SAndroid Build Coastguard Worker     exitStructDeclaration();
6644*8975f5c5SAndroid Build Coastguard Worker 
6645*8975f5c5SAndroid Build Coastguard Worker     return typeSpecifierNonArray;
6646*8975f5c5SAndroid Build Coastguard Worker }
6647*8975f5c5SAndroid Build Coastguard Worker 
addSwitch(TIntermTyped * init,TIntermBlock * statementList,const TSourceLoc & loc)6648*8975f5c5SAndroid Build Coastguard Worker TIntermSwitch *TParseContext::addSwitch(TIntermTyped *init,
6649*8975f5c5SAndroid Build Coastguard Worker                                         TIntermBlock *statementList,
6650*8975f5c5SAndroid Build Coastguard Worker                                         const TSourceLoc &loc)
6651*8975f5c5SAndroid Build Coastguard Worker {
6652*8975f5c5SAndroid Build Coastguard Worker     TBasicType switchType = init->getBasicType();
6653*8975f5c5SAndroid Build Coastguard Worker     if ((switchType != EbtInt && switchType != EbtUInt) || init->isMatrix() || init->isArray() ||
6654*8975f5c5SAndroid Build Coastguard Worker         init->isVector())
6655*8975f5c5SAndroid Build Coastguard Worker     {
6656*8975f5c5SAndroid Build Coastguard Worker         error(init->getLine(), "init-expression in a switch statement must be a scalar integer",
6657*8975f5c5SAndroid Build Coastguard Worker               "switch");
6658*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
6659*8975f5c5SAndroid Build Coastguard Worker     }
6660*8975f5c5SAndroid Build Coastguard Worker 
6661*8975f5c5SAndroid Build Coastguard Worker     ASSERT(statementList);
6662*8975f5c5SAndroid Build Coastguard Worker     if (!ValidateSwitchStatementList(switchType, mDiagnostics, statementList, loc))
6663*8975f5c5SAndroid Build Coastguard Worker     {
6664*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mDiagnostics->numErrors() > 0);
6665*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
6666*8975f5c5SAndroid Build Coastguard Worker     }
6667*8975f5c5SAndroid Build Coastguard Worker 
6668*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(init);
6669*8975f5c5SAndroid Build Coastguard Worker     TIntermSwitch *node = new TIntermSwitch(init, statementList);
6670*8975f5c5SAndroid Build Coastguard Worker     node->setLine(loc);
6671*8975f5c5SAndroid Build Coastguard Worker     return node;
6672*8975f5c5SAndroid Build Coastguard Worker }
6673*8975f5c5SAndroid Build Coastguard Worker 
addCase(TIntermTyped * condition,const TSourceLoc & loc)6674*8975f5c5SAndroid Build Coastguard Worker TIntermCase *TParseContext::addCase(TIntermTyped *condition, const TSourceLoc &loc)
6675*8975f5c5SAndroid Build Coastguard Worker {
6676*8975f5c5SAndroid Build Coastguard Worker     if (mSwitchNestingLevel == 0)
6677*8975f5c5SAndroid Build Coastguard Worker     {
6678*8975f5c5SAndroid Build Coastguard Worker         error(loc, "case labels need to be inside switch statements", "case");
6679*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
6680*8975f5c5SAndroid Build Coastguard Worker     }
6681*8975f5c5SAndroid Build Coastguard Worker     if (condition == nullptr)
6682*8975f5c5SAndroid Build Coastguard Worker     {
6683*8975f5c5SAndroid Build Coastguard Worker         error(loc, "case label must have a condition", "case");
6684*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
6685*8975f5c5SAndroid Build Coastguard Worker     }
6686*8975f5c5SAndroid Build Coastguard Worker     if ((condition->getBasicType() != EbtInt && condition->getBasicType() != EbtUInt) ||
6687*8975f5c5SAndroid Build Coastguard Worker         condition->isMatrix() || condition->isArray() || condition->isVector())
6688*8975f5c5SAndroid Build Coastguard Worker     {
6689*8975f5c5SAndroid Build Coastguard Worker         error(condition->getLine(), "case label must be a scalar integer", "case");
6690*8975f5c5SAndroid Build Coastguard Worker     }
6691*8975f5c5SAndroid Build Coastguard Worker     TIntermConstantUnion *conditionConst = condition->getAsConstantUnion();
6692*8975f5c5SAndroid Build Coastguard Worker     // ANGLE should be able to fold any EvqConst expressions resulting in an integer - but to be
6693*8975f5c5SAndroid Build Coastguard Worker     // safe against corner cases we still check for conditionConst. Some interpretations of the
6694*8975f5c5SAndroid Build Coastguard Worker     // spec have allowed constant expressions with side effects - like array length() method on a
6695*8975f5c5SAndroid Build Coastguard Worker     // non-constant array.
6696*8975f5c5SAndroid Build Coastguard Worker     if (condition->getQualifier() != EvqConst || conditionConst == nullptr)
6697*8975f5c5SAndroid Build Coastguard Worker     {
6698*8975f5c5SAndroid Build Coastguard Worker         error(condition->getLine(), "case label must be constant", "case");
6699*8975f5c5SAndroid Build Coastguard Worker     }
6700*8975f5c5SAndroid Build Coastguard Worker     TIntermCase *node = new TIntermCase(condition);
6701*8975f5c5SAndroid Build Coastguard Worker     node->setLine(loc);
6702*8975f5c5SAndroid Build Coastguard Worker     return node;
6703*8975f5c5SAndroid Build Coastguard Worker }
6704*8975f5c5SAndroid Build Coastguard Worker 
addDefault(const TSourceLoc & loc)6705*8975f5c5SAndroid Build Coastguard Worker TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
6706*8975f5c5SAndroid Build Coastguard Worker {
6707*8975f5c5SAndroid Build Coastguard Worker     if (mSwitchNestingLevel == 0)
6708*8975f5c5SAndroid Build Coastguard Worker     {
6709*8975f5c5SAndroid Build Coastguard Worker         error(loc, "default labels need to be inside switch statements", "default");
6710*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
6711*8975f5c5SAndroid Build Coastguard Worker     }
6712*8975f5c5SAndroid Build Coastguard Worker     TIntermCase *node = new TIntermCase(nullptr);
6713*8975f5c5SAndroid Build Coastguard Worker     node->setLine(loc);
6714*8975f5c5SAndroid Build Coastguard Worker     return node;
6715*8975f5c5SAndroid Build Coastguard Worker }
6716*8975f5c5SAndroid Build Coastguard Worker 
createUnaryMath(TOperator op,TIntermTyped * child,const TSourceLoc & loc,const TFunction * func)6717*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::createUnaryMath(TOperator op,
6718*8975f5c5SAndroid Build Coastguard Worker                                              TIntermTyped *child,
6719*8975f5c5SAndroid Build Coastguard Worker                                              const TSourceLoc &loc,
6720*8975f5c5SAndroid Build Coastguard Worker                                              const TFunction *func)
6721*8975f5c5SAndroid Build Coastguard Worker {
6722*8975f5c5SAndroid Build Coastguard Worker     ASSERT(child != nullptr);
6723*8975f5c5SAndroid Build Coastguard Worker 
6724*8975f5c5SAndroid Build Coastguard Worker     switch (op)
6725*8975f5c5SAndroid Build Coastguard Worker     {
6726*8975f5c5SAndroid Build Coastguard Worker         case EOpLogicalNot:
6727*8975f5c5SAndroid Build Coastguard Worker             if (child->getBasicType() != EbtBool || child->isMatrix() || child->isArray() ||
6728*8975f5c5SAndroid Build Coastguard Worker                 child->isVector())
6729*8975f5c5SAndroid Build Coastguard Worker             {
6730*8975f5c5SAndroid Build Coastguard Worker                 unaryOpError(loc, GetOperatorString(op), child->getType());
6731*8975f5c5SAndroid Build Coastguard Worker                 return nullptr;
6732*8975f5c5SAndroid Build Coastguard Worker             }
6733*8975f5c5SAndroid Build Coastguard Worker             break;
6734*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseNot:
6735*8975f5c5SAndroid Build Coastguard Worker             if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
6736*8975f5c5SAndroid Build Coastguard Worker                 child->isMatrix() || child->isArray())
6737*8975f5c5SAndroid Build Coastguard Worker             {
6738*8975f5c5SAndroid Build Coastguard Worker                 unaryOpError(loc, GetOperatorString(op), child->getType());
6739*8975f5c5SAndroid Build Coastguard Worker                 return nullptr;
6740*8975f5c5SAndroid Build Coastguard Worker             }
6741*8975f5c5SAndroid Build Coastguard Worker             break;
6742*8975f5c5SAndroid Build Coastguard Worker         case EOpPostIncrement:
6743*8975f5c5SAndroid Build Coastguard Worker         case EOpPreIncrement:
6744*8975f5c5SAndroid Build Coastguard Worker         case EOpPostDecrement:
6745*8975f5c5SAndroid Build Coastguard Worker         case EOpPreDecrement:
6746*8975f5c5SAndroid Build Coastguard Worker         case EOpNegative:
6747*8975f5c5SAndroid Build Coastguard Worker         case EOpPositive:
6748*8975f5c5SAndroid Build Coastguard Worker             if (child->getBasicType() == EbtStruct || child->isInterfaceBlock() ||
6749*8975f5c5SAndroid Build Coastguard Worker                 child->getBasicType() == EbtBool || child->isArray() ||
6750*8975f5c5SAndroid Build Coastguard Worker                 child->getBasicType() == EbtVoid || IsOpaqueType(child->getBasicType()))
6751*8975f5c5SAndroid Build Coastguard Worker             {
6752*8975f5c5SAndroid Build Coastguard Worker                 unaryOpError(loc, GetOperatorString(op), child->getType());
6753*8975f5c5SAndroid Build Coastguard Worker                 return nullptr;
6754*8975f5c5SAndroid Build Coastguard Worker             }
6755*8975f5c5SAndroid Build Coastguard Worker             break;
6756*8975f5c5SAndroid Build Coastguard Worker         // Operators for math built-ins are already type checked against their prototype.
6757*8975f5c5SAndroid Build Coastguard Worker         default:
6758*8975f5c5SAndroid Build Coastguard Worker             break;
6759*8975f5c5SAndroid Build Coastguard Worker     }
6760*8975f5c5SAndroid Build Coastguard Worker 
6761*8975f5c5SAndroid Build Coastguard Worker     if (child->getMemoryQualifier().writeonly)
6762*8975f5c5SAndroid Build Coastguard Worker     {
6763*8975f5c5SAndroid Build Coastguard Worker         const char *opStr =
6764*8975f5c5SAndroid Build Coastguard Worker             BuiltInGroup::IsBuiltIn(op) ? func->name().data() : GetOperatorString(op);
6765*8975f5c5SAndroid Build Coastguard Worker         unaryOpError(loc, opStr, child->getType());
6766*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
6767*8975f5c5SAndroid Build Coastguard Worker     }
6768*8975f5c5SAndroid Build Coastguard Worker 
6769*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(child);
6770*8975f5c5SAndroid Build Coastguard Worker     TIntermUnary *node = new TIntermUnary(op, child, func);
6771*8975f5c5SAndroid Build Coastguard Worker     node->setLine(loc);
6772*8975f5c5SAndroid Build Coastguard Worker 
6773*8975f5c5SAndroid Build Coastguard Worker     return node->fold(mDiagnostics);
6774*8975f5c5SAndroid Build Coastguard Worker }
6775*8975f5c5SAndroid Build Coastguard Worker 
addUnaryMath(TOperator op,TIntermTyped * child,const TSourceLoc & loc)6776*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
6777*8975f5c5SAndroid Build Coastguard Worker {
6778*8975f5c5SAndroid Build Coastguard Worker     ASSERT(op != EOpNull);
6779*8975f5c5SAndroid Build Coastguard Worker     TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
6780*8975f5c5SAndroid Build Coastguard Worker     if (node == nullptr)
6781*8975f5c5SAndroid Build Coastguard Worker     {
6782*8975f5c5SAndroid Build Coastguard Worker         return child;
6783*8975f5c5SAndroid Build Coastguard Worker     }
6784*8975f5c5SAndroid Build Coastguard Worker     return node;
6785*8975f5c5SAndroid Build Coastguard Worker }
6786*8975f5c5SAndroid Build Coastguard Worker 
addUnaryMathLValue(TOperator op,TIntermTyped * child,const TSourceLoc & loc)6787*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addUnaryMathLValue(TOperator op,
6788*8975f5c5SAndroid Build Coastguard Worker                                                 TIntermTyped *child,
6789*8975f5c5SAndroid Build Coastguard Worker                                                 const TSourceLoc &loc)
6790*8975f5c5SAndroid Build Coastguard Worker {
6791*8975f5c5SAndroid Build Coastguard Worker     checkCanBeLValue(loc, GetOperatorString(op), child);
6792*8975f5c5SAndroid Build Coastguard Worker     return addUnaryMath(op, child, loc);
6793*8975f5c5SAndroid Build Coastguard Worker }
6794*8975f5c5SAndroid Build Coastguard Worker 
expressionOrFoldedResult(TIntermTyped * expression)6795*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::expressionOrFoldedResult(TIntermTyped *expression)
6796*8975f5c5SAndroid Build Coastguard Worker {
6797*8975f5c5SAndroid Build Coastguard Worker     // If we can, we should return the folded version of the expression for subsequent parsing. This
6798*8975f5c5SAndroid Build Coastguard Worker     // enables folding the containing expression during parsing as well, instead of the separate
6799*8975f5c5SAndroid Build Coastguard Worker     // FoldExpressions() step where folding nested expressions requires multiple full AST
6800*8975f5c5SAndroid Build Coastguard Worker     // traversals.
6801*8975f5c5SAndroid Build Coastguard Worker 
6802*8975f5c5SAndroid Build Coastguard Worker     // Even if folding fails the fold() functions return some node representing the expression,
6803*8975f5c5SAndroid Build Coastguard Worker     // typically the original node. So "folded" can be assumed to be non-null.
6804*8975f5c5SAndroid Build Coastguard Worker     TIntermTyped *folded = expression->fold(mDiagnostics);
6805*8975f5c5SAndroid Build Coastguard Worker     ASSERT(folded != nullptr);
6806*8975f5c5SAndroid Build Coastguard Worker     if (folded->getQualifier() == expression->getQualifier())
6807*8975f5c5SAndroid Build Coastguard Worker     {
6808*8975f5c5SAndroid Build Coastguard Worker         // We need this expression to have the correct qualifier when validating the consuming
6809*8975f5c5SAndroid Build Coastguard Worker         // expression. So we can only return the folded node from here in case it has the same
6810*8975f5c5SAndroid Build Coastguard Worker         // qualifier as the original expression. In this kind of a cases the qualifier of the folded
6811*8975f5c5SAndroid Build Coastguard Worker         // node is EvqConst, whereas the qualifier of the expression is EvqTemporary:
6812*8975f5c5SAndroid Build Coastguard Worker         //  1. (true ? 1.0 : non_constant)
6813*8975f5c5SAndroid Build Coastguard Worker         //  2. (non_constant, 1.0)
6814*8975f5c5SAndroid Build Coastguard Worker         return folded;
6815*8975f5c5SAndroid Build Coastguard Worker     }
6816*8975f5c5SAndroid Build Coastguard Worker     return expression;
6817*8975f5c5SAndroid Build Coastguard Worker }
6818*8975f5c5SAndroid Build Coastguard Worker 
binaryOpCommonCheck(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)6819*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::binaryOpCommonCheck(TOperator op,
6820*8975f5c5SAndroid Build Coastguard Worker                                         TIntermTyped *left,
6821*8975f5c5SAndroid Build Coastguard Worker                                         TIntermTyped *right,
6822*8975f5c5SAndroid Build Coastguard Worker                                         const TSourceLoc &loc)
6823*8975f5c5SAndroid Build Coastguard Worker {
6824*8975f5c5SAndroid Build Coastguard Worker     if (left->getBasicType() == EbtVoid || right->getBasicType() == EbtVoid)
6825*8975f5c5SAndroid Build Coastguard Worker     {
6826*8975f5c5SAndroid Build Coastguard Worker         error(loc, "operation with void operands", GetOperatorString(op));
6827*8975f5c5SAndroid Build Coastguard Worker         return false;
6828*8975f5c5SAndroid Build Coastguard Worker     }
6829*8975f5c5SAndroid Build Coastguard Worker     // Check opaque types are not allowed to be operands in expressions other than array indexing
6830*8975f5c5SAndroid Build Coastguard Worker     // and structure member selection.
6831*8975f5c5SAndroid Build Coastguard Worker     if (IsOpaqueType(left->getBasicType()) || IsOpaqueType(right->getBasicType()))
6832*8975f5c5SAndroid Build Coastguard Worker     {
6833*8975f5c5SAndroid Build Coastguard Worker         switch (op)
6834*8975f5c5SAndroid Build Coastguard Worker         {
6835*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirect:
6836*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexIndirect:
6837*8975f5c5SAndroid Build Coastguard Worker                 break;
6838*8975f5c5SAndroid Build Coastguard Worker 
6839*8975f5c5SAndroid Build Coastguard Worker             default:
6840*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(op != EOpIndexDirectStruct);
6841*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "Invalid operation for variables with an opaque type",
6842*8975f5c5SAndroid Build Coastguard Worker                       GetOperatorString(op));
6843*8975f5c5SAndroid Build Coastguard Worker                 return false;
6844*8975f5c5SAndroid Build Coastguard Worker         }
6845*8975f5c5SAndroid Build Coastguard Worker     }
6846*8975f5c5SAndroid Build Coastguard Worker 
6847*8975f5c5SAndroid Build Coastguard Worker     if (right->getMemoryQualifier().writeonly)
6848*8975f5c5SAndroid Build Coastguard Worker     {
6849*8975f5c5SAndroid Build Coastguard Worker         error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
6850*8975f5c5SAndroid Build Coastguard Worker         return false;
6851*8975f5c5SAndroid Build Coastguard Worker     }
6852*8975f5c5SAndroid Build Coastguard Worker 
6853*8975f5c5SAndroid Build Coastguard Worker     if (left->getMemoryQualifier().writeonly)
6854*8975f5c5SAndroid Build Coastguard Worker     {
6855*8975f5c5SAndroid Build Coastguard Worker         switch (op)
6856*8975f5c5SAndroid Build Coastguard Worker         {
6857*8975f5c5SAndroid Build Coastguard Worker             case EOpAssign:
6858*8975f5c5SAndroid Build Coastguard Worker             case EOpInitialize:
6859*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirect:
6860*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexIndirect:
6861*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirectStruct:
6862*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirectInterfaceBlock:
6863*8975f5c5SAndroid Build Coastguard Worker                 break;
6864*8975f5c5SAndroid Build Coastguard Worker             default:
6865*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "Invalid operation for variables with writeonly", GetOperatorString(op));
6866*8975f5c5SAndroid Build Coastguard Worker                 return false;
6867*8975f5c5SAndroid Build Coastguard Worker         }
6868*8975f5c5SAndroid Build Coastguard Worker     }
6869*8975f5c5SAndroid Build Coastguard Worker 
6870*8975f5c5SAndroid Build Coastguard Worker     if (left->getType().getStruct() || right->getType().getStruct())
6871*8975f5c5SAndroid Build Coastguard Worker     {
6872*8975f5c5SAndroid Build Coastguard Worker         switch (op)
6873*8975f5c5SAndroid Build Coastguard Worker         {
6874*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirectStruct:
6875*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(left->getType().getStruct());
6876*8975f5c5SAndroid Build Coastguard Worker                 break;
6877*8975f5c5SAndroid Build Coastguard Worker             case EOpEqual:
6878*8975f5c5SAndroid Build Coastguard Worker             case EOpNotEqual:
6879*8975f5c5SAndroid Build Coastguard Worker             case EOpAssign:
6880*8975f5c5SAndroid Build Coastguard Worker             case EOpInitialize:
6881*8975f5c5SAndroid Build Coastguard Worker                 if (left->getType() != right->getType())
6882*8975f5c5SAndroid Build Coastguard Worker                 {
6883*8975f5c5SAndroid Build Coastguard Worker                     return false;
6884*8975f5c5SAndroid Build Coastguard Worker                 }
6885*8975f5c5SAndroid Build Coastguard Worker                 break;
6886*8975f5c5SAndroid Build Coastguard Worker             default:
6887*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "Invalid operation for structs", GetOperatorString(op));
6888*8975f5c5SAndroid Build Coastguard Worker                 return false;
6889*8975f5c5SAndroid Build Coastguard Worker         }
6890*8975f5c5SAndroid Build Coastguard Worker     }
6891*8975f5c5SAndroid Build Coastguard Worker 
6892*8975f5c5SAndroid Build Coastguard Worker     if (left->isInterfaceBlock() || right->isInterfaceBlock())
6893*8975f5c5SAndroid Build Coastguard Worker     {
6894*8975f5c5SAndroid Build Coastguard Worker         switch (op)
6895*8975f5c5SAndroid Build Coastguard Worker         {
6896*8975f5c5SAndroid Build Coastguard Worker             case EOpIndexDirectInterfaceBlock:
6897*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(left->getType().getInterfaceBlock());
6898*8975f5c5SAndroid Build Coastguard Worker                 break;
6899*8975f5c5SAndroid Build Coastguard Worker             default:
6900*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "Invalid operation for interface blocks", GetOperatorString(op));
6901*8975f5c5SAndroid Build Coastguard Worker                 return false;
6902*8975f5c5SAndroid Build Coastguard Worker         }
6903*8975f5c5SAndroid Build Coastguard Worker     }
6904*8975f5c5SAndroid Build Coastguard Worker 
6905*8975f5c5SAndroid Build Coastguard Worker     if (left->isArray() != right->isArray())
6906*8975f5c5SAndroid Build Coastguard Worker     {
6907*8975f5c5SAndroid Build Coastguard Worker         error(loc, "array / non-array mismatch", GetOperatorString(op));
6908*8975f5c5SAndroid Build Coastguard Worker         return false;
6909*8975f5c5SAndroid Build Coastguard Worker     }
6910*8975f5c5SAndroid Build Coastguard Worker 
6911*8975f5c5SAndroid Build Coastguard Worker     if (left->isArray())
6912*8975f5c5SAndroid Build Coastguard Worker     {
6913*8975f5c5SAndroid Build Coastguard Worker         ASSERT(right->isArray());
6914*8975f5c5SAndroid Build Coastguard Worker         if (mShaderVersion < 300)
6915*8975f5c5SAndroid Build Coastguard Worker         {
6916*8975f5c5SAndroid Build Coastguard Worker             error(loc, "Invalid operation for arrays", GetOperatorString(op));
6917*8975f5c5SAndroid Build Coastguard Worker             return false;
6918*8975f5c5SAndroid Build Coastguard Worker         }
6919*8975f5c5SAndroid Build Coastguard Worker 
6920*8975f5c5SAndroid Build Coastguard Worker         switch (op)
6921*8975f5c5SAndroid Build Coastguard Worker         {
6922*8975f5c5SAndroid Build Coastguard Worker             case EOpEqual:
6923*8975f5c5SAndroid Build Coastguard Worker             case EOpNotEqual:
6924*8975f5c5SAndroid Build Coastguard Worker             case EOpAssign:
6925*8975f5c5SAndroid Build Coastguard Worker             case EOpInitialize:
6926*8975f5c5SAndroid Build Coastguard Worker                 break;
6927*8975f5c5SAndroid Build Coastguard Worker             default:
6928*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "Invalid operation for arrays", GetOperatorString(op));
6929*8975f5c5SAndroid Build Coastguard Worker                 return false;
6930*8975f5c5SAndroid Build Coastguard Worker         }
6931*8975f5c5SAndroid Build Coastguard Worker         // At this point, size of implicitly sized arrays should be resolved.
6932*8975f5c5SAndroid Build Coastguard Worker         if (left->getType().getArraySizes() != right->getType().getArraySizes())
6933*8975f5c5SAndroid Build Coastguard Worker         {
6934*8975f5c5SAndroid Build Coastguard Worker             error(loc, "array size mismatch", GetOperatorString(op));
6935*8975f5c5SAndroid Build Coastguard Worker             return false;
6936*8975f5c5SAndroid Build Coastguard Worker         }
6937*8975f5c5SAndroid Build Coastguard Worker     }
6938*8975f5c5SAndroid Build Coastguard Worker 
6939*8975f5c5SAndroid Build Coastguard Worker     // Check ops which require integer / ivec parameters
6940*8975f5c5SAndroid Build Coastguard Worker     bool isBitShift = false;
6941*8975f5c5SAndroid Build Coastguard Worker     switch (op)
6942*8975f5c5SAndroid Build Coastguard Worker     {
6943*8975f5c5SAndroid Build Coastguard Worker         case EOpBitShiftLeft:
6944*8975f5c5SAndroid Build Coastguard Worker         case EOpBitShiftRight:
6945*8975f5c5SAndroid Build Coastguard Worker         case EOpBitShiftLeftAssign:
6946*8975f5c5SAndroid Build Coastguard Worker         case EOpBitShiftRightAssign:
6947*8975f5c5SAndroid Build Coastguard Worker             // Unsigned can be bit-shifted by signed and vice versa, but we need to
6948*8975f5c5SAndroid Build Coastguard Worker             // check that the basic type is an integer type.
6949*8975f5c5SAndroid Build Coastguard Worker             isBitShift = true;
6950*8975f5c5SAndroid Build Coastguard Worker             if (!IsInteger(left->getBasicType()) || !IsInteger(right->getBasicType()))
6951*8975f5c5SAndroid Build Coastguard Worker             {
6952*8975f5c5SAndroid Build Coastguard Worker                 return false;
6953*8975f5c5SAndroid Build Coastguard Worker             }
6954*8975f5c5SAndroid Build Coastguard Worker             break;
6955*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseAnd:
6956*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseXor:
6957*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseOr:
6958*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseAndAssign:
6959*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseXorAssign:
6960*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseOrAssign:
6961*8975f5c5SAndroid Build Coastguard Worker             // It is enough to check the type of only one operand, since later it
6962*8975f5c5SAndroid Build Coastguard Worker             // is checked that the operand types match.
6963*8975f5c5SAndroid Build Coastguard Worker             if (!IsInteger(left->getBasicType()))
6964*8975f5c5SAndroid Build Coastguard Worker             {
6965*8975f5c5SAndroid Build Coastguard Worker                 return false;
6966*8975f5c5SAndroid Build Coastguard Worker             }
6967*8975f5c5SAndroid Build Coastguard Worker             break;
6968*8975f5c5SAndroid Build Coastguard Worker         default:
6969*8975f5c5SAndroid Build Coastguard Worker             break;
6970*8975f5c5SAndroid Build Coastguard Worker     }
6971*8975f5c5SAndroid Build Coastguard Worker 
6972*8975f5c5SAndroid Build Coastguard Worker     // Implicit type casting is not allowed in ESSL.
6973*8975f5c5SAndroid Build Coastguard Worker     if (!isBitShift && left->getBasicType() != right->getBasicType())
6974*8975f5c5SAndroid Build Coastguard Worker     {
6975*8975f5c5SAndroid Build Coastguard Worker         return false;
6976*8975f5c5SAndroid Build Coastguard Worker     }
6977*8975f5c5SAndroid Build Coastguard Worker 
6978*8975f5c5SAndroid Build Coastguard Worker     // Check that:
6979*8975f5c5SAndroid Build Coastguard Worker     // 1. Type sizes match exactly on ops that require that.
6980*8975f5c5SAndroid Build Coastguard Worker     // 2. Restrictions for structs that contain arrays or samplers are respected.
6981*8975f5c5SAndroid Build Coastguard Worker     // 3. Arithmetic op type dimensionality restrictions for ops other than multiply are respected.
6982*8975f5c5SAndroid Build Coastguard Worker     switch (op)
6983*8975f5c5SAndroid Build Coastguard Worker     {
6984*8975f5c5SAndroid Build Coastguard Worker         case EOpAssign:
6985*8975f5c5SAndroid Build Coastguard Worker         case EOpInitialize:
6986*8975f5c5SAndroid Build Coastguard Worker         case EOpEqual:
6987*8975f5c5SAndroid Build Coastguard Worker         case EOpNotEqual:
6988*8975f5c5SAndroid Build Coastguard Worker             // ESSL 1.00 sections 5.7, 5.8, 5.9
6989*8975f5c5SAndroid Build Coastguard Worker             if (mShaderVersion < 300 && left->getType().isStructureContainingArrays())
6990*8975f5c5SAndroid Build Coastguard Worker             {
6991*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "undefined operation for structs containing arrays",
6992*8975f5c5SAndroid Build Coastguard Worker                       GetOperatorString(op));
6993*8975f5c5SAndroid Build Coastguard Worker                 return false;
6994*8975f5c5SAndroid Build Coastguard Worker             }
6995*8975f5c5SAndroid Build Coastguard Worker             // Samplers as l-values are disallowed also in ESSL 3.00, see section 4.1.7,
6996*8975f5c5SAndroid Build Coastguard Worker             // we interpret the spec so that this extends to structs containing samplers,
6997*8975f5c5SAndroid Build Coastguard Worker             // similarly to ESSL 1.00 spec.
6998*8975f5c5SAndroid Build Coastguard Worker             if ((mShaderVersion < 300 || op == EOpAssign || op == EOpInitialize) &&
6999*8975f5c5SAndroid Build Coastguard Worker                 left->getType().isStructureContainingSamplers())
7000*8975f5c5SAndroid Build Coastguard Worker             {
7001*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "undefined operation for structs containing samplers",
7002*8975f5c5SAndroid Build Coastguard Worker                       GetOperatorString(op));
7003*8975f5c5SAndroid Build Coastguard Worker                 return false;
7004*8975f5c5SAndroid Build Coastguard Worker             }
7005*8975f5c5SAndroid Build Coastguard Worker 
7006*8975f5c5SAndroid Build Coastguard Worker             if ((left->getNominalSize() != right->getNominalSize()) ||
7007*8975f5c5SAndroid Build Coastguard Worker                 (left->getSecondarySize() != right->getSecondarySize()))
7008*8975f5c5SAndroid Build Coastguard Worker             {
7009*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "dimension mismatch", GetOperatorString(op));
7010*8975f5c5SAndroid Build Coastguard Worker                 return false;
7011*8975f5c5SAndroid Build Coastguard Worker             }
7012*8975f5c5SAndroid Build Coastguard Worker             break;
7013*8975f5c5SAndroid Build Coastguard Worker         case EOpLessThan:
7014*8975f5c5SAndroid Build Coastguard Worker         case EOpGreaterThan:
7015*8975f5c5SAndroid Build Coastguard Worker         case EOpLessThanEqual:
7016*8975f5c5SAndroid Build Coastguard Worker         case EOpGreaterThanEqual:
7017*8975f5c5SAndroid Build Coastguard Worker             if (!left->isScalar() || !right->isScalar())
7018*8975f5c5SAndroid Build Coastguard Worker             {
7019*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "comparison operator only defined for scalars", GetOperatorString(op));
7020*8975f5c5SAndroid Build Coastguard Worker                 return false;
7021*8975f5c5SAndroid Build Coastguard Worker             }
7022*8975f5c5SAndroid Build Coastguard Worker             break;
7023*8975f5c5SAndroid Build Coastguard Worker         case EOpAdd:
7024*8975f5c5SAndroid Build Coastguard Worker         case EOpSub:
7025*8975f5c5SAndroid Build Coastguard Worker         case EOpDiv:
7026*8975f5c5SAndroid Build Coastguard Worker         case EOpIMod:
7027*8975f5c5SAndroid Build Coastguard Worker         case EOpBitShiftLeft:
7028*8975f5c5SAndroid Build Coastguard Worker         case EOpBitShiftRight:
7029*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseAnd:
7030*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseXor:
7031*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseOr:
7032*8975f5c5SAndroid Build Coastguard Worker         case EOpAddAssign:
7033*8975f5c5SAndroid Build Coastguard Worker         case EOpSubAssign:
7034*8975f5c5SAndroid Build Coastguard Worker         case EOpDivAssign:
7035*8975f5c5SAndroid Build Coastguard Worker         case EOpIModAssign:
7036*8975f5c5SAndroid Build Coastguard Worker         case EOpBitShiftLeftAssign:
7037*8975f5c5SAndroid Build Coastguard Worker         case EOpBitShiftRightAssign:
7038*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseAndAssign:
7039*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseXorAssign:
7040*8975f5c5SAndroid Build Coastguard Worker         case EOpBitwiseOrAssign:
7041*8975f5c5SAndroid Build Coastguard Worker             if ((left->isMatrix() && right->isVector()) || (left->isVector() && right->isMatrix()))
7042*8975f5c5SAndroid Build Coastguard Worker             {
7043*8975f5c5SAndroid Build Coastguard Worker                 return false;
7044*8975f5c5SAndroid Build Coastguard Worker             }
7045*8975f5c5SAndroid Build Coastguard Worker 
7046*8975f5c5SAndroid Build Coastguard Worker             // Are the sizes compatible?
7047*8975f5c5SAndroid Build Coastguard Worker             if (left->getNominalSize() != right->getNominalSize() ||
7048*8975f5c5SAndroid Build Coastguard Worker                 left->getSecondarySize() != right->getSecondarySize())
7049*8975f5c5SAndroid Build Coastguard Worker             {
7050*8975f5c5SAndroid Build Coastguard Worker                 // If the nominal sizes of operands do not match:
7051*8975f5c5SAndroid Build Coastguard Worker                 // One of them must be a scalar.
7052*8975f5c5SAndroid Build Coastguard Worker                 if (!left->isScalar() && !right->isScalar())
7053*8975f5c5SAndroid Build Coastguard Worker                     return false;
7054*8975f5c5SAndroid Build Coastguard Worker 
7055*8975f5c5SAndroid Build Coastguard Worker                 // In the case of compound assignment other than multiply-assign,
7056*8975f5c5SAndroid Build Coastguard Worker                 // the right side needs to be a scalar. Otherwise a vector/matrix
7057*8975f5c5SAndroid Build Coastguard Worker                 // would be assigned to a scalar. A scalar can't be shifted by a
7058*8975f5c5SAndroid Build Coastguard Worker                 // vector either.
7059*8975f5c5SAndroid Build Coastguard Worker                 if (!right->isScalar() &&
7060*8975f5c5SAndroid Build Coastguard Worker                     (IsAssignment(op) || op == EOpBitShiftLeft || op == EOpBitShiftRight))
7061*8975f5c5SAndroid Build Coastguard Worker                     return false;
7062*8975f5c5SAndroid Build Coastguard Worker             }
7063*8975f5c5SAndroid Build Coastguard Worker             break;
7064*8975f5c5SAndroid Build Coastguard Worker         default:
7065*8975f5c5SAndroid Build Coastguard Worker             break;
7066*8975f5c5SAndroid Build Coastguard Worker     }
7067*8975f5c5SAndroid Build Coastguard Worker 
7068*8975f5c5SAndroid Build Coastguard Worker     return true;
7069*8975f5c5SAndroid Build Coastguard Worker }
7070*8975f5c5SAndroid Build Coastguard Worker 
isMultiplicationTypeCombinationValid(TOperator op,const TType & left,const TType & right)7071*8975f5c5SAndroid Build Coastguard Worker bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
7072*8975f5c5SAndroid Build Coastguard Worker                                                          const TType &left,
7073*8975f5c5SAndroid Build Coastguard Worker                                                          const TType &right)
7074*8975f5c5SAndroid Build Coastguard Worker {
7075*8975f5c5SAndroid Build Coastguard Worker     switch (op)
7076*8975f5c5SAndroid Build Coastguard Worker     {
7077*8975f5c5SAndroid Build Coastguard Worker         case EOpMul:
7078*8975f5c5SAndroid Build Coastguard Worker         case EOpMulAssign:
7079*8975f5c5SAndroid Build Coastguard Worker             return left.getNominalSize() == right.getNominalSize() &&
7080*8975f5c5SAndroid Build Coastguard Worker                    left.getSecondarySize() == right.getSecondarySize();
7081*8975f5c5SAndroid Build Coastguard Worker         case EOpVectorTimesScalar:
7082*8975f5c5SAndroid Build Coastguard Worker             return true;
7083*8975f5c5SAndroid Build Coastguard Worker         case EOpVectorTimesScalarAssign:
7084*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!left.isMatrix() && !right.isMatrix());
7085*8975f5c5SAndroid Build Coastguard Worker             return left.isVector() && !right.isVector();
7086*8975f5c5SAndroid Build Coastguard Worker         case EOpVectorTimesMatrix:
7087*8975f5c5SAndroid Build Coastguard Worker             return left.getNominalSize() == right.getRows();
7088*8975f5c5SAndroid Build Coastguard Worker         case EOpVectorTimesMatrixAssign:
7089*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!left.isMatrix() && right.isMatrix());
7090*8975f5c5SAndroid Build Coastguard Worker             return left.isVector() && left.getNominalSize() == right.getRows() &&
7091*8975f5c5SAndroid Build Coastguard Worker                    left.getNominalSize() == right.getCols();
7092*8975f5c5SAndroid Build Coastguard Worker         case EOpMatrixTimesVector:
7093*8975f5c5SAndroid Build Coastguard Worker             return left.getCols() == right.getNominalSize();
7094*8975f5c5SAndroid Build Coastguard Worker         case EOpMatrixTimesScalar:
7095*8975f5c5SAndroid Build Coastguard Worker             return true;
7096*8975f5c5SAndroid Build Coastguard Worker         case EOpMatrixTimesScalarAssign:
7097*8975f5c5SAndroid Build Coastguard Worker             ASSERT(left.isMatrix() && !right.isMatrix());
7098*8975f5c5SAndroid Build Coastguard Worker             return !right.isVector();
7099*8975f5c5SAndroid Build Coastguard Worker         case EOpMatrixTimesMatrix:
7100*8975f5c5SAndroid Build Coastguard Worker             return left.getCols() == right.getRows();
7101*8975f5c5SAndroid Build Coastguard Worker         case EOpMatrixTimesMatrixAssign:
7102*8975f5c5SAndroid Build Coastguard Worker             ASSERT(left.isMatrix() && right.isMatrix());
7103*8975f5c5SAndroid Build Coastguard Worker             // We need to check two things:
7104*8975f5c5SAndroid Build Coastguard Worker             // 1. The matrix multiplication step is valid.
7105*8975f5c5SAndroid Build Coastguard Worker             // 2. The result will have the same number of columns as the lvalue.
7106*8975f5c5SAndroid Build Coastguard Worker             return left.getCols() == right.getRows() && left.getCols() == right.getCols();
7107*8975f5c5SAndroid Build Coastguard Worker 
7108*8975f5c5SAndroid Build Coastguard Worker         default:
7109*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
7110*8975f5c5SAndroid Build Coastguard Worker             return false;
7111*8975f5c5SAndroid Build Coastguard Worker     }
7112*8975f5c5SAndroid Build Coastguard Worker }
7113*8975f5c5SAndroid Build Coastguard Worker 
addBinaryMathInternal(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)7114*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
7115*8975f5c5SAndroid Build Coastguard Worker                                                    TIntermTyped *left,
7116*8975f5c5SAndroid Build Coastguard Worker                                                    TIntermTyped *right,
7117*8975f5c5SAndroid Build Coastguard Worker                                                    const TSourceLoc &loc)
7118*8975f5c5SAndroid Build Coastguard Worker {
7119*8975f5c5SAndroid Build Coastguard Worker     if (!binaryOpCommonCheck(op, left, right, loc))
7120*8975f5c5SAndroid Build Coastguard Worker         return nullptr;
7121*8975f5c5SAndroid Build Coastguard Worker 
7122*8975f5c5SAndroid Build Coastguard Worker     switch (op)
7123*8975f5c5SAndroid Build Coastguard Worker     {
7124*8975f5c5SAndroid Build Coastguard Worker         case EOpEqual:
7125*8975f5c5SAndroid Build Coastguard Worker         case EOpNotEqual:
7126*8975f5c5SAndroid Build Coastguard Worker         case EOpLessThan:
7127*8975f5c5SAndroid Build Coastguard Worker         case EOpGreaterThan:
7128*8975f5c5SAndroid Build Coastguard Worker         case EOpLessThanEqual:
7129*8975f5c5SAndroid Build Coastguard Worker         case EOpGreaterThanEqual:
7130*8975f5c5SAndroid Build Coastguard Worker             break;
7131*8975f5c5SAndroid Build Coastguard Worker         case EOpLogicalOr:
7132*8975f5c5SAndroid Build Coastguard Worker         case EOpLogicalXor:
7133*8975f5c5SAndroid Build Coastguard Worker         case EOpLogicalAnd:
7134*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
7135*8975f5c5SAndroid Build Coastguard Worker                    !right->getType().getStruct());
7136*8975f5c5SAndroid Build Coastguard Worker             if (left->getBasicType() != EbtBool || !left->isScalar() || !right->isScalar())
7137*8975f5c5SAndroid Build Coastguard Worker             {
7138*8975f5c5SAndroid Build Coastguard Worker                 return nullptr;
7139*8975f5c5SAndroid Build Coastguard Worker             }
7140*8975f5c5SAndroid Build Coastguard Worker             // Basic types matching should have been already checked.
7141*8975f5c5SAndroid Build Coastguard Worker             ASSERT(right->getBasicType() == EbtBool);
7142*8975f5c5SAndroid Build Coastguard Worker             break;
7143*8975f5c5SAndroid Build Coastguard Worker         case EOpAdd:
7144*8975f5c5SAndroid Build Coastguard Worker         case EOpSub:
7145*8975f5c5SAndroid Build Coastguard Worker         case EOpDiv:
7146*8975f5c5SAndroid Build Coastguard Worker         case EOpMul:
7147*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
7148*8975f5c5SAndroid Build Coastguard Worker                    !right->getType().getStruct());
7149*8975f5c5SAndroid Build Coastguard Worker             if (left->getBasicType() == EbtBool)
7150*8975f5c5SAndroid Build Coastguard Worker             {
7151*8975f5c5SAndroid Build Coastguard Worker                 return nullptr;
7152*8975f5c5SAndroid Build Coastguard Worker             }
7153*8975f5c5SAndroid Build Coastguard Worker             break;
7154*8975f5c5SAndroid Build Coastguard Worker         case EOpIMod:
7155*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!left->isArray() && !right->isArray() && !left->getType().getStruct() &&
7156*8975f5c5SAndroid Build Coastguard Worker                    !right->getType().getStruct());
7157*8975f5c5SAndroid Build Coastguard Worker             // Note that this is only for the % operator, not for mod()
7158*8975f5c5SAndroid Build Coastguard Worker             if (left->getBasicType() == EbtBool || left->getBasicType() == EbtFloat)
7159*8975f5c5SAndroid Build Coastguard Worker             {
7160*8975f5c5SAndroid Build Coastguard Worker                 return nullptr;
7161*8975f5c5SAndroid Build Coastguard Worker             }
7162*8975f5c5SAndroid Build Coastguard Worker             break;
7163*8975f5c5SAndroid Build Coastguard Worker         default:
7164*8975f5c5SAndroid Build Coastguard Worker             break;
7165*8975f5c5SAndroid Build Coastguard Worker     }
7166*8975f5c5SAndroid Build Coastguard Worker 
7167*8975f5c5SAndroid Build Coastguard Worker     if (op == EOpMul)
7168*8975f5c5SAndroid Build Coastguard Worker     {
7169*8975f5c5SAndroid Build Coastguard Worker         op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
7170*8975f5c5SAndroid Build Coastguard Worker         if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
7171*8975f5c5SAndroid Build Coastguard Worker         {
7172*8975f5c5SAndroid Build Coastguard Worker             return nullptr;
7173*8975f5c5SAndroid Build Coastguard Worker         }
7174*8975f5c5SAndroid Build Coastguard Worker     }
7175*8975f5c5SAndroid Build Coastguard Worker 
7176*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *node = new TIntermBinary(op, left, right);
7177*8975f5c5SAndroid Build Coastguard Worker     ASSERT(op != EOpAssign);
7178*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(left);
7179*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(right);
7180*8975f5c5SAndroid Build Coastguard Worker     node->setLine(loc);
7181*8975f5c5SAndroid Build Coastguard Worker     return expressionOrFoldedResult(node);
7182*8975f5c5SAndroid Build Coastguard Worker }
7183*8975f5c5SAndroid Build Coastguard Worker 
addBinaryMath(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)7184*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addBinaryMath(TOperator op,
7185*8975f5c5SAndroid Build Coastguard Worker                                            TIntermTyped *left,
7186*8975f5c5SAndroid Build Coastguard Worker                                            TIntermTyped *right,
7187*8975f5c5SAndroid Build Coastguard Worker                                            const TSourceLoc &loc)
7188*8975f5c5SAndroid Build Coastguard Worker {
7189*8975f5c5SAndroid Build Coastguard Worker     TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
7190*8975f5c5SAndroid Build Coastguard Worker     if (node == 0)
7191*8975f5c5SAndroid Build Coastguard Worker     {
7192*8975f5c5SAndroid Build Coastguard Worker         binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
7193*8975f5c5SAndroid Build Coastguard Worker         return left;
7194*8975f5c5SAndroid Build Coastguard Worker     }
7195*8975f5c5SAndroid Build Coastguard Worker     return node;
7196*8975f5c5SAndroid Build Coastguard Worker }
7197*8975f5c5SAndroid Build Coastguard Worker 
addBinaryMathBooleanResult(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)7198*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addBinaryMathBooleanResult(TOperator op,
7199*8975f5c5SAndroid Build Coastguard Worker                                                         TIntermTyped *left,
7200*8975f5c5SAndroid Build Coastguard Worker                                                         TIntermTyped *right,
7201*8975f5c5SAndroid Build Coastguard Worker                                                         const TSourceLoc &loc)
7202*8975f5c5SAndroid Build Coastguard Worker {
7203*8975f5c5SAndroid Build Coastguard Worker     TIntermTyped *node = addBinaryMathInternal(op, left, right, loc);
7204*8975f5c5SAndroid Build Coastguard Worker     if (node == nullptr)
7205*8975f5c5SAndroid Build Coastguard Worker     {
7206*8975f5c5SAndroid Build Coastguard Worker         binaryOpError(loc, GetOperatorString(op), left->getType(), right->getType());
7207*8975f5c5SAndroid Build Coastguard Worker         node = CreateBoolNode(false);
7208*8975f5c5SAndroid Build Coastguard Worker         node->setLine(loc);
7209*8975f5c5SAndroid Build Coastguard Worker     }
7210*8975f5c5SAndroid Build Coastguard Worker     return node;
7211*8975f5c5SAndroid Build Coastguard Worker }
7212*8975f5c5SAndroid Build Coastguard Worker 
addAssign(TOperator op,TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)7213*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addAssign(TOperator op,
7214*8975f5c5SAndroid Build Coastguard Worker                                        TIntermTyped *left,
7215*8975f5c5SAndroid Build Coastguard Worker                                        TIntermTyped *right,
7216*8975f5c5SAndroid Build Coastguard Worker                                        const TSourceLoc &loc)
7217*8975f5c5SAndroid Build Coastguard Worker {
7218*8975f5c5SAndroid Build Coastguard Worker     checkCanBeLValue(loc, "assign", left);
7219*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *node = nullptr;
7220*8975f5c5SAndroid Build Coastguard Worker     if (binaryOpCommonCheck(op, left, right, loc))
7221*8975f5c5SAndroid Build Coastguard Worker     {
7222*8975f5c5SAndroid Build Coastguard Worker         TIntermBinary *lValue = left->getAsBinaryNode();
7223*8975f5c5SAndroid Build Coastguard Worker         if ((lValue != nullptr) &&
7224*8975f5c5SAndroid Build Coastguard Worker             (lValue->getOp() == EOpIndexIndirect || lValue->getOp() == EOpIndexDirect) &&
7225*8975f5c5SAndroid Build Coastguard Worker             IsTessellationControlShaderOutput(mShaderType, lValue->getLeft()->getQualifier()))
7226*8975f5c5SAndroid Build Coastguard Worker         {
7227*8975f5c5SAndroid Build Coastguard Worker             checkTCSOutVarIndexIsValid(lValue, loc);
7228*8975f5c5SAndroid Build Coastguard Worker         }
7229*8975f5c5SAndroid Build Coastguard Worker 
7230*8975f5c5SAndroid Build Coastguard Worker         if (op == EOpMulAssign)
7231*8975f5c5SAndroid Build Coastguard Worker         {
7232*8975f5c5SAndroid Build Coastguard Worker             op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
7233*8975f5c5SAndroid Build Coastguard Worker             if (isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
7234*8975f5c5SAndroid Build Coastguard Worker             {
7235*8975f5c5SAndroid Build Coastguard Worker                 node = new TIntermBinary(op, left, right);
7236*8975f5c5SAndroid Build Coastguard Worker             }
7237*8975f5c5SAndroid Build Coastguard Worker         }
7238*8975f5c5SAndroid Build Coastguard Worker         else
7239*8975f5c5SAndroid Build Coastguard Worker         {
7240*8975f5c5SAndroid Build Coastguard Worker             node = new TIntermBinary(op, left, right);
7241*8975f5c5SAndroid Build Coastguard Worker         }
7242*8975f5c5SAndroid Build Coastguard Worker     }
7243*8975f5c5SAndroid Build Coastguard Worker     if (node == nullptr)
7244*8975f5c5SAndroid Build Coastguard Worker     {
7245*8975f5c5SAndroid Build Coastguard Worker         assignError(loc, "assign", left->getType(), right->getType());
7246*8975f5c5SAndroid Build Coastguard Worker         return left;
7247*8975f5c5SAndroid Build Coastguard Worker     }
7248*8975f5c5SAndroid Build Coastguard Worker     if (op != EOpAssign)
7249*8975f5c5SAndroid Build Coastguard Worker     {
7250*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(left);
7251*8975f5c5SAndroid Build Coastguard Worker     }
7252*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(right);
7253*8975f5c5SAndroid Build Coastguard Worker     node->setLine(loc);
7254*8975f5c5SAndroid Build Coastguard Worker     return node;
7255*8975f5c5SAndroid Build Coastguard Worker }
7256*8975f5c5SAndroid Build Coastguard Worker 
addComma(TIntermTyped * left,TIntermTyped * right,const TSourceLoc & loc)7257*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addComma(TIntermTyped *left,
7258*8975f5c5SAndroid Build Coastguard Worker                                       TIntermTyped *right,
7259*8975f5c5SAndroid Build Coastguard Worker                                       const TSourceLoc &loc)
7260*8975f5c5SAndroid Build Coastguard Worker {
7261*8975f5c5SAndroid Build Coastguard Worker     // WebGL2 section 5.26, the following results in an error:
7262*8975f5c5SAndroid Build Coastguard Worker     // "Sequence operator applied to void, arrays, or structs containing arrays"
7263*8975f5c5SAndroid Build Coastguard Worker     if (mShaderSpec == SH_WEBGL2_SPEC &&
7264*8975f5c5SAndroid Build Coastguard Worker         (left->isArray() || left->getBasicType() == EbtVoid ||
7265*8975f5c5SAndroid Build Coastguard Worker          left->getType().isStructureContainingArrays() || right->isArray() ||
7266*8975f5c5SAndroid Build Coastguard Worker          right->getBasicType() == EbtVoid || right->getType().isStructureContainingArrays()))
7267*8975f5c5SAndroid Build Coastguard Worker     {
7268*8975f5c5SAndroid Build Coastguard Worker         error(loc,
7269*8975f5c5SAndroid Build Coastguard Worker               "sequence operator is not allowed for void, arrays, or structs containing arrays",
7270*8975f5c5SAndroid Build Coastguard Worker               ",");
7271*8975f5c5SAndroid Build Coastguard Worker     }
7272*8975f5c5SAndroid Build Coastguard Worker     if (left->isInterfaceBlock() || right->isInterfaceBlock())
7273*8975f5c5SAndroid Build Coastguard Worker     {
7274*8975f5c5SAndroid Build Coastguard Worker         error(loc, "sequence operator is not allowed for interface blocks", ",");
7275*8975f5c5SAndroid Build Coastguard Worker     }
7276*8975f5c5SAndroid Build Coastguard Worker 
7277*8975f5c5SAndroid Build Coastguard Worker     TIntermBinary *commaNode = TIntermBinary::CreateComma(left, right, mShaderVersion);
7278*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(left);
7279*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(right);
7280*8975f5c5SAndroid Build Coastguard Worker     commaNode->setLine(loc);
7281*8975f5c5SAndroid Build Coastguard Worker 
7282*8975f5c5SAndroid Build Coastguard Worker     return expressionOrFoldedResult(commaNode);
7283*8975f5c5SAndroid Build Coastguard Worker }
7284*8975f5c5SAndroid Build Coastguard Worker 
addBranch(TOperator op,const TSourceLoc & loc)7285*8975f5c5SAndroid Build Coastguard Worker TIntermBranch *TParseContext::addBranch(TOperator op, const TSourceLoc &loc)
7286*8975f5c5SAndroid Build Coastguard Worker {
7287*8975f5c5SAndroid Build Coastguard Worker     switch (op)
7288*8975f5c5SAndroid Build Coastguard Worker     {
7289*8975f5c5SAndroid Build Coastguard Worker         case EOpContinue:
7290*8975f5c5SAndroid Build Coastguard Worker             if (mLoopNestingLevel <= 0)
7291*8975f5c5SAndroid Build Coastguard Worker             {
7292*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "continue statement only allowed in loops", "");
7293*8975f5c5SAndroid Build Coastguard Worker             }
7294*8975f5c5SAndroid Build Coastguard Worker             break;
7295*8975f5c5SAndroid Build Coastguard Worker         case EOpBreak:
7296*8975f5c5SAndroid Build Coastguard Worker             if (mLoopNestingLevel <= 0 && mSwitchNestingLevel <= 0)
7297*8975f5c5SAndroid Build Coastguard Worker             {
7298*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "break statement only allowed in loops and switch statements", "");
7299*8975f5c5SAndroid Build Coastguard Worker             }
7300*8975f5c5SAndroid Build Coastguard Worker             break;
7301*8975f5c5SAndroid Build Coastguard Worker         case EOpReturn:
7302*8975f5c5SAndroid Build Coastguard Worker             if (mCurrentFunctionType->getBasicType() != EbtVoid)
7303*8975f5c5SAndroid Build Coastguard Worker             {
7304*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "non-void function must return a value", "return");
7305*8975f5c5SAndroid Build Coastguard Worker             }
7306*8975f5c5SAndroid Build Coastguard Worker             if (mDeclaringMain)
7307*8975f5c5SAndroid Build Coastguard Worker             {
7308*8975f5c5SAndroid Build Coastguard Worker                 errorIfPLSDeclared(loc, PLSIllegalOperations::ReturnFromMain);
7309*8975f5c5SAndroid Build Coastguard Worker             }
7310*8975f5c5SAndroid Build Coastguard Worker             break;
7311*8975f5c5SAndroid Build Coastguard Worker         case EOpKill:
7312*8975f5c5SAndroid Build Coastguard Worker             if (mShaderType != GL_FRAGMENT_SHADER)
7313*8975f5c5SAndroid Build Coastguard Worker             {
7314*8975f5c5SAndroid Build Coastguard Worker                 error(loc, "discard supported in fragment shaders only", "discard");
7315*8975f5c5SAndroid Build Coastguard Worker             }
7316*8975f5c5SAndroid Build Coastguard Worker             else
7317*8975f5c5SAndroid Build Coastguard Worker             {
7318*8975f5c5SAndroid Build Coastguard Worker                 errorIfPLSDeclared(loc, PLSIllegalOperations::Discard);
7319*8975f5c5SAndroid Build Coastguard Worker             }
7320*8975f5c5SAndroid Build Coastguard Worker             mHasDiscard = true;
7321*8975f5c5SAndroid Build Coastguard Worker             break;
7322*8975f5c5SAndroid Build Coastguard Worker         default:
7323*8975f5c5SAndroid Build Coastguard Worker             UNREACHABLE();
7324*8975f5c5SAndroid Build Coastguard Worker             break;
7325*8975f5c5SAndroid Build Coastguard Worker     }
7326*8975f5c5SAndroid Build Coastguard Worker     return addBranch(op, nullptr, loc);
7327*8975f5c5SAndroid Build Coastguard Worker }
7328*8975f5c5SAndroid Build Coastguard Worker 
addBranch(TOperator op,TIntermTyped * expression,const TSourceLoc & loc)7329*8975f5c5SAndroid Build Coastguard Worker TIntermBranch *TParseContext::addBranch(TOperator op,
7330*8975f5c5SAndroid Build Coastguard Worker                                         TIntermTyped *expression,
7331*8975f5c5SAndroid Build Coastguard Worker                                         const TSourceLoc &loc)
7332*8975f5c5SAndroid Build Coastguard Worker {
7333*8975f5c5SAndroid Build Coastguard Worker     if (expression != nullptr)
7334*8975f5c5SAndroid Build Coastguard Worker     {
7335*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(expression);
7336*8975f5c5SAndroid Build Coastguard Worker         ASSERT(op == EOpReturn);
7337*8975f5c5SAndroid Build Coastguard Worker         mFunctionReturnsValue = true;
7338*8975f5c5SAndroid Build Coastguard Worker         if (mCurrentFunctionType->getBasicType() == EbtVoid)
7339*8975f5c5SAndroid Build Coastguard Worker         {
7340*8975f5c5SAndroid Build Coastguard Worker             error(loc, "void function cannot return a value", "return");
7341*8975f5c5SAndroid Build Coastguard Worker         }
7342*8975f5c5SAndroid Build Coastguard Worker         else if (*mCurrentFunctionType != expression->getType())
7343*8975f5c5SAndroid Build Coastguard Worker         {
7344*8975f5c5SAndroid Build Coastguard Worker             error(loc, "function return is not matching type:", "return");
7345*8975f5c5SAndroid Build Coastguard Worker         }
7346*8975f5c5SAndroid Build Coastguard Worker     }
7347*8975f5c5SAndroid Build Coastguard Worker     TIntermBranch *node = new TIntermBranch(op, expression);
7348*8975f5c5SAndroid Build Coastguard Worker     node->setLine(loc);
7349*8975f5c5SAndroid Build Coastguard Worker     return node;
7350*8975f5c5SAndroid Build Coastguard Worker }
7351*8975f5c5SAndroid Build Coastguard Worker 
appendStatement(TIntermBlock * block,TIntermNode * statement)7352*8975f5c5SAndroid Build Coastguard Worker void TParseContext::appendStatement(TIntermBlock *block, TIntermNode *statement)
7353*8975f5c5SAndroid Build Coastguard Worker {
7354*8975f5c5SAndroid Build Coastguard Worker     if (statement != nullptr)
7355*8975f5c5SAndroid Build Coastguard Worker     {
7356*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(statement);
7357*8975f5c5SAndroid Build Coastguard Worker         block->appendStatement(statement);
7358*8975f5c5SAndroid Build Coastguard Worker     }
7359*8975f5c5SAndroid Build Coastguard Worker }
7360*8975f5c5SAndroid Build Coastguard Worker 
checkTextureGather(TIntermAggregate * functionCall)7361*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkTextureGather(TIntermAggregate *functionCall)
7362*8975f5c5SAndroid Build Coastguard Worker {
7363*8975f5c5SAndroid Build Coastguard Worker     const TOperator op    = functionCall->getOp();
7364*8975f5c5SAndroid Build Coastguard Worker     const TFunction *func = functionCall->getFunction();
7365*8975f5c5SAndroid Build Coastguard Worker     if (BuiltInGroup::IsTextureGather(op))
7366*8975f5c5SAndroid Build Coastguard Worker     {
7367*8975f5c5SAndroid Build Coastguard Worker         bool isTextureGatherOffsetOrOffsets =
7368*8975f5c5SAndroid Build Coastguard Worker             BuiltInGroup::IsTextureGatherOffset(op) || BuiltInGroup::IsTextureGatherOffsets(op);
7369*8975f5c5SAndroid Build Coastguard Worker         TIntermNode *componentNode = nullptr;
7370*8975f5c5SAndroid Build Coastguard Worker         TIntermSequence *arguments = functionCall->getSequence();
7371*8975f5c5SAndroid Build Coastguard Worker         ASSERT(arguments->size() >= 2u && arguments->size() <= 4u);
7372*8975f5c5SAndroid Build Coastguard Worker         const TIntermTyped *sampler = arguments->front()->getAsTyped();
7373*8975f5c5SAndroid Build Coastguard Worker         ASSERT(sampler != nullptr);
7374*8975f5c5SAndroid Build Coastguard Worker         switch (sampler->getBasicType())
7375*8975f5c5SAndroid Build Coastguard Worker         {
7376*8975f5c5SAndroid Build Coastguard Worker             case EbtSampler2D:
7377*8975f5c5SAndroid Build Coastguard Worker             case EbtISampler2D:
7378*8975f5c5SAndroid Build Coastguard Worker             case EbtUSampler2D:
7379*8975f5c5SAndroid Build Coastguard Worker             case EbtSampler2DArray:
7380*8975f5c5SAndroid Build Coastguard Worker             case EbtISampler2DArray:
7381*8975f5c5SAndroid Build Coastguard Worker             case EbtUSampler2DArray:
7382*8975f5c5SAndroid Build Coastguard Worker                 if ((!isTextureGatherOffsetOrOffsets && arguments->size() == 3u) ||
7383*8975f5c5SAndroid Build Coastguard Worker                     (isTextureGatherOffsetOrOffsets && arguments->size() == 4u))
7384*8975f5c5SAndroid Build Coastguard Worker                 {
7385*8975f5c5SAndroid Build Coastguard Worker                     componentNode = arguments->back();
7386*8975f5c5SAndroid Build Coastguard Worker                 }
7387*8975f5c5SAndroid Build Coastguard Worker                 break;
7388*8975f5c5SAndroid Build Coastguard Worker             case EbtSamplerCube:
7389*8975f5c5SAndroid Build Coastguard Worker             case EbtISamplerCube:
7390*8975f5c5SAndroid Build Coastguard Worker             case EbtUSamplerCube:
7391*8975f5c5SAndroid Build Coastguard Worker             case EbtSamplerCubeArray:
7392*8975f5c5SAndroid Build Coastguard Worker             case EbtISamplerCubeArray:
7393*8975f5c5SAndroid Build Coastguard Worker             case EbtUSamplerCubeArray:
7394*8975f5c5SAndroid Build Coastguard Worker                 ASSERT(!isTextureGatherOffsetOrOffsets);
7395*8975f5c5SAndroid Build Coastguard Worker                 if (arguments->size() == 3u)
7396*8975f5c5SAndroid Build Coastguard Worker                 {
7397*8975f5c5SAndroid Build Coastguard Worker                     componentNode = arguments->back();
7398*8975f5c5SAndroid Build Coastguard Worker                 }
7399*8975f5c5SAndroid Build Coastguard Worker                 break;
7400*8975f5c5SAndroid Build Coastguard Worker             case EbtSampler2DShadow:
7401*8975f5c5SAndroid Build Coastguard Worker             case EbtSampler2DArrayShadow:
7402*8975f5c5SAndroid Build Coastguard Worker             case EbtSamplerCubeShadow:
7403*8975f5c5SAndroid Build Coastguard Worker             case EbtSamplerCubeArrayShadow:
7404*8975f5c5SAndroid Build Coastguard Worker                 break;
7405*8975f5c5SAndroid Build Coastguard Worker             default:
7406*8975f5c5SAndroid Build Coastguard Worker                 UNREACHABLE();
7407*8975f5c5SAndroid Build Coastguard Worker                 break;
7408*8975f5c5SAndroid Build Coastguard Worker         }
7409*8975f5c5SAndroid Build Coastguard Worker         if (componentNode)
7410*8975f5c5SAndroid Build Coastguard Worker         {
7411*8975f5c5SAndroid Build Coastguard Worker             const TIntermConstantUnion *componentConstantUnion =
7412*8975f5c5SAndroid Build Coastguard Worker                 componentNode->getAsConstantUnion();
7413*8975f5c5SAndroid Build Coastguard Worker             if (componentNode->getAsTyped()->getQualifier() != EvqConst || !componentConstantUnion)
7414*8975f5c5SAndroid Build Coastguard Worker             {
7415*8975f5c5SAndroid Build Coastguard Worker                 error(functionCall->getLine(), "Texture component must be a constant expression",
7416*8975f5c5SAndroid Build Coastguard Worker                       func->name());
7417*8975f5c5SAndroid Build Coastguard Worker             }
7418*8975f5c5SAndroid Build Coastguard Worker             else
7419*8975f5c5SAndroid Build Coastguard Worker             {
7420*8975f5c5SAndroid Build Coastguard Worker                 int component = componentConstantUnion->getIConst(0);
7421*8975f5c5SAndroid Build Coastguard Worker                 if (component < 0 || component > 3)
7422*8975f5c5SAndroid Build Coastguard Worker                 {
7423*8975f5c5SAndroid Build Coastguard Worker                     error(functionCall->getLine(), "Component must be in the range [0;3]",
7424*8975f5c5SAndroid Build Coastguard Worker                           func->name());
7425*8975f5c5SAndroid Build Coastguard Worker                 }
7426*8975f5c5SAndroid Build Coastguard Worker             }
7427*8975f5c5SAndroid Build Coastguard Worker         }
7428*8975f5c5SAndroid Build Coastguard Worker     }
7429*8975f5c5SAndroid Build Coastguard Worker }
7430*8975f5c5SAndroid Build Coastguard Worker 
checkTextureOffset(TIntermAggregate * functionCall)7431*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkTextureOffset(TIntermAggregate *functionCall)
7432*8975f5c5SAndroid Build Coastguard Worker {
7433*8975f5c5SAndroid Build Coastguard Worker     const TOperator op         = functionCall->getOp();
7434*8975f5c5SAndroid Build Coastguard Worker     const TFunction *func      = functionCall->getFunction();
7435*8975f5c5SAndroid Build Coastguard Worker     TIntermNode *offset        = nullptr;
7436*8975f5c5SAndroid Build Coastguard Worker     TIntermSequence *arguments = functionCall->getSequence();
7437*8975f5c5SAndroid Build Coastguard Worker 
7438*8975f5c5SAndroid Build Coastguard Worker     if (BuiltInGroup::IsTextureOffsetNoBias(op) || BuiltInGroup::IsTextureGatherOffsetNoComp(op) ||
7439*8975f5c5SAndroid Build Coastguard Worker         BuiltInGroup::IsTextureGatherOffsetsNoComp(op))
7440*8975f5c5SAndroid Build Coastguard Worker     {
7441*8975f5c5SAndroid Build Coastguard Worker         offset = arguments->back();
7442*8975f5c5SAndroid Build Coastguard Worker     }
7443*8975f5c5SAndroid Build Coastguard Worker     else if (BuiltInGroup::IsTextureOffsetBias(op) || BuiltInGroup::IsTextureGatherOffsetComp(op) ||
7444*8975f5c5SAndroid Build Coastguard Worker              BuiltInGroup::IsTextureGatherOffsetsComp(op))
7445*8975f5c5SAndroid Build Coastguard Worker     {
7446*8975f5c5SAndroid Build Coastguard Worker         // A bias or comp parameter follows the offset parameter.
7447*8975f5c5SAndroid Build Coastguard Worker         ASSERT(arguments->size() >= 3);
7448*8975f5c5SAndroid Build Coastguard Worker         offset = (*arguments)[2];
7449*8975f5c5SAndroid Build Coastguard Worker     }
7450*8975f5c5SAndroid Build Coastguard Worker 
7451*8975f5c5SAndroid Build Coastguard Worker     // If not one of the above built-ins, there's nothing to do here.
7452*8975f5c5SAndroid Build Coastguard Worker     if (offset == nullptr)
7453*8975f5c5SAndroid Build Coastguard Worker     {
7454*8975f5c5SAndroid Build Coastguard Worker         return;
7455*8975f5c5SAndroid Build Coastguard Worker     }
7456*8975f5c5SAndroid Build Coastguard Worker 
7457*8975f5c5SAndroid Build Coastguard Worker     bool isTextureGatherOffset             = BuiltInGroup::IsTextureGatherOffset(op);
7458*8975f5c5SAndroid Build Coastguard Worker     bool isTextureGatherOffsets            = BuiltInGroup::IsTextureGatherOffsets(op);
7459*8975f5c5SAndroid Build Coastguard Worker     bool useTextureGatherOffsetConstraints = isTextureGatherOffset || isTextureGatherOffsets;
7460*8975f5c5SAndroid Build Coastguard Worker 
7461*8975f5c5SAndroid Build Coastguard Worker     int minOffsetValue =
7462*8975f5c5SAndroid Build Coastguard Worker         useTextureGatherOffsetConstraints ? mMinProgramTextureGatherOffset : mMinProgramTexelOffset;
7463*8975f5c5SAndroid Build Coastguard Worker     int maxOffsetValue =
7464*8975f5c5SAndroid Build Coastguard Worker         useTextureGatherOffsetConstraints ? mMaxProgramTextureGatherOffset : mMaxProgramTexelOffset;
7465*8975f5c5SAndroid Build Coastguard Worker 
7466*8975f5c5SAndroid Build Coastguard Worker     if (isTextureGatherOffsets)
7467*8975f5c5SAndroid Build Coastguard Worker     {
7468*8975f5c5SAndroid Build Coastguard Worker         // If textureGatherOffsets, the offsets parameter is an array, which is expected as an
7469*8975f5c5SAndroid Build Coastguard Worker         // aggregate constructor node or as a symbol node with a constant value.
7470*8975f5c5SAndroid Build Coastguard Worker         TIntermAggregate *offsetAggregate = offset->getAsAggregate();
7471*8975f5c5SAndroid Build Coastguard Worker         TIntermSymbol *offsetSymbol       = offset->getAsSymbolNode();
7472*8975f5c5SAndroid Build Coastguard Worker 
7473*8975f5c5SAndroid Build Coastguard Worker         const TConstantUnion *offsetValues = offsetAggregate ? offsetAggregate->getConstantValue()
7474*8975f5c5SAndroid Build Coastguard Worker                                              : offsetSymbol  ? offsetSymbol->getConstantValue()
7475*8975f5c5SAndroid Build Coastguard Worker                                                              : nullptr;
7476*8975f5c5SAndroid Build Coastguard Worker 
7477*8975f5c5SAndroid Build Coastguard Worker         if (offsetValues == nullptr)
7478*8975f5c5SAndroid Build Coastguard Worker         {
7479*8975f5c5SAndroid Build Coastguard Worker             error(functionCall->getLine(), "Texture offsets must be a constant expression",
7480*8975f5c5SAndroid Build Coastguard Worker                   func->name());
7481*8975f5c5SAndroid Build Coastguard Worker             return;
7482*8975f5c5SAndroid Build Coastguard Worker         }
7483*8975f5c5SAndroid Build Coastguard Worker 
7484*8975f5c5SAndroid Build Coastguard Worker         constexpr unsigned int kOffsetsCount = 4;
7485*8975f5c5SAndroid Build Coastguard Worker         const TType &offsetType =
7486*8975f5c5SAndroid Build Coastguard Worker             offsetAggregate != nullptr ? offsetAggregate->getType() : offsetSymbol->getType();
7487*8975f5c5SAndroid Build Coastguard Worker         if (offsetType.getNumArraySizes() != 1 || offsetType.getArraySizes()[0] != kOffsetsCount)
7488*8975f5c5SAndroid Build Coastguard Worker         {
7489*8975f5c5SAndroid Build Coastguard Worker             error(functionCall->getLine(), "Texture offsets must be an array of 4 elements",
7490*8975f5c5SAndroid Build Coastguard Worker                   func->name());
7491*8975f5c5SAndroid Build Coastguard Worker             return;
7492*8975f5c5SAndroid Build Coastguard Worker         }
7493*8975f5c5SAndroid Build Coastguard Worker 
7494*8975f5c5SAndroid Build Coastguard Worker         size_t size = offsetType.getObjectSize() / kOffsetsCount;
7495*8975f5c5SAndroid Build Coastguard Worker         for (unsigned int i = 0; i < kOffsetsCount; ++i)
7496*8975f5c5SAndroid Build Coastguard Worker         {
7497*8975f5c5SAndroid Build Coastguard Worker             checkSingleTextureOffset(offset->getLine(), &offsetValues[i * size], size,
7498*8975f5c5SAndroid Build Coastguard Worker                                      minOffsetValue, maxOffsetValue);
7499*8975f5c5SAndroid Build Coastguard Worker         }
7500*8975f5c5SAndroid Build Coastguard Worker     }
7501*8975f5c5SAndroid Build Coastguard Worker     else
7502*8975f5c5SAndroid Build Coastguard Worker     {
7503*8975f5c5SAndroid Build Coastguard Worker         // If textureOffset or textureGatherOffset, the offset is expected to be found as a constant
7504*8975f5c5SAndroid Build Coastguard Worker         // union.
7505*8975f5c5SAndroid Build Coastguard Worker         TIntermConstantUnion *offsetConstantUnion = offset->getAsConstantUnion();
7506*8975f5c5SAndroid Build Coastguard Worker 
7507*8975f5c5SAndroid Build Coastguard Worker         // ES3.2 or ES3.1's EXT_gpu_shader5 allow non-const offsets to be passed to
7508*8975f5c5SAndroid Build Coastguard Worker         // textureGatherOffset.
7509*8975f5c5SAndroid Build Coastguard Worker         bool textureGatherOffsetMustBeConst = mShaderVersion <= 310 &&
7510*8975f5c5SAndroid Build Coastguard Worker                                               !isExtensionEnabled(TExtension::EXT_gpu_shader5) &&
7511*8975f5c5SAndroid Build Coastguard Worker                                               !isExtensionEnabled(TExtension::OES_gpu_shader5);
7512*8975f5c5SAndroid Build Coastguard Worker 
7513*8975f5c5SAndroid Build Coastguard Worker         bool isOffsetConst =
7514*8975f5c5SAndroid Build Coastguard Worker             offset->getAsTyped()->getQualifier() == EvqConst && offsetConstantUnion != nullptr;
7515*8975f5c5SAndroid Build Coastguard Worker         bool offsetMustBeConst = !isTextureGatherOffset || textureGatherOffsetMustBeConst;
7516*8975f5c5SAndroid Build Coastguard Worker 
7517*8975f5c5SAndroid Build Coastguard Worker         if (!isOffsetConst && offsetMustBeConst)
7518*8975f5c5SAndroid Build Coastguard Worker         {
7519*8975f5c5SAndroid Build Coastguard Worker             error(functionCall->getLine(), "Texture offset must be a constant expression",
7520*8975f5c5SAndroid Build Coastguard Worker                   func->name());
7521*8975f5c5SAndroid Build Coastguard Worker             return;
7522*8975f5c5SAndroid Build Coastguard Worker         }
7523*8975f5c5SAndroid Build Coastguard Worker 
7524*8975f5c5SAndroid Build Coastguard Worker         // We cannot verify non-constant offsets to textureGatherOffset.
7525*8975f5c5SAndroid Build Coastguard Worker         if (offsetConstantUnion == nullptr)
7526*8975f5c5SAndroid Build Coastguard Worker         {
7527*8975f5c5SAndroid Build Coastguard Worker             ASSERT(!offsetMustBeConst);
7528*8975f5c5SAndroid Build Coastguard Worker             return;
7529*8975f5c5SAndroid Build Coastguard Worker         }
7530*8975f5c5SAndroid Build Coastguard Worker 
7531*8975f5c5SAndroid Build Coastguard Worker         size_t size                  = offsetConstantUnion->getType().getObjectSize();
7532*8975f5c5SAndroid Build Coastguard Worker         const TConstantUnion *values = offsetConstantUnion->getConstantValue();
7533*8975f5c5SAndroid Build Coastguard Worker         checkSingleTextureOffset(offset->getLine(), values, size, minOffsetValue, maxOffsetValue);
7534*8975f5c5SAndroid Build Coastguard Worker     }
7535*8975f5c5SAndroid Build Coastguard Worker }
7536*8975f5c5SAndroid Build Coastguard Worker 
checkSingleTextureOffset(const TSourceLoc & line,const TConstantUnion * values,size_t size,int minOffsetValue,int maxOffsetValue)7537*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkSingleTextureOffset(const TSourceLoc &line,
7538*8975f5c5SAndroid Build Coastguard Worker                                              const TConstantUnion *values,
7539*8975f5c5SAndroid Build Coastguard Worker                                              size_t size,
7540*8975f5c5SAndroid Build Coastguard Worker                                              int minOffsetValue,
7541*8975f5c5SAndroid Build Coastguard Worker                                              int maxOffsetValue)
7542*8975f5c5SAndroid Build Coastguard Worker {
7543*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0u; i < size; ++i)
7544*8975f5c5SAndroid Build Coastguard Worker     {
7545*8975f5c5SAndroid Build Coastguard Worker         ASSERT(values[i].getType() == EbtInt);
7546*8975f5c5SAndroid Build Coastguard Worker         int offsetValue = values[i].getIConst();
7547*8975f5c5SAndroid Build Coastguard Worker         if (offsetValue > maxOffsetValue || offsetValue < minOffsetValue)
7548*8975f5c5SAndroid Build Coastguard Worker         {
7549*8975f5c5SAndroid Build Coastguard Worker             std::stringstream tokenStream = sh::InitializeStream<std::stringstream>();
7550*8975f5c5SAndroid Build Coastguard Worker             tokenStream << offsetValue;
7551*8975f5c5SAndroid Build Coastguard Worker             std::string token = tokenStream.str();
7552*8975f5c5SAndroid Build Coastguard Worker             error(line, "Texture offset value out of valid range", token.c_str());
7553*8975f5c5SAndroid Build Coastguard Worker         }
7554*8975f5c5SAndroid Build Coastguard Worker     }
7555*8975f5c5SAndroid Build Coastguard Worker }
7556*8975f5c5SAndroid Build Coastguard Worker 
checkInterpolationFS(TIntermAggregate * functionCall)7557*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkInterpolationFS(TIntermAggregate *functionCall)
7558*8975f5c5SAndroid Build Coastguard Worker {
7559*8975f5c5SAndroid Build Coastguard Worker     const TFunction *func = functionCall->getFunction();
7560*8975f5c5SAndroid Build Coastguard Worker     if (!BuiltInGroup::IsInterpolationFS(functionCall->getOp()))
7561*8975f5c5SAndroid Build Coastguard Worker     {
7562*8975f5c5SAndroid Build Coastguard Worker         return;
7563*8975f5c5SAndroid Build Coastguard Worker     }
7564*8975f5c5SAndroid Build Coastguard Worker 
7565*8975f5c5SAndroid Build Coastguard Worker     TIntermTyped *arg0 = nullptr;
7566*8975f5c5SAndroid Build Coastguard Worker 
7567*8975f5c5SAndroid Build Coastguard Worker     if (functionCall->getAsAggregate())
7568*8975f5c5SAndroid Build Coastguard Worker     {
7569*8975f5c5SAndroid Build Coastguard Worker         const TIntermSequence *argp = functionCall->getSequence();
7570*8975f5c5SAndroid Build Coastguard Worker         if (argp->size() > 0)
7571*8975f5c5SAndroid Build Coastguard Worker             arg0 = (*argp)[0]->getAsTyped();
7572*8975f5c5SAndroid Build Coastguard Worker     }
7573*8975f5c5SAndroid Build Coastguard Worker     else
7574*8975f5c5SAndroid Build Coastguard Worker     {
7575*8975f5c5SAndroid Build Coastguard Worker         assert(functionCall->getAsUnaryNode());
7576*8975f5c5SAndroid Build Coastguard Worker         arg0 = functionCall->getAsUnaryNode()->getOperand();
7577*8975f5c5SAndroid Build Coastguard Worker     }
7578*8975f5c5SAndroid Build Coastguard Worker 
7579*8975f5c5SAndroid Build Coastguard Worker     // Make sure the first argument is an interpolant, or an array element of an interpolant
7580*8975f5c5SAndroid Build Coastguard Worker     if (!IsVaryingIn(arg0->getType().getQualifier()))
7581*8975f5c5SAndroid Build Coastguard Worker     {
7582*8975f5c5SAndroid Build Coastguard Worker         // It might still be an array element.
7583*8975f5c5SAndroid Build Coastguard Worker         const TIntermTyped *base = FindLValueBase(arg0);
7584*8975f5c5SAndroid Build Coastguard Worker 
7585*8975f5c5SAndroid Build Coastguard Worker         if (base == nullptr || (!IsVaryingIn(base->getType().getQualifier())))
7586*8975f5c5SAndroid Build Coastguard Worker             error(arg0->getLine(),
7587*8975f5c5SAndroid Build Coastguard Worker                   "first argument must be an interpolant, or interpolant-array element",
7588*8975f5c5SAndroid Build Coastguard Worker                   func->name());
7589*8975f5c5SAndroid Build Coastguard Worker     }
7590*8975f5c5SAndroid Build Coastguard Worker }
7591*8975f5c5SAndroid Build Coastguard Worker 
checkAtomicMemoryBuiltinFunctions(TIntermAggregate * functionCall)7592*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkAtomicMemoryBuiltinFunctions(TIntermAggregate *functionCall)
7593*8975f5c5SAndroid Build Coastguard Worker {
7594*8975f5c5SAndroid Build Coastguard Worker     const TFunction *func = functionCall->getFunction();
7595*8975f5c5SAndroid Build Coastguard Worker     if (BuiltInGroup::IsAtomicMemory(functionCall->getOp()))
7596*8975f5c5SAndroid Build Coastguard Worker     {
7597*8975f5c5SAndroid Build Coastguard Worker         TIntermSequence *arguments = functionCall->getSequence();
7598*8975f5c5SAndroid Build Coastguard Worker         TIntermTyped *memNode      = (*arguments)[0]->getAsTyped();
7599*8975f5c5SAndroid Build Coastguard Worker 
7600*8975f5c5SAndroid Build Coastguard Worker         if (IsBufferOrSharedVariable(memNode))
7601*8975f5c5SAndroid Build Coastguard Worker         {
7602*8975f5c5SAndroid Build Coastguard Worker             return;
7603*8975f5c5SAndroid Build Coastguard Worker         }
7604*8975f5c5SAndroid Build Coastguard Worker 
7605*8975f5c5SAndroid Build Coastguard Worker         while (memNode->getAsBinaryNode() || memNode->getAsSwizzleNode())
7606*8975f5c5SAndroid Build Coastguard Worker         {
7607*8975f5c5SAndroid Build Coastguard Worker             // Child 0 is "left" if binary, and the expression being swizzled if swizzle.
7608*8975f5c5SAndroid Build Coastguard Worker             // Note: we don't need to check that the binary operation is one of EOp*Index*, as any
7609*8975f5c5SAndroid Build Coastguard Worker             // other operation will result in a temp value which cannot be passed to this
7610*8975f5c5SAndroid Build Coastguard Worker             // out/inout parameter anyway.
7611*8975f5c5SAndroid Build Coastguard Worker             memNode = memNode->getChildNode(0)->getAsTyped();
7612*8975f5c5SAndroid Build Coastguard Worker             if (IsBufferOrSharedVariable(memNode))
7613*8975f5c5SAndroid Build Coastguard Worker             {
7614*8975f5c5SAndroid Build Coastguard Worker                 return;
7615*8975f5c5SAndroid Build Coastguard Worker             }
7616*8975f5c5SAndroid Build Coastguard Worker         }
7617*8975f5c5SAndroid Build Coastguard Worker 
7618*8975f5c5SAndroid Build Coastguard Worker         error(memNode->getLine(),
7619*8975f5c5SAndroid Build Coastguard Worker               "The value passed to the mem argument of an atomic memory function does not "
7620*8975f5c5SAndroid Build Coastguard Worker               "correspond to a buffer or shared variable.",
7621*8975f5c5SAndroid Build Coastguard Worker               func->name());
7622*8975f5c5SAndroid Build Coastguard Worker     }
7623*8975f5c5SAndroid Build Coastguard Worker }
7624*8975f5c5SAndroid Build Coastguard Worker 
7625*8975f5c5SAndroid Build Coastguard Worker // GLSL ES 3.10 Revision 4, 4.9 Memory Access Qualifiers
checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate * functionCall)7626*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkImageMemoryAccessForBuiltinFunctions(TIntermAggregate *functionCall)
7627*8975f5c5SAndroid Build Coastguard Worker {
7628*8975f5c5SAndroid Build Coastguard Worker     const TOperator op = functionCall->getOp();
7629*8975f5c5SAndroid Build Coastguard Worker 
7630*8975f5c5SAndroid Build Coastguard Worker     if (BuiltInGroup::IsImage(op))
7631*8975f5c5SAndroid Build Coastguard Worker     {
7632*8975f5c5SAndroid Build Coastguard Worker         TIntermSequence *arguments = functionCall->getSequence();
7633*8975f5c5SAndroid Build Coastguard Worker         TIntermTyped *imageNode    = (*arguments)[0]->getAsTyped();
7634*8975f5c5SAndroid Build Coastguard Worker 
7635*8975f5c5SAndroid Build Coastguard Worker         const TMemoryQualifier &memoryQualifier = imageNode->getMemoryQualifier();
7636*8975f5c5SAndroid Build Coastguard Worker 
7637*8975f5c5SAndroid Build Coastguard Worker         if (BuiltInGroup::IsImageStore(op))
7638*8975f5c5SAndroid Build Coastguard Worker         {
7639*8975f5c5SAndroid Build Coastguard Worker             if (memoryQualifier.readonly)
7640*8975f5c5SAndroid Build Coastguard Worker             {
7641*8975f5c5SAndroid Build Coastguard Worker                 error(imageNode->getLine(),
7642*8975f5c5SAndroid Build Coastguard Worker                       "'imageStore' cannot be used with images qualified as 'readonly'",
7643*8975f5c5SAndroid Build Coastguard Worker                       GetImageArgumentToken(imageNode));
7644*8975f5c5SAndroid Build Coastguard Worker             }
7645*8975f5c5SAndroid Build Coastguard Worker         }
7646*8975f5c5SAndroid Build Coastguard Worker         else if (BuiltInGroup::IsImageLoad(op))
7647*8975f5c5SAndroid Build Coastguard Worker         {
7648*8975f5c5SAndroid Build Coastguard Worker             if (memoryQualifier.writeonly)
7649*8975f5c5SAndroid Build Coastguard Worker             {
7650*8975f5c5SAndroid Build Coastguard Worker                 error(imageNode->getLine(),
7651*8975f5c5SAndroid Build Coastguard Worker                       "'imageLoad' cannot be used with images qualified as 'writeonly'",
7652*8975f5c5SAndroid Build Coastguard Worker                       GetImageArgumentToken(imageNode));
7653*8975f5c5SAndroid Build Coastguard Worker             }
7654*8975f5c5SAndroid Build Coastguard Worker         }
7655*8975f5c5SAndroid Build Coastguard Worker         else if (BuiltInGroup::IsImageAtomic(op))
7656*8975f5c5SAndroid Build Coastguard Worker         {
7657*8975f5c5SAndroid Build Coastguard Worker             if (memoryQualifier.readonly)
7658*8975f5c5SAndroid Build Coastguard Worker             {
7659*8975f5c5SAndroid Build Coastguard Worker                 error(imageNode->getLine(),
7660*8975f5c5SAndroid Build Coastguard Worker                       "'imageAtomic' cannot be used with images qualified as 'readonly'",
7661*8975f5c5SAndroid Build Coastguard Worker                       GetImageArgumentToken(imageNode));
7662*8975f5c5SAndroid Build Coastguard Worker             }
7663*8975f5c5SAndroid Build Coastguard Worker             if (memoryQualifier.writeonly)
7664*8975f5c5SAndroid Build Coastguard Worker             {
7665*8975f5c5SAndroid Build Coastguard Worker                 error(imageNode->getLine(),
7666*8975f5c5SAndroid Build Coastguard Worker                       "'imageAtomic' cannot be used with images qualified as 'writeonly'",
7667*8975f5c5SAndroid Build Coastguard Worker                       GetImageArgumentToken(imageNode));
7668*8975f5c5SAndroid Build Coastguard Worker             }
7669*8975f5c5SAndroid Build Coastguard Worker         }
7670*8975f5c5SAndroid Build Coastguard Worker     }
7671*8975f5c5SAndroid Build Coastguard Worker }
7672*8975f5c5SAndroid Build Coastguard Worker 
7673*8975f5c5SAndroid Build Coastguard Worker // GLSL ES 3.10 Revision 4, 13.51 Matching of Memory Qualifiers in Function Parameters
checkImageMemoryAccessForUserDefinedFunctions(const TFunction * functionDefinition,const TIntermAggregate * functionCall)7674*8975f5c5SAndroid Build Coastguard Worker void TParseContext::checkImageMemoryAccessForUserDefinedFunctions(
7675*8975f5c5SAndroid Build Coastguard Worker     const TFunction *functionDefinition,
7676*8975f5c5SAndroid Build Coastguard Worker     const TIntermAggregate *functionCall)
7677*8975f5c5SAndroid Build Coastguard Worker {
7678*8975f5c5SAndroid Build Coastguard Worker     ASSERT(functionCall->getOp() == EOpCallFunctionInAST);
7679*8975f5c5SAndroid Build Coastguard Worker 
7680*8975f5c5SAndroid Build Coastguard Worker     const TIntermSequence &arguments = *functionCall->getSequence();
7681*8975f5c5SAndroid Build Coastguard Worker 
7682*8975f5c5SAndroid Build Coastguard Worker     ASSERT(functionDefinition->getParamCount() == arguments.size());
7683*8975f5c5SAndroid Build Coastguard Worker 
7684*8975f5c5SAndroid Build Coastguard Worker     for (size_t i = 0; i < arguments.size(); ++i)
7685*8975f5c5SAndroid Build Coastguard Worker     {
7686*8975f5c5SAndroid Build Coastguard Worker         TIntermTyped *typedArgument        = arguments[i]->getAsTyped();
7687*8975f5c5SAndroid Build Coastguard Worker         const TType &functionArgumentType  = typedArgument->getType();
7688*8975f5c5SAndroid Build Coastguard Worker         const TType &functionParameterType = functionDefinition->getParam(i)->getType();
7689*8975f5c5SAndroid Build Coastguard Worker         ASSERT(functionArgumentType.getBasicType() == functionParameterType.getBasicType());
7690*8975f5c5SAndroid Build Coastguard Worker 
7691*8975f5c5SAndroid Build Coastguard Worker         if (IsImage(functionArgumentType.getBasicType()))
7692*8975f5c5SAndroid Build Coastguard Worker         {
7693*8975f5c5SAndroid Build Coastguard Worker             const TMemoryQualifier &functionArgumentMemoryQualifier =
7694*8975f5c5SAndroid Build Coastguard Worker                 functionArgumentType.getMemoryQualifier();
7695*8975f5c5SAndroid Build Coastguard Worker             const TMemoryQualifier &functionParameterMemoryQualifier =
7696*8975f5c5SAndroid Build Coastguard Worker                 functionParameterType.getMemoryQualifier();
7697*8975f5c5SAndroid Build Coastguard Worker             if (functionArgumentMemoryQualifier.readonly &&
7698*8975f5c5SAndroid Build Coastguard Worker                 !functionParameterMemoryQualifier.readonly)
7699*8975f5c5SAndroid Build Coastguard Worker             {
7700*8975f5c5SAndroid Build Coastguard Worker                 error(functionCall->getLine(),
7701*8975f5c5SAndroid Build Coastguard Worker                       "Function call discards the 'readonly' qualifier from image",
7702*8975f5c5SAndroid Build Coastguard Worker                       GetImageArgumentToken(typedArgument));
7703*8975f5c5SAndroid Build Coastguard Worker             }
7704*8975f5c5SAndroid Build Coastguard Worker 
7705*8975f5c5SAndroid Build Coastguard Worker             if (functionArgumentMemoryQualifier.writeonly &&
7706*8975f5c5SAndroid Build Coastguard Worker                 !functionParameterMemoryQualifier.writeonly)
7707*8975f5c5SAndroid Build Coastguard Worker             {
7708*8975f5c5SAndroid Build Coastguard Worker                 error(functionCall->getLine(),
7709*8975f5c5SAndroid Build Coastguard Worker                       "Function call discards the 'writeonly' qualifier from image",
7710*8975f5c5SAndroid Build Coastguard Worker                       GetImageArgumentToken(typedArgument));
7711*8975f5c5SAndroid Build Coastguard Worker             }
7712*8975f5c5SAndroid Build Coastguard Worker 
7713*8975f5c5SAndroid Build Coastguard Worker             if (functionArgumentMemoryQualifier.coherent &&
7714*8975f5c5SAndroid Build Coastguard Worker                 !functionParameterMemoryQualifier.coherent)
7715*8975f5c5SAndroid Build Coastguard Worker             {
7716*8975f5c5SAndroid Build Coastguard Worker                 error(functionCall->getLine(),
7717*8975f5c5SAndroid Build Coastguard Worker                       "Function call discards the 'coherent' qualifier from image",
7718*8975f5c5SAndroid Build Coastguard Worker                       GetImageArgumentToken(typedArgument));
7719*8975f5c5SAndroid Build Coastguard Worker             }
7720*8975f5c5SAndroid Build Coastguard Worker 
7721*8975f5c5SAndroid Build Coastguard Worker             if (functionArgumentMemoryQualifier.volatileQualifier &&
7722*8975f5c5SAndroid Build Coastguard Worker                 !functionParameterMemoryQualifier.volatileQualifier)
7723*8975f5c5SAndroid Build Coastguard Worker             {
7724*8975f5c5SAndroid Build Coastguard Worker                 error(functionCall->getLine(),
7725*8975f5c5SAndroid Build Coastguard Worker                       "Function call discards the 'volatile' qualifier from image",
7726*8975f5c5SAndroid Build Coastguard Worker                       GetImageArgumentToken(typedArgument));
7727*8975f5c5SAndroid Build Coastguard Worker             }
7728*8975f5c5SAndroid Build Coastguard Worker         }
7729*8975f5c5SAndroid Build Coastguard Worker     }
7730*8975f5c5SAndroid Build Coastguard Worker }
7731*8975f5c5SAndroid Build Coastguard Worker 
addFunctionCallOrMethod(TFunctionLookup * fnCall,const TSourceLoc & loc)7732*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
7733*8975f5c5SAndroid Build Coastguard Worker {
7734*8975f5c5SAndroid Build Coastguard Worker     if (fnCall->thisNode() != nullptr)
7735*8975f5c5SAndroid Build Coastguard Worker     {
7736*8975f5c5SAndroid Build Coastguard Worker         return addMethod(fnCall, loc);
7737*8975f5c5SAndroid Build Coastguard Worker     }
7738*8975f5c5SAndroid Build Coastguard Worker     if (fnCall->isConstructor())
7739*8975f5c5SAndroid Build Coastguard Worker     {
7740*8975f5c5SAndroid Build Coastguard Worker         return addConstructor(fnCall, loc);
7741*8975f5c5SAndroid Build Coastguard Worker     }
7742*8975f5c5SAndroid Build Coastguard Worker     return addNonConstructorFunctionCall(fnCall, loc);
7743*8975f5c5SAndroid Build Coastguard Worker }
7744*8975f5c5SAndroid Build Coastguard Worker 
addMethod(TFunctionLookup * fnCall,const TSourceLoc & loc)7745*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc)
7746*8975f5c5SAndroid Build Coastguard Worker {
7747*8975f5c5SAndroid Build Coastguard Worker     TIntermTyped *thisNode = fnCall->thisNode();
7748*8975f5c5SAndroid Build Coastguard Worker     // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
7749*8975f5c5SAndroid Build Coastguard Worker     // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
7750*8975f5c5SAndroid Build Coastguard Worker     // mode after a dot, which makes type identifiers to be parsed as FIELD_SELECTION instead.
7751*8975f5c5SAndroid Build Coastguard Worker     // So accessing fnCall->name() below is safe.
7752*8975f5c5SAndroid Build Coastguard Worker     if (fnCall->name() != "length")
7753*8975f5c5SAndroid Build Coastguard Worker     {
7754*8975f5c5SAndroid Build Coastguard Worker         error(loc, "invalid method", fnCall->name());
7755*8975f5c5SAndroid Build Coastguard Worker     }
7756*8975f5c5SAndroid Build Coastguard Worker     else if (!fnCall->arguments().empty())
7757*8975f5c5SAndroid Build Coastguard Worker     {
7758*8975f5c5SAndroid Build Coastguard Worker         error(loc, "method takes no parameters", "length");
7759*8975f5c5SAndroid Build Coastguard Worker     }
7760*8975f5c5SAndroid Build Coastguard Worker     else if (!thisNode->isArray())
7761*8975f5c5SAndroid Build Coastguard Worker     {
7762*8975f5c5SAndroid Build Coastguard Worker         error(loc, "length can only be called on arrays", "length");
7763*8975f5c5SAndroid Build Coastguard Worker     }
7764*8975f5c5SAndroid Build Coastguard Worker     else if (thisNode->getQualifier() == EvqPerVertexIn &&
7765*8975f5c5SAndroid Build Coastguard Worker              mGeometryShaderInputPrimitiveType == EptUndefined)
7766*8975f5c5SAndroid Build Coastguard Worker     {
7767*8975f5c5SAndroid Build Coastguard Worker         ASSERT(mShaderType == GL_GEOMETRY_SHADER_EXT);
7768*8975f5c5SAndroid Build Coastguard Worker         error(loc, "missing input primitive declaration before calling length on gl_in", "length");
7769*8975f5c5SAndroid Build Coastguard Worker     }
7770*8975f5c5SAndroid Build Coastguard Worker     else
7771*8975f5c5SAndroid Build Coastguard Worker     {
7772*8975f5c5SAndroid Build Coastguard Worker         TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
7773*8975f5c5SAndroid Build Coastguard Worker         markStaticReadIfSymbol(thisNode);
7774*8975f5c5SAndroid Build Coastguard Worker         node->setLine(loc);
7775*8975f5c5SAndroid Build Coastguard Worker         return node->fold(mDiagnostics);
7776*8975f5c5SAndroid Build Coastguard Worker     }
7777*8975f5c5SAndroid Build Coastguard Worker     return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
7778*8975f5c5SAndroid Build Coastguard Worker }
7779*8975f5c5SAndroid Build Coastguard Worker 
addNonConstructorFunctionCallImpl(TFunctionLookup * fnCall,const TSourceLoc & loc)7780*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addNonConstructorFunctionCallImpl(TFunctionLookup *fnCall,
7781*8975f5c5SAndroid Build Coastguard Worker                                                                const TSourceLoc &loc)
7782*8975f5c5SAndroid Build Coastguard Worker {
7783*8975f5c5SAndroid Build Coastguard Worker     // First check whether the function has been hidden by a variable name or struct typename by
7784*8975f5c5SAndroid Build Coastguard Worker     // using the symbol looked up in the lexical phase. If the function is not hidden, look for one
7785*8975f5c5SAndroid Build Coastguard Worker     // with a matching argument list.
7786*8975f5c5SAndroid Build Coastguard Worker     if (fnCall->symbol() != nullptr && !fnCall->symbol()->isFunction())
7787*8975f5c5SAndroid Build Coastguard Worker     {
7788*8975f5c5SAndroid Build Coastguard Worker         error(loc, "function name expected", fnCall->name());
7789*8975f5c5SAndroid Build Coastguard Worker     }
7790*8975f5c5SAndroid Build Coastguard Worker     else
7791*8975f5c5SAndroid Build Coastguard Worker     {
7792*8975f5c5SAndroid Build Coastguard Worker         // There are no inner functions, so it's enough to look for user-defined functions in the
7793*8975f5c5SAndroid Build Coastguard Worker         // global scope.
7794*8975f5c5SAndroid Build Coastguard Worker         const TSymbol *symbol = symbolTable.findGlobal(fnCall->getMangledName());
7795*8975f5c5SAndroid Build Coastguard Worker 
7796*8975f5c5SAndroid Build Coastguard Worker         if (symbol != nullptr)
7797*8975f5c5SAndroid Build Coastguard Worker         {
7798*8975f5c5SAndroid Build Coastguard Worker             // A user-defined function - could be an overloaded built-in as well.
7799*8975f5c5SAndroid Build Coastguard Worker             ASSERT(symbol->symbolType() == SymbolType::UserDefined);
7800*8975f5c5SAndroid Build Coastguard Worker             const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
7801*8975f5c5SAndroid Build Coastguard Worker             TIntermAggregate *callNode =
7802*8975f5c5SAndroid Build Coastguard Worker                 TIntermAggregate::CreateFunctionCall(*fnCandidate, &fnCall->arguments());
7803*8975f5c5SAndroid Build Coastguard Worker             callNode->setLine(loc);
7804*8975f5c5SAndroid Build Coastguard Worker             checkImageMemoryAccessForUserDefinedFunctions(fnCandidate, callNode);
7805*8975f5c5SAndroid Build Coastguard Worker             functionCallRValueLValueErrorCheck(fnCandidate, callNode);
7806*8975f5c5SAndroid Build Coastguard Worker             return callNode;
7807*8975f5c5SAndroid Build Coastguard Worker         }
7808*8975f5c5SAndroid Build Coastguard Worker 
7809*8975f5c5SAndroid Build Coastguard Worker         symbol = symbolTable.findBuiltIn(fnCall->getMangledName(), mShaderVersion);
7810*8975f5c5SAndroid Build Coastguard Worker 
7811*8975f5c5SAndroid Build Coastguard Worker         if (symbol != nullptr)
7812*8975f5c5SAndroid Build Coastguard Worker         {
7813*8975f5c5SAndroid Build Coastguard Worker             // A built-in function.
7814*8975f5c5SAndroid Build Coastguard Worker             ASSERT(symbol->symbolType() == SymbolType::BuiltIn);
7815*8975f5c5SAndroid Build Coastguard Worker             const TFunction *fnCandidate = static_cast<const TFunction *>(symbol);
7816*8975f5c5SAndroid Build Coastguard Worker 
7817*8975f5c5SAndroid Build Coastguard Worker             if (!fnCandidate->extensions().empty() &&
7818*8975f5c5SAndroid Build Coastguard Worker                 fnCandidate->extensions()[0] != TExtension::UNDEFINED)
7819*8975f5c5SAndroid Build Coastguard Worker             {
7820*8975f5c5SAndroid Build Coastguard Worker                 checkCanUseOneOfExtensions(loc, fnCandidate->extensions());
7821*8975f5c5SAndroid Build Coastguard Worker             }
7822*8975f5c5SAndroid Build Coastguard Worker 
7823*8975f5c5SAndroid Build Coastguard Worker             // All function calls are mapped to a built-in operation.
7824*8975f5c5SAndroid Build Coastguard Worker             TOperator op = fnCandidate->getBuiltInOp();
7825*8975f5c5SAndroid Build Coastguard Worker             if (BuiltInGroup::IsMath(op) && fnCandidate->getParamCount() == 1)
7826*8975f5c5SAndroid Build Coastguard Worker             {
7827*8975f5c5SAndroid Build Coastguard Worker                 // Treat it like a built-in unary operator.
7828*8975f5c5SAndroid Build Coastguard Worker                 TIntermNode *unaryParamNode = fnCall->arguments().front();
7829*8975f5c5SAndroid Build Coastguard Worker                 return createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
7830*8975f5c5SAndroid Build Coastguard Worker             }
7831*8975f5c5SAndroid Build Coastguard Worker 
7832*8975f5c5SAndroid Build Coastguard Worker             TIntermAggregate *callNode =
7833*8975f5c5SAndroid Build Coastguard Worker                 TIntermAggregate::CreateBuiltInFunctionCall(*fnCandidate, &fnCall->arguments());
7834*8975f5c5SAndroid Build Coastguard Worker             callNode->setLine(loc);
7835*8975f5c5SAndroid Build Coastguard Worker 
7836*8975f5c5SAndroid Build Coastguard Worker             if (UsesDerivatives(callNode))
7837*8975f5c5SAndroid Build Coastguard Worker             {
7838*8975f5c5SAndroid Build Coastguard Worker                 mUsesDerivatives = true;
7839*8975f5c5SAndroid Build Coastguard Worker             }
7840*8975f5c5SAndroid Build Coastguard Worker 
7841*8975f5c5SAndroid Build Coastguard Worker             checkAtomicMemoryBuiltinFunctions(callNode);
7842*8975f5c5SAndroid Build Coastguard Worker             checkTextureOffset(callNode);
7843*8975f5c5SAndroid Build Coastguard Worker             checkTextureGather(callNode);
7844*8975f5c5SAndroid Build Coastguard Worker             checkInterpolationFS(callNode);
7845*8975f5c5SAndroid Build Coastguard Worker             checkImageMemoryAccessForBuiltinFunctions(callNode);
7846*8975f5c5SAndroid Build Coastguard Worker 
7847*8975f5c5SAndroid Build Coastguard Worker             // Some built-in functions have out parameters too.
7848*8975f5c5SAndroid Build Coastguard Worker             functionCallRValueLValueErrorCheck(fnCandidate, callNode);
7849*8975f5c5SAndroid Build Coastguard Worker 
7850*8975f5c5SAndroid Build Coastguard Worker             // See if we can constant fold a built-in. Note that this may be possible
7851*8975f5c5SAndroid Build Coastguard Worker             // even if it is not const-qualified.
7852*8975f5c5SAndroid Build Coastguard Worker             return callNode->fold(mDiagnostics);
7853*8975f5c5SAndroid Build Coastguard Worker         }
7854*8975f5c5SAndroid Build Coastguard Worker         else
7855*8975f5c5SAndroid Build Coastguard Worker         {
7856*8975f5c5SAndroid Build Coastguard Worker             error(loc, "no matching overloaded function found", fnCall->name());
7857*8975f5c5SAndroid Build Coastguard Worker         }
7858*8975f5c5SAndroid Build Coastguard Worker     }
7859*8975f5c5SAndroid Build Coastguard Worker     return nullptr;
7860*8975f5c5SAndroid Build Coastguard Worker }
7861*8975f5c5SAndroid Build Coastguard Worker 
addNonConstructorFunctionCall(TFunctionLookup * fnCall,const TSourceLoc & loc)7862*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCall,
7863*8975f5c5SAndroid Build Coastguard Worker                                                            const TSourceLoc &loc)
7864*8975f5c5SAndroid Build Coastguard Worker {
7865*8975f5c5SAndroid Build Coastguard Worker     TIntermTyped *result = addNonConstructorFunctionCallImpl(fnCall, loc);
7866*8975f5c5SAndroid Build Coastguard Worker     if (result != nullptr)
7867*8975f5c5SAndroid Build Coastguard Worker     {
7868*8975f5c5SAndroid Build Coastguard Worker         return result;
7869*8975f5c5SAndroid Build Coastguard Worker     }
7870*8975f5c5SAndroid Build Coastguard Worker     // Error message was already written. Put on an unused node for error recovery.
7871*8975f5c5SAndroid Build Coastguard Worker     return CreateZeroNode(TType(EbtFloat, EbpMedium, EvqConst));
7872*8975f5c5SAndroid Build Coastguard Worker }
7873*8975f5c5SAndroid Build Coastguard Worker 
addTernarySelection(TIntermTyped * cond,TIntermTyped * trueExpression,TIntermTyped * falseExpression,const TSourceLoc & loc)7874*8975f5c5SAndroid Build Coastguard Worker TIntermTyped *TParseContext::addTernarySelection(TIntermTyped *cond,
7875*8975f5c5SAndroid Build Coastguard Worker                                                  TIntermTyped *trueExpression,
7876*8975f5c5SAndroid Build Coastguard Worker                                                  TIntermTyped *falseExpression,
7877*8975f5c5SAndroid Build Coastguard Worker                                                  const TSourceLoc &loc)
7878*8975f5c5SAndroid Build Coastguard Worker {
7879*8975f5c5SAndroid Build Coastguard Worker     if (!checkIsScalarBool(loc, cond))
7880*8975f5c5SAndroid Build Coastguard Worker     {
7881*8975f5c5SAndroid Build Coastguard Worker         return falseExpression;
7882*8975f5c5SAndroid Build Coastguard Worker     }
7883*8975f5c5SAndroid Build Coastguard Worker 
7884*8975f5c5SAndroid Build Coastguard Worker     if (trueExpression->getType() != falseExpression->getType())
7885*8975f5c5SAndroid Build Coastguard Worker     {
7886*8975f5c5SAndroid Build Coastguard Worker         TInfoSinkBase reasonStream;
7887*8975f5c5SAndroid Build Coastguard Worker         reasonStream << "mismatching ternary operator operand types '" << trueExpression->getType()
7888*8975f5c5SAndroid Build Coastguard Worker                      << " and '" << falseExpression->getType() << "'";
7889*8975f5c5SAndroid Build Coastguard Worker         error(loc, reasonStream.c_str(), "?:");
7890*8975f5c5SAndroid Build Coastguard Worker         return falseExpression;
7891*8975f5c5SAndroid Build Coastguard Worker     }
7892*8975f5c5SAndroid Build Coastguard Worker     if (IsOpaqueType(trueExpression->getBasicType()))
7893*8975f5c5SAndroid Build Coastguard Worker     {
7894*8975f5c5SAndroid Build Coastguard Worker         // ESSL 1.00 section 4.1.7
7895*8975f5c5SAndroid Build Coastguard Worker         // ESSL 3.00.6 section 4.1.7
7896*8975f5c5SAndroid Build Coastguard Worker         // Opaque/sampler types are not allowed in most types of expressions, including ternary.
7897*8975f5c5SAndroid Build Coastguard Worker         // Note that structs containing opaque types don't need to be checked as structs are
7898*8975f5c5SAndroid Build Coastguard Worker         // forbidden below.
7899*8975f5c5SAndroid Build Coastguard Worker         error(loc, "ternary operator is not allowed for opaque types", "?:");
7900*8975f5c5SAndroid Build Coastguard Worker         return falseExpression;
7901*8975f5c5SAndroid Build Coastguard Worker     }
7902*8975f5c5SAndroid Build Coastguard Worker 
7903*8975f5c5SAndroid Build Coastguard Worker     if (cond->getMemoryQualifier().writeonly || trueExpression->getMemoryQualifier().writeonly ||
7904*8975f5c5SAndroid Build Coastguard Worker         falseExpression->getMemoryQualifier().writeonly)
7905*8975f5c5SAndroid Build Coastguard Worker     {
7906*8975f5c5SAndroid Build Coastguard Worker         error(loc, "ternary operator is not allowed for variables with writeonly", "?:");
7907*8975f5c5SAndroid Build Coastguard Worker         return falseExpression;
7908*8975f5c5SAndroid Build Coastguard Worker     }
7909*8975f5c5SAndroid Build Coastguard Worker 
7910*8975f5c5SAndroid Build Coastguard Worker     // ESSL 1.00.17 sections 5.2 and 5.7:
7911*8975f5c5SAndroid Build Coastguard Worker     // Ternary operator is not among the operators allowed for structures/arrays.
7912*8975f5c5SAndroid Build Coastguard Worker     // ESSL 3.00 and ESSL 3.10 section 5.7:
7913*8975f5c5SAndroid Build Coastguard Worker     // Ternary operator supports structs, but array support is optional for arrays.
7914*8975f5c5SAndroid Build Coastguard Worker     // ESSL 3.20 section 5.7:
7915*8975f5c5SAndroid Build Coastguard Worker     // Ternary operator supports structs and arrays unconditionally.
7916*8975f5c5SAndroid Build Coastguard Worker     // In WebGL2 section 5.26, ternary is banned for both arrays and structs.
7917*8975f5c5SAndroid Build Coastguard Worker     if ((mShaderVersion < 300 || mShaderSpec == SH_WEBGL2_SPEC) && trueExpression->isArray())
7918*8975f5c5SAndroid Build Coastguard Worker     {
7919*8975f5c5SAndroid Build Coastguard Worker         error(loc, "ternary operator is not allowed for arrays in ESSL 1.0 and webgl", "?:");
7920*8975f5c5SAndroid Build Coastguard Worker         return falseExpression;
7921*8975f5c5SAndroid Build Coastguard Worker     }
7922*8975f5c5SAndroid Build Coastguard Worker     if ((mShaderVersion < 300 || mShaderSpec == SH_WEBGL2_SPEC) &&
7923*8975f5c5SAndroid Build Coastguard Worker         trueExpression->getBasicType() == EbtStruct)
7924*8975f5c5SAndroid Build Coastguard Worker     {
7925*8975f5c5SAndroid Build Coastguard Worker         error(loc, "ternary operator is not allowed for structures in ESSL 1.0 and webgl", "?:");
7926*8975f5c5SAndroid Build Coastguard Worker         return falseExpression;
7927*8975f5c5SAndroid Build Coastguard Worker     }
7928*8975f5c5SAndroid Build Coastguard Worker     if (trueExpression->getBasicType() == EbtInterfaceBlock)
7929*8975f5c5SAndroid Build Coastguard Worker     {
7930*8975f5c5SAndroid Build Coastguard Worker         error(loc, "ternary operator is not allowed for interface blocks", "?:");
7931*8975f5c5SAndroid Build Coastguard Worker         return falseExpression;
7932*8975f5c5SAndroid Build Coastguard Worker     }
7933*8975f5c5SAndroid Build Coastguard Worker 
7934*8975f5c5SAndroid Build Coastguard Worker     // WebGL2 section 5.26, the following results in an error:
7935*8975f5c5SAndroid Build Coastguard Worker     // "Ternary operator applied to void, arrays, or structs containing arrays"
7936*8975f5c5SAndroid Build Coastguard Worker     if (mShaderSpec == SH_WEBGL2_SPEC && trueExpression->getBasicType() == EbtVoid)
7937*8975f5c5SAndroid Build Coastguard Worker     {
7938*8975f5c5SAndroid Build Coastguard Worker         error(loc, "ternary operator is not allowed for void", "?:");
7939*8975f5c5SAndroid Build Coastguard Worker         return falseExpression;
7940*8975f5c5SAndroid Build Coastguard Worker     }
7941*8975f5c5SAndroid Build Coastguard Worker 
7942*8975f5c5SAndroid Build Coastguard Worker     TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
7943*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(cond);
7944*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(trueExpression);
7945*8975f5c5SAndroid Build Coastguard Worker     markStaticReadIfSymbol(falseExpression);
7946*8975f5c5SAndroid Build Coastguard Worker     node->setLine(loc);
7947*8975f5c5SAndroid Build Coastguard Worker     return expressionOrFoldedResult(node);
7948*8975f5c5SAndroid Build Coastguard Worker }
7949*8975f5c5SAndroid Build Coastguard Worker 
7950*8975f5c5SAndroid Build Coastguard Worker //
7951*8975f5c5SAndroid Build Coastguard Worker // Parse an array of strings using yyparse.
7952*8975f5c5SAndroid Build Coastguard Worker //
7953*8975f5c5SAndroid Build Coastguard Worker // Returns 0 for success.
7954*8975f5c5SAndroid Build Coastguard Worker //
PaParseStrings(size_t count,const char * const string[],const int length[],TParseContext * context)7955*8975f5c5SAndroid Build Coastguard Worker int PaParseStrings(size_t count,
7956*8975f5c5SAndroid Build Coastguard Worker                    const char *const string[],
7957*8975f5c5SAndroid Build Coastguard Worker                    const int length[],
7958*8975f5c5SAndroid Build Coastguard Worker                    TParseContext *context)
7959*8975f5c5SAndroid Build Coastguard Worker {
7960*8975f5c5SAndroid Build Coastguard Worker     if ((count == 0) || (string == nullptr))
7961*8975f5c5SAndroid Build Coastguard Worker         return 1;
7962*8975f5c5SAndroid Build Coastguard Worker 
7963*8975f5c5SAndroid Build Coastguard Worker     if (glslang_initialize(context))
7964*8975f5c5SAndroid Build Coastguard Worker         return 1;
7965*8975f5c5SAndroid Build Coastguard Worker 
7966*8975f5c5SAndroid Build Coastguard Worker     int error = glslang_scan(count, string, length, context);
7967*8975f5c5SAndroid Build Coastguard Worker     if (!error)
7968*8975f5c5SAndroid Build Coastguard Worker         error = glslang_parse(context);
7969*8975f5c5SAndroid Build Coastguard Worker 
7970*8975f5c5SAndroid Build Coastguard Worker     glslang_finalize(context);
7971*8975f5c5SAndroid Build Coastguard Worker 
7972*8975f5c5SAndroid Build Coastguard Worker     return (error == 0) && (context->numErrors() == 0) ? 0 : 1;
7973*8975f5c5SAndroid Build Coastguard Worker }
7974*8975f5c5SAndroid Build Coastguard Worker 
7975*8975f5c5SAndroid Build Coastguard Worker }  // namespace sh
7976