• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2002-2005  3Dlabs Inc. Ltd.
3 // Copyright (C) 2012-2013 LunarG, Inc.
4 // Copyright (C) 2015-2018 Google, Inc.
5 //
6 // All rights reserved.
7 //
8 // Redistribution and use in source and binary forms, with or without
9 // modification, are permitted provided that the following conditions
10 // are met:
11 //
12 //    Redistributions of source code must retain the above copyright
13 //    notice, this list of conditions and the following disclaimer.
14 //
15 //    Redistributions in binary form must reproduce the above
16 //    copyright notice, this list of conditions and the following
17 //    disclaimer in the documentation and/or other materials provided
18 //    with the distribution.
19 //
20 //    Neither the name of 3Dlabs Inc. Ltd. nor the names of its
21 //    contributors may be used to endorse or promote products derived
22 //    from this software without specific prior written permission.
23 //
24 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
25 // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
26 // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
27 // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
28 // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
29 // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
30 // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
31 // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32 // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33 // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
34 // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
35 // POSSIBILITY OF SUCH DAMAGE.
36 //
37 
38 //
39 // This header defines a two-level parse-helper hierarchy, derived from
40 // TParseVersions:
41 //  - TParseContextBase:  sharable across multiple parsers
42 //  - TParseContext:      GLSL specific helper
43 //
44 
45 #ifndef _PARSER_HELPER_INCLUDED_
46 #define _PARSER_HELPER_INCLUDED_
47 
48 #include <cstdarg>
49 #include <functional>
50 
51 #include "parseVersions.h"
52 #include "../Include/ShHandle.h"
53 #include "SymbolTable.h"
54 #include "localintermediate.h"
55 #include "Scan.h"
56 #include "attribute.h"
57 
58 namespace glslang {
59 
60 struct TPragma {
TPragmaTPragma61     TPragma(bool o, bool d) : optimize(o), debug(d) { }
62     bool optimize;
63     bool debug;
64     TPragmaTable pragmaTable;
65 };
66 
67 class TScanContext;
68 class TPpContext;
69 
70 typedef std::set<long long> TIdSetType;
71 typedef std::map<const TTypeList*, std::map<size_t, const TTypeList*>> TStructRecord;
72 
73 //
74 // Sharable code (as well as what's in TParseVersions) across
75 // parse helpers.
76 //
77 class TParseContextBase : public TParseVersions {
78 public:
79     TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version,
80                       EProfile profile, const SpvVersion& spvVersion, EShLanguage language,
81                       TInfoSink& infoSink, bool forwardCompatible, EShMessages messages,
82                       const TString* entryPoint = nullptr)
TParseVersions(interm,version,profile,spvVersion,language,infoSink,forwardCompatible,messages)83           : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
84             scopeMangler("::"),
85             symbolTable(symbolTable),
86             statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), blockNestingLevel(0), controlFlowNestingLevel(0),
87             currentFunctionType(nullptr),
88             postEntryPointReturn(false),
89             contextPragma(true, false),
90             beginInvocationInterlockCount(0), endInvocationInterlockCount(0),
91             parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr),
92             limits(resources.limits),
93             globalUniformBlock(nullptr),
94             globalUniformBinding(TQualifier::layoutBindingEnd),
95             globalUniformSet(TQualifier::layoutSetEnd),
96             atomicCounterBlockSet(TQualifier::layoutSetEnd)
97     {
98         // use storage buffer on SPIR-V 1.3 and up
99         if (spvVersion.spv >= EShTargetSpv_1_3)
100             intermediate.setUseStorageBuffer();
101 
102         if (entryPoint != nullptr)
103             sourceEntryPointName = *entryPoint;
104     }
~TParseContextBase()105     virtual ~TParseContextBase() { }
106 
107     virtual void C_DECL   error(const TSourceLoc&, const char* szReason, const char* szToken,
108                                 const char* szExtraInfoFormat, ...);
109     virtual void C_DECL    warn(const TSourceLoc&, const char* szReason, const char* szToken,
110                                 const char* szExtraInfoFormat, ...);
111     virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken,
112                                 const char* szExtraInfoFormat, ...);
113     virtual void C_DECL  ppWarn(const TSourceLoc&, const char* szReason, const char* szToken,
114                                 const char* szExtraInfoFormat, ...);
115 
116     virtual void setLimits(const TBuiltInResource&) = 0;
117 
118     void checkIndex(const TSourceLoc&, const TType&, int& index);
119 
getLanguage()120     EShLanguage getLanguage() const { return language; }
setScanContext(TScanContext * c)121     void setScanContext(TScanContext* c) { scanContext = c; }
getScanContext()122     TScanContext* getScanContext() const { return scanContext; }
setPpContext(TPpContext * c)123     void setPpContext(TPpContext* c) { ppContext = c; }
getPpContext()124     TPpContext* getPpContext() const { return ppContext; }
125 
setLineCallback(const std::function<void (int,int,bool,int,const char *)> & func)126     virtual void setLineCallback(const std::function<void(int, int, bool, int, const char*)>& func) { lineCallback = func; }
setExtensionCallback(const std::function<void (int,const char *,const char *)> & func)127     virtual void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; }
setVersionCallback(const std::function<void (int,int,const char *)> & func)128     virtual void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; }
setPragmaCallback(const std::function<void (int,const TVector<TString> &)> & func)129     virtual void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; }
setErrorCallback(const std::function<void (int,const char *)> & func)130     virtual void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; }
131 
132     virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0;
133     virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0;
134     virtual bool lineDirectiveShouldSetNextLine() const = 0;
135     virtual void handlePragma(const TSourceLoc&, const TVector<TString>&) = 0;
136 
137     virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0;
138 
notifyVersion(int line,int version,const char * type_string)139     virtual void notifyVersion(int line, int version, const char* type_string)
140     {
141         if (versionCallback)
142             versionCallback(line, version, type_string);
143     }
notifyErrorDirective(int line,const char * error_message)144     virtual void notifyErrorDirective(int line, const char* error_message)
145     {
146         if (errorCallback)
147             errorCallback(line, error_message);
148     }
notifyLineDirective(int curLineNo,int newLineNo,bool hasSource,int sourceNum,const char * sourceName)149     virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName)
150     {
151         if (lineCallback)
152             lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName);
153     }
notifyExtensionDirective(int line,const char * extension,const char * behavior)154     virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior)
155     {
156         if (extensionCallback)
157             extensionCallback(line, extension, behavior);
158     }
159 
160     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
161     virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
162 
163     // Manage global buffer (used for backing atomic counters in GLSL when using relaxed Vulkan semantics)
164     virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr);
165 
166     // Potentially rename shader entry point function
renameShaderFunction(TString * & name)167     void renameShaderFunction(TString*& name) const
168     {
169         // Replace the entry point name given in the shader with the real entry point name,
170         // if there is a substitution.
171         if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0)
172             name = NewPoolTString(intermediate.getEntryPointName().c_str());
173     }
174 
175     virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
176     virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*);
177 
178     const char* const scopeMangler;
179 
180     // Basic parsing state, easily accessible to the grammar
181 
182     TSymbolTable& symbolTable;        // symbol table that goes with the current language, version, and profile
183     TVector<TString> relaxedSymbols;
184     int statementNestingLevel;        // 0 if outside all flow control or compound statements
185     int loopNestingLevel;             // 0 if outside all loops
186     int structNestingLevel;           // 0 if outside structures
187     int blockNestingLevel;            // 0 if outside blocks
188     int controlFlowNestingLevel;      // 0 if outside all flow control
189     const TType* currentFunctionType; // the return type of the function that's currently being parsed
190     bool functionReturnsValue;        // true if a non-void function has a return
191     // if inside a function, true if the function is the entry point and this is after a return statement
192     bool postEntryPointReturn;
193     // case, node, case, case, node, ...; ensure only one node between cases;   stack of them for nesting
194     TList<TIntermSequence*> switchSequenceStack;
195     // the statementNestingLevel the current switch statement is at, which must match the level of its case statements
196     TList<int> switchLevel;
197     struct TPragma contextPragma;
198     int beginInvocationInterlockCount;
199     int endInvocationInterlockCount;
200     bool compileOnly = false;
201 
202 protected:
203     TParseContextBase(TParseContextBase&);
204     TParseContextBase& operator=(TParseContextBase&);
205 
206     const bool parsingBuiltins;       // true if parsing built-in symbols/functions
207     TVector<TSymbol*> linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving
208     TScanContext* scanContext;
209     TPpContext* ppContext;
210     TBuiltInResource resources;
211     TLimits& limits;
212     TString sourceEntryPointName;
213 
214     // These, if set, will be called when a line, pragma ... is preprocessed.
215     // They will be called with any parameters to the original directive.
216     std::function<void(int, int, bool, int, const char*)> lineCallback;
217     std::function<void(int, const TVector<TString>&)> pragmaCallback;
218     std::function<void(int, int, const char*)> versionCallback;
219     std::function<void(int, const char*, const char*)> extensionCallback;
220     std::function<void(int, const char*)> errorCallback;
221 
222     // see implementation for detail
223     const TFunction* selectFunction(const TVector<const TFunction*>, const TFunction&,
224         std::function<bool(const TType&, const TType&, TOperator, int arg)>,
225         std::function<bool(const TType&, const TType&, const TType&)>,
226         /* output */ bool& tie);
227 
228     virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size,
229                                       TSwizzleSelectors<TVectorSelector>&);
230 
231     // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL)
232     TVariable* globalUniformBlock;     // the actual block, inserted into the symbol table
233     unsigned int globalUniformBinding; // the block's binding number
234     unsigned int globalUniformSet;     // the block's set number
235     int firstNewMember;                // the index of the first member not yet inserted into the symbol table
236     // override this to set the language-specific name
getGlobalUniformBlockName()237     virtual const char* getGlobalUniformBlockName() const { return ""; }
setUniformBlockDefaults(TType &)238     virtual void setUniformBlockDefaults(TType&) const { }
finalizeGlobalUniformBlockLayout(TVariable &)239     virtual void finalizeGlobalUniformBlockLayout(TVariable&) {}
240 
241     // Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed)
242     TMap<int, TVariable*> atomicCounterBuffers;
243     unsigned int atomicCounterBlockSet;
244     TMap<int, int> atomicCounterBlockFirstNewMember;
245     // override this to set the language-specific name
getAtomicCounterBlockName()246     virtual const char* getAtomicCounterBlockName() const { return ""; }
setAtomicCounterBlockDefaults(TType &)247     virtual void setAtomicCounterBlockDefaults(TType&) const {}
setInvariant(const TSourceLoc &,const char *)248     virtual void setInvariant(const TSourceLoc&, const char*) {}
finalizeAtomicCounterBlockLayout(TVariable &)249     virtual void finalizeAtomicCounterBlockLayout(TVariable&) {}
isAtomicCounterBlock(const TSymbol & symbol)250     bool isAtomicCounterBlock(const TSymbol& symbol) {
251         const TVariable* var = symbol.getAsVariable();
252         if (!var)
253             return false;
254         const auto& at = atomicCounterBuffers.find(var->getType().getQualifier().layoutBinding);
255         return (at != atomicCounterBuffers.end() && (*at).second->getType() == var->getType());
256     }
257 
258     virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken,
259                                const char* szExtraInfoFormat, TPrefixType prefix,
260                                va_list args);
261     virtual void trackLinkage(TSymbol& symbol);
262     virtual void makeEditable(TSymbol*&);
263     virtual TVariable* getEditableVariable(const char* name);
264     virtual void finish();
265 };
266 
267 //
268 // Manage the state for when to respect precision qualifiers and when to warn about
269 // the defaults being different than might be expected.
270 //
271 class TPrecisionManager {
272 public:
TPrecisionManager()273     TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ }
~TPrecisionManager()274     virtual ~TPrecisionManager() {}
275 
respectPrecisionQualifiers()276     void respectPrecisionQualifiers() { obey = true; }
respectingPrecisionQualifiers()277     bool respectingPrecisionQualifiers() const { return obey; }
shouldWarnAboutDefaults()278     bool shouldWarnAboutDefaults() const { return warn; }
defaultWarningGiven()279     void defaultWarningGiven() { warn = false; }
warnAboutDefaults()280     void warnAboutDefaults() { warn = true; }
explicitIntDefaultSeen()281     void explicitIntDefaultSeen()
282     {
283         explicitIntDefault = true;
284         if (explicitFloatDefault)
285             warn = false;
286     }
explicitFloatDefaultSeen()287     void explicitFloatDefaultSeen()
288     {
289         explicitFloatDefault = true;
290         if (explicitIntDefault)
291             warn = false;
292     }
293 
294 protected:
295     bool obey;                  // respect precision qualifiers
296     bool warn;                  // need to give a warning about the defaults
297     bool explicitIntDefault;    // user set the default for int/uint
298     bool explicitFloatDefault;  // user set the default for float
299 };
300 
301 //
302 // GLSL-specific parse helper.  Should have GLSL in the name, but that's
303 // too big of a change for comparing branches at the moment, and perhaps
304 // impacts downstream consumers as well.
305 //
306 class TParseContext : public TParseContextBase {
307 public:
308     TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&,
309                   bool forwardCompatible = false, EShMessages messages = EShMsgDefault,
310                   const TString* entryPoint = nullptr);
311     virtual ~TParseContext();
312 
obeyPrecisionQualifiers()313     bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); }
314     void setPrecisionDefaults();
315 
316     void setLimits(const TBuiltInResource&) override;
317     bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override;
318     void parserError(const char* s);     // for bison's yyerror
319 
320     virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
321     virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override;
322 
323     void reservedErrorCheck(const TSourceLoc&, const TString&);
324     void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override;
325     bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override;
326     bool lineDirectiveShouldSetNextLine() const override;
327     bool builtInName(const TString&);
328 
329     void handlePragma(const TSourceLoc&, const TVector<TString>&) override;
330     TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string);
331     TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
332     void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index);
333 
334     void makeEditable(TSymbol*&) override;
335     void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier);
336     bool isIoResizeArray(const TType&) const;
337     void fixIoArraySize(const TSourceLoc&, TType&);
338     void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base);
339     void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false);
340     int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const;
341     void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&);
342 
343     TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right);
344     TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode);
345     TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
346     TIntermTyped* handleDotSwizzle(const TSourceLoc&, TIntermTyped* base, const TString& field);
347     void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName);
348     TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
349     TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
350     TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
351     TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function);
352     void computeBuiltinPrecisions(TIntermTyped&, const TFunction&);
353     TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*);
354     void checkLocation(const TSourceLoc&, TOperator);
355     TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
356     void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
357     TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
358     TIntermTyped* addAssign(const TSourceLoc&, TOperator op, TIntermTyped* left, TIntermTyped* right);
359     void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
360     void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&);
361     void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&);
362     void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*);
363     TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
364     void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier);
365     void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier);
366     void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode);
367 
368     TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
369     // returns true if the variable was remapped to something else
370     bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&);
371     void vkRelaxedRemapUniformMembers(const TSourceLoc&, const TPublicType&, const TType&, const TString&);
372     void vkRelaxedRemapFunctionParameter(TFunction*, TParameter&, std::vector<int>* newParams = nullptr);
373     TIntermNode* vkRelaxedRemapFunctionArgument(const TSourceLoc&, TFunction*, TIntermTyped*);
374     TIntermTyped* vkRelaxedRemapDotDereference(const TSourceLoc&, TIntermTyped&, const TType&, const TString&);
375 
376     void assignError(const TSourceLoc&, const char* op, TString left, TString right);
377     void unaryOpError(const TSourceLoc&, const char* op, TString operand);
378     void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right);
379     void variableCheck(TIntermTyped*& nodePtr);
380     bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
381     void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override;
382     void constantValueCheck(TIntermTyped* node, const char* token);
383     void integerCheck(const TIntermTyped* node, const char* token);
384     void globalCheck(const TSourceLoc&, const char* token);
385     bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&);
386     bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&);
387     void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType, const bool allowZero = false);
388     bool arrayQualifierError(const TSourceLoc&, const TQualifier&);
389     bool arrayError(const TSourceLoc&, const TType&);
390     void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&);
391     void structArrayCheck(const TSourceLoc&, const TType& structure);
392     void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember);
393     void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*);
394     bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType);
395     void boolCheck(const TSourceLoc&, const TIntermTyped*);
396     void boolCheck(const TSourceLoc&, const TPublicType&);
397     void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer);
398     void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier);
399     void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier);
400     void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier);
401     void memberQualifierCheck(glslang::TPublicType&);
402     void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false, const TPublicType* publicType = nullptr);
403     void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&);
404     bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
405     void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force);
406     void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier);
407     int computeSamplerTypeIndex(TSampler&);
408     TPrecisionQualifier getDefaultPrecision(TPublicType&);
409     void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&, bool isCoopMat);
410     void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type);
411     bool containsFieldWithBasicType(const TType& type ,TBasicType basicType);
412     TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&);
413     void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
414     void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type);
415     void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type);
416     void nestedBlockCheck(const TSourceLoc&);
417     void nestedStructCheck(const TSourceLoc&);
418     void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op);
419     void opaqueCheck(const TSourceLoc&, const TType&, const char* op);
420     void referenceCheck(const TSourceLoc&, const TType&, const char* op);
421     void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op);
422     void specializationCheck(const TSourceLoc&, const TType&, const char* op);
423     void structTypeCheck(const TSourceLoc&, TPublicType&);
424     void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop);
425     void arrayLimitCheck(const TSourceLoc&, const TString&, int size);
426     void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature);
427     void coopMatTypeParametersCheck(const TSourceLoc&, const TPublicType&);
428 
429     void inductiveLoopBodyCheck(TIntermNode*, long long loopIndexId, TSymbolTable&);
430     void constantIndexExpressionCheck(TIntermNode*);
431 
432     void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&);
433     void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*);
434     void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly);
435     void layoutObjectCheck(const TSourceLoc&, const TSymbol&);
436     void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes);
437     void layoutTypeCheck(const TSourceLoc&, const TType&);
438     void layoutQualifierCheck(const TSourceLoc&, const TQualifier&);
439     void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&);
440     void fixOffset(const TSourceLoc&, TSymbol&);
441 
442     const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
443     const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
444     const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
445     const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
446     const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn);
447     void declareTypeDefaults(const TSourceLoc&, const TPublicType&);
448     TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = nullptr, TIntermTyped* initializer = nullptr);
449     TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&);
450     TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&);
451     TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset);
452     void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to);
453     void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = nullptr, TArraySizes* arraySizes = nullptr);
454     void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&);
455     void blockStageIoCheck(const TSourceLoc&, const TQualifier&);
456     void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName);
457     void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation);
458     void fixXfbOffsets(TQualifier&, TTypeList&);
459     void fixBlockUniformOffsets(TQualifier&, TTypeList&);
460     void fixBlockUniformLayoutMatrix(TQualifier&, TTypeList*, TTypeList*);
461     void fixBlockUniformLayoutPacking(TQualifier&, TTypeList*, TTypeList*);
462     void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier);
463     void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&);
464     void invariantCheck(const TSourceLoc&, const TQualifier&);
465     void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&);
466     void updateBindlessQualifier(TType& memberType);
467     void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode);
468     TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body);
469     const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*);
470     TLayoutFormat mapLegacyLayoutFormat(TLayoutFormat legacyLayoutFormat, TBasicType imageType);
471 
472     TAttributeType attributeFromName(const TString& name) const;
473     TAttributes* makeAttributes(const TString& identifier) const;
474     TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const;
475     TAttributes* mergeAttributes(TAttributes*, TAttributes*) const;
476 
477     // Determine selection control from attributes
478     void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*);
479     void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*);
480     // Determine loop control from attributes
481     void handleLoopAttributes(const TAttributes& attributes, TIntermNode*);
482     // Function attributes
483     void handleFunctionAttributes(const TSourceLoc&, const TAttributes&);
484 
485     // GL_EXT_spirv_intrinsics
486     TSpirvRequirement* makeSpirvRequirement(const TSourceLoc& loc, const TString& name,
487                                             const TIntermAggregate* extensions, const TIntermAggregate* capabilities);
488     TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1,
489                                                 TSpirvRequirement* spirvReq2);
490     TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant);
491     TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TPublicType& type);
492     TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1,
493                                                    TSpirvTypeParameters* spirvTypeParams2);
494     TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value);
495     TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value);
496     TSpirvInstruction* mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1,
497                                              TSpirvInstruction* spirvInst2);
498     void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember);
499 
500 protected:
501     void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type);
502     void inheritGlobalDefaults(TQualifier& dst) const;
503     TVariable* makeInternalVariable(const char* name, const TType&) const;
504     TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&);
505     void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&);
506     void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&);
507     bool isRuntimeLength(const TIntermTyped&) const;
508     TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
509     TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer);
510     void finish() override;
511 
512     virtual const char* getGlobalUniformBlockName() const override;
513     virtual void finalizeGlobalUniformBlockLayout(TVariable&) override;
514     virtual void setUniformBlockDefaults(TType& block) const override;
515 
516     virtual const char* getAtomicCounterBlockName() const override;
517     virtual void finalizeAtomicCounterBlockLayout(TVariable&) override;
518     virtual void setAtomicCounterBlockDefaults(TType& block) const override;
519     virtual void setInvariant(const TSourceLoc& loc, const char* builtin) override;
520 
521 public:
522     //
523     // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access
524     //
525 
526     // Current state of parsing
527     bool inMain;                 // if inside a function, true if the function is main
528     const TString* blockName;
529     TQualifier currentBlockQualifier;
530     TPrecisionQualifier defaultPrecision[EbtNumTypes];
531     TBuiltInResource resources;
532     TLimits& limits;
533 
534 protected:
535     TParseContext(TParseContext&);
536     TParseContext& operator=(TParseContext&);
537 
538     static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex()
539     TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex];
540     TPrecisionManager precisionManager;
541     TQualifier globalBufferDefaults;
542     TQualifier globalUniformDefaults;
543     TQualifier globalInputDefaults;
544     TQualifier globalOutputDefaults;
545     TQualifier globalSharedDefaults;
546     TString currentCaller;        // name of last function body entered (not valid when at global scope)
547     int* atomicUintOffsets;       // to become an array of the right size to hold an offset per binding point
548     bool anyIndexLimits;
549     TIdSetType inductiveLoopIds;
550     TVector<TIntermTyped*> needsIndexLimitationChecking;
551     TStructRecord matrixFixRecord;
552     TStructRecord packingFixRecord;
553 
554     //
555     // Geometry shader input arrays:
556     //  - array sizing is based on input primitive and/or explicit size
557     //
558     // Tessellation control output arrays:
559     //  - array sizing is based on output layout(vertices=...) and/or explicit size
560     //
561     // Both:
562     //  - array sizing is retroactive
563     //  - built-in block redeclarations interact with this
564     //
565     // Design:
566     //  - use a per-context "resize-list", a list of symbols whose array sizes
567     //    can be fixed
568     //
569     //  - the resize-list starts empty at beginning of user-shader compilation, it does
570     //    not have built-ins in it
571     //
572     //  - on built-in array use: copyUp() symbol and add it to the resize-list
573     //
574     //  - on user array declaration: add it to the resize-list
575     //
576     //  - on block redeclaration: copyUp() symbol and add it to the resize-list
577     //     * note, that appropriately gives an error if redeclaring a block that
578     //       was already used and hence already copied-up
579     //
580     //  - on seeing a layout declaration that sizes the array, fix everything in the
581     //    resize-list, giving errors for mismatch
582     //
583     //  - on seeing an array size declaration, give errors on mismatch between it and previous
584     //    array-sizing declarations
585     //
586     TVector<TSymbol*> ioArraySymbolResizeList;
587 };
588 
589 } // end namespace glslang
590 
591 #endif // _PARSER_HELPER_INCLUDED_
592