HLSL: Flesh out the loop grammar and productions.

This commit is contained in:
John Kessenich 2016-06-05 15:44:07 -06:00
parent 0d2b6de45b
commit 119f8f6906
11 changed files with 645 additions and 2 deletions

View File

@ -0,0 +1,116 @@
hlsl.doLoop.frag
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:7 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:3 Loop with condition not tested first
0:3 Loop Condition
0:3 Constant:
0:3 false (const bool)
0:3 No loop body
0:4 Loop with condition not tested first
0:4 Loop Condition
0:4 Constant:
0:4 false (const bool)
0:4 No loop body
0:5 Loop with condition not tested first
0:5 Loop Condition
0:5 Compare Equal (temp bool)
0:5 'input' (temp 4-component vector of float)
0:5 'input' (temp 4-component vector of float)
0:5 Loop Body
0:5 Branch: Return with expression
0:5 'input' (temp 4-component vector of float)
0:? Linker Objects
Linked fragment stage:
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:7 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:3 Loop with condition not tested first
0:3 Loop Condition
0:3 Constant:
0:3 false (const bool)
0:3 No loop body
0:4 Loop with condition not tested first
0:4 Loop Condition
0:4 Constant:
0:4 false (const bool)
0:4 No loop body
0:5 Loop with condition not tested first
0:5 Loop Condition
0:5 Compare Equal (temp bool)
0:5 'input' (temp 4-component vector of float)
0:5 'input' (temp 4-component vector of float)
0:5 Loop Body
0:5 Branch: Return with expression
0:5 'input' (temp 4-component vector of float)
0:? Linker Objects
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 31
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "PixelShaderFunction"
ExecutionMode 4 OriginUpperLeft
Source HLSL 450
Name 4 "PixelShaderFunction"
Name 23 "input"
2: TypeVoid
3: TypeFunction 2
10: TypeBool
11: 10(bool) ConstantFalse
20: TypeFloat 32
21: TypeVector 20(float) 4
22: TypePointer Function 21(fvec4)
28: TypeVector 10(bool) 4
4(PixelShaderFunction): 2 Function None 3
5: Label
23(input): 22(ptr) Variable Function
Branch 6
6: Label
LoopMerge 8 9 None
Branch 7
7: Label
Branch 9
9: Label
BranchConditional 11 6 8
8: Label
Branch 12
12: Label
LoopMerge 14 15 None
Branch 13
13: Label
Branch 15
15: Label
BranchConditional 11 12 14
14: Label
Branch 16
16: Label
LoopMerge 18 19 None
Branch 17
17: Label
24: 21(fvec4) Load 23(input)
ReturnValue 24
19: Label
26: 21(fvec4) Load 23(input)
27: 21(fvec4) Load 23(input)
29: 28(bvec4) FOrdEqual 26 27
30: 10(bool) All 29
BranchConditional 30 16 18
18: Label
Return
FunctionEnd

View File

