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