diff --git a/Test/baseResults/hlsl.scope.frag.out b/Test/baseResults/hlsl.scope.frag.out new file mode 100755 index 00000000..274477a4 --- /dev/null +++ b/Test/baseResults/hlsl.scope.frag.out @@ -0,0 +1,150 @@ +hlsl.scope.frag +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:31 Function Definition: PixelShaderFunction(vf4; (temp 4-component vector of float) +0:2 Function Parameters: +0:2 'input' (temp 4-component vector of float) +0:? Sequence +0:4 'x' (temp int) +0:? Sequence +0:7 'x' (temp float) +0:? Sequence +0:10 'x' (temp bool) +0:? Sequence +0:13 'x' (temp 3-component vector of float) +0:15 'x' (temp bool) +0:17 'x' (temp float) +0:19 'x' (temp int) +0:21 Test condition and select (temp void) +0:21 Condition +0:21 Compare Greater Than (temp bool) +0:21 'x' (temp int) +0:21 Constant: +0:21 0 (const int) +0:21 true case is null +0:24 Loop with condition tested first +0:24 Loop Condition +0:24 Compare Greater Than (temp bool) +0:24 'x' (temp int) +0:24 Constant: +0:24 0 (const int) +0:24 No loop body +0:27 Loop with condition not tested first +0:27 Loop Condition +0:29 Compare Greater Than (temp bool) +0:29 'x' (temp int) +0:29 Constant: +0:29 0 (const int) +0:27 No loop body +0:? Linker Objects + + +Linked fragment stage: + + +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:31 Function Definition: PixelShaderFunction(vf4; (temp 4-component vector of float) +0:2 Function Parameters: +0:2 'input' (temp 4-component vector of float) +0:? Sequence +0:4 'x' (temp int) +0:? Sequence +0:7 'x' (temp float) +0:? Sequence +0:10 'x' (temp bool) +0:? Sequence +0:13 'x' (temp 3-component vector of float) +0:15 'x' (temp bool) +0:17 'x' (temp float) +0:19 'x' (temp int) +0:21 Test condition and select (temp void) +0:21 Condition +0:21 Compare Greater Than (temp bool) +0:21 'x' (temp int) +0:21 Constant: +0:21 0 (const int) +0:21 true case is null +0:24 Loop with condition tested first +0:24 Loop Condition +0:24 Compare Greater Than (temp bool) +0:24 'x' (temp int) +0:24 Constant: +0:24 0 (const int) +0:24 No loop body +0:27 Loop with condition not tested first +0:27 Loop Condition +0:29 Compare Greater Than (temp bool) +0:29 'x' (temp int) +0:29 Constant: +0:29 0 (const int) +0:27 No loop body +0:? Linker Objects + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 36 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "PixelShaderFunction" + ExecutionMode 4 OriginUpperLeft + Source HLSL 450 + Name 4 "PixelShaderFunction" + Name 8 "x" + Name 11 "x" + Name 14 "x" + Name 17 "x" + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 1 + 7: TypePointer Function 6(int) + 9: TypeFloat 32 + 10: TypePointer Function 9(float) + 12: TypeBool + 13: TypePointer Function 12(bool) + 15: TypeVector 9(float) 3 + 16: TypePointer Function 15(fvec3) + 19: 6(int) Constant 0 +4(PixelShaderFunction): 2 Function None 3 + 5: Label + 8(x): 7(ptr) Variable Function + 11(x): 10(ptr) Variable Function + 14(x): 13(ptr) Variable Function + 17(x): 16(ptr) Variable Function + 18: 6(int) Load 8(x) + 20: 12(bool) SGreaterThan 18 19 + SelectionMerge 22 None + BranchConditional 20 21 22 + 21: Label + Branch 22 + 22: Label + Branch 23 + 23: Label + LoopMerge 25 26 None + Branch 27 + 27: Label + 28: 6(int) Load 8(x) + 29: 12(bool) SGreaterThan 28 19 + BranchConditional 29 24 25 + 24: Label + Branch 26 + 26: Label + Branch 23 + 25: Label + Branch 30 + 30: Label + LoopMerge 32 33 None + Branch 31 + 31: Label + Branch 33 + 33: Label + 34: 6(int) Load 8(x) + 35: 12(bool) SGreaterThan 34 19 + BranchConditional 35 30 32 + 32: Label + Return + FunctionEnd diff --git a/Test/hlsl.scope.frag b/Test/hlsl.scope.frag new file mode 100644 index 00000000..0d8cc1ad --- /dev/null +++ b/Test/hlsl.scope.frag @@ -0,0 +1,30 @@ +float4 PixelShaderFunction(float4 input) : COLOR0 +{ + int x; + x; + { + float x; + x; + { + bool x; + x; + { + float3 x; + x; + } + x; + } + x; + } + x; + + if (x > 0) + bool x; + + while (x > 0) + bool x; + + do { + bool x; + } while (x > 0); +} diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 4a127c1f..fa3442cd 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -88,6 +88,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.max.frag", "PixelShaderFunction"}, {"hlsl.precedence.frag", "PixelShaderFunction"}, {"hlsl.precedence2.frag", "PixelShaderFunction"}, + {"hlsl.scope.frag", "PixelShaderFunction"}, {"hlsl.sin.frag", "PixelShaderFunction"}, {"hlsl.whileLoop.frag", "PixelShaderFunction"}, {"hlsl.void.frag", "PixelShaderFunction"}, diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index b7cb8423..9ea14dae 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -209,9 +209,6 @@ void HlslGrammar::acceptQualifier(TQualifier& qualifier) // Otherwise, return false, and don't advance bool HlslGrammar::acceptType(TType& type) { - if (! token.isType) - return false; - switch (peek()) { case EHTokVoid: new(&type) TType(EbtVoid); @@ -616,7 +613,7 @@ bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& no { TFunction* functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */); - // This does a symbol table push + // This does a pushScope() node = parseContext.handleFunctionDefinition(token.loc, *functionDeclarator); // compound_statement @@ -625,7 +622,7 @@ bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& no node = intermediate.growAggregate(node, functionBody); intermediate.setAggregateOperator(node, EOpFunction, functionDeclarator->getType(), token.loc); node->getAsAggregate()->setName(functionDeclarator->getMangledName().c_str()); - parseContext.symbolTable.pop(nullptr); + parseContext.popScope(); return true; } @@ -882,7 +879,7 @@ bool HlslGrammar::acceptPostfixExpression(TIntermTyped*& node) } else if (acceptIdentifier(idToken)) { // identifier or function_call name if (! peekTokenClass(EHTokLeftParen)) { - node = parseContext.handleVariable(idToken.loc, idToken.symbol, token.string); + node = parseContext.handleVariable(idToken.loc, token.string); } else if (acceptFunctionCall(idToken, node)) { // function_call (nothing else to do yet) } else { @@ -1072,17 +1069,17 @@ bool HlslGrammar::acceptCompoundStatement(TIntermNode*& retStatement) bool HlslGrammar::acceptScopedStatement(TIntermNode*& statement) { parseContext.pushScope(); - bool result = acceptNestedStatement(statement); + bool result = acceptStatement(statement); parseContext.popScope(); return result; } -bool HlslGrammar::acceptNestedStatement(TIntermNode*& statement) +bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement) { - parseContext.nestStatement(); - bool result = acceptStatement(statement); - parseContext.unnestStatement(); + parseContext.pushScope(); + bool result = acceptCompoundStatement(statement); + parseContext.popScope(); return result; } @@ -1111,7 +1108,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement) // attributed_statement switch (peek()) { case EHTokLeftBrace: - return acceptCompoundStatement(statement); + return acceptScopedCompoundStatement(statement); case EHTokIf: return acceptSelectionStatement(statement); diff --git a/hlsl/hlslGrammar.h b/hlsl/hlslGrammar.h index 69535f30..ba92c922 100755 --- a/hlsl/hlslGrammar.h +++ b/hlsl/hlslGrammar.h @@ -77,6 +77,7 @@ namespace glslang { bool acceptCompoundStatement(TIntermNode*&); bool acceptStatement(TIntermNode*&); bool acceptScopedStatement(TIntermNode*&); + bool acceptScopedCompoundStatement(TIntermNode*&); bool acceptNestedStatement(TIntermNode*&); void acceptAttributes(); bool acceptSelectionStatement(TIntermNode*&); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 2cdaf0c0..e5c15648 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -51,7 +51,7 @@ HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& int int version, EProfile profile, int spv, int vulkan, EShLanguage language, TInfoSink& infoSink, bool forwardCompatible, EShMessages messages) : TParseContextBase(symbolTable, interm, version, profile, spv, vulkan, language, infoSink, forwardCompatible, messages), - contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), statementNestingLevel(0), + contextPragma(true, false), loopNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0), postMainReturn(false), limits(resources.limits), afterEOF(false) @@ -282,8 +282,9 @@ void C_DECL HlslParseContext::ppWarn(const TSourceLoc& loc, const char* szReason // // Handle seeing a variable identifier in the grammar. // -TIntermTyped* HlslParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symbol, const TString* string) +TIntermTyped* HlslParseContext::handleVariable(const TSourceLoc& loc, const TString* string) { + TSymbol* symbol = symbolTable.find(*string); TIntermTyped* node = nullptr; // Error check for requiring specific extensions present. @@ -714,7 +715,7 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l // // New symbol table scope for body of function plus its arguments // - symbolTable.push(); + pushScope(); // // Insert parameters into the symbol table. @@ -747,7 +748,6 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l } intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc); loopNestingLevel = 0; - statementNestingLevel = 0; controlFlowNestingLevel = 0; postMainReturn = false; diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index 6f920d8c..e1fbbf85 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -65,7 +65,7 @@ public: bool builtInName(const TString&); void handlePragma(const TSourceLoc&, const TVector&); - TIntermTyped* handleVariable(const TSourceLoc&, TSymbol* symbol, const TString* string); + TIntermTyped* handleVariable(const TSourceLoc&, const TString* string); TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); void checkIndex(const TSourceLoc&, const TType&, int& index); @@ -139,8 +139,6 @@ public: void updateImplicitArraySize(const TSourceLoc&, TIntermNode*, int index); - void nestStatement() { ++statementNestingLevel; } - void unnestStatement() { --statementNestingLevel; } void nestLooping() { ++loopNestingLevel; } void unnestLooping() { --loopNestingLevel; } void pushScope() { symbolTable.push(); } @@ -163,7 +161,6 @@ protected: 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 inEntrypoint; // if inside a function, true if the function is the entry point diff --git a/hlsl/hlslScanContext.cpp b/hlsl/hlslScanContext.cpp index 38e765ab..dc470ffe 100755 --- a/hlsl/hlslScanContext.cpp +++ b/hlsl/hlslScanContext.cpp @@ -314,11 +314,8 @@ void HlslScanContext::deleteKeywordMap() // Wrapper for tokenizeClass()"] = to get everything inside the token. void HlslScanContext::tokenize(HlslToken& token) { - token.isType = false; EHlslTokenClass tokenClass = tokenizeClass(token); token.tokenClass = tokenClass; - if (token.isType) - afterType = true; } // @@ -338,13 +335,13 @@ EHlslTokenClass HlslScanContext::tokenizeClass(HlslToken& token) loc = ppToken.loc; parserToken->loc = loc; switch (ppToken.token) { - case ';': afterType = false; return EHTokSemicolon; - case ',': afterType = false; return EHTokComma; + case ';': return EHTokSemicolon; + case ',': return EHTokComma; case ':': return EHTokColon; - case '=': afterType = false; return EHTokAssign; - case '(': afterType = false; return EHTokLeftParen; - case ')': afterType = false; return EHTokRightParen; - case '.': field = true; return EHTokDot; + case '=': return EHTokAssign; + case '(': return EHTokLeftParen; + case ')': return EHTokRightParen; + case '.': return EHTokDot; case '!': return EHTokBang; case '-': return EHTokDash; case '~': return EHTokTilde; @@ -400,7 +397,6 @@ EHlslTokenClass HlslScanContext::tokenizeClass(HlslToken& token) case PpAtomIdentifier: { EHlslTokenClass token = tokenizeIdentifier(); - field = false; return token; } @@ -542,7 +538,6 @@ EHlslTokenClass HlslScanContext::tokenizeIdentifier() case EHTokDouble4x2: case EHTokDouble4x3: case EHTokDouble4x4: - parserToken->isType = true; return keyword; // texturing types @@ -560,7 +555,6 @@ EHlslTokenClass HlslScanContext::tokenizeIdentifier() case EHTokTexture2darray: case EHTokTexture3d: case EHTokTextureCube: - parserToken->isType = true; return keyword; // variable, user type, ... @@ -598,19 +592,6 @@ EHlslTokenClass HlslScanContext::tokenizeIdentifier() EHlslTokenClass HlslScanContext::identifierOrType() { parserToken->string = NewPoolTString(tokenText); - if (field) - return EHTokIdentifier; - - parserToken->symbol = parseContext.symbolTable.find(*parserToken->string); - if (afterType == false && parserToken->symbol) { - if (const TVariable* variable = parserToken->symbol->getAsVariable()) { - if (variable->isUserType()) { - afterType = true; - - return EHTokTypeName; - } - } - } return EHTokIdentifier; } diff --git a/hlsl/hlslScanContext.h b/hlsl/hlslScanContext.h index d761e3a8..75c01a9d 100755 --- a/hlsl/hlslScanContext.h +++ b/hlsl/hlslScanContext.h @@ -54,10 +54,9 @@ class TPpToken; // Everything needed to fully describe a token. // struct HlslToken { - HlslToken() : isType(false), string(nullptr), symbol(nullptr) { loc.init(); } + HlslToken() : string(nullptr) { loc.init(); } TSourceLoc loc; // location of token in the source EHlslTokenClass tokenClass; // what kind of token it is - bool isType; // true if the token represents a type union { // what data the token holds glslang::TString *string; // for identifiers int i; // for literals @@ -65,7 +64,6 @@ struct HlslToken { bool b; double d; }; - glslang::TSymbol* symbol; // if a symbol table lookup was done already, this is the result }; // @@ -76,7 +74,7 @@ struct HlslToken { class HlslScanContext { public: HlslScanContext(TParseContextBase& parseContext, TPpContext& ppContext) - : parseContext(parseContext), ppContext(ppContext), afterType(false), field(false) { } + : parseContext(parseContext), ppContext(ppContext) { } virtual ~HlslScanContext() { } static void fillInKeywordMap(); @@ -97,8 +95,6 @@ protected: TParseContextBase& parseContext; TPpContext& ppContext; - bool afterType; // true if we've recognized a type, so can only be looking for an identifier - bool field; // true if we're on a field, right after a '.' TSourceLoc loc; TPpToken* ppToken; HlslToken* parserToken;