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