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