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 if (entryPoint != nullptr) 99 sourceEntryPointName = *entryPoint; 100 } ~TParseContextBase()101 virtual ~TParseContextBase() { } 102 103 #if !defined(GLSLANG_WEB) || defined(GLSLANG_WEB_DEVEL) 104 virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, 105 const char* szExtraInfoFormat, ...); 106 virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, 107 const char* szExtraInfoFormat, ...); 108 virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, 109 const char* szExtraInfoFormat, ...); 110 virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, 111 const char* szExtraInfoFormat, ...); 112 #endif 113 114 virtual void setLimits(const TBuiltInResource&) = 0; 115 116 void checkIndex(const TSourceLoc&, const TType&, int& index); 117 getLanguage()118 EShLanguage getLanguage() const { return language; } setScanContext(TScanContext * c)119 void setScanContext(TScanContext* c) { scanContext = c; } getScanContext()120 TScanContext* getScanContext() const { return scanContext; } setPpContext(TPpContext * c)121 void setPpContext(TPpContext* c) { ppContext = c; } getPpContext()122 TPpContext* getPpContext() const { return ppContext; } 123 setLineCallback(const std::function<void (int,int,bool,int,const char *)> & func)124 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)125 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)126 virtual void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; } setPragmaCallback(const std::function<void (int,const TVector<TString> &)> & func)127 virtual void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; } setErrorCallback(const std::function<void (int,const char *)> & func)128 virtual void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; } 129 130 virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0; 131 virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0; 132 virtual bool lineDirectiveShouldSetNextLine() const = 0; 133 virtual void handlePragma(const TSourceLoc&, const TVector<TString>&) = 0; 134 135 virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0; 136 notifyVersion(int line,int version,const char * type_string)137 virtual void notifyVersion(int line, int version, const char* type_string) 138 { 139 if (versionCallback) 140 versionCallback(line, version, type_string); 141 } notifyErrorDirective(int line,const char * error_message)142 virtual void notifyErrorDirective(int line, const char* error_message) 143 { 144 if (errorCallback) 145 errorCallback(line, error_message); 146 } notifyLineDirective(int curLineNo,int newLineNo,bool hasSource,int sourceNum,const char * sourceName)147 virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName) 148 { 149 if (lineCallback) 150 lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName); 151 } notifyExtensionDirective(int line,const char * extension,const char * behavior)152 virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior) 153 { 154 if (extensionCallback) 155 extensionCallback(line, extension, behavior); 156 } 157 158 // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) 159 virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); 160 161 // Manage global buffer (used for backing atomic counters in GLSL when using relaxed Vulkan semantics) 162 virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); 163 164 // Potentially rename shader entry point function renameShaderFunction(TString * & name)165 void renameShaderFunction(TString*& name) const 166 { 167 // Replace the entry point name given in the shader with the real entry point name, 168 // if there is a substitution. 169 if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0) 170 name = NewPoolTString(intermediate.getEntryPointName().c_str()); 171 } 172 173 virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); 174 virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); 175 176 const char* const scopeMangler; 177 178 // Basic parsing state, easily accessible to the grammar 179 180 TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile 181 int statementNestingLevel; // 0 if outside all flow control or compound statements 182 int loopNestingLevel; // 0 if outside all loops 183 int structNestingLevel; // 0 if outside structures 184 int blockNestingLevel; // 0 if outside blocks 185 int controlFlowNestingLevel; // 0 if outside all flow control 186 const TType* currentFunctionType; // the return type of the function that's currently being parsed 187 bool functionReturnsValue; // true if a non-void function has a return 188 // if inside a function, true if the function is the entry point and this is after a return statement 189 bool postEntryPointReturn; 190 // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting 191 TList<TIntermSequence*> switchSequenceStack; 192 // the statementNestingLevel the current switch statement is at, which must match the level of its case statements 193 TList<int> switchLevel; 194 struct TPragma contextPragma; 195 int beginInvocationInterlockCount; 196 int endInvocationInterlockCount; 197 198 protected: 199 TParseContextBase(TParseContextBase&); 200 TParseContextBase& operator=(TParseContextBase&); 201 202 const bool parsingBuiltins; // true if parsing built-in symbols/functions 203 TVector<TSymbol*> linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving 204 TScanContext* scanContext; 205 TPpContext* ppContext; 206 TBuiltInResource resources; 207 TLimits& limits; 208 TString sourceEntryPointName; 209 210 // These, if set, will be called when a line, pragma ... is preprocessed. 211 // They will be called with any parameters to the original directive. 212 std::function<void(int, int, bool, int, const char*)> lineCallback; 213 std::function<void(int, const TVector<TString>&)> pragmaCallback; 214 std::function<void(int, int, const char*)> versionCallback; 215 std::function<void(int, const char*, const char*)> extensionCallback; 216 std::function<void(int, const char*)> errorCallback; 217 218 // see implementation for detail 219 const TFunction* selectFunction(const TVector<const TFunction*>, const TFunction&, 220 std::function<bool(const TType&, const TType&, TOperator, int arg)>, 221 std::function<bool(const TType&, const TType&, const TType&)>, 222 /* output */ bool& tie); 223 224 virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size, 225 TSwizzleSelectors<TVectorSelector>&); 226 227 // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) 228 TVariable* globalUniformBlock; // the actual block, inserted into the symbol table 229 unsigned int globalUniformBinding; // the block's binding number 230 unsigned int globalUniformSet; // the block's set number 231 int firstNewMember; // the index of the first member not yet inserted into the symbol table 232 // override this to set the language-specific name getGlobalUniformBlockName()233 virtual const char* getGlobalUniformBlockName() const { return ""; } setUniformBlockDefaults(TType &)234 virtual void setUniformBlockDefaults(TType&) const { } finalizeGlobalUniformBlockLayout(TVariable &)235 virtual void finalizeGlobalUniformBlockLayout(TVariable&) {} 236 237 // Manage the atomic counter block (used for atomic_uints with Vulkan-Relaxed) 238 TMap<int, TVariable*> atomicCounterBuffers; 239 unsigned int atomicCounterBlockSet; 240 TMap<int, int> atomicCounterBlockFirstNewMember; 241 // override this to set the language-specific name getAtomicCounterBlockName()242 virtual const char* getAtomicCounterBlockName() const { return ""; } setAtomicCounterBlockDefaults(TType &)243 virtual void setAtomicCounterBlockDefaults(TType&) const {} setInvariant(const TSourceLoc &,const char *)244 virtual void setInvariant(const TSourceLoc&, const char*) {} finalizeAtomicCounterBlockLayout(TVariable &)245 virtual void finalizeAtomicCounterBlockLayout(TVariable&) {} isAtomicCounterBlock(const TSymbol & symbol)246 bool isAtomicCounterBlock(const TSymbol& symbol) { 247 const TVariable* var = symbol.getAsVariable(); 248 if (!var) 249 return false; 250 const auto& at = atomicCounterBuffers.find(var->getType().getQualifier().layoutBinding); 251 return (at != atomicCounterBuffers.end() && (*at).second->getType() == var->getType()); 252 } 253 254 virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, 255 const char* szExtraInfoFormat, TPrefixType prefix, 256 va_list args); 257 virtual void trackLinkage(TSymbol& symbol); 258 virtual void makeEditable(TSymbol*&); 259 virtual TVariable* getEditableVariable(const char* name); 260 virtual void finish(); 261 }; 262 263 // 264 // Manage the state for when to respect precision qualifiers and when to warn about 265 // the defaults being different than might be expected. 266 // 267 class TPrecisionManager { 268 public: TPrecisionManager()269 TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ } ~TPrecisionManager()270 virtual ~TPrecisionManager() {} 271 respectPrecisionQualifiers()272 void respectPrecisionQualifiers() { obey = true; } respectingPrecisionQualifiers()273 bool respectingPrecisionQualifiers() const { return obey; } shouldWarnAboutDefaults()274 bool shouldWarnAboutDefaults() const { return warn; } defaultWarningGiven()275 void defaultWarningGiven() { warn = false; } warnAboutDefaults()276 void warnAboutDefaults() { warn = true; } explicitIntDefaultSeen()277 void explicitIntDefaultSeen() 278 { 279 explicitIntDefault = true; 280 if (explicitFloatDefault) 281 warn = false; 282 } explicitFloatDefaultSeen()283 void explicitFloatDefaultSeen() 284 { 285 explicitFloatDefault = true; 286 if (explicitIntDefault) 287 warn = false; 288 } 289 290 protected: 291 bool obey; // respect precision qualifiers 292 bool warn; // need to give a warning about the defaults 293 bool explicitIntDefault; // user set the default for int/uint 294 bool explicitFloatDefault; // user set the default for float 295 }; 296 297 // 298 // GLSL-specific parse helper. Should have GLSL in the name, but that's 299 // too big of a change for comparing branches at the moment, and perhaps 300 // impacts downstream consumers as well. 301 // 302 class TParseContext : public TParseContextBase { 303 public: 304 TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, 305 bool forwardCompatible = false, EShMessages messages = EShMsgDefault, 306 const TString* entryPoint = nullptr); 307 virtual ~TParseContext(); 308 obeyPrecisionQualifiers()309 bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); } 310 void setPrecisionDefaults(); 311 312 void setLimits(const TBuiltInResource&) override; 313 bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; 314 void parserError(const char* s); // for bison's yyerror 315 316 virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override; 317 virtual void growAtomicCounterBlock(int binding, const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr) override; 318 319 void reservedErrorCheck(const TSourceLoc&, const TString&); 320 void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override; 321 bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override; 322 bool lineDirectiveShouldSetNextLine() const override; 323 bool builtInName(const TString&); 324 325 void handlePragma(const TSourceLoc&, const TVector<TString>&) override; 326 TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string); 327 TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); 328 void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); 329 330 #ifndef GLSLANG_WEB 331 void makeEditable(TSymbol*&) override; 332 void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); 333 #endif 334 bool isIoResizeArray(const TType&) const; 335 void fixIoArraySize(const TSourceLoc&, TType&); 336 void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); 337 void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); 338 int getIoArrayImplicitSize(const TQualifier&, TString* featureString = nullptr) const; 339 void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); 340 341 TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); 342 TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); 343 TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); 344 TIntermTyped* handleDotSwizzle(const TSourceLoc&, TIntermTyped* base, const TString& field); 345 void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName); 346 TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); 347 TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); 348 TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); 349 TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function); 350 void computeBuiltinPrecisions(TIntermTyped&, const TFunction&); 351 TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); 352 void checkLocation(const TSourceLoc&, TOperator); 353 TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); 354 void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; 355 TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; 356 TIntermTyped* addAssign(const TSourceLoc&, TOperator op, TIntermTyped* left, TIntermTyped* right); 357 void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); 358 void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&); 359 void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&); 360 void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*); 361 TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&); 362 void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier); 363 void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); 364 void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode); 365 366 TIntermTyped* vkRelaxedRemapFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); 367 // returns true if the variable was remapped to something else 368 bool vkRelaxedRemapUniformVariable(const TSourceLoc&, TString&, const TPublicType&, TArraySizes*, TIntermTyped*, TType&); 369 370 void assignError(const TSourceLoc&, const char* op, TString left, TString right); 371 void unaryOpError(const TSourceLoc&, const char* op, TString operand); 372 void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); 373 void variableCheck(TIntermTyped*& nodePtr); 374 bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; 375 void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; 376 void constantValueCheck(TIntermTyped* node, const char* token); 377 void integerCheck(const TIntermTyped* node, const char* token); 378 void globalCheck(const TSourceLoc&, const char* token); 379 bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&); 380 bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&); 381 void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&, const char *sizeType); 382 bool arrayQualifierError(const TSourceLoc&, const TQualifier&); 383 bool arrayError(const TSourceLoc&, const TType&); 384 void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); 385 void structArrayCheck(const TSourceLoc&, const TType& structure); 386 void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember); 387 void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*); 388 bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); 389 void boolCheck(const TSourceLoc&, const TIntermTyped*); 390 void boolCheck(const TSourceLoc&, const TPublicType&); 391 void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); 392 void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); 393 void accStructCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); 394 void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); 395 void memberQualifierCheck(glslang::TPublicType&); 396 void globalQualifierFixCheck(const TSourceLoc&, TQualifier&, bool isMemberCheck = false); 397 void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&); 398 bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); 399 void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force); 400 void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier); 401 int computeSamplerTypeIndex(TSampler&); 402 TPrecisionQualifier getDefaultPrecision(TPublicType&); 403 void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&); 404 void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type); 405 bool containsFieldWithBasicType(const TType& type ,TBasicType basicType); 406 TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); 407 void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); 408 void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type); 409 void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type); 410 void nestedBlockCheck(const TSourceLoc&); 411 void nestedStructCheck(const TSourceLoc&); 412 void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op); 413 void opaqueCheck(const TSourceLoc&, const TType&, const char* op); 414 void referenceCheck(const TSourceLoc&, const TType&, const char* op); 415 void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op); 416 void specializationCheck(const TSourceLoc&, const TType&, const char* op); 417 void structTypeCheck(const TSourceLoc&, TPublicType&); 418 void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop); 419 void arrayLimitCheck(const TSourceLoc&, const TString&, int size); 420 void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature); 421 422 void inductiveLoopBodyCheck(TIntermNode*, long long loopIndexId, TSymbolTable&); 423 void constantIndexExpressionCheck(TIntermNode*); 424 425 void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&); 426 void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*); 427 void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); 428 void layoutObjectCheck(const TSourceLoc&, const TSymbol&); 429 void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes); 430 void layoutTypeCheck(const TSourceLoc&, const TType&); 431 void layoutQualifierCheck(const TSourceLoc&, const TQualifier&); 432 void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); 433 void fixOffset(const TSourceLoc&, TSymbol&); 434 435 const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn); 436 const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn); 437 const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn); 438 const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn); 439 const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn); 440 void declareTypeDefaults(const TSourceLoc&, const TPublicType&); 441 TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = nullptr, TIntermTyped* initializer = nullptr); 442 TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); 443 TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); 444 TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); 445 void inheritMemoryQualifiers(const TQualifier& from, TQualifier& to); 446 void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = nullptr, TArraySizes* arraySizes = nullptr); 447 void blockStorageRemap(const TSourceLoc&, const TString*, TQualifier&); 448 void blockStageIoCheck(const TSourceLoc&, const TQualifier&); 449 void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); 450 void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); 451 void fixXfbOffsets(TQualifier&, TTypeList&); 452 void fixBlockUniformOffsets(TQualifier&, TTypeList&); 453 void fixBlockUniformLayoutMatrix(TQualifier&, TTypeList*, TTypeList*); 454 void fixBlockUniformLayoutPacking(TQualifier&, TTypeList*, TTypeList*); 455 void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); 456 void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); 457 void invariantCheck(const TSourceLoc&, const TQualifier&); 458 void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); 459 void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); 460 TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body); 461 const TTypeList* recordStructCopy(TStructRecord&, const TType*, const TType*); 462 463 #ifndef GLSLANG_WEB 464 TAttributeType attributeFromName(const TString& name) const; 465 TAttributes* makeAttributes(const TString& identifier) const; 466 TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const; 467 TAttributes* mergeAttributes(TAttributes*, TAttributes*) const; 468 469 // Determine selection control from attributes 470 void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*); 471 void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*); 472 // Determine loop control from attributes 473 void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); 474 // Function attributes 475 void handleFunctionAttributes(const TSourceLoc&, const TAttributes&); 476 477 // GL_EXT_spirv_intrinsics 478 TSpirvRequirement* makeSpirvRequirement(const TSourceLoc& loc, const TString& name, 479 const TIntermAggregate* extensions, const TIntermAggregate* capabilities); 480 TSpirvRequirement* mergeSpirvRequirements(const TSourceLoc& loc, TSpirvRequirement* spirvReq1, 481 TSpirvRequirement* spirvReq2); 482 TSpirvTypeParameters* makeSpirvTypeParameters(const TSourceLoc& loc, const TIntermConstantUnion* constant); 483 TSpirvTypeParameters* mergeSpirvTypeParameters(TSpirvTypeParameters* spirvTypeParams1, 484 TSpirvTypeParameters* spirvTypeParams2); 485 TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, const TString& value); 486 TSpirvInstruction* makeSpirvInstruction(const TSourceLoc& loc, const TString& name, int value); 487 TSpirvInstruction* mergeSpirvInstruction(const TSourceLoc& loc, TSpirvInstruction* spirvInst1, 488 TSpirvInstruction* spirvInst2); 489 #endif 490 491 void checkAndResizeMeshViewDim(const TSourceLoc&, TType&, bool isBlockMember); 492 493 protected: 494 void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type); 495 void inheritGlobalDefaults(TQualifier& dst) const; 496 TVariable* makeInternalVariable(const char* name, const TType&) const; 497 TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&); 498 void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&); 499 void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&); 500 bool isRuntimeLength(const TIntermTyped&) const; 501 TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); 502 TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer); 503 #ifndef GLSLANG_WEB 504 void finish() override; 505 #endif 506 507 virtual const char* getGlobalUniformBlockName() const override; 508 virtual void finalizeGlobalUniformBlockLayout(TVariable&) override; 509 virtual void setUniformBlockDefaults(TType& block) const override; 510 511 virtual const char* getAtomicCounterBlockName() const override; 512 virtual void finalizeAtomicCounterBlockLayout(TVariable&) override; 513 virtual void setAtomicCounterBlockDefaults(TType& block) const override; 514 virtual void setInvariant(const TSourceLoc& loc, const char* builtin) override; 515 516 public: 517 // 518 // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access 519 // 520 521 // Current state of parsing 522 bool inMain; // if inside a function, true if the function is main 523 const TString* blockName; 524 TQualifier currentBlockQualifier; 525 TPrecisionQualifier defaultPrecision[EbtNumTypes]; 526 TBuiltInResource resources; 527 TLimits& limits; 528 529 protected: 530 TParseContext(TParseContext&); 531 TParseContext& operator=(TParseContext&); 532 533 static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex() 534 TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex]; 535 TPrecisionManager precisionManager; 536 TQualifier globalBufferDefaults; 537 TQualifier globalUniformDefaults; 538 TQualifier globalInputDefaults; 539 TQualifier globalOutputDefaults; 540 TQualifier globalSharedDefaults; 541 TString currentCaller; // name of last function body entered (not valid when at global scope) 542 #ifndef GLSLANG_WEB 543 int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point 544 bool anyIndexLimits; 545 TIdSetType inductiveLoopIds; 546 TVector<TIntermTyped*> needsIndexLimitationChecking; 547 TStructRecord matrixFixRecord; 548 TStructRecord packingFixRecord; 549 550 // 551 // Geometry shader input arrays: 552 // - array sizing is based on input primitive and/or explicit size 553 // 554 // Tessellation control output arrays: 555 // - array sizing is based on output layout(vertices=...) and/or explicit size 556 // 557 // Both: 558 // - array sizing is retroactive 559 // - built-in block redeclarations interact with this 560 // 561 // Design: 562 // - use a per-context "resize-list", a list of symbols whose array sizes 563 // can be fixed 564 // 565 // - the resize-list starts empty at beginning of user-shader compilation, it does 566 // not have built-ins in it 567 // 568 // - on built-in array use: copyUp() symbol and add it to the resize-list 569 // 570 // - on user array declaration: add it to the resize-list 571 // 572 // - on block redeclaration: copyUp() symbol and add it to the resize-list 573 // * note, that appropriately gives an error if redeclaring a block that 574 // was already used and hence already copied-up 575 // 576 // - on seeing a layout declaration that sizes the array, fix everything in the 577 // resize-list, giving errors for mismatch 578 // 579 // - on seeing an array size declaration, give errors on mismatch between it and previous 580 // array-sizing declarations 581 // 582 TVector<TSymbol*> ioArraySymbolResizeList; 583 #endif 584 }; 585 586 } // end namespace glslang 587 588 #endif // _PARSER_HELPER_INCLUDED_ 589