@ -0,0 +1,220 @@
hlsl.forLoop.frag
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:9 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:? Sequence
0:3 Loop with condition tested first
0:3 No loop condition
0:3 No loop body
0:4 Sequence
0:4 Pre-Increment (temp 4-component vector of float)
0:4 'input' (temp 4-component vector of float)
0:4 Loop with condition tested first
0:4 No loop condition
0:4 No loop body
0:? Sequence
0:5 Loop with condition tested first
0:5 Loop Condition
0:5 Compare Not Equal (temp bool)
0:5 'input' (temp 4-component vector of float)
0:5 'input' (temp 4-component vector of float)
0:5 No loop body
0:? Sequence
0:6 Loop with condition tested first
0:6 Loop Condition
0:6 Compare Not Equal (temp bool)
0:6 'input' (temp 4-component vector of float)
0:6 'input' (temp 4-component vector of float)
0:6 Loop Body
0:? Sequence
0:6 Branch: Return with expression
0:6 Negate value (temp 4-component vector of float)
0:6 'input' (temp 4-component vector of float)
0:7 Sequence
0:7 Pre-Decrement (temp 4-component vector of float)
0:7 'input' (temp 4-component vector of float)
0:7 Loop with condition tested first
0:7 Loop Condition
0:7 Compare Not Equal (temp bool)
0:7 'input' (temp 4-component vector of float)
0:7 'input' (temp 4-component vector of float)
0:7 Loop Body
0:? Sequence
0:7 Branch: Return with expression
0:7 Negate value (temp 4-component vector of float)
0:7 'input' (temp 4-component vector of float)
0:7 Loop Terminal Expression
0:7 add second child into first child (temp 4-component vector of float)
0:7 'input' (temp 4-component vector of float)
0:7 Constant:
0:7 2.000000
0:? Linker Objects
Linked fragment stage:
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:9 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:? Sequence
0:3 Loop with condition tested first
0:3 No loop condition
0:3 No loop body
0:4 Sequence
0:4 Pre-Increment (temp 4-component vector of float)
0:4 'input' (temp 4-component vector of float)
0:4 Loop with condition tested first
0:4 No loop condition
0:4 No loop body
0:? Sequence
0:5 Loop with condition tested first
0:5 Loop Condition
0:5 Compare Not Equal (temp bool)
0:5 'input' (temp 4-component vector of float)
0:5 'input' (temp 4-component vector of float)
0:5 No loop body
0:? Sequence
0:6 Loop with condition tested first
0:6 Loop Condition
0:6 Compare Not Equal (temp bool)
0:6 'input' (temp 4-component vector of float)
0:6 'input' (temp 4-component vector of float)
0:6 Loop Body
0:? Sequence
0:6 Branch: Return with expression
0:6 Negate value (temp 4-component vector of float)
0:6 'input' (temp 4-component vector of float)
0:7 Sequence
0:7 Pre-Decrement (temp 4-component vector of float)
0:7 'input' (temp 4-component vector of float)
0:7 Loop with condition tested first
0:7 Loop Condition
0:7 Compare Not Equal (temp bool)
0:7 'input' (temp 4-component vector of float)
0:7 'input' (temp 4-component vector of float)
0:7 Loop Body
0:? Sequence
0:7 Branch: Return with expression
0:7 Negate value (temp 4-component vector of float)
0:7 'input' (temp 4-component vector of float)
0:7 Loop Terminal Expression
0:7 add second child into first child (temp 4-component vector of float)
0:7 'input' (temp 4-component vector of float)
0:7 Constant:
0:7 2.000000
0:? Linker Objects
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 64
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "PixelShaderFunction"
ExecutionMode 4 OriginUpperLeft
Source HLSL 450
Name 4 "PixelShaderFunction"
Name 13 "input"
2: TypeVoid
3: TypeFunction 2
10: TypeFloat 32
11: TypeVector 10(float) 4
12: TypePointer Function 11(fvec4)
15: 10(float) Constant 1065353216
29: TypeBool
30: TypeVector 29(bool) 4
60: 10(float) Constant 1073741824
4(PixelShaderFunction): 2 Function None 3
5: Label
13(input): 12(ptr) Variable Function
Branch 6
6: Label
LoopMerge 8 9 None
Branch 7
7: Label
Branch 9
9: Label
Branch 6
8: Label
14: 11(fvec4) Load 13(input)
16: 11(fvec4) CompositeConstruct 15 15 15 15
17: 11(fvec4) FAdd 14 16
Store 13(input) 17
Branch 18
18: Label
LoopMerge 20 21 None
Branch 19
19: Label
Branch 21
21: Label
Branch 18
20: Label
Branch 22
22: Label
LoopMerge 24 25 None
Branch 26
26: Label
27: 11(fvec4) Load 13(input)
28: 11(fvec4) Load 13(input)
31: 30(bvec4) FOrdNotEqual 27 28
32: 29(bool) Any 31
BranchConditional 32 23 24
23: Label
Branch 25
25: Label
Branch 22
24: Label
Branch 33
33: Label
LoopMerge 35 36 None
Branch 37
37: Label
38: 11(fvec4) Load 13(input)
39: 11(fvec4) Load 13(input)
40: 30(bvec4) FOrdNotEqual 38 39
41: 29(bool) Any 40
BranchConditional 41 34 35
34: Label
42: 11(fvec4) Load 13(input)
43: 11(fvec4) FNegate 42
ReturnValue 43
36: Label
Branch 33
35: Label
45: 11(fvec4) Load 13(input)
46: 11(fvec4) CompositeConstruct 15 15 15 15
47: 11(fvec4) FSub 45 46
Store 13(input) 47
Branch 48
48: Label
LoopMerge 50 51 None
Branch 52
52: Label
53: 11(fvec4) Load 13(input)
54: 11(fvec4) Load 13(input)
55: 30(bvec4) FOrdNotEqual 53 54
56: 29(bool) Any 55
BranchConditional 56 49 50
49: Label
57: 11(fvec4) Load 13(input)
58: 11(fvec4) FNegate 57
ReturnValue 58
51: Label
61: 11(fvec4) Load 13(input)
62: 11(fvec4) CompositeConstruct 60 60 60 60
63: 11(fvec4) FAdd 61 62
Store 13(input) 63
Branch 48
50: Label
Return
FunctionEnd

