From 00957f8110208e567c041adbb476ca36d0bd68dc Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Wed, 27 Jul 2016 10:39:57 -0600 Subject: [PATCH] HLSL: Implement ?: grammar productions. Missing are implicit conversions between int/bool/etc. --- Test/baseResults/hlsl.conditional.frag.out | 357 +++++++++++++++++++++ Test/hlsl.conditional.frag | 16 + gtests/Hlsl.FromFile.cpp | 1 + hlsl/hlslGrammar.cpp | 55 +++- hlsl/hlslGrammar.h | 1 + 5 files changed, 423 insertions(+), 7 deletions(-) create mode 100755 Test/baseResults/hlsl.conditional.frag.out create mode 100644 Test/hlsl.conditional.frag diff --git a/Test/baseResults/hlsl.conditional.frag.out b/Test/baseResults/hlsl.conditional.frag.out new file mode 100755 index 00000000..f5acec3b --- /dev/null +++ b/Test/baseResults/hlsl.conditional.frag.out @@ -0,0 +1,357 @@ +hlsl.conditional.frag +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:17 Function Definition: PixelShaderFunction(vf4; (global 4-component vector of float) +0:2 Function Parameters: +0:2 'input' (in 4-component vector of float) +0:? Sequence +0:3 Sequence +0:3 move second child to first child (temp int) +0:3 'a' (temp int) +0:3 Constant: +0:3 5 (const int) +0:4 Sequence +0:4 move second child to first child (temp int) +0:4 'b' (temp int) +0:4 Constant: +0:4 6 (const int) +0:5 Sequence +0:5 move second child to first child (temp int) +0:5 'c' (temp int) +0:5 Constant: +0:5 7 (const int) +0:6 Sequence +0:6 move second child to first child (temp int) +0:6 'd' (temp int) +0:6 Constant: +0:6 7 (const int) +0:7 Sequence +0:7 move second child to first child (temp 4-component vector of float) +0:7 'ret' (temp 4-component vector of float) +0:8 add (temp 4-component vector of float) +0:7 add (temp 4-component vector of float) +0:7 vector-scale (temp 4-component vector of float) +0:7 Convert int to float (temp float) +0:7 'a' (temp int) +0:7 'input' (in 4-component vector of float) +0:8 vector-scale (temp 4-component vector of float) +0:8 Convert int to float (temp float) +0:8 'b' (temp int) +0:8 'input' (in 4-component vector of float) +0:9 add (temp 4-component vector of float) +0:9 vector-scale (temp 4-component vector of float) +0:9 Convert int to float (temp float) +0:9 'c' (temp int) +0:9 'input' (in 4-component vector of float) +0:10 vector-scale (temp 4-component vector of float) +0:10 Convert int to float (temp float) +0:10 'd' (temp int) +0:10 'input' (in 4-component vector of float) +0:12 Comma (temp int) +0:12 move second child to first child (temp int) +0:12 'e' (temp int) +0:12 move second child to first child (temp int) +0:12 'a' (temp int) +0:12 Test condition and select (temp int) +0:12 Condition +0:12 'b' (temp int) +0:12 true case +0:12 move second child to first child (temp int) +0:12 'c' (temp int) +0:12 'd' (temp int) +0:12 false case +0:12 Constant: +0:12 10 (const int) +0:12 move second child to first child (temp int) +0:12 'b' (temp int) +0:12 Test condition and select (temp int) +0:12 Condition +0:12 'a' (temp int) +0:12 true case +0:12 move second child to first child (temp int) +0:12 'd' (temp int) +0:12 'c' (temp int) +0:12 false case +0:12 Constant: +0:12 11 (const int) +0:14 move second child to first child (temp 4-component vector of float) +0:14 'f' (temp 4-component vector of float) +0:14 Test condition and select (temp 4-component vector of float) +0:14 Condition +0:14 Compare Less Than (temp bool) +0:14 direct index (temp float) +0:14 'ret' (temp 4-component vector of float) +0:14 Constant: +0:14 0 (const int) +0:14 direct index (temp float) +0:14 'input' (in 4-component vector of float) +0:14 Constant: +0:14 1 (const int) +0:14 true case +0:14 vector-scale (temp 4-component vector of float) +0:14 Convert int to float (temp float) +0:14 'c' (temp int) +0:14 'input' (in 4-component vector of float) +0:14 false case +0:14 vector-scale (temp 4-component vector of float) +0:14 Convert int to float (temp float) +0:14 'd' (temp int) +0:14 'input' (in 4-component vector of float) +0:15 Branch: Return with expression +0:15 add (temp 4-component vector of float) +0:15 vector-scale (temp 4-component vector of float) +0:15 Convert int to float (temp float) +0:15 'e' (temp int) +0:15 'ret' (temp 4-component vector of float) +0:15 'f' (temp 4-component vector of float) +0:? Linker Objects + + +Linked fragment stage: + + +Shader version: 450 +gl_FragCoord origin is upper left +0:? Sequence +0:17 Function Definition: PixelShaderFunction(vf4; (global 4-component vector of float) +0:2 Function Parameters: +0:2 'input' (in 4-component vector of float) +0:? Sequence +0:3 Sequence +0:3 move second child to first child (temp int) +0:3 'a' (temp int) +0:3 Constant: +0:3 5 (const int) +0:4 Sequence +0:4 move second child to first child (temp int) +0:4 'b' (temp int) +0:4 Constant: +0:4 6 (const int) +0:5 Sequence +0:5 move second child to first child (temp int) +0:5 'c' (temp int) +0:5 Constant: +0:5 7 (const int) +0:6 Sequence +0:6 move second child to first child (temp int) +0:6 'd' (temp int) +0:6 Constant: +0:6 7 (const int) +0:7 Sequence +0:7 move second child to first child (temp 4-component vector of float) +0:7 'ret' (temp 4-component vector of float) +0:8 add (temp 4-component vector of float) +0:7 add (temp 4-component vector of float) +0:7 vector-scale (temp 4-component vector of float) +0:7 Convert int to float (temp float) +0:7 'a' (temp int) +0:7 'input' (in 4-component vector of float) +0:8 vector-scale (temp 4-component vector of float) +0:8 Convert int to float (temp float) +0:8 'b' (temp int) +0:8 'input' (in 4-component vector of float) +0:9 add (temp 4-component vector of float) +0:9 vector-scale (temp 4-component vector of float) +0:9 Convert int to float (temp float) +0:9 'c' (temp int) +0:9 'input' (in 4-component vector of float) +0:10 vector-scale (temp 4-component vector of float) +0:10 Convert int to float (temp float) +0:10 'd' (temp int) +0:10 'input' (in 4-component vector of float) +0:12 Comma (temp int) +0:12 move second child to first child (temp int) +0:12 'e' (temp int) +0:12 move second child to first child (temp int) +0:12 'a' (temp int) +0:12 Test condition and select (temp int) +0:12 Condition +0:12 'b' (temp int) +0:12 true case +0:12 move second child to first child (temp int) +0:12 'c' (temp int) +0:12 'd' (temp int) +0:12 false case +0:12 Constant: +0:12 10 (const int) +0:12 move second child to first child (temp int) +0:12 'b' (temp int) +0:12 Test condition and select (temp int) +0:12 Condition +0:12 'a' (temp int) +0:12 true case +0:12 move second child to first child (temp int) +0:12 'd' (temp int) +0:12 'c' (temp int) +0:12 false case +0:12 Constant: +0:12 11 (const int) +0:14 move second child to first child (temp 4-component vector of float) +0:14 'f' (temp 4-component vector of float) +0:14 Test condition and select (temp 4-component vector of float) +0:14 Condition +0:14 Compare Less Than (temp bool) +0:14 direct index (temp float) +0:14 'ret' (temp 4-component vector of float) +0:14 Constant: +0:14 0 (const int) +0:14 direct index (temp float) +0:14 'input' (in 4-component vector of float) +0:14 Constant: +0:14 1 (const int) +0:14 true case +0:14 vector-scale (temp 4-component vector of float) +0:14 Convert int to float (temp float) +0:14 'c' (temp int) +0:14 'input' (in 4-component vector of float) +0:14 false case +0:14 vector-scale (temp 4-component vector of float) +0:14 Convert int to float (temp float) +0:14 'd' (temp int) +0:14 'input' (in 4-component vector of float) +0:15 Branch: Return with expression +0:15 add (temp 4-component vector of float) +0:15 vector-scale (temp 4-component vector of float) +0:15 Convert int to float (temp float) +0:15 'e' (temp int) +0:15 'ret' (temp 4-component vector of float) +0:15 'f' (temp 4-component vector of float) +0:? Linker Objects + +// Module Version 10000 +// Generated by (magic number): 80001 +// Id's are bound by 89 + + Capability Shader + 1: ExtInstImport "GLSL.std.450" + MemoryModel Logical GLSL450 + EntryPoint Fragment 4 "PixelShaderFunction" 22 + ExecutionMode 4 OriginUpperLeft + Source HLSL 450 + Name 4 "PixelShaderFunction" + Name 8 "a" + Name 10 "b" + Name 12 "c" + Name 14 "d" + Name 18 "ret" + Name 22 "input" + Name 40 "e" + Name 57 "f" + 2: TypeVoid + 3: TypeFunction 2 + 6: TypeInt 32 1 + 7: TypePointer Function 6(int) + 9: 6(int) Constant 5 + 11: 6(int) Constant 6 + 13: 6(int) Constant 7 + 15: TypeFloat 32 + 16: TypeVector 15(float) 4 + 17: TypePointer Function 16(fvec4) + 21: TypePointer Input 16(fvec4) + 22(input): 21(ptr) Variable Input + 47: 6(int) Constant 10 + 55: 6(int) Constant 11 + 59: TypeInt 32 0 + 60: 59(int) Constant 0 + 61: TypePointer Function 15(float) + 64: 59(int) Constant 1 + 65: TypePointer Input 15(float) + 68: TypeBool +4(PixelShaderFunction): 2 Function None 3 + 5: Label + 8(a): 7(ptr) Variable Function + 10(b): 7(ptr) Variable Function + 12(c): 7(ptr) Variable Function + 14(d): 7(ptr) Variable Function + 18(ret): 17(ptr) Variable Function + 40(e): 7(ptr) Variable Function + 41: 7(ptr) Variable Function + 49: 7(ptr) Variable Function + 57(f): 17(ptr) Variable Function + 58: 17(ptr) Variable Function + Store 8(a) 9 + Store 10(b) 11 + Store 12(c) 13 + Store 14(d) 13 + 19: 6(int) Load 8(a) + 20: 15(float) ConvertSToF 19 + 23: 16(fvec4) Load 22(input) + 24: 16(fvec4) VectorTimesScalar 23 20 + 25: 6(int) Load 10(b) + 26: 15(float) ConvertSToF 25 + 27: 16(fvec4) Load 22(input) + 28: 16(fvec4) VectorTimesScalar 27 26 + 29: 16(fvec4) FAdd 24 28 + 30: 6(int) Load 12(c) + 31: 15(float) ConvertSToF 30 + 32: 16(fvec4) Load 22(input) + 33: 16(fvec4) VectorTimesScalar 32 31 + 34: 6(int) Load 14(d) + 35: 15(float) ConvertSToF 34 + 36: 16(fvec4) Load 22(input) + 37: 16(fvec4) VectorTimesScalar 36 35 + 38: 16(fvec4) FAdd 33 37 + 39: 16(fvec4) FAdd 29 38 + Store 18(ret) 39 + 42: 6(int) Load 10(b) + SelectionMerge 44 None + BranchConditional 42 43 46 + 43: Label + 45: 6(int) Load 14(d) + Store 12(c) 45 + Store 41 45 + Branch 44 + 46: Label + Store 41 47 + Branch 44 + 44: Label + 48: 6(int) Load 41 + Store 8(a) 48 + Store 40(e) 48 + 50: 6(int) Load 8(a) + SelectionMerge 52 None + BranchConditional 50 51 54 + 51: Label + 53: 6(int) Load 12(c) + Store 14(d) 53 + Store 49 53 + Branch 52 + 54: Label + Store 49 55 + Branch 52 + 52: Label + 56: 6(int) Load 49 + Store 10(b) 56 + 62: 61(ptr) AccessChain 18(ret) 60 + 63: 15(float) Load 62 + 66: 65(ptr) AccessChain 22(input) 64 + 67: 15(float) Load 66 + 69: 68(bool) FOrdLessThan 63 67 + SelectionMerge 71 None + BranchConditional 69 70 76 + 70: Label + 72: 6(int) Load 12(c) + 73: 15(float) ConvertSToF 72 + 74: 16(fvec4) Load 22(input) + 75: 16(fvec4) VectorTimesScalar 74 73 + Store 58 75 + Branch 71 + 76: Label + 77: 6(int) Load 14(d) + 78: 15(float) ConvertSToF 77 + 79: 16(fvec4) Load 22(input) + 80: 16(fvec4) VectorTimesScalar 79 78 + Store 58 80 + Branch 71 + 71: Label + 81: 16(fvec4) Load 58 + Store 57(f) 81 + 82: 6(int) Load 40(e) + 83: 15(float) ConvertSToF 82 + 84: 16(fvec4) Load 18(ret) + 85: 16(fvec4) VectorTimesScalar 84 83 + 86: 16(fvec4) Load 57(f) + 87: 16(fvec4) FAdd 85 86 + ReturnValue 87 + FunctionEnd diff --git a/Test/hlsl.conditional.frag b/Test/hlsl.conditional.frag new file mode 100644 index 00000000..128c5931 --- /dev/null +++ b/Test/hlsl.conditional.frag @@ -0,0 +1,16 @@ +float4 PixelShaderFunction(float4 input) : COLOR0 +{ + int a = 1 < 2 ? 3 < 4 ? 5 : 6 : 7; + int b = 1 < 2 ? 3 > 4 ? 5 : 6 : 7; + int c = 1 > 2 ? 3 > 4 ? 5 : 6 : 7; + int d = 1 > 2 ? 3 < 4 ? 5 : 6 : 7; + float4 ret = a * input + + b * input + + c * input + + d * input; + int e; + e = a = b ? c = d : 10, b = a ? d = c : 11; + float4 f; + f = ret.x < input.y ? c * input : d * input; + return e * ret + f; +} diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp index 7717e092..2561af99 100644 --- a/gtests/Hlsl.FromFile.cpp +++ b/gtests/Hlsl.FromFile.cpp @@ -77,6 +77,7 @@ INSTANTIATE_TEST_CASE_P( {"hlsl.attribute.frag", "PixelShaderFunction"}, {"hlsl.buffer.frag", "PixelShaderFunction"}, {"hlsl.cast.frag", "PixelShaderFunction"}, + {"hlsl.conditional.frag", "PixelShaderFunction"}, {"hlsl.discard.frag", "PixelShaderFunction"}, {"hlsl.doLoop.frag", "PixelShaderFunction"}, {"hlsl.float1.frag", "PixelShaderFunction"}, diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index be148eb3..3c965600 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -1548,8 +1548,9 @@ bool HlslGrammar::acceptInitializer(TIntermTyped*& node) // a op (b op (c op d)) // // assigment_expression -// : binary_expression op binary_expression op binary_expression ... -// | initializer +// : initializer +// | conditional_expression +// | conditional_expression assign_op conditional_expression assign_op conditional_expression ... // bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node) { @@ -1562,8 +1563,8 @@ bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node) return false; } - // binary_expression - if (! acceptBinaryExpression(node, PlLogicalOr)) + // conditional_expression + if (! acceptConditionalExpression(node)) return false; // assignment operation? @@ -1571,12 +1572,12 @@ bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node) if (assignOp == EOpNull) return true; - // assignment op + // assign_op TSourceLoc loc = token.loc; advanceToken(); - // binary_expression - // But, done by recursing this function, which automatically + // conditional_expression assign_op conditional_expression ... + // Done by recursing this function, which automatically // gets the right-to-left associativity. TIntermTyped* rightNode = nullptr; if (! acceptAssignmentExpression(rightNode)) { @@ -1595,6 +1596,46 @@ bool HlslGrammar::acceptAssignmentExpression(TIntermTyped*& node) return true; } +// Accept a conditional expression, which associates right-to-left, +// accomplished by the "true" expression calling down to lower +// precedence levels than this level. +// +// conditional_expression +// : binary_expression +// | binary_expression QUESTION expression COLON assignment_expression +// +bool HlslGrammar::acceptConditionalExpression(TIntermTyped*& node) +{ + // binary_expression + if (! acceptBinaryExpression(node, PlLogicalOr)) + return false; + + if (! acceptTokenClass(EHTokQuestion)) + return true; + + TIntermTyped* trueNode = nullptr; + if (! acceptExpression(trueNode)) { + expected("expression after ?"); + return false; + } + TSourceLoc loc = token.loc; + + if (! acceptTokenClass(EHTokColon)) { + expected(":"); + return false; + } + + TIntermTyped* falseNode = nullptr; + if (! acceptAssignmentExpression(falseNode)) { + expected("expression after :"); + return false; + } + + node = intermediate.addSelection(node, trueNode, falseNode, loc); + + return true; +} + // Accept a binary expression, for binary operations that // associate left-to-right. This is, it is implicit, for example // diff --git a/hlsl/hlslGrammar.h b/hlsl/hlslGrammar.h index 9f224fef..c522df4c 100755 --- a/hlsl/hlslGrammar.h +++ b/hlsl/hlslGrammar.h @@ -83,6 +83,7 @@ namespace glslang { bool acceptExpression(TIntermTyped*&); bool acceptInitializer(TIntermTyped*&); bool acceptAssignmentExpression(TIntermTyped*&); + bool acceptConditionalExpression(TIntermTyped*&); bool acceptBinaryExpression(TIntermTyped*&, PrecedenceLevel); bool acceptUnaryExpression(TIntermTyped*&); bool acceptPostfixExpression(TIntermTyped*&);