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