View File

@ -0,0 +1,145 @@
hlsl.whileLoop.frag
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:8 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:3 Loop with condition tested first
0:3 Loop Condition
0:3 Compare Not Equal (temp bool)
0:3 'input' (temp 4-component vector of float)
0:3 'input' (temp 4-component vector of float)
0:3 Loop Body
0:? Sequence
0:3 Branch: Return with expression
0:3 'input' (temp 4-component vector of float)
0:4 Loop with condition tested first
0:4 Loop Condition
0:4 Constant:
0:4 false (const bool)
0:4 No loop body
0:5 Loop with condition tested first
0:5 Loop Condition
0:5 Constant:
0:5 false (const bool)
0:5 No loop body
0:6 Loop with condition tested first
0:6 Loop Condition
0:6 Constant:
0:6 false (const bool)
0:6 No loop body
0:? Linker Objects
Linked fragment stage:
Shader version: 450
gl_FragCoord origin is upper left
0:? Sequence
0:8 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:3 Loop with condition tested first
0:3 Loop Condition
0:3 Compare Not Equal (temp bool)
0:3 'input' (temp 4-component vector of float)
0:3 'input' (temp 4-component vector of float)
0:3 Loop Body
0:? Sequence
0:3 Branch: Return with expression
0:3 'input' (temp 4-component vector of float)
0:4 Loop with condition tested first
0:4 Loop Condition
0:4 Constant:
0:4 false (const bool)
0:4 No loop body
0:5 Loop with condition tested first
0:5 Loop Condition
0:5 Constant:
0:5 false (const bool)
0:5 No loop body
0:6 Loop with condition tested first
0:6 Loop Condition
0:6 Constant:
0:6 false (const bool)
0:6 No loop body
0:? Linker Objects
// Module Version 10000
// Generated by (magic number): 80001
// Id's are bound by 39
Capability Shader
1: ExtInstImport "GLSL.std.450"
MemoryModel Logical GLSL450
EntryPoint Fragment 4 "PixelShaderFunction"
ExecutionMode 4 OriginUpperLeft
Source HLSL 450
Name 4 "PixelShaderFunction"
Name 14 "input"
2: TypeVoid
3: TypeFunction 2
11: TypeFloat 32
12: TypeVector 11(float) 4
13: TypePointer Function 12(fvec4)
17: TypeBool
18: TypeVector 17(bool) 4
28: 17(bool) ConstantFalse
4(PixelShaderFunction): 2 Function None 3
5: Label
14(input): 13(ptr) Variable Function
Branch 6
6: Label
LoopMerge 8 9 None
Branch 10
10: Label
15: 12(fvec4) Load 14(input)
16: 12(fvec4) Load 14(input)
19: 18(bvec4) FOrdNotEqual 15 16
20: 17(bool) Any 19
BranchConditional 20 7 8
7: Label
21: 12(fvec4) Load 14(input)
ReturnValue 21
9: Label
Branch 6
8: Label
Branch 23
23: Label
LoopMerge 25 26 None
Branch 27
27: Label
BranchConditional 28 24 25
24: Label
Branch 26
26: Label
Branch 23
25: Label
Branch 29
29: Label
LoopMerge 31 32 None
Branch 33
33: Label
BranchConditional 28 30 31
30: Label
Branch 32
32: Label
Branch 29
31: Label
Branch 34
34: Label
LoopMerge 36 37 None
Branch 38
38: Label
BranchConditional 28 35 36
35: Label
Branch 37
37: Label
Branch 34
36: Label
Return
FunctionEnd

6
Test/hlsl.doLoop.frag Normal file
View File

@ -0,0 +1,6 @@
float4 PixelShaderFunction(float4 input) : COLOR0
{
[unroll] do {} while (false);
[unroll] do {;} while (false);
do { return input; } while (input == input);
}

8
Test/hlsl.forLoop.frag Normal file
View File

@ -0,0 +1,8 @@
float4 PixelShaderFunction(float4 input) : COLOR0
{
for (;;) ;
for (++input; ; ) ;
[unroll] for (; input != input; ) {}
for (; input != input; ) { return -input; }
for (--input; input != input; input += 2) { return -input; }
}

7
Test/hlsl.whileLoop.frag Normal file
View File

@ -0,0 +1,7 @@
float4 PixelShaderFunction(float4 input) : COLOR0
{
while (input != input) { return input; }
while (false) ;
[unroll] while (false) { }
while ((false)) { }
}

View File

@ -1028,7 +1028,7 @@ const TIntermTyped* TIntermediate::findLValueBase(const TIntermTyped* node, bool
}
//
// Create loop nodes.
// Create while and do-while loop nodes.
//
TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc)
{
@ -1038,6 +1038,22 @@ TIntermLoop* TIntermediate::addLoop(TIntermNode* body, TIntermTyped* test, TInte
return node;
}
//
// Create a for-loop sequence.
//
TIntermAggregate* TIntermediate::addForLoop(TIntermNode* body, TIntermNode* initializer, TIntermTyped* test, TIntermTyped* terminal, bool testFirst, const TSourceLoc& loc)
{
TIntermLoop* node = new TIntermLoop(body, test, terminal, testFirst);
node->setLoc(loc);
// make a sequence of the initializer and statement
TIntermAggregate* loopSequence = makeAggregate(initializer, loc);
loopSequence = growAggregate(loopSequence, node);
loopSequence->setOperator(EOpSequence);
return loopSequence;
}
//
// Add branches.
//

View File

@ -198,6 +198,7 @@ public:
TIntermTyped* promoteConstantUnion(TBasicType, TIntermConstantUnion*) const;
bool parseConstTree(TIntermNode*, TConstUnionArray, TOperator, const TType&, bool singleConstantParam = false);
TIntermLoop* addLoop(TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
TIntermAggregate* addForLoop(TIntermNode*, TIntermNode*, TIntermTyped*, TIntermTyped*, bool testFirst, const TSourceLoc&);
TIntermBranch* addBranch(TOperator, const TSourceLoc&);
TIntermBranch* addBranch(TOperator, TIntermTyped*, const TSourceLoc&);
TIntermTyped* addSwizzle(TVectorFields&, const TSourceLoc&);

View File

@ -75,8 +75,10 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.assoc.frag", "PixelShaderFunction"},
{"hlsl.attribute.frag", "PixelShaderFunction"},
{"hlsl.cast.frag", "PixelShaderFunction"},
{"hlsl.doLoop.frag", "PixelShaderFunction"},
{"hlsl.float1.frag", "PixelShaderFunction"},
{"hlsl.float4.frag", "PixelShaderFunction"},
{"hlsl.forLoop.frag", "PixelShaderFunction"},
{"hlsl.if.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.frag", "PixelShaderFunction"},
{"hlsl.intrinsics.negative.frag", "PixelShaderFunction"},
@ -87,6 +89,7 @@ INSTANTIATE_TEST_CASE_P(
{"hlsl.precedence.frag", "PixelShaderFunction"},
{"hlsl.precedence2.frag", "PixelShaderFunction"},
{"hlsl.sin.frag", "PixelShaderFunction"},
{"hlsl.whileLoop.frag", "PixelShaderFunction"},
}),
FileNameAsCustomTestSuffix
);

View File

@ -1119,9 +1119,128 @@ bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement)
return false;
}
// iteration_statement
// : WHILE LEFT_PAREN condition RIGHT_PAREN statement
// | DO LEFT_BRACE statement RIGHT_BRACE WHILE LEFT_PAREN expression RIGHT_PAREN SEMICOLON
// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
//
// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement)
{
return false;
TSourceLoc loc = token.loc;
TIntermTyped* condition = nullptr;
EHlslTokenClass loop = peek();
assert(loop == EHTokDo || loop == EHTokFor || loop == EHTokWhile);
// WHILE or DO or FOR
advanceToken();
switch (loop) {
case EHTokWhile:
// so that something declared in the condition is scoped to the lifetime
// of the while sub-statement
parseContext.pushScope();
parseContext.nestLooping();
// LEFT_PAREN condition RIGHT_PAREN
if (! acceptParenExpression(condition))
return false;
// statement
if (! acceptScopedStatement(statement)) {
expected("while sub-statement");
return false;
}
parseContext.unnestLooping();
parseContext.popScope();
statement = intermediate.addLoop(statement, condition, nullptr, true, loc);
return true;
case EHTokDo:
parseContext.nestLooping();
if (! acceptTokenClass(EHTokLeftBrace))
expected("{");
// statement
if (! peekTokenClass(EHTokRightBrace) && ! acceptScopedStatement(statement)) {
expected("do sub-statement");
return false;
}
if (! acceptTokenClass(EHTokRightBrace))
expected("}");
// WHILE
if (! acceptTokenClass(EHTokWhile)) {
expected("while");
return false;
}
// LEFT_PAREN condition RIGHT_PAREN
TIntermTyped* condition;
if (! acceptParenExpression(condition))
return false;
if (! acceptTokenClass(EHTokSemicolon))
expected(";");
parseContext.unnestLooping();
statement = intermediate.addLoop(statement, condition, 0, false, loc);
return true;
case EHTokFor:
{
// LEFT_PAREN
if (! acceptTokenClass(EHTokLeftParen))
expected("(");
// so that something declared in the condition is scoped to the lifetime
// of the for sub-statement
parseContext.pushScope();
// initializer SEMI_COLON
TIntermTyped* initializer = nullptr; // TODO, "for (initializer" needs to support decl. statement
acceptExpression(initializer);
if (! acceptTokenClass(EHTokSemicolon))
expected(";");
parseContext.nestLooping();
// condition SEMI_COLON
acceptExpression(condition);
if (! acceptTokenClass(EHTokSemicolon))
expected(";");
// iterator SEMI_COLON
TIntermTyped* iterator = nullptr;
acceptExpression(iterator);
if (! acceptTokenClass(EHTokRightParen))
expected(")");
// statement
if (! acceptScopedStatement(statement)) {
expected("for sub-statement");
return false;
}
statement = intermediate.addForLoop(statement, initializer, condition, iterator, true, loc);
parseContext.popScope();
parseContext.unnestLooping();
return true;
}
default:
return false;
}
}
// jump_statement

View File

@ -141,6 +141,8 @@ public:
void nestStatement() { ++statementNestingLevel; }
void unnestStatement() { --statementNestingLevel; }
void nestLooping() { ++loopNestingLevel; }
void unnestLooping() { --loopNestingLevel; }
void pushScope() { symbolTable.push(); }
void popScope() { symbolTable.pop(0); }