HLSL: Fix #919: for-init-statement is arbitrary declaration or expression.

Unlike "if (XXX)" and "while (XXX)", with "for (YYY...", the YYY can be
more kinds of statements than the XXX.
This commit is contained in:
John Kessenich 2017-06-06 11:37:33 -06:00
parent e00e8f45a6
commit 0e07119ae2
5 changed files with 322 additions and 62 deletions

View File

@ -110,6 +110,80 @@ gl_FragCoord origin is upper left
0:11 'ii' ( temp int) 0:11 'ii' ( temp int)
0:12 Pre-Decrement ( temp float) 0:12 Pre-Decrement ( temp float)
0:12 'ii' ( temp float) 0:12 'ii' ( temp float)
0:13 Sequence
0:13 move second child to first child ( temp int)
0:13 'first' ( temp int)
0:13 Constant:
0:13 0 (const int)
0:13 move second child to first child ( temp int)
0:13 'second' ( temp int)
0:13 Constant:
0:13 1 (const int)
0:13 Loop with condition tested first
0:13 No loop condition
0:13 Loop Body
0:13 add ( temp int)
0:13 'first' ( temp int)
0:13 'second' ( temp int)
0:14 Sequence
0:14 move second child to first child ( temp int)
0:14 'i' ( temp int)
0:14 Constant:
0:14 0 (const int)
0:14 move second child to first child ( temp int)
0:14 'count' ( temp int)
0:14 Convert float to int ( temp int)
0:14 'ii' ( temp float)
0:14 Loop with condition tested first
0:14 Loop Condition
0:14 Compare Less Than ( temp bool)
0:14 'i' ( temp int)
0:14 'count' ( temp int)
0:14 No loop body
0:14 Loop Terminal Expression
0:14 Post-Increment ( temp int)
0:14 'i' ( temp int)
0:15 Sequence
0:15 move second child to first child ( temp float)
0:15 'first' ( temp float)
0:15 Constant:
0:15 0.000000
0:15 Loop with condition tested first
0:15 Loop Condition
0:15 Compare Less Than ( temp bool)
0:15 'first' ( temp float)
0:15 direct index ( temp float)
0:15 'second' ( temp 2-element array of float)
0:15 Constant:
0:15 0 (const int)
0:15 Loop Body
0:15 add ( temp float)
0:15 add ( temp float)
0:15 'first' ( temp float)
0:15 direct index ( temp float)
0:15 'second' ( temp 2-element array of float)
0:15 Constant:
0:15 1 (const int)
0:15 'third' ( temp float)
0:15 Loop Terminal Expression
0:15 Pre-Increment ( temp float)
0:15 direct index ( temp float)
0:15 'second' ( temp 2-element array of float)
0:15 Constant:
0:15 1 (const int)
0:? Sequence
0:16 Comma ( temp float)
0:16 Comma ( temp float)
0:16 Pre-Decrement ( temp float)
0:16 'ii' ( temp float)
0:16 Pre-Decrement ( temp float)
0:16 'ii' ( temp float)
0:16 Pre-Decrement ( temp float)
0:16 'ii' ( temp float)
0:16 Loop with condition tested first
0:16 No loop condition
0:16 Loop Body
0:16 'ii' ( temp float)
0:2 Function Definition: PixelShaderFunction( ( temp void) 0:2 Function Definition: PixelShaderFunction( ( temp void)
0:2 Function Parameters: 0:2 Function Parameters:
0:? Sequence 0:? Sequence
@ -239,6 +313,80 @@ gl_FragCoord origin is upper left
0:11 'ii' ( temp int) 0:11 'ii' ( temp int)
0:12 Pre-Decrement ( temp float) 0:12 Pre-Decrement ( temp float)
0:12 'ii' ( temp float) 0:12 'ii' ( temp float)
0:13 Sequence
0:13 move second child to first child ( temp int)
0:13 'first' ( temp int)
0:13 Constant:
0:13 0 (const int)
0:13 move second child to first child ( temp int)
0:13 'second' ( temp int)
0:13 Constant:
0:13 1 (const int)
0:13 Loop with condition tested first
0:13 No loop condition
0:13 Loop Body
0:13 add ( temp int)
0:13 'first' ( temp int)
0:13 'second' ( temp int)
0:14 Sequence
0:14 move second child to first child ( temp int)
0:14 'i' ( temp int)
0:14 Constant:
0:14 0 (const int)
0:14 move second child to first child ( temp int)
0:14 'count' ( temp int)
0:14 Convert float to int ( temp int)
0:14 'ii' ( temp float)
0:14 Loop with condition tested first
0:14 Loop Condition
0:14 Compare Less Than ( temp bool)
0:14 'i' ( temp int)
0:14 'count' ( temp int)
0:14 No loop body
0:14 Loop Terminal Expression
0:14 Post-Increment ( temp int)
0:14 'i' ( temp int)
0:15 Sequence
0:15 move second child to first child ( temp float)
0:15 'first' ( temp float)
0:15 Constant:
0:15 0.000000
0:15 Loop with condition tested first
0:15 Loop Condition
0:15 Compare Less Than ( temp bool)
0:15 'first' ( temp float)
0:15 direct index ( temp float)
0:15 'second' ( temp 2-element array of float)
0:15 Constant:
0:15 0 (const int)
0:15 Loop Body
0:15 add ( temp float)
0:15 add ( temp float)
0:15 'first' ( temp float)
0:15 direct index ( temp float)
0:15 'second' ( temp 2-element array of float)
0:15 Constant:
0:15 1 (const int)
0:15 'third' ( temp float)
0:15 Loop Terminal Expression
0:15 Pre-Increment ( temp float)
0:15 direct index ( temp float)
0:15 'second' ( temp 2-element array of float)
0:15 Constant:
0:15 1 (const int)
0:? Sequence
0:16 Comma ( temp float)
0:16 Comma ( temp float)
0:16 Pre-Decrement ( temp float)
0:16 'ii' ( temp float)
0:16 Pre-Decrement ( temp float)
0:16 'ii' ( temp float)
0:16 Pre-Decrement ( temp float)
0:16 'ii' ( temp float)
0:16 Loop with condition tested first
0:16 No loop condition
0:16 Loop Body
0:16 'ii' ( temp float)
0:2 Function Definition: PixelShaderFunction( ( temp void) 0:2 Function Definition: PixelShaderFunction( ( temp void)
0:2 Function Parameters: 0:2 Function Parameters:
0:? Sequence 0:? Sequence
@ -255,12 +403,12 @@ gl_FragCoord origin is upper left
// Module Version 10000 // Module Version 10000
// Generated by (magic number): 80001 // Generated by (magic number): 80001
// Id's are bound by 124 // Id's are bound by 183
Capability Shader Capability Shader
1: ExtInstImport "GLSL.std.450" 1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450 MemoryModel Logical GLSL450
EntryPoint Fragment 4 "PixelShaderFunction" 117 120 EntryPoint Fragment 4 "PixelShaderFunction" 176 179
ExecutionMode 4 OriginUpperLeft ExecutionMode 4 OriginUpperLeft
Source HLSL 500 Source HLSL 500
Name 4 "PixelShaderFunction" Name 4 "PixelShaderFunction"
@ -268,12 +416,19 @@ gl_FragCoord origin is upper left
Name 10 "input" Name 10 "input"
Name 92 "ii" Name 92 "ii"
Name 111 "ii" Name 111 "ii"
Name 115 "input" Name 114 "first"
Name 117 "input" Name 116 "second"
Name 120 "@entryPointOutput" Name 124 "i"
Name 121 "param" Name 125 "count"
Decorate 117(input) Location 0 Name 138 "first"
Decorate 120(@entryPointOutput) Location 0 Name 149 "second"
Name 157 "third"
Name 174 "input"
Name 176 "input"
Name 179 "@entryPointOutput"
Name 180 "param"
Decorate 176(input) Location 0
Decorate 179(@entryPointOutput) Location 0
2: TypeVoid 2: TypeVoid
3: TypeFunction 2 3: TypeFunction 2
6: TypeFloat 32 6: TypeFloat 32
@ -293,20 +448,25 @@ gl_FragCoord origin is upper left
100: 90(int) Constant 3 100: 90(int) Constant 3
103: 90(int) Constant 2 103: 90(int) Constant 2
109: 90(int) Constant 1 109: 90(int) Constant 1
116: TypePointer Input 7(fvec4) 115: 90(int) Constant 0
117(input): 116(ptr) Variable Input 139: 6(float) Constant 0
119: TypePointer Output 7(fvec4) 146: 71(int) Constant 2
120(@entryPointOutput): 119(ptr) Variable Output 147: TypeArray 6(float) 146
148: TypePointer Function 147
175: TypePointer Input 7(fvec4)
176(input): 175(ptr) Variable Input
178: TypePointer Output 7(fvec4)
179(@entryPointOutput): 178(ptr) Variable Output
4(PixelShaderFunction): 2 Function None 3 4(PixelShaderFunction): 2 Function None 3
5: Label 5: Label
115(input): 8(ptr) Variable Function 174(input): 8(ptr) Variable Function
121(param): 8(ptr) Variable Function 180(param): 8(ptr) Variable Function
118: 7(fvec4) Load 117(input) 177: 7(fvec4) Load 176(input)
Store 115(input) 118 Store 174(input) 177
122: 7(fvec4) Load 115(input) 181: 7(fvec4) Load 174(input)
Store 121(param) 122 Store 180(param) 181
123: 7(fvec4) FunctionCall 11(@PixelShaderFunction(vf4;) 121(param) 182: 7(fvec4) FunctionCall 11(@PixelShaderFunction(vf4;) 180(param)
Store 120(@entryPointOutput) 123 Store 179(@entryPointOutput) 182
Return Return
FunctionEnd FunctionEnd
11(@PixelShaderFunction(vf4;): 7(fvec4) Function None 9 11(@PixelShaderFunction(vf4;): 7(fvec4) Function None 9
@ -314,6 +474,13 @@ gl_FragCoord origin is upper left
12: Label 12: Label
92(ii): 91(ptr) Variable Function 92(ii): 91(ptr) Variable Function
111(ii): 73(ptr) Variable Function 111(ii): 73(ptr) Variable Function
114(first): 91(ptr) Variable Function
116(second): 91(ptr) Variable Function
124(i): 91(ptr) Variable Function
125(count): 91(ptr) Variable Function
138(first): 73(ptr) Variable Function
149(second): 148(ptr) Variable Function
157(third): 73(ptr) Variable Function
Branch 13 Branch 13
13: Label 13: Label
LoopMerge 15 16 None LoopMerge 15 16 None
@ -454,6 +621,85 @@ gl_FragCoord origin is upper left
112: 6(float) Load 111(ii) 112: 6(float) Load 111(ii)
113: 6(float) FSub 112 18 113: 6(float) FSub 112 18
Store 111(ii) 113 Store 111(ii) 113
114: 7(fvec4) Undef Store 114(first) 115
ReturnValue 114 Store 116(second) 109
Branch 117
117: Label
LoopMerge 119 120 None
Branch 118
118: Label
121: 90(int) Load 114(first)
122: 90(int) Load 116(second)
123: 90(int) IAdd 121 122
Branch 120
120: Label
Branch 117
119: Label
Store 124(i) 115
126: 6(float) Load 111(ii)
127: 90(int) ConvertFToS 126
Store 125(count) 127
Branch 128
128: Label
LoopMerge 130 131 None
Branch 132
132: Label
133: 90(int) Load 124(i)
134: 90(int) Load 125(count)
135: 32(bool) SLessThan 133 134
BranchConditional 135 129 130
129: Label
Branch 131
131: Label
136: 90(int) Load 124(i)
137: 90(int) IAdd 136 109
Store 124(i) 137
Branch 128
130: Label
Store 138(first) 139
Branch 140
140: Label
LoopMerge 142 143 None
Branch 144
144: Label
145: 6(float) Load 138(first)
150: 73(ptr) AccessChain 149(second) 115
151: 6(float) Load 150
152: 32(bool) FOrdLessThan 145 151
BranchConditional 152 141 142
141: Label
153: 6(float) Load 138(first)
154: 73(ptr) AccessChain 149(second) 109
155: 6(float) Load 154
156: 6(float) FAdd 153 155
158: 6(float) Load 157(third)
159: 6(float) FAdd 156 158
Branch 143
143: Label
160: 73(ptr) AccessChain 149(second) 109
161: 6(float) Load 160
162: 6(float) FAdd 161 18
Store 160 162
Branch 140
142: Label
163: 6(float) Load 111(ii)
164: 6(float) FSub 163 18
Store 111(ii) 164
165: 6(float) Load 111(ii)
166: 6(float) FSub 165 18
Store 111(ii) 166
167: 6(float) Load 111(ii)
168: 6(float) FSub 167 18
Store 111(ii) 168
Branch 169
169: Label
LoopMerge 171 172 None
Branch 170
170: Label
Branch 172
172: Label
Branch 169
171: Label
173: 7(fvec4) Undef
ReturnValue 173
FunctionEnd FunctionEnd

View File

@ -5,9 +5,13 @@ float4 PixelShaderFunction(float4 input) : COLOR0
[unroll] for (; any(input != input); ) {} [unroll] for (; any(input != input); ) {}
for (; any(input != input); ) { return -input; } for (; any(input != input); ) { return -input; }
for (--input; any(input != input); input += 2) { return -input; } for (--input; any(input != input); input += 2) { return -input; }
for (;;) if (input.x > 2.0) break; for (;;) if (input.x > 2.0) break;
for (;;) if (input.x > 2.0) continue; for (;;) if (input.x > 2.0) continue;
float ii; float ii;
for (int ii = -1; ii < 3; ++ii) if (ii == 2) continue; for (int ii = -1; ii < 3; ++ii) if (ii == 2) continue;
--ii; --ii;
for (int first = 0, second = 1; ;) first + second;
for ( int i = 0, count = int(ii); i < count; i++ );
for (float first = 0, second[2], third; first < second[0]; ++second[1]) first + second[1] + third;
for (--ii, --ii, --ii;;) ii;
} }

View File

@ -1735,8 +1735,13 @@ TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* init
node->setLoc(loc); node->setLoc(loc);
node->setLoopControl(control); node->setLoopControl(control);
// make a sequence of the initializer and statement // make a sequence of the initializer and statement, but try to reuse the
TIntermAggregate* loopSequence = makeAggregate(initializer, loc); // aggregate already created for whatever is in the initializer, if there is one
TIntermAggregate* loopSequence = (initializer == nullptr ||
initializer->getAsAggregate() == nullptr) ? makeAggregate(initializer, loc)
: initializer->getAsAggregate();
if (loopSequence != nullptr && loopSequence->getOp() == EOpSequence)
loopSequence->setOp(EOpNull);
loopSequence = growAggregate(loopSequence, node); loopSequence = growAggregate(loopSequence, node);
loopSequence->setOperator(EOpSequence); loopSequence->setOperator(EOpSequence);

View File

@ -3039,6 +3039,37 @@ bool HlslGrammar::acceptLiteral(TIntermTyped*& node)
return true; return true;
} }
// simple_statement
// : SEMICOLON
// | declaration_statement
// | expression SEMICOLON
//
bool HlslGrammar::acceptSimpleStatement(TIntermNode*& statement)
{
// SEMICOLON
if (acceptTokenClass(EHTokSemicolon))
return true;
// declaration
if (acceptDeclaration(statement))
return true;
// expression
TIntermTyped* node;
if (acceptExpression(node))
statement = node;
else
return false;
// SEMICOLON (following an expression)
if (acceptTokenClass(EHTokSemicolon))
return true;
else {
expected(";");
return false;
}
}
// compound_statement // compound_statement
// : LEFT_CURLY statement statement ... RIGHT_CURLY // : LEFT_CURLY statement statement ... RIGHT_CURLY
// //
@ -3096,12 +3127,11 @@ bool HlslGrammar::acceptScopedCompoundStatement(TIntermNode*& statement)
// //
// attributed_statement // attributed_statement
// : compound_statement // : compound_statement
// | SEMICOLON // | simple_statement
// | expression SEMICOLON
// | declaration_statement
// | selection_statement // | selection_statement
// | switch_statement // | switch_statement
// | case_label // | case_label
// | default_label
// | iteration_statement // | iteration_statement
// | jump_statement // | jump_statement
// //
@ -3140,33 +3170,13 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
case EHTokDefault: case EHTokDefault:
return acceptDefaultLabel(statement); return acceptDefaultLabel(statement);
case EHTokSemicolon:
return acceptTokenClass(EHTokSemicolon);
case EHTokRightBrace: case EHTokRightBrace:
// Performance: not strictly necessary, but stops a bunch of hunting early, // Performance: not strictly necessary, but stops a bunch of hunting early,
// and is how sequences of statements end. // and is how sequences of statements end.
return false; return false;
default: default:
{ return acceptSimpleStatement(statement);
// declaration
if (acceptDeclaration(statement))
return true;
// expression
TIntermTyped* node;
if (acceptExpression(node))
statement = node;
else
return false;
// SEMICOLON (following an expression)
if (! acceptTokenClass(EHTokSemicolon)) {
expected(";");
return false;
}
}
} }
return true; return true;
@ -3420,14 +3430,8 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
// initializer // initializer
TIntermNode* initNode = nullptr; TIntermNode* initNode = nullptr;
if (! acceptControlDeclaration(initNode)) { if (! acceptSimpleStatement(initNode))
TIntermTyped* initExpr = nullptr; expected("for-loop initializer statement");
acceptExpression(initExpr);
initNode = initExpr;
}
// SEMI_COLON
if (! acceptTokenClass(EHTokSemicolon))
expected(";");
parseContext.nestLooping(); parseContext.nestLooping();

View File

@ -108,10 +108,11 @@ namespace glslang {
bool acceptFunctionCall(const TSourceLoc&, TString& name, TIntermTyped*&, TIntermTyped* objectBase); bool acceptFunctionCall(const TSourceLoc&, TString& name, TIntermTyped*&, TIntermTyped* objectBase);
bool acceptArguments(TFunction*, TIntermTyped*&); bool acceptArguments(TFunction*, TIntermTyped*&);
bool acceptLiteral(TIntermTyped*&); bool acceptLiteral(TIntermTyped*&);
bool acceptSimpleStatement(TIntermNode*&);
bool acceptCompoundStatement(TIntermNode*&); bool acceptCompoundStatement(TIntermNode*&);
bool acceptStatement(TIntermNode*&);
bool acceptScopedStatement(TIntermNode*&); bool acceptScopedStatement(TIntermNode*&);
bool acceptScopedCompoundStatement(TIntermNode*&); bool acceptScopedCompoundStatement(TIntermNode*&);
bool acceptStatement(TIntermNode*&);
bool acceptNestedStatement(TIntermNode*&); bool acceptNestedStatement(TIntermNode*&);
void acceptAttributes(TAttributeMap&); void acceptAttributes(TAttributeMap&);
bool acceptSelectionStatement(TIntermNode*&); bool acceptSelectionStatement(TIntermNode*&);