From 9b2531ba23fb100677fd3752f140e1ba0e06ef8f Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Tue, 6 Jun 2017 19:19:45 -0600 Subject: [PATCH] Infrastructure: Move nesting counters, etc., to base class. This lets all languages share the same definitions. --- glslang/MachineIndependent/ParseHelper.cpp | 8 ++--- glslang/MachineIndependent/ParseHelper.h | 35 ++++++++++++++-------- glslang/MachineIndependent/glslang.y | 2 +- glslang/MachineIndependent/glslang_tab.cpp | 2 +- hlsl/hlslParseHelper.cpp | 8 ++--- hlsl/hlslParseHelper.h | 10 ------- 6 files changed, 33 insertions(+), 32 deletions(-) diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index 329dea66f..0208224b8 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -51,8 +51,8 @@ TParseContext::TParseContext(TSymbolTable& symbolTable, TIntermediate& interm, b int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) : TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), - contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), statementNestingLevel(0), - inMain(false), postMainReturn(false), currentFunctionType(nullptr), blockName(nullptr), + inMain(false), + blockName(nullptr), limits(resources.limits), atomicUintOffsets(nullptr), anyIndexLimits(false) { @@ -912,7 +912,7 @@ TIntermAggregate* TParseContext::handleFunctionDefinition(const TSourceLoc& loc, loopNestingLevel = 0; statementNestingLevel = 0; controlFlowNestingLevel = 0; - postMainReturn = false; + postEntryPointReturn = false; return paramNodes; } @@ -1193,7 +1193,7 @@ void TParseContext::checkLocation(const TSourceLoc& loc, TOperator op) error(loc, "tessellation control barrier() cannot be placed within flow control", "", ""); if (! inMain) error(loc, "tessellation control barrier() must be in main()", "", ""); - else if (postMainReturn) + else if (postEntryPointReturn) error(loc, "tessellation control barrier() cannot be placed after a return from main()", "", ""); } break; diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index 17acf5d78..fb1f789ce 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -77,6 +77,10 @@ public: TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) : TParseVersions(interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), symbolTable(symbolTable), + statementNestingLevel(0), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), + postEntryPointReturn(false), + contextPragma(true, false), + limits(resources.limits), parsingBuiltins(parsingBuiltins), scanContext(nullptr), ppContext(nullptr), globalUniformBlock(nullptr) { } @@ -133,8 +137,6 @@ public: extensionCallback(line, extension, behavior); } - TSymbolTable& symbolTable; // symbol table that goes with the current language, version, and profile - // Manage the global uniform block (default uniforms in GLSL, $Global in HLSL) virtual void growGlobalUniformBlock(const TSourceLoc&, TType&, const TString& memberName, TTypeList* typeList = nullptr); @@ -143,6 +145,23 @@ public: 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 switchSequenceStack; + // the statementNestingLevel the current switch statement is at, which must match the level of its case statements + TList switchLevel; + struct TPragma contextPragma; + protected: TParseContextBase(TParseContextBase&); TParseContextBase& operator=(TParseContextBase&); @@ -151,6 +170,8 @@ protected: TVector linkageSymbols; // these need to be transferred to 'linkage', after all editing is done TScanContext* scanContext; TPpContext* ppContext; + TBuiltInResource resources; + TLimits& limits; // These, if set, will be called when a line, pragma ... is preprocessed. // They will be called with any parameters to the original directive. @@ -384,17 +405,7 @@ public: // // Current state of parsing - struct TPragma contextPragma; - int loopNestingLevel; // 0 if outside all loops - int structNestingLevel; // 0 if outside blocks and structures - int controlFlowNestingLevel; // 0 if outside all flow control - int statementNestingLevel; // 0 if outside all flow control or compound statements - TList switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting - TList switchLevel; // the statementNestingLevel the current switch statement is at, which must match the level of its case statements bool inMain; // if inside a function, true if the function is main - bool postMainReturn; // if inside a function, true if the function is main and this is after a return statement - 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 const TString* blockName; TQualifier currentBlockQualifier; TPrecisionQualifier defaultPrecision[EbtNumTypes]; diff --git a/glslang/MachineIndependent/glslang.y b/glslang/MachineIndependent/glslang.y index 611236e71..43ad3df1c 100644 --- a/glslang/MachineIndependent/glslang.y +++ b/glslang/MachineIndependent/glslang.y @@ -2777,7 +2777,7 @@ jump_statement if (parseContext.currentFunctionType->getBasicType() != EbtVoid) parseContext.error($1.loc, "non-void function must return a value", "return", ""); if (parseContext.inMain) - parseContext.postMainReturn = true; + parseContext.postEntryPointReturn = true; } | RETURN expression SEMICOLON { $$ = parseContext.handleReturnValue($1.loc, $2); diff --git a/glslang/MachineIndependent/glslang_tab.cpp b/glslang/MachineIndependent/glslang_tab.cpp index 52b6c45f2..92795b9bd 100644 --- a/glslang/MachineIndependent/glslang_tab.cpp +++ b/glslang/MachineIndependent/glslang_tab.cpp @@ -7704,7 +7704,7 @@ yyreduce: if (parseContext.currentFunctionType->getBasicType() != EbtVoid) parseContext.error((yyvsp[-1].lex).loc, "non-void function must return a value", "return", ""); if (parseContext.inMain) - parseContext.postMainReturn = true; + parseContext.postEntryPointReturn = true; } #line 7710 "MachineIndependent/glslang_tab.cpp" /* yacc.c:1646 */ break; diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index ff0c7771e..0fbfa35d4 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -57,10 +57,7 @@ HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& int const TString sourceEntryPointName, bool forwardCompatible, EShMessages messages) : TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages), - contextPragma(true, false), - loopNestingLevel(0), annotationNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), - postEntryPointReturn(false), - limits(resources.limits), + annotationNestingLevel(0), inputPatch(nullptr), builtInIoIndex(nullptr), builtInIoBase(nullptr), @@ -520,6 +517,9 @@ TIntermTyped* HlslParseContext::handleSamplerLvalue(const TSourceLoc& loc, const return node; } + if (controlFlowNestingLevel > 0) + error(loc, "can't alias sampler in control flow", op, ""); + // Best is if we are aliasing a flattened struct member "S.s1 = s2", // in which case we want to update the flattening information with the alias, // making everything else work seamlessly. diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index 9a9896423..9e772d166 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -314,17 +314,7 @@ protected: TIntermSymbol* findLinkageSymbol(TBuiltInVariable biType) const; // Current state of parsing - struct TPragma contextPragma; - int loopNestingLevel; // 0 if outside all loops int annotationNestingLevel; // 0 if outside all annotations - int structNestingLevel; // 0 if outside blocks and structures - int controlFlowNestingLevel; // 0 if outside all flow control - TList switchSequenceStack; // case, node, case, case, node, ...; ensure only one node between cases; stack of them for nesting - bool postEntryPointReturn; // if inside a function, true if the function is the entry point and this is after a return statement - 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 - TBuiltInResource resources; - TLimits& limits; HlslParseContext(HlslParseContext&); HlslParseContext& operator=(HlslParseContext&);