| // |
| // Copyright (C) 2002-2005 3Dlabs Inc. Ltd. |
| // Copyright (C) 2012-2013 LunarG, Inc. |
| // Copyright (C) 2015-2018 Google, Inc. |
| // |
| // All rights reserved. |
| // |
| // Redistribution and use in source and binary forms, with or without |
| // modification, are permitted provided that the following conditions |
| // are met: |
| // |
| // Redistributions of source code must retain the above copyright |
| // notice, this list of conditions and the following disclaimer. |
| // |
| // Redistributions in binary form must reproduce the above |
| // copyright notice, this list of conditions and the following |
| // disclaimer in the documentation and/or other materials provided |
| // with the distribution. |
| // |
| // Neither the name of 3Dlabs Inc. Ltd. nor the names of its |
| // contributors may be used to endorse or promote products derived |
| // from this software without specific prior written permission. |
| // |
| // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| // "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| // LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS |
| // FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE |
| // COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, |
| // INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, |
| // BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| // LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER |
| // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT |
| // LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN |
| // ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| // POSSIBILITY OF SUCH DAMAGE. |
| // |
| |
| // |
| // This header defines a two-level parse-helper hierarchy, derived from |
| // TParseVersions: |
| // - TParseContextBase: sharable across multiple parsers |
| // - TParseContext: GLSL specific helper |
| // |
| |
| #ifndef _PARSER_HELPER_INCLUDED_ |
| #define _PARSER_HELPER_INCLUDED_ |
| |
| #include <cstdarg> |
| #include <functional> |
| |
| #include "parseVersions.h" |
| #include "../Include/ShHandle.h" |
| #include "SymbolTable.h" |
| #include "localintermediate.h" |
| #include "Scan.h" |
| #include "attribute.h" |
| |
| namespace glslang { |
| |
| struct TPragma { |
| TPragma(bool o, bool d) : optimize(o), debug(d) { } |
| bool optimize; |
| bool debug; |
| TPragmaTable pragmaTable; |
| }; |
| |
| class TScanContext; |
| class TPpContext; |
| |
| typedef std::set<int> TIdSetType; |
| |
| // |
| // Sharable code (as well as what's in TParseVersions) across |
| // parse helpers. |
| // |
| class TParseContextBase : public TParseVersions { |
| public: |
| TParseContextBase(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins, int version, |
| EProfile profile, const SpvVersion& spvVersion, EShLanguage language, |
| TInfoSink& infoSink, bool forwardCompatible, EShMessages messages, |
| const TString* entryPoint = nullptr) |
| : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), |
| scopeMangler("::"), |
| symbolTable(symbolTable), |
| statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), |
| postEntryPointReturn(false), |
| contextPragma(true, false), |
| parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr), |
| limits(resources.limits), |
| globalUniformBlock(nullptr), |
| globalUniformBinding(TQualifier::layoutBindingEnd), |
| globalUniformSet(TQualifier::layoutSetEnd) |
| { |
| if (entryPoint != nullptr) |
| sourceEntryPointName = *entryPoint; |
| } |
| virtual ~TParseContextBase() { } |
| |
| virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, |
| const char* szExtraInfoFormat, ...); |
| virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, |
| const char* szExtraInfoFormat, ...); |
| virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, |
| const char* szExtraInfoFormat, ...); |
| virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, |
| const char* szExtraInfoFormat, ...); |
| |
| virtual void setLimits(const TBuiltInResource&) = 0; |
| |
| void checkIndex(const TSourceLoc&, const TType&, int& index); |
| |
| EShLanguage getLanguage() const { return language; } |
| void setScanContext(TScanContext* c) { scanContext = c; } |
| TScanContext* getScanContext() const { return scanContext; } |
| void setPpContext(TPpContext* c) { ppContext = c; } |
| TPpContext* getPpContext() const { return ppContext; } |
| |
| virtual void setLineCallback(const std::function<void(int, int, bool, int, const char*)>& func) { lineCallback = func; } |
| virtual void setExtensionCallback(const std::function<void(int, const char*, const char*)>& func) { extensionCallback = func; } |
| virtual void setVersionCallback(const std::function<void(int, int, const char*)>& func) { versionCallback = func; } |
| virtual void setPragmaCallback(const std::function<void(int, const TVector<TString>&)>& func) { pragmaCallback = func; } |
| virtual void setErrorCallback(const std::function<void(int, const char*)>& func) { errorCallback = func; } |
| |
| virtual void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) = 0; |
| virtual bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) = 0; |
| virtual bool lineDirectiveShouldSetNextLine() const = 0; |
| virtual void handlePragma(const TSourceLoc&, const TVector<TString>&) = 0; |
| |
| virtual bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) = 0; |
| |
| virtual void notifyVersion(int line, int version, const char* type_string) |
| { |
| if (versionCallback) |
| versionCallback(line, version, type_string); |
| } |
| virtual void notifyErrorDirective(int line, const char* error_message) |
| { |
| if (errorCallback) |
| errorCallback(line, error_message); |
| } |
| virtual void notifyLineDirective(int curLineNo, int newLineNo, bool hasSource, int sourceNum, const char* sourceName) |
| { |
| if (lineCallback) |
| lineCallback(curLineNo, newLineNo, hasSource, sourceNum, sourceName); |
| } |
| virtual void notifyExtensionDirective(int line, const char* extension, const char* behavior) |
| { |
| if (extensionCallback) |
| extensionCallback(line, extension, behavior); |
| } |
| |
| // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) |
| virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); |
| |
| // Potentially rename shader entry point function |
| void renameShaderFunction(TString*& name) const |
| { |
| // Replace the entry point name given in the shader with the real entry point name, |
| // if there is a substitution. |
| if (name != nullptr && *name == sourceEntryPointName && intermediate.getEntryPointName().size() > 0) |
| name = NewPoolTString(intermediate.getEntryPointName().c_str()); |
| } |
| |
| virtual bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); |
| virtual void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*); |
| |
| const char* const scopeMangler; |
| |
| // Basic parsing state, easily accessible to the grammar |
| |
| TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile |
| int statementNestingLevel; // 0 if outside all flow control or compound statements |
| int loopNestingLevel; // 0 if outside all loops |
| int structNestingLevel; // 0 if outside blocks and structures |
| int controlFlowNestingLevel; // 0 if outside all flow control |
| const TType* currentFunctionType; // the return type of the function that's currently being parsed |
| bool functionReturnsValue; // true if a non-void function has a return |
| // if inside a function, true if the function is the entry point and this is after a return statement |
| bool postEntryPointReturn; |
| // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting |
| TList<TIntermSequence*> switchSequenceStack; |
| // the statementNestingLevel the current switch statement is at, which must match the level of its case statements |
| TList<int> switchLevel; |
| struct TPragma contextPragma; |
| |
| protected: |
| TParseContextBase(TParseContextBase&); |
| TParseContextBase& operator=(TParseContextBase&); |
| |
| const bool parsingBuiltins; // true if parsing built-in symbols/functions |
| TVector<TSymbol*> linkageSymbols; // will be transferred to 'linkage', after all editing is done, order preserving |
| TScanContext* scanContext; |
| TPpContext* ppContext; |
| TBuiltInResource resources; |
| TLimits& limits; |
| TString sourceEntryPointName; |
| |
| // These, if set, will be called when a line, pragma ... is preprocessed. |
| // They will be called with any parameters to the original directive. |
| std::function<void(int, int, bool, int, const char*)> lineCallback; |
| std::function<void(int, const TVector<TString>&)> pragmaCallback; |
| std::function<void(int, int, const char*)> versionCallback; |
| std::function<void(int, const char*, const char*)> extensionCallback; |
| std::function<void(int, const char*)> errorCallback; |
| |
| // see implementation for detail |
| const TFunction* selectFunction(const TVector<const TFunction*>, const TFunction&, |
| std::function<bool(const TType&, const TType&, TOperator, int arg)>, |
| std::function<bool(const TType&, const TType&, const TType&)>, |
| /* output */ bool& tie); |
| |
| virtual void parseSwizzleSelector(const TSourceLoc&, const TString&, int size, |
| TSwizzleSelectors<TVectorSelector>&); |
| |
| // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) |
| TVariable* globalUniformBlock; // the actual block, inserted into the symbol table |
| unsigned int globalUniformBinding; // the block's binding number |
| unsigned int globalUniformSet; // the block's set number |
| int firstNewMember; // the index of the first member not yet inserted into the symbol table |
| // override this to set the language-specific name |
| virtual const char* getGlobalUniformBlockName() const { return ""; } |
| virtual void setUniformBlockDefaults(TType&) const { } |
| virtual void finalizeGlobalUniformBlockLayout(TVariable&) { } |
| virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, |
| const char* szExtraInfoFormat, TPrefixType prefix, |
| va_list args); |
| virtual void trackLinkage(TSymbol& symbol); |
| virtual void makeEditable(TSymbol*&); |
| virtual TVariable* getEditableVariable(const char* name); |
| virtual void finish(); |
| }; |
| |
| // |
| // Manage the state for when to respect precision qualifiers and when to warn about |
| // the defaults being different than might be expected. |
| // |
| class TPrecisionManager { |
| public: |
| TPrecisionManager() : obey(false), warn(false), explicitIntDefault(false), explicitFloatDefault(false){ } |
| virtual ~TPrecisionManager() {} |
| |
| void respectPrecisionQualifiers() { obey = true; } |
| bool respectingPrecisionQualifiers() const { return obey; } |
| bool shouldWarnAboutDefaults() const { return warn; } |
| void defaultWarningGiven() { warn = false; } |
| void warnAboutDefaults() { warn = true; } |
| void explicitIntDefaultSeen() |
| { |
| explicitIntDefault = true; |
| if (explicitFloatDefault) |
| warn = false; |
| } |
| void explicitFloatDefaultSeen() |
| { |
| explicitFloatDefault = true; |
| if (explicitIntDefault) |
| warn = false; |
| } |
| |
| protected: |
| bool obey; // respect precision qualifiers |
| bool warn; // need to give a warning about the defaults |
| bool explicitIntDefault; // user set the default for int/uint |
| bool explicitFloatDefault; // user set the default for float |
| }; |
| |
| // |
| // GLSL-specific parse helper. Should have GLSL in the name, but that's |
| // too big of a change for comparing branches at the moment, and perhaps |
| // impacts downstream consumers as well. |
| // |
| class TParseContext : public TParseContextBase { |
| public: |
| TParseContext(TSymbolTable&, TIntermediate&, bool parsingBuiltins, int version, EProfile, const SpvVersion& spvVersion, EShLanguage, TInfoSink&, |
| bool forwardCompatible = false, EShMessages messages = EShMsgDefault, |
| const TString* entryPoint = nullptr); |
| virtual ~TParseContext(); |
| |
| bool obeyPrecisionQualifiers() const { return precisionManager.respectingPrecisionQualifiers(); }; |
| void setPrecisionDefaults(); |
| |
| void setLimits(const TBuiltInResource&) override; |
| bool parseShaderStrings(TPpContext&, TInputScanner& input, bool versionWillBeError = false) override; |
| void parserError(const char* s); // for bison's yyerror |
| |
| void reservedErrorCheck(const TSourceLoc&, const TString&); |
| void reservedPpErrorCheck(const TSourceLoc&, const char* name, const char* op) override; |
| bool lineContinuationCheck(const TSourceLoc&, bool endOfComment) override; |
| bool lineDirectiveShouldSetNextLine() const override; |
| bool builtInName(const TString&); |
| |
| void handlePragma(const TSourceLoc&, const TVector<TString>&) override; |
| TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string); |
| TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); |
| void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); |
| |
| void makeEditable(TSymbol*&) override; |
| bool isIoResizeArray(const TType&) const; |
| void fixIoArraySize(const TSourceLoc&, TType&); |
| void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); |
| void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); |
| void checkIoArraysConsistency(const TSourceLoc&, const TQualifier&, bool tailOnly = false); |
| int getIoArrayImplicitSize(const TQualifier&) const; |
| void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); |
| |
| TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); |
| TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); |
| TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); |
| void blockMemberExtensionCheck(const TSourceLoc&, const TIntermTyped* base, int member, const TString& memberName); |
| TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype); |
| TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&); |
| TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*); |
| TIntermTyped* handleBuiltInFunctionCall(TSourceLoc, TIntermNode* arguments, const TFunction& function); |
| void computeBuiltinPrecisions(TIntermTyped&, const TFunction&); |
| TIntermNode* handleReturnValue(const TSourceLoc&, TIntermTyped*); |
| void checkLocation(const TSourceLoc&, TOperator); |
| TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*); |
| void addInputArgumentConversions(const TFunction&, TIntermNode*&) const; |
| TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const; |
| void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); |
| void nonOpBuiltInCheck(const TSourceLoc&, const TFunction&, TIntermAggregate&); |
| void userFunctionCallCheck(const TSourceLoc&, TIntermAggregate&); |
| void samplerConstructorLocationCheck(const TSourceLoc&, const char* token, TIntermNode*); |
| TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&); |
| void handlePrecisionQualifier(const TSourceLoc&, TQualifier&, TPrecisionQualifier); |
| void checkPrecisionQualifier(const TSourceLoc&, TPrecisionQualifier); |
| void memorySemanticsCheck(const TSourceLoc&, const TFunction&, const TIntermOperator& callNode); |
| |
| void assignError(const TSourceLoc&, const char* op, TString left, TString right); |
| void unaryOpError(const TSourceLoc&, const char* op, TString operand); |
| void binaryOpError(const TSourceLoc&, const char* op, TString left, TString right); |
| void variableCheck(TIntermTyped*& nodePtr); |
| bool lValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; |
| void rValueErrorCheck(const TSourceLoc&, const char* op, TIntermTyped*) override; |
| void constantValueCheck(TIntermTyped* node, const char* token); |
| void integerCheck(const TIntermTyped* node, const char* token); |
| void globalCheck(const TSourceLoc&, const char* token); |
| bool constructorError(const TSourceLoc&, TIntermNode*, TFunction&, TOperator, TType&); |
| bool constructorTextureSamplerError(const TSourceLoc&, const TFunction&); |
| void arraySizeCheck(const TSourceLoc&, TIntermTyped* expr, TArraySize&); |
| bool arrayQualifierError(const TSourceLoc&, const TQualifier&); |
| bool arrayError(const TSourceLoc&, const TType&); |
| void arraySizeRequiredCheck(const TSourceLoc&, const TArraySizes&); |
| void structArrayCheck(const TSourceLoc&, const TType& structure); |
| void arraySizesCheck(const TSourceLoc&, const TQualifier&, TArraySizes*, const TIntermTyped* initializer, bool lastMember); |
| void arrayOfArrayVersionCheck(const TSourceLoc&, const TArraySizes*); |
| bool voidErrorCheck(const TSourceLoc&, const TString&, TBasicType); |
| void boolCheck(const TSourceLoc&, const TIntermTyped*); |
| void boolCheck(const TSourceLoc&, const TPublicType&); |
| void samplerCheck(const TSourceLoc&, const TType&, const TString& identifier, TIntermTyped* initializer); |
| void atomicUintCheck(const TSourceLoc&, const TType&, const TString& identifier); |
| void accStructNVCheck(const TSourceLoc & loc, const TType & type, const TString & identifier); |
| void transparentOpaqueCheck(const TSourceLoc&, const TType&, const TString& identifier); |
| void memberQualifierCheck(glslang::TPublicType&); |
| void globalQualifierFixCheck(const TSourceLoc&, TQualifier&); |
| void globalQualifierTypeCheck(const TSourceLoc&, const TQualifier&, const TPublicType&); |
| bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType); |
| void mergeQualifiers(const TSourceLoc&, TQualifier& dst, const TQualifier& src, bool force); |
| void setDefaultPrecision(const TSourceLoc&, TPublicType&, TPrecisionQualifier); |
| int computeSamplerTypeIndex(TSampler&); |
| TPrecisionQualifier getDefaultPrecision(TPublicType&); |
| void precisionQualifierCheck(const TSourceLoc&, TBasicType, TQualifier&); |
| void parameterTypeCheck(const TSourceLoc&, TStorageQualifier qualifier, const TType& type); |
| bool containsFieldWithBasicType(const TType& type ,TBasicType basicType); |
| TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&); |
| void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes); |
| void paramCheckFixStorage(const TSourceLoc&, const TStorageQualifier&, TType& type); |
| void paramCheckFix(const TSourceLoc&, const TQualifier&, TType& type); |
| void nestedBlockCheck(const TSourceLoc&); |
| void nestedStructCheck(const TSourceLoc&); |
| void arrayObjectCheck(const TSourceLoc&, const TType&, const char* op); |
| void opaqueCheck(const TSourceLoc&, const TType&, const char* op); |
| void storage16BitAssignmentCheck(const TSourceLoc&, const TType&, const char* op); |
| void specializationCheck(const TSourceLoc&, const TType&, const char* op); |
| void structTypeCheck(const TSourceLoc&, TPublicType&); |
| void inductiveLoopCheck(const TSourceLoc&, TIntermNode* init, TIntermLoop* loop); |
| void arrayLimitCheck(const TSourceLoc&, const TString&, int size); |
| void limitCheck(const TSourceLoc&, int value, const char* limit, const char* feature); |
| |
| void inductiveLoopBodyCheck(TIntermNode*, int loopIndexId, TSymbolTable&); |
| void constantIndexExpressionCheck(TIntermNode*); |
| |
| void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&); |
| void setLayoutQualifier(const TSourceLoc&, TPublicType&, TString&, const TIntermTyped*); |
| void mergeObjectLayoutQualifiers(TQualifier& dest, const TQualifier& src, bool inheritOnly); |
| void layoutObjectCheck(const TSourceLoc&, const TSymbol&); |
| void layoutMemberLocationArrayCheck(const TSourceLoc&, bool memberWithLocation, TArraySizes* arraySizes); |
| void layoutTypeCheck(const TSourceLoc&, const TType&); |
| void layoutQualifierCheck(const TSourceLoc&, const TQualifier&); |
| void checkNoShaderLayouts(const TSourceLoc&, const TShaderQualifiers&); |
| void fixOffset(const TSourceLoc&, TSymbol&); |
| |
| const TFunction* findFunction(const TSourceLoc& loc, const TFunction& call, bool& builtIn); |
| const TFunction* findFunctionExact(const TSourceLoc& loc, const TFunction& call, bool& builtIn); |
| const TFunction* findFunction120(const TSourceLoc& loc, const TFunction& call, bool& builtIn); |
| const TFunction* findFunction400(const TSourceLoc& loc, const TFunction& call, bool& builtIn); |
| const TFunction* findFunctionExplicitTypes(const TSourceLoc& loc, const TFunction& call, bool& builtIn); |
| void declareTypeDefaults(const TSourceLoc&, const TPublicType&); |
| TIntermNode* declareVariable(const TSourceLoc&, TString& identifier, const TPublicType&, TArraySizes* typeArray = 0, TIntermTyped* initializer = 0); |
| TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); |
| TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); |
| TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); |
| void declareBlock(const TSourceLoc&, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0); |
| void blockStageIoCheck(const TSourceLoc&, const TQualifier&); |
| void blockQualifierCheck(const TSourceLoc&, const TQualifier&, bool instanceName); |
| void fixBlockLocations(const TSourceLoc&, TQualifier&, TTypeList&, bool memberWithLocation, bool memberWithoutLocation); |
| void fixXfbOffsets(TQualifier&, TTypeList&); |
| void fixBlockUniformOffsets(TQualifier&, TTypeList&); |
| void addQualifierToExisting(const TSourceLoc&, TQualifier, const TString& identifier); |
| void addQualifierToExisting(const TSourceLoc&, TQualifier, TIdentifierList&); |
| void invariantCheck(const TSourceLoc&, const TQualifier&); |
| void updateStandaloneQualifierDefaults(const TSourceLoc&, const TPublicType&); |
| void wrapupSwitchSubsequence(TIntermAggregate* statements, TIntermNode* branchNode); |
| TIntermNode* addSwitch(const TSourceLoc&, TIntermTyped* expression, TIntermAggregate* body); |
| |
| TAttributeType attributeFromName(const TString& name) const; |
| TAttributes* makeAttributes(const TString& identifier) const; |
| TAttributes* makeAttributes(const TString& identifier, TIntermNode* node) const; |
| TAttributes* mergeAttributes(TAttributes*, TAttributes*) const; |
| |
| // Determine selection control from attributes |
| void handleSelectionAttributes(const TAttributes& attributes, TIntermNode*); |
| void handleSwitchAttributes(const TAttributes& attributes, TIntermNode*); |
| |
| // Determine loop control from attributes |
| void handleLoopAttributes(const TAttributes& attributes, TIntermNode*); |
| |
| void resizeMeshViewDimension(const TSourceLoc&, TType&); |
| |
| protected: |
| void nonInitConstCheck(const TSourceLoc&, TString& identifier, TType& type); |
| void inheritGlobalDefaults(TQualifier& dst) const; |
| TVariable* makeInternalVariable(const char* name, const TType&) const; |
| TVariable* declareNonArray(const TSourceLoc&, const TString& identifier, const TType&); |
| void declareArray(const TSourceLoc&, const TString& identifier, const TType&, TSymbol*&); |
| void checkRuntimeSizable(const TSourceLoc&, const TIntermTyped&); |
| bool isRuntimeLength(const TIntermTyped&) const; |
| TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); |
| TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer); |
| void finish() override; |
| |
| public: |
| // |
| // Generally, bison productions, the scanner, and the PP need read/write access to these; just give them direct access |
| // |
| |
| // Current state of parsing |
| bool inMain; // if inside a function, true if the function is main |
| const TString* blockName; |
| TQualifier currentBlockQualifier; |
| TPrecisionQualifier defaultPrecision[EbtNumTypes]; |
| TBuiltInResource resources; |
| TLimits& limits; |
| |
| protected: |
| TParseContext(TParseContext&); |
| TParseContext& operator=(TParseContext&); |
| |
| static const int maxSamplerIndex = EsdNumDims * (EbtNumTypes * (2 * 2 * 2 * 2 * 2)); // see computeSamplerTypeIndex() |
| TPrecisionQualifier defaultSamplerPrecision[maxSamplerIndex]; |
| TPrecisionManager precisionManager; |
| TQualifier globalBufferDefaults; |
| TQualifier globalUniformDefaults; |
| TQualifier globalInputDefaults; |
| TQualifier globalOutputDefaults; |
| int* atomicUintOffsets; // to become an array of the right size to hold an offset per binding point |
| TString currentCaller; // name of last function body entered (not valid when at global scope) |
| TIdSetType inductiveLoopIds; |
| bool anyIndexLimits; |
| TVector<TIntermTyped*> needsIndexLimitationChecking; |
| |
| // |
| // Geometry shader input arrays: |
| // - array sizing is based on input primitive and/or explicit size |
| // |
| // Tessellation control output arrays: |
| // - array sizing is based on output layout(vertices=...) and/or explicit size |
| // |
| // Both: |
| // - array sizing is retroactive |
| // - built-in block redeclarations interact with this |
| // |
| // Design: |
| // - use a per-context "resize-list", a list of symbols whose array sizes |
| // can be fixed |
| // |
| // - the resize-list starts empty at beginning of user-shader compilation, it does |
| // not have built-ins in it |
| // |
| // - on built-in array use: copyUp() symbol and add it to the resize-list |
| // |
| // - on user array declaration: add it to the resize-list |
| // |
| // - on block redeclaration: copyUp() symbol and add it to the resize-list |
| // * note, that appropriately gives an error if redeclaring a block that |
| // was already used and hence already copied-up |
| // |
| // - on seeing a layout declaration that sizes the array, fix everything in the |
| // resize-list, giving errors for mismatch |
| // |
| // - on seeing an array size declaration, give errors on mismatch between it and previous |
| // array-sizing declarations |
| // |
| TVector<TSymbol*> ioArraySymbolResizeList; |
| }; |
| |
| } // end namespace glslang |
| |
| #endif // _PARSER_HELPER_INCLUDED_ |