Merge pull request #632 from steve-lunarg/structure-splitting

HLSL: inter-stage structure splitting.
diff --git a/Test/baseResults/hlsl.basic.geom.out b/Test/baseResults/hlsl.basic.geom.out
index 2c20b43..67477fb 100644
--- a/Test/baseResults/hlsl.basic.geom.out
+++ b/Test/baseResults/hlsl.basic.geom.out
@@ -9,7 +9,7 @@
 0:16    Function Parameters: 
 0:16      'VertexID' (layout(location=0 ) in 3-element array of uint)
 0:16      'test' (layout(location=3 ) in 3-element array of uint)
-0:16      'OutputStream' (out structure{temp float myfloat, temp int something})
+0:16      'OutputStream' (layout(location=0 ) out structure{temp float myfloat, temp int something})
 0:?     Sequence
 0:19      move second child to first child (temp float)
 0:19        myfloat: direct index for structure (temp float)
@@ -43,20 +43,19 @@
 0:20              0 (const int)
 0:22      Sequence
 0:22        move second child to first child (temp structure{temp float myfloat, temp int something})
-0:22          'OutputStream' (out structure{temp float myfloat, temp int something})
+0:22          'OutputStream' (layout(location=0 ) out structure{temp float myfloat, temp int something})
 0:22          'Vert' (temp structure{temp float myfloat, temp int something})
 0:22        EmitVertex (temp void)
 0:23      Sequence
 0:23        move second child to first child (temp structure{temp float myfloat, temp int something})
-0:23          'OutputStream' (out structure{temp float myfloat, temp int something})
+0:23          'OutputStream' (layout(location=0 ) out structure{temp float myfloat, temp int something})
 0:23          'Vert' (temp structure{temp float myfloat, temp int something})
 0:23        EmitVertex (temp void)
 0:24      EndPrimitive (temp void)
 0:?   Linker Objects
 0:?     'VertexID' (layout(location=0 ) in 3-element array of uint)
 0:?     'test' (layout(location=3 ) in 3-element array of uint)
-0:?     'myfloat' (layout(location=0 ) out float)
-0:?     'something' (layout(location=1 ) out int)
+0:?     'OutputStream' (layout(location=0 ) out structure{temp float myfloat, temp int something})
 
 
 Linked geometry stage:
@@ -72,7 +71,7 @@
 0:16    Function Parameters: 
 0:16      'VertexID' (layout(location=0 ) in 3-element array of uint)
 0:16      'test' (layout(location=3 ) in 3-element array of uint)
-0:16      'OutputStream' (out structure{temp float myfloat, temp int something})
+0:16      'OutputStream' (layout(location=0 ) out structure{temp float myfloat, temp int something})
 0:?     Sequence
 0:19      move second child to first child (temp float)
 0:19        myfloat: direct index for structure (temp float)
@@ -106,29 +105,28 @@
 0:20              0 (const int)
 0:22      Sequence
 0:22        move second child to first child (temp structure{temp float myfloat, temp int something})
-0:22          'OutputStream' (out structure{temp float myfloat, temp int something})
+0:22          'OutputStream' (layout(location=0 ) out structure{temp float myfloat, temp int something})
 0:22          'Vert' (temp structure{temp float myfloat, temp int something})
 0:22        EmitVertex (temp void)
 0:23      Sequence
 0:23        move second child to first child (temp structure{temp float myfloat, temp int something})
-0:23          'OutputStream' (out structure{temp float myfloat, temp int something})
+0:23          'OutputStream' (layout(location=0 ) out structure{temp float myfloat, temp int something})
 0:23          'Vert' (temp structure{temp float myfloat, temp int something})
 0:23        EmitVertex (temp void)
 0:24      EndPrimitive (temp void)
 0:?   Linker Objects
 0:?     'VertexID' (layout(location=0 ) in 3-element array of uint)
 0:?     'test' (layout(location=3 ) in 3-element array of uint)
-0:?     'myfloat' (layout(location=0 ) out float)
-0:?     'something' (layout(location=1 ) out int)
+0:?     'OutputStream' (layout(location=0 ) out structure{temp float myfloat, temp int something})
 
 // Module Version 10000
 // Generated by (magic number): 80001
-// Id's are bound by 45
+// Id's are bound by 41
 
                               Capability Geometry
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint Geometry 4  "main" 16 31 38 42 44
+                              EntryPoint Geometry 4  "main" 16 31 38
                               ExecutionMode 4 Triangles
                               ExecutionMode 4 Invocations 1
                               ExecutionMode 4 OutputLineStrip
@@ -141,12 +139,9 @@
                               Name 16  "test"
                               Name 31  "VertexID"
                               Name 38  "OutputStream"
-                              Name 42  "myfloat"
-                              Name 44  "something"
                               Decorate 16(test) Location 3
                               Decorate 31(VertexID) Location 0
-                              Decorate 42(myfloat) Location 0
-                              Decorate 44(something) Location 1
+                              Decorate 38(OutputStream) Location 0
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeFloat 32
@@ -167,10 +162,6 @@
               35:             TypePointer Function 7(int)
               37:             TypePointer Output 8(PSInput)
 38(OutputStream):     37(ptr) Variable Output
-              41:             TypePointer Output 6(float)
-     42(myfloat):     41(ptr) Variable Output
-              43:             TypePointer Output 7(int)
-   44(something):     43(ptr) Variable Output
          4(main):           2 Function None 3
                5:             Label
         10(Vert):      9(ptr) Variable Function
diff --git a/Test/baseResults/hlsl.entry-in.frag.out b/Test/baseResults/hlsl.entry-in.frag.out
index 04e3935..686b355 100755
--- a/Test/baseResults/hlsl.entry-in.frag.out
+++ b/Test/baseResults/hlsl.entry-in.frag.out
@@ -4,84 +4,48 @@
 0:? Sequence
 0:8  Function Definition: fun(struct-InParam-vf2-vf4-vi21; (temp float)
 0:8    Function Parameters: 
-0:8      'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:8      'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:?     Sequence
 0:9      Branch: Return with expression
 0:9        add (temp float)
 0:9          direct index (temp float)
 0:9            v: direct index for structure (temp 2-component vector of float)
-0:9              'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:9              'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:9              Constant:
 0:9                0 (const int)
 0:9            Constant:
 0:9              1 (const int)
 0:9          direct index (temp float)
 0:9            fragCoord: direct index for structure (temp 4-component vector of float FragCoord)
-0:9              'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:9              'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:9              Constant:
 0:9                1 (const int)
 0:9            Constant:
 0:9              0 (const int)
 0:13  Function Definition: PixelShaderFunction(struct-InParam-vf2-vf4-vi21; (temp 4-component vector of float)
 0:13    Function Parameters: 
-0:13      'i' (in structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:13      'i' (layout(location=0 ) in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:?     Sequence
-0:15      Sequence
-0:15        move second child to first child (temp 2-component vector of float)
-0:15          v: direct index for structure (temp 2-component vector of float)
-0:15            'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:15            Constant:
-0:15              0 (const int)
-0:?           'v' (layout(location=0 ) in 2-component vector of float)
-0:15        move second child to first child (temp 4-component vector of float)
-0:15          fragCoord: direct index for structure (temp 4-component vector of float)
-0:15            'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:15            Constant:
-0:15              1 (const int)
-0:?           'fragCoord' (in 4-component vector of float FragCoord)
-0:15        move second child to first child (temp 2-component vector of int)
-0:15          i2: direct index for structure (temp 2-component vector of int)
-0:15            'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:15            Constant:
-0:15              2 (const int)
-0:?           'i2' (layout(location=1 ) in 2-component vector of int)
+0:15      move second child to first child (temp structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
+0:15        'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
+0:15        'i' (layout(location=0 ) in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:16      Sequence
 0:16        move second child to first child (temp float)
 0:16          'ret1' (temp float)
 0:16          Function Call: fun(struct-InParam-vf2-vf4-vi21; (temp float)
-0:16            'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:16            'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:17      Sequence
 0:17        move second child to first child (temp float)
 0:17          'ret2' (temp float)
 0:17          Function Call: fun(struct-InParam-vf2-vf4-vi21; (temp float)
-0:17            Comma (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:17              Sequence
-0:17                move second child to first child (temp 2-component vector of float)
-0:17                  v: direct index for structure (temp 2-component vector of float)
-0:17                    'aggShadow' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:17                    Constant:
-0:17                      0 (const int)
-0:?                   'v' (layout(location=0 ) in 2-component vector of float)
-0:17                move second child to first child (temp 4-component vector of float)
-0:17                  fragCoord: direct index for structure (temp 4-component vector of float)
-0:17                    'aggShadow' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:17                    Constant:
-0:17                      1 (const int)
-0:?                   'fragCoord' (in 4-component vector of float FragCoord)
-0:17                move second child to first child (temp 2-component vector of int)
-0:17                  i2: direct index for structure (temp 2-component vector of int)
-0:17                    'aggShadow' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:17                    Constant:
-0:17                      2 (const int)
-0:?                   'i2' (layout(location=1 ) in 2-component vector of int)
-0:17              'aggShadow' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:17            'i' (layout(location=0 ) in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:19      Sequence
 0:19        move second child to first child (temp 4-component vector of float)
 0:?           '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
 0:19          vector-scale (temp 4-component vector of float)
 0:19            vector-scale (temp 4-component vector of float)
-0:19              fragCoord: direct index for structure (temp 4-component vector of float)
-0:19                'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:19              fragCoord: direct index for structure (temp 4-component vector of float FragCoord)
+0:19                'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:19                Constant:
 0:19                  1 (const int)
 0:19              'ret1' (temp float)
@@ -89,9 +53,7 @@
 0:19        Branch: Return
 0:?   Linker Objects
 0:?     '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
-0:?     'v' (layout(location=0 ) in 2-component vector of float)
-0:?     'fragCoord' (in 4-component vector of float FragCoord)
-0:?     'i2' (layout(location=1 ) in 2-component vector of int)
+0:?     'i' (layout(location=0 ) in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 
 
 Linked fragment stage:
@@ -102,84 +64,48 @@
 0:? Sequence
 0:8  Function Definition: fun(struct-InParam-vf2-vf4-vi21; (temp float)
 0:8    Function Parameters: 
-0:8      'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:8      'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:?     Sequence
 0:9      Branch: Return with expression
 0:9        add (temp float)
 0:9          direct index (temp float)
 0:9            v: direct index for structure (temp 2-component vector of float)
-0:9              'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:9              'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:9              Constant:
 0:9                0 (const int)
 0:9            Constant:
 0:9              1 (const int)
 0:9          direct index (temp float)
 0:9            fragCoord: direct index for structure (temp 4-component vector of float FragCoord)
-0:9              'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:9              'p' (in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:9              Constant:
 0:9                1 (const int)
 0:9            Constant:
 0:9              0 (const int)
 0:13  Function Definition: PixelShaderFunction(struct-InParam-vf2-vf4-vi21; (temp 4-component vector of float)
 0:13    Function Parameters: 
-0:13      'i' (in structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:13      'i' (layout(location=0 ) in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:?     Sequence
-0:15      Sequence
-0:15        move second child to first child (temp 2-component vector of float)
-0:15          v: direct index for structure (temp 2-component vector of float)
-0:15            'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:15            Constant:
-0:15              0 (const int)
-0:?           'v' (layout(location=0 ) in 2-component vector of float)
-0:15        move second child to first child (temp 4-component vector of float)
-0:15          fragCoord: direct index for structure (temp 4-component vector of float)
-0:15            'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:15            Constant:
-0:15              1 (const int)
-0:?           'fragCoord' (in 4-component vector of float FragCoord)
-0:15        move second child to first child (temp 2-component vector of int)
-0:15          i2: direct index for structure (temp 2-component vector of int)
-0:15            'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:15            Constant:
-0:15              2 (const int)
-0:?           'i2' (layout(location=1 ) in 2-component vector of int)
+0:15      move second child to first child (temp structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
+0:15        'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
+0:15        'i' (layout(location=0 ) in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:16      Sequence
 0:16        move second child to first child (temp float)
 0:16          'ret1' (temp float)
 0:16          Function Call: fun(struct-InParam-vf2-vf4-vi21; (temp float)
-0:16            'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:16            'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:17      Sequence
 0:17        move second child to first child (temp float)
 0:17          'ret2' (temp float)
 0:17          Function Call: fun(struct-InParam-vf2-vf4-vi21; (temp float)
-0:17            Comma (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:17              Sequence
-0:17                move second child to first child (temp 2-component vector of float)
-0:17                  v: direct index for structure (temp 2-component vector of float)
-0:17                    'aggShadow' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:17                    Constant:
-0:17                      0 (const int)
-0:?                   'v' (layout(location=0 ) in 2-component vector of float)
-0:17                move second child to first child (temp 4-component vector of float)
-0:17                  fragCoord: direct index for structure (temp 4-component vector of float)
-0:17                    'aggShadow' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:17                    Constant:
-0:17                      1 (const int)
-0:?                   'fragCoord' (in 4-component vector of float FragCoord)
-0:17                move second child to first child (temp 2-component vector of int)
-0:17                  i2: direct index for structure (temp 2-component vector of int)
-0:17                    'aggShadow' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
-0:17                    Constant:
-0:17                      2 (const int)
-0:?                   'i2' (layout(location=1 ) in 2-component vector of int)
-0:17              'aggShadow' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:17            'i' (layout(location=0 ) in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:19      Sequence
 0:19        move second child to first child (temp 4-component vector of float)
 0:?           '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
 0:19          vector-scale (temp 4-component vector of float)
 0:19            vector-scale (temp 4-component vector of float)
-0:19              fragCoord: direct index for structure (temp 4-component vector of float)
-0:19                'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float fragCoord, temp 2-component vector of int i2})
+0:19              fragCoord: direct index for structure (temp 4-component vector of float FragCoord)
+0:19                'local' (temp structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 0:19                Constant:
 0:19                  1 (const int)
 0:19              'ret1' (temp float)
@@ -187,18 +113,16 @@
 0:19        Branch: Return
 0:?   Linker Objects
 0:?     '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
-0:?     'v' (layout(location=0 ) in 2-component vector of float)
-0:?     'fragCoord' (in 4-component vector of float FragCoord)
-0:?     'i2' (layout(location=1 ) in 2-component vector of int)
+0:?     'i' (layout(location=0 ) in structure{temp 2-component vector of float v, temp 4-component vector of float FragCoord fragCoord, temp 2-component vector of int i2})
 
 // Module Version 10000
 // Generated by (magic number): 80001
-// Id's are bound by 71
+// Id's are bound by 52
 
                               Capability Shader
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint Fragment 4  "PixelShaderFunction" 32 37 43 63
+                              EntryPoint Fragment 4  "PixelShaderFunction" 32 43
                               ExecutionMode 4 OriginUpperLeft
                               Name 4  "PixelShaderFunction"
                               Name 11  "InParam"
@@ -208,19 +132,15 @@
                               Name 15  "fun(struct-InParam-vf2-vf4-vi21;"
                               Name 14  "p"
                               Name 30  "local"
-                              Name 32  "v"
-                              Name 37  "fragCoord"
-                              Name 43  "i2"
-                              Name 47  "ret1"
-                              Name 48  "param"
-                              Name 51  "ret2"
-                              Name 52  "aggShadow"
-                              Name 59  "param"
-                              Name 63  "@entryPointOutput"
-                              Decorate 32(v) Location 0
-                              Decorate 37(fragCoord) BuiltIn FragCoord
-                              Decorate 43(i2) Location 1
-                              Decorate 63(@entryPointOutput) Location 0
+                              Name 32  "i"
+                              Name 34  "ret1"
+                              Name 35  "param"
+                              Name 38  "ret2"
+                              Name 39  "param"
+                              Name 43  "@entryPointOutput"
+                              MemberDecorate 11(InParam) 1 BuiltIn FragCoord
+                              Decorate 32(i) Location 0
+                              Decorate 43(@entryPointOutput) Location 0
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeFloat 32
@@ -237,59 +157,35 @@
               20:             TypePointer Function 6(float)
               23:      9(int) Constant 1
               24:     18(int) Constant 0
-              31:             TypePointer Input 7(fvec2)
-           32(v):     31(ptr) Variable Input
-              34:             TypePointer Function 7(fvec2)
-              36:             TypePointer Input 8(fvec4)
-   37(fragCoord):     36(ptr) Variable Input
-              39:             TypePointer Function 8(fvec4)
-              41:      9(int) Constant 2
-              42:             TypePointer Input 10(ivec2)
-          43(i2):     42(ptr) Variable Input
-              45:             TypePointer Function 10(ivec2)
-              62:             TypePointer Output 8(fvec4)
-63(@entryPointOutput):     62(ptr) Variable Output
+              31:             TypePointer Input 11(InParam)
+           32(i):     31(ptr) Variable Input
+              42:             TypePointer Output 8(fvec4)
+43(@entryPointOutput):     42(ptr) Variable Output
+              44:             TypePointer Function 8(fvec4)
 4(PixelShaderFunction):           2 Function None 3
                5:             Label
        30(local):     12(ptr) Variable Function
-        47(ret1):     20(ptr) Variable Function
-       48(param):     12(ptr) Variable Function
-        51(ret2):     20(ptr) Variable Function
-   52(aggShadow):     12(ptr) Variable Function
-       59(param):     12(ptr) Variable Function
-              33:    7(fvec2) Load 32(v)
-              35:     34(ptr) AccessChain 30(local) 17
-                              Store 35 33
-              38:    8(fvec4) Load 37(fragCoord)
-              40:     39(ptr) AccessChain 30(local) 23
-                              Store 40 38
-              44:   10(ivec2) Load 43(i2)
-              46:     45(ptr) AccessChain 30(local) 41
-                              Store 46 44
-              49: 11(InParam) Load 30(local)
-                              Store 48(param) 49
-              50:    6(float) FunctionCall 15(fun(struct-InParam-vf2-vf4-vi21;) 48(param)
-                              Store 47(ret1) 50
-              53:    7(fvec2) Load 32(v)
-              54:     34(ptr) AccessChain 52(aggShadow) 17
-                              Store 54 53
-              55:    8(fvec4) Load 37(fragCoord)
-              56:     39(ptr) AccessChain 52(aggShadow) 23
-                              Store 56 55
-              57:   10(ivec2) Load 43(i2)
-              58:     45(ptr) AccessChain 52(aggShadow) 41
-                              Store 58 57
-              60: 11(InParam) Load 52(aggShadow)
-                              Store 59(param) 60
-              61:    6(float) FunctionCall 15(fun(struct-InParam-vf2-vf4-vi21;) 59(param)
-                              Store 51(ret2) 61
-              64:     39(ptr) AccessChain 30(local) 23
-              65:    8(fvec4) Load 64
-              66:    6(float) Load 47(ret1)
-              67:    8(fvec4) VectorTimesScalar 65 66
-              68:    6(float) Load 51(ret2)
-              69:    8(fvec4) VectorTimesScalar 67 68
-                              Store 63(@entryPointOutput) 69
+        34(ret1):     20(ptr) Variable Function
+       35(param):     12(ptr) Variable Function
+        38(ret2):     20(ptr) Variable Function
+       39(param):     12(ptr) Variable Function
+              33: 11(InParam) Load 32(i)
+                              Store 30(local) 33
+              36: 11(InParam) Load 30(local)
+                              Store 35(param) 36
+              37:    6(float) FunctionCall 15(fun(struct-InParam-vf2-vf4-vi21;) 35(param)
+                              Store 34(ret1) 37
+              40: 11(InParam) Load 32(i)
+                              Store 39(param) 40
+              41:    6(float) FunctionCall 15(fun(struct-InParam-vf2-vf4-vi21;) 39(param)
+                              Store 38(ret2) 41
+              45:     44(ptr) AccessChain 30(local) 23
+              46:    8(fvec4) Load 45
+              47:    6(float) Load 34(ret1)
+              48:    8(fvec4) VectorTimesScalar 46 47
+              49:    6(float) Load 38(ret2)
+              50:    8(fvec4) VectorTimesScalar 48 49
+                              Store 43(@entryPointOutput) 50
                               Return
                               FunctionEnd
 15(fun(struct-InParam-vf2-vf4-vi21;):    6(float) Function None 13
diff --git a/Test/baseResults/hlsl.gather.basic.dx10.vert.out b/Test/baseResults/hlsl.gather.basic.dx10.vert.out
index a893675..3226769 100644
--- a/Test/baseResults/hlsl.gather.basic.dx10.vert.out
+++ b/Test/baseResults/hlsl.gather.basic.dx10.vert.out
@@ -1,7 +1,7 @@
 hlsl.gather.basic.dx10.vert
 Shader version: 450
 0:? Sequence
-0:28  Function Definition: main( (temp structure{temp 4-component vector of float Pos})
+0:28  Function Definition: main( (temp structure{temp 4-component vector of float Position Pos})
 0:28    Function Parameters: 
 0:?     Sequence
 0:33      Sequence
@@ -87,7 +87,6 @@
 0:45                0 (const int)
 0:45        Branch: Return
 0:?   Linker Objects
-0:?     'Pos' (out 4-component vector of float Position)
 0:?     'g_sSamp' (layout(binding=0 ) uniform sampler)
 0:?     'g_sSamp2d' (uniform sampler)
 0:?     'g_tTex1df4a' (layout(binding=1 ) uniform texture1D)
@@ -103,6 +102,7 @@
 0:?     'g_tTexcdf4' (uniform textureCube)
 0:?     'g_tTexcdi4' (uniform itextureCube)
 0:?     'g_tTexcdu4' (uniform utextureCube)
+0:?     'Pos' (out 4-component vector of float Position)
 
 
 Linked vertex stage:
@@ -110,7 +110,7 @@
 
 Shader version: 450
 0:? Sequence
-0:28  Function Definition: main( (temp structure{temp 4-component vector of float Pos})
+0:28  Function Definition: main( (temp structure{temp 4-component vector of float Position Pos})
 0:28    Function Parameters: 
 0:?     Sequence
 0:33      Sequence
@@ -196,7 +196,6 @@
 0:45                0 (const int)
 0:45        Branch: Return
 0:?   Linker Objects
-0:?     'Pos' (out 4-component vector of float Position)
 0:?     'g_sSamp' (layout(binding=0 ) uniform sampler)
 0:?     'g_sSamp2d' (uniform sampler)
 0:?     'g_tTex1df4a' (layout(binding=1 ) uniform texture1D)
@@ -212,6 +211,7 @@
 0:?     'g_tTexcdf4' (uniform textureCube)
 0:?     'g_tTexcdi4' (uniform itextureCube)
 0:?     'g_tTexcdu4' (uniform utextureCube)
+0:?     'Pos' (out 4-component vector of float Position)
 
 // Module Version 10000
 // Generated by (magic number): 80001
diff --git a/Test/baseResults/hlsl.getdimensions.dx10.vert.out b/Test/baseResults/hlsl.getdimensions.dx10.vert.out
index c1c90f4..77316b1 100644
--- a/Test/baseResults/hlsl.getdimensions.dx10.vert.out
+++ b/Test/baseResults/hlsl.getdimensions.dx10.vert.out
@@ -1,7 +1,7 @@
 hlsl.getdimensions.dx10.vert
 Shader version: 450
 0:? Sequence
-0:11  Function Definition: main( (temp structure{temp 4-component vector of float Pos})
+0:11  Function Definition: main( (temp structure{temp 4-component vector of float Position Pos})
 0:11    Function Parameters: 
 0:?     Sequence
 0:21      Sequence
@@ -46,9 +46,9 @@
 0:26                0 (const int)
 0:26        Branch: Return
 0:?   Linker Objects
-0:?     'Pos' (out 4-component vector of float Position)
 0:?     'g_sSamp' (layout(binding=0 ) uniform sampler)
 0:?     'g_tTex1df4' (layout(binding=0 ) uniform texture1D)
+0:?     'Pos' (out 4-component vector of float Position)
 
 
 Linked vertex stage:
@@ -56,7 +56,7 @@
 
 Shader version: 450
 0:? Sequence
-0:11  Function Definition: main( (temp structure{temp 4-component vector of float Pos})
+0:11  Function Definition: main( (temp structure{temp 4-component vector of float Position Pos})
 0:11    Function Parameters: 
 0:?     Sequence
 0:21      Sequence
@@ -101,9 +101,9 @@
 0:26                0 (const int)
 0:26        Branch: Return
 0:?   Linker Objects
-0:?     'Pos' (out 4-component vector of float Position)
 0:?     'g_sSamp' (layout(binding=0 ) uniform sampler)
 0:?     'g_tTex1df4' (layout(binding=0 ) uniform texture1D)
+0:?     'Pos' (out 4-component vector of float Position)
 
 // Module Version 10000
 // Generated by (magic number): 80001
diff --git a/Test/baseResults/hlsl.load.basic.dx10.vert.out b/Test/baseResults/hlsl.load.basic.dx10.vert.out
index a86f0ae..7441d49 100644
--- a/Test/baseResults/hlsl.load.basic.dx10.vert.out
+++ b/Test/baseResults/hlsl.load.basic.dx10.vert.out
@@ -1,7 +1,7 @@
 hlsl.load.basic.dx10.vert
 Shader version: 450
 0:? Sequence
-0:47  Function Definition: main( (temp structure{temp 4-component vector of float Pos})
+0:47  Function Definition: main( (temp structure{temp 4-component vector of float Position Pos})
 0:47    Function Parameters: 
 0:?     Sequence
 0:51      textureFetch (temp 4-component vector of float)
@@ -195,7 +195,6 @@
 0:69                0 (const int)
 0:69        Branch: Return
 0:?   Linker Objects
-0:?     'Pos' (out 4-component vector of float Position)
 0:?     'g_sSamp' (layout(binding=0 ) uniform sampler)
 0:?     'g_tTex1df4' (layout(binding=0 ) uniform texture1D)
 0:?     'g_tTex1di4' (uniform itexture1D)
@@ -219,6 +218,7 @@
 0:?     'g_tTexcdi4a' (uniform itextureCubeArray)
 0:?     'g_tTexcdu4a' (uniform utextureCubeArray)
 0:?     'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int c1, layout(offset=8 ) uniform 2-component vector of int c2, layout(offset=16 ) uniform 3-component vector of int c3, layout(offset=32 ) uniform 4-component vector of int c4, layout(offset=48 ) uniform int o1, layout(offset=56 ) uniform 2-component vector of int o2, layout(offset=64 ) uniform 3-component vector of int o3, layout(offset=80 ) uniform 4-component vector of int o4})
+0:?     'Pos' (out 4-component vector of float Position)
 
 
 Linked vertex stage:
@@ -226,7 +226,7 @@
 
 Shader version: 450
 0:? Sequence
-0:47  Function Definition: main( (temp structure{temp 4-component vector of float Pos})
+0:47  Function Definition: main( (temp structure{temp 4-component vector of float Position Pos})
 0:47    Function Parameters: 
 0:?     Sequence
 0:51      textureFetch (temp 4-component vector of float)
@@ -420,7 +420,6 @@
 0:69                0 (const int)
 0:69        Branch: Return
 0:?   Linker Objects
-0:?     'Pos' (out 4-component vector of float Position)
 0:?     'g_sSamp' (layout(binding=0 ) uniform sampler)
 0:?     'g_tTex1df4' (layout(binding=0 ) uniform texture1D)
 0:?     'g_tTex1di4' (uniform itexture1D)
@@ -444,6 +443,7 @@
 0:?     'g_tTexcdi4a' (uniform itextureCubeArray)
 0:?     'g_tTexcdu4a' (uniform utextureCubeArray)
 0:?     'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform int c1, layout(offset=8 ) uniform 2-component vector of int c2, layout(offset=16 ) uniform 3-component vector of int c3, layout(offset=32 ) uniform 4-component vector of int c4, layout(offset=48 ) uniform int o1, layout(offset=56 ) uniform 2-component vector of int o2, layout(offset=64 ) uniform 3-component vector of int o3, layout(offset=80 ) uniform 4-component vector of int o4})
+0:?     'Pos' (out 4-component vector of float Position)
 
 // Module Version 10000
 // Generated by (magic number): 80001
diff --git a/Test/baseResults/hlsl.samplegrad.basic.dx10.vert.out b/Test/baseResults/hlsl.samplegrad.basic.dx10.vert.out
index f6d37c3..d7ea386 100644
--- a/Test/baseResults/hlsl.samplegrad.basic.dx10.vert.out
+++ b/Test/baseResults/hlsl.samplegrad.basic.dx10.vert.out
@@ -1,7 +1,7 @@
 hlsl.samplegrad.basic.dx10.vert
 Shader version: 450
 0:? Sequence
-0:27  Function Definition: main( (temp structure{temp 4-component vector of float Pos})
+0:27  Function Definition: main( (temp structure{temp 4-component vector of float Position Pos})
 0:27    Function Parameters: 
 0:?     Sequence
 0:30      Sequence
@@ -225,7 +225,6 @@
 0:48                0 (const int)
 0:48        Branch: Return
 0:?   Linker Objects
-0:?     'Pos' (out 4-component vector of float Position)
 0:?     'g_sSamp' (layout(binding=0 ) uniform sampler)
 0:?     'g_tTex1df4a' (layout(binding=1 ) uniform texture1D)
 0:?     'g_tTex1df4' (layout(binding=0 ) uniform texture1D)
@@ -240,6 +239,7 @@
 0:?     'g_tTexcdf4' (uniform textureCube)
 0:?     'g_tTexcdi4' (uniform itextureCube)
 0:?     'g_tTexcdu4' (uniform utextureCube)
+0:?     'Pos' (out 4-component vector of float Position)
 
 
 Linked vertex stage:
@@ -247,7 +247,7 @@
 
 Shader version: 450
 0:? Sequence
-0:27  Function Definition: main( (temp structure{temp 4-component vector of float Pos})
+0:27  Function Definition: main( (temp structure{temp 4-component vector of float Position Pos})
 0:27    Function Parameters: 
 0:?     Sequence
 0:30      Sequence
@@ -471,7 +471,6 @@
 0:48                0 (const int)
 0:48        Branch: Return
 0:?   Linker Objects
-0:?     'Pos' (out 4-component vector of float Position)
 0:?     'g_sSamp' (layout(binding=0 ) uniform sampler)
 0:?     'g_tTex1df4a' (layout(binding=1 ) uniform texture1D)
 0:?     'g_tTex1df4' (layout(binding=0 ) uniform texture1D)
@@ -486,6 +485,7 @@
 0:?     'g_tTexcdf4' (uniform textureCube)
 0:?     'g_tTexcdi4' (uniform itextureCube)
 0:?     'g_tTexcdu4' (uniform utextureCube)
+0:?     'Pos' (out 4-component vector of float Position)
 
 // Module Version 10000
 // Generated by (magic number): 80001
diff --git a/Test/baseResults/hlsl.samplelevel.basic.dx10.vert.out b/Test/baseResults/hlsl.samplelevel.basic.dx10.vert.out
index 04d0870..35a9ede 100644
--- a/Test/baseResults/hlsl.samplelevel.basic.dx10.vert.out
+++ b/Test/baseResults/hlsl.samplelevel.basic.dx10.vert.out
@@ -1,7 +1,7 @@
 hlsl.samplelevel.basic.dx10.vert
 Shader version: 450
 0:? Sequence
-0:27  Function Definition: main( (temp structure{temp 4-component vector of float Pos})
+0:27  Function Definition: main( (temp structure{temp 4-component vector of float Position Pos})
 0:27    Function Parameters: 
 0:?     Sequence
 0:30      Sequence
@@ -171,7 +171,6 @@
 0:48                0 (const int)
 0:48        Branch: Return
 0:?   Linker Objects
-0:?     'Pos' (out 4-component vector of float Position)
 0:?     'g_sSamp' (layout(binding=0 ) uniform sampler)
 0:?     'g_tTex1df4a' (layout(binding=1 ) uniform texture1D)
 0:?     'g_tTex1df4' (layout(binding=0 ) uniform texture1D)
@@ -186,6 +185,7 @@
 0:?     'g_tTexcdf4' (uniform textureCube)
 0:?     'g_tTexcdi4' (uniform itextureCube)
 0:?     'g_tTexcdu4' (uniform utextureCube)
+0:?     'Pos' (out 4-component vector of float Position)
 
 
 Linked vertex stage:
@@ -193,7 +193,7 @@
 
 Shader version: 450
 0:? Sequence
-0:27  Function Definition: main( (temp structure{temp 4-component vector of float Pos})
+0:27  Function Definition: main( (temp structure{temp 4-component vector of float Position Pos})
 0:27    Function Parameters: 
 0:?     Sequence
 0:30      Sequence
@@ -363,7 +363,6 @@
 0:48                0 (const int)
 0:48        Branch: Return
 0:?   Linker Objects
-0:?     'Pos' (out 4-component vector of float Position)
 0:?     'g_sSamp' (layout(binding=0 ) uniform sampler)
 0:?     'g_tTex1df4a' (layout(binding=1 ) uniform texture1D)
 0:?     'g_tTex1df4' (layout(binding=0 ) uniform texture1D)
@@ -378,6 +377,7 @@
 0:?     'g_tTexcdf4' (uniform textureCube)
 0:?     'g_tTexcdi4' (uniform itextureCube)
 0:?     'g_tTexcdu4' (uniform utextureCube)
+0:?     'Pos' (out 4-component vector of float Position)
 
 // Module Version 10000
 // Generated by (magic number): 80001
diff --git a/Test/baseResults/hlsl.struct.frag.out b/Test/baseResults/hlsl.struct.frag.out
index c14018e..e2b2f72 100755
--- a/Test/baseResults/hlsl.struct.frag.out
+++ b/Test/baseResults/hlsl.struct.frag.out
@@ -9,7 +9,7 @@
 0:34  Function Definition: PixelShaderFunction(vf4;struct-IN_S-vf4-b1-vf1-vf2-b1-b1-b1-vf41; (temp 4-component vector of float)
 0:34    Function Parameters: 
 0:34      'input' (layout(location=0 ) in 4-component vector of float)
-0:34      's' (in structure{temp 4-component vector of float a, temp bool b, temp 1-component vector of float c, temp 2-component vector of float d, temp bool ff1, temp bool ff2, temp bool ff3, temp 4-component vector of float ff4})
+0:34      's' (layout(location=1 ) in structure{smooth temp 4-component vector of float a, flat temp bool b, centroid noperspective temp 1-component vector of float c, centroid sample temp 2-component vector of float d, temp bool Face ff1, layout(offset=4 ) temp bool ff2, layout(binding=0 offset=4 ) temp bool ff3, layout(binding=0 offset=4 ) temp 4-component vector of float ff4})
 0:?     Sequence
 0:39      Compare Equal (temp bool)
 0:39        's3' (temp structure{temp 3-component vector of bool b3})
@@ -19,7 +19,10 @@
 0:40          's2' (global structure{temp 4-component vector of float i})
 0:40          Constant:
 0:40            0 (const int)
-0:?         'ff4' (layout(location=7 binding=0 offset=4 ) in 4-component vector of float)
+0:40        ff4: direct index for structure (layout(binding=0 offset=4 ) temp 4-component vector of float)
+0:40          's' (layout(location=1 ) in structure{smooth temp 4-component vector of float a, flat temp bool b, centroid noperspective temp 1-component vector of float c, centroid sample temp 2-component vector of float d, temp bool Face ff1, layout(offset=4 ) temp bool ff2, layout(binding=0 offset=4 ) temp bool ff3, layout(binding=0 offset=4 ) temp 4-component vector of float ff4})
+0:40          Constant:
+0:40            7 (const int)
 0:42      Sequence
 0:42        move second child to first child (temp 4-component vector of float)
 0:?           '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
@@ -28,14 +31,7 @@
 0:?   Linker Objects
 0:?     '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
 0:?     'input' (layout(location=0 ) in 4-component vector of float)
-0:?     'a' (layout(location=1 ) smooth in 4-component vector of float)
-0:?     'b' (layout(location=2 ) flat in bool)
-0:?     'c' (layout(location=3 ) centroid noperspective in 1-component vector of float)
-0:?     'd' (layout(location=4 ) centroid sample in 2-component vector of float)
-0:?     'ff1' (in bool Face)
-0:?     'ff2' (layout(location=5 offset=4 ) in bool)
-0:?     'ff3' (layout(location=6 binding=0 offset=4 ) in bool)
-0:?     'ff4' (layout(location=7 binding=0 offset=4 ) in 4-component vector of float)
+0:?     's' (layout(location=1 ) in structure{smooth temp 4-component vector of float a, flat temp bool b, centroid noperspective temp 1-component vector of float c, centroid sample temp 2-component vector of float d, temp bool Face ff1, layout(offset=4 ) temp bool ff2, layout(binding=0 offset=4 ) temp bool ff3, layout(binding=0 offset=4 ) temp 4-component vector of float ff4})
 0:?     's2' (global structure{temp 4-component vector of float i})
 0:?     'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform structure{temp bool b, temp bool c, temp 4-component vector of float a, temp 4-component vector of float d} s1, layout(binding=5 offset=1620 ) uniform float ff5, layout(binding=8 offset=1636 ) uniform float ff6})
 
@@ -49,7 +45,7 @@
 0:34  Function Definition: PixelShaderFunction(vf4;struct-IN_S-vf4-b1-vf1-vf2-b1-b1-b1-vf41; (temp 4-component vector of float)
 0:34    Function Parameters: 
 0:34      'input' (layout(location=0 ) in 4-component vector of float)
-0:34      's' (in structure{temp 4-component vector of float a, temp bool b, temp 1-component vector of float c, temp 2-component vector of float d, temp bool ff1, temp bool ff2, temp bool ff3, temp 4-component vector of float ff4})
+0:34      's' (layout(location=1 ) in structure{smooth temp 4-component vector of float a, flat temp bool b, centroid noperspective temp 1-component vector of float c, centroid sample temp 2-component vector of float d, temp bool Face ff1, layout(offset=4 ) temp bool ff2, layout(binding=0 offset=4 ) temp bool ff3, layout(binding=0 offset=4 ) temp 4-component vector of float ff4})
 0:?     Sequence
 0:39      Compare Equal (temp bool)
 0:39        's3' (temp structure{temp 3-component vector of bool b3})
@@ -59,7 +55,10 @@
 0:40          's2' (global structure{temp 4-component vector of float i})
 0:40          Constant:
 0:40            0 (const int)
-0:?         'ff4' (layout(location=7 binding=0 offset=4 ) in 4-component vector of float)
+0:40        ff4: direct index for structure (layout(binding=0 offset=4 ) temp 4-component vector of float)
+0:40          's' (layout(location=1 ) in structure{smooth temp 4-component vector of float a, flat temp bool b, centroid noperspective temp 1-component vector of float c, centroid sample temp 2-component vector of float d, temp bool Face ff1, layout(offset=4 ) temp bool ff2, layout(binding=0 offset=4 ) temp bool ff3, layout(binding=0 offset=4 ) temp 4-component vector of float ff4})
+0:40          Constant:
+0:40            7 (const int)
 0:42      Sequence
 0:42        move second child to first child (temp 4-component vector of float)
 0:?           '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
@@ -68,25 +67,18 @@
 0:?   Linker Objects
 0:?     '@entryPointOutput' (layout(location=0 ) out 4-component vector of float)
 0:?     'input' (layout(location=0 ) in 4-component vector of float)
-0:?     'a' (layout(location=1 ) smooth in 4-component vector of float)
-0:?     'b' (layout(location=2 ) flat in bool)
-0:?     'c' (layout(location=3 ) centroid noperspective in 1-component vector of float)
-0:?     'd' (layout(location=4 ) centroid sample in 2-component vector of float)
-0:?     'ff1' (in bool Face)
-0:?     'ff2' (layout(location=5 offset=4 ) in bool)
-0:?     'ff3' (layout(location=6 binding=0 offset=4 ) in bool)
-0:?     'ff4' (layout(location=7 binding=0 offset=4 ) in 4-component vector of float)
+0:?     's' (layout(location=1 ) in structure{smooth temp 4-component vector of float a, flat temp bool b, centroid noperspective temp 1-component vector of float c, centroid sample temp 2-component vector of float d, temp bool Face ff1, layout(offset=4 ) temp bool ff2, layout(binding=0 offset=4 ) temp bool ff3, layout(binding=0 offset=4 ) temp 4-component vector of float ff4})
 0:?     's2' (global structure{temp 4-component vector of float i})
 0:?     'anon@0' (layout(row_major std140 ) uniform block{layout(offset=0 ) uniform structure{temp bool b, temp bool c, temp 4-component vector of float a, temp 4-component vector of float d} s1, layout(binding=5 offset=1620 ) uniform float ff5, layout(binding=8 offset=1636 ) uniform float ff6})
 
 // Module Version 10000
 // Generated by (magic number): 80001
-// Id's are bound by 50
+// Id's are bound by 44
 
                               Capability Shader
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint Fragment 4  "PixelShaderFunction" 25 30 31 34 36 38 41 42 43 44
+                              EntryPoint Fragment 4  "PixelShaderFunction" 27 35 36
                               ExecutionMode 4 OriginUpperLeft
                               Name 4  "PixelShaderFunction"
                               Name 8  "FS"
@@ -95,54 +87,41 @@
                               Name 19  ""
                               MemberName 19 0  "i"
                               Name 21  "s2"
-                              Name 25  "ff4"
-                              Name 30  "@entryPointOutput"
-                              Name 31  "input"
-                              Name 34  "a"
-                              Name 36  "b"
-                              Name 38  "c"
-                              Name 41  "d"
-                              Name 42  "ff1"
-                              Name 43  "ff2"
-                              Name 44  "ff3"
-                              Name 46  "myS"
-                              MemberName 46(myS) 0  "b"
-                              MemberName 46(myS) 1  "c"
-                              MemberName 46(myS) 2  "a"
-                              MemberName 46(myS) 3  "d"
-                              Name 47  "$Global"
-                              MemberName 47($Global) 0  "s1"
-                              MemberName 47($Global) 1  "ff5"
-                              MemberName 47($Global) 2  "ff6"
-                              Name 49  ""
-                              Decorate 25(ff4) Offset 4
-                              Decorate 25(ff4) Location 7
-                              Decorate 25(ff4) Binding 0
-                              Decorate 30(@entryPointOutput) Location 0
-                              Decorate 31(input) Location 0
-                              Decorate 34(a) Location 1
-                              Decorate 36(b) Flat
-                              Decorate 36(b) Location 2
-                              Decorate 38(c) NoPerspective
-                              Decorate 38(c) Centroid
-                              Decorate 38(c) Location 3
-                              Decorate 41(d) Centroid
-                              Decorate 41(d) Location 4
-                              Decorate 42(ff1) BuiltIn FrontFacing
-                              Decorate 43(ff2) Offset 4
-                              Decorate 43(ff2) Location 5
-                              Decorate 44(ff3) Offset 4
-                              Decorate 44(ff3) Location 6
-                              Decorate 44(ff3) Binding 0
-                              MemberDecorate 46(myS) 0 Offset 0
-                              MemberDecorate 46(myS) 1 Offset 4
-                              MemberDecorate 46(myS) 2 Offset 16
-                              MemberDecorate 46(myS) 3 Offset 32
-                              MemberDecorate 47($Global) 0 Offset 0
-                              MemberDecorate 47($Global) 1 Offset 1620
-                              MemberDecorate 47($Global) 2 Offset 1636
-                              Decorate 47($Global) Block
-                              Decorate 49 DescriptorSet 0
+                              Name 25  "IN_S"
+                              MemberName 25(IN_S) 0  "a"
+                              MemberName 25(IN_S) 1  "b"
+                              MemberName 25(IN_S) 2  "c"
+                              MemberName 25(IN_S) 3  "d"
+                              MemberName 25(IN_S) 4  "ff1"
+                              MemberName 25(IN_S) 5  "ff2"
+                              MemberName 25(IN_S) 6  "ff3"
+                              MemberName 25(IN_S) 7  "ff4"
+                              Name 27  "s"
+                              Name 35  "@entryPointOutput"
+                              Name 36  "input"
+                              Name 40  "myS"
+                              MemberName 40(myS) 0  "b"
+                              MemberName 40(myS) 1  "c"
+                              MemberName 40(myS) 2  "a"
+                              MemberName 40(myS) 3  "d"
+                              Name 41  "$Global"
+                              MemberName 41($Global) 0  "s1"
+                              MemberName 41($Global) 1  "ff5"
+                              MemberName 41($Global) 2  "ff6"
+                              Name 43  ""
+                              MemberDecorate 25(IN_S) 4 BuiltIn FrontFacing
+                              Decorate 27(s) Location 1
+                              Decorate 35(@entryPointOutput) Location 0
+                              Decorate 36(input) Location 0
+                              MemberDecorate 40(myS) 0 Offset 0
+                              MemberDecorate 40(myS) 1 Offset 4
+                              MemberDecorate 40(myS) 2 Offset 16
+                              MemberDecorate 40(myS) 3 Offset 32
+                              MemberDecorate 41($Global) 0 Offset 0
+                              MemberDecorate 41($Global) 1 Offset 1620
+                              MemberDecorate 41($Global) 2 Offset 1636
+                              Decorate 41($Global) Block
+                              Decorate 43 DescriptorSet 0
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeBool
@@ -156,28 +135,21 @@
           21(s2):     20(ptr) Variable Private
               22:             TypeInt 32 1
               23:     22(int) Constant 0
-              24:             TypePointer Input 18(fvec4)
-         25(ff4):     24(ptr) Variable Input
-              27:             TypePointer Private 18(fvec4)
-              29:             TypePointer Output 18(fvec4)
-30(@entryPointOutput):     29(ptr) Variable Output
-       31(input):     24(ptr) Variable Input
-           34(a):     24(ptr) Variable Input
-              35:             TypePointer Input 6(bool)
-           36(b):     35(ptr) Variable Input
-              37:             TypePointer Input 17(float)
-           38(c):     37(ptr) Variable Input
-              39:             TypeVector 17(float) 2
-              40:             TypePointer Input 39(fvec2)
-           41(d):     40(ptr) Variable Input
-         42(ff1):     35(ptr) Variable Input
-         43(ff2):     35(ptr) Variable Input
-         44(ff3):     35(ptr) Variable Input
-              45:             TypeInt 32 0
-         46(myS):             TypeStruct 45(int) 45(int) 18(fvec4) 18(fvec4)
-     47($Global):             TypeStruct 46(myS) 17(float) 17(float)
-              48:             TypePointer Uniform 47($Global)
-              49:     48(ptr) Variable Uniform
+              24:             TypeVector 17(float) 2
+        25(IN_S):             TypeStruct 18(fvec4) 6(bool) 17(float) 24(fvec2) 6(bool) 6(bool) 6(bool) 18(fvec4)
+              26:             TypePointer Input 25(IN_S)
+           27(s):     26(ptr) Variable Input
+              28:     22(int) Constant 7
+              29:             TypePointer Input 18(fvec4)
+              32:             TypePointer Private 18(fvec4)
+              34:             TypePointer Output 18(fvec4)
+35(@entryPointOutput):     34(ptr) Variable Output
+       36(input):     29(ptr) Variable Input
+              39:             TypeInt 32 0
+         40(myS):             TypeStruct 39(int) 39(int) 18(fvec4) 18(fvec4)
+     41($Global):             TypeStruct 40(myS) 17(float) 17(float)
+              42:             TypePointer Uniform 41($Global)
+              43:     42(ptr) Variable Uniform
 4(PixelShaderFunction):           2 Function None 3
                5:             Label
           10(s3):      9(ptr) Variable Function
@@ -187,10 +159,11 @@
               14:    7(bvec3) CompositeExtract 12 0
               15:    7(bvec3) LogicalEqual 13 14
               16:     6(bool) All 15
-              26:   18(fvec4) Load 25(ff4)
-              28:     27(ptr) AccessChain 21(s2) 23
-                              Store 28 26
-              32:   18(fvec4) Load 31(input)
-                              Store 30(@entryPointOutput) 32
+              30:     29(ptr) AccessChain 27(s) 28
+              31:   18(fvec4) Load 30
+              33:     32(ptr) AccessChain 21(s2) 23
+                              Store 33 31
+              37:   18(fvec4) Load 36(input)
+                              Store 35(@entryPointOutput) 37
                               Return
                               FunctionEnd
diff --git a/Test/baseResults/hlsl.struct.split-1.vert.out b/Test/baseResults/hlsl.struct.split-1.vert.out
new file mode 100644
index 0000000..62431ac
--- /dev/null
+++ b/Test/baseResults/hlsl.struct.split-1.vert.out
@@ -0,0 +1,209 @@
+hlsl.struct.split-1.vert
+Shader version: 450
+0:? Sequence
+0:17  Function Definition: main(struct-VS_INPUT-i1-vf4-i11;vf4; (temp structure{temp int x0_out, temp 4-component vector of float Position Pos_out, temp int x1_out})
+0:17    Function Parameters: 
+0:17      'vsin' (in structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:17      'Pos_loose' (in 4-component vector of float Position)
+0:?     Sequence
+0:20      move second child to first child (temp int)
+0:20        x0_out: direct index for structure (temp int)
+0:20          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:20          Constant:
+0:20            0 (const int)
+0:?         'x0_in' (layout(location=0 ) in int)
+0:21      move second child to first child (temp 4-component vector of float)
+0:21        Pos_out: direct index for structure (temp 4-component vector of float)
+0:21          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:21          Constant:
+0:21            1 (const int)
+0:21        add (temp 4-component vector of float)
+0:?           'Pos_in' (in 4-component vector of float Position)
+0:21          'Pos_loose' (in 4-component vector of float Position)
+0:22      move second child to first child (temp int)
+0:22        x1_out: direct index for structure (temp int)
+0:22          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:22          Constant:
+0:22            2 (const int)
+0:?         'x1_in' (layout(location=1 ) in int)
+0:24      Sequence
+0:24        Sequence
+0:24          move second child to first child (temp int)
+0:24            x0_out: direct index for structure (temp int)
+0:24              '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:24              Constant:
+0:24                0 (const int)
+0:24            x0_out: direct index for structure (temp int)
+0:24              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:24              Constant:
+0:24                0 (const int)
+0:24          move second child to first child (temp 4-component vector of float)
+0:?             'Pos_out' (out 4-component vector of float Position)
+0:24            Pos_out: direct index for structure (temp 4-component vector of float)
+0:24              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:24              Constant:
+0:24                1 (const int)
+0:24          move second child to first child (temp int)
+0:24            x1_out: direct index for structure (temp int)
+0:24              '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:24              Constant:
+0:24                1 (const int)
+0:24            x1_out: direct index for structure (temp int)
+0:24              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:24              Constant:
+0:24                2 (const int)
+0:24        Branch: Return
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:?     'x0_in' (layout(location=0 ) in int)
+0:?     'Pos_in' (in 4-component vector of float Position)
+0:?     'x1_in' (layout(location=1 ) in int)
+0:?     'Pos_loose' (in 4-component vector of float Position)
+0:?     'Pos_out' (out 4-component vector of float Position)
+
+
+Linked vertex stage:
+
+
+Shader version: 450
+0:? Sequence
+0:17  Function Definition: main(struct-VS_INPUT-i1-vf4-i11;vf4; (temp structure{temp int x0_out, temp 4-component vector of float Position Pos_out, temp int x1_out})
+0:17    Function Parameters: 
+0:17      'vsin' (in structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:17      'Pos_loose' (in 4-component vector of float Position)
+0:?     Sequence
+0:20      move second child to first child (temp int)
+0:20        x0_out: direct index for structure (temp int)
+0:20          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:20          Constant:
+0:20            0 (const int)
+0:?         'x0_in' (layout(location=0 ) in int)
+0:21      move second child to first child (temp 4-component vector of float)
+0:21        Pos_out: direct index for structure (temp 4-component vector of float)
+0:21          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:21          Constant:
+0:21            1 (const int)
+0:21        add (temp 4-component vector of float)
+0:?           'Pos_in' (in 4-component vector of float Position)
+0:21          'Pos_loose' (in 4-component vector of float Position)
+0:22      move second child to first child (temp int)
+0:22        x1_out: direct index for structure (temp int)
+0:22          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:22          Constant:
+0:22            2 (const int)
+0:?         'x1_in' (layout(location=1 ) in int)
+0:24      Sequence
+0:24        Sequence
+0:24          move second child to first child (temp int)
+0:24            x0_out: direct index for structure (temp int)
+0:24              '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:24              Constant:
+0:24                0 (const int)
+0:24            x0_out: direct index for structure (temp int)
+0:24              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:24              Constant:
+0:24                0 (const int)
+0:24          move second child to first child (temp 4-component vector of float)
+0:?             'Pos_out' (out 4-component vector of float Position)
+0:24            Pos_out: direct index for structure (temp 4-component vector of float)
+0:24              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:24              Constant:
+0:24                1 (const int)
+0:24          move second child to first child (temp int)
+0:24            x1_out: direct index for structure (temp int)
+0:24              '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:24              Constant:
+0:24                1 (const int)
+0:24            x1_out: direct index for structure (temp int)
+0:24              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:24              Constant:
+0:24                2 (const int)
+0:24        Branch: Return
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:?     'x0_in' (layout(location=0 ) in int)
+0:?     'Pos_in' (in 4-component vector of float Position)
+0:?     'x1_in' (layout(location=1 ) in int)
+0:?     'Pos_loose' (in 4-component vector of float Position)
+0:?     'Pos_out' (out 4-component vector of float Position)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 46
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Vertex 4  "main" 14 20 22 28 33 39
+                              Name 4  "main"
+                              Name 9  "VS_OUTPUT"
+                              MemberName 9(VS_OUTPUT) 0  "x0_out"
+                              MemberName 9(VS_OUTPUT) 1  "Pos_out"
+                              MemberName 9(VS_OUTPUT) 2  "x1_out"
+                              Name 11  "vsout"
+                              Name 14  "x0_in"
+                              Name 20  "Pos_in"
+                              Name 22  "Pos_loose"
+                              Name 28  "x1_in"
+                              Name 31  "VS_OUTPUT"
+                              MemberName 31(VS_OUTPUT) 0  "x0_out"
+                              MemberName 31(VS_OUTPUT) 1  "x1_out"
+                              Name 33  "@entryPointOutput"
+                              Name 39  "Pos_out"
+                              Decorate 14(x0_in) Location 0
+                              Decorate 20(Pos_in) BuiltIn Position
+                              Decorate 22(Pos_loose) BuiltIn Position
+                              Decorate 28(x1_in) Location 1
+                              Decorate 33(@entryPointOutput) Location 0
+                              Decorate 39(Pos_out) BuiltIn Position
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+               7:             TypeFloat 32
+               8:             TypeVector 7(float) 4
+    9(VS_OUTPUT):             TypeStruct 6(int) 8(fvec4) 6(int)
+              10:             TypePointer Function 9(VS_OUTPUT)
+              12:      6(int) Constant 0
+              13:             TypePointer Input 6(int)
+       14(x0_in):     13(ptr) Variable Input
+              16:             TypePointer Function 6(int)
+              18:      6(int) Constant 1
+              19:             TypePointer Input 8(fvec4)
+      20(Pos_in):     19(ptr) Variable Input
+   22(Pos_loose):     19(ptr) Variable Input
+              25:             TypePointer Function 8(fvec4)
+              27:      6(int) Constant 2
+       28(x1_in):     13(ptr) Variable Input
+   31(VS_OUTPUT):             TypeStruct 6(int) 6(int)
+              32:             TypePointer Output 31(VS_OUTPUT)
+33(@entryPointOutput):     32(ptr) Variable Output
+              36:             TypePointer Output 6(int)
+              38:             TypePointer Output 8(fvec4)
+     39(Pos_out):     38(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+       11(vsout):     10(ptr) Variable Function
+              15:      6(int) Load 14(x0_in)
+              17:     16(ptr) AccessChain 11(vsout) 12
+                              Store 17 15
+              21:    8(fvec4) Load 20(Pos_in)
+              23:    8(fvec4) Load 22(Pos_loose)
+              24:    8(fvec4) FAdd 21 23
+              26:     25(ptr) AccessChain 11(vsout) 18
+                              Store 26 24
+              29:      6(int) Load 28(x1_in)
+              30:     16(ptr) AccessChain 11(vsout) 27
+                              Store 30 29
+              34:     16(ptr) AccessChain 11(vsout) 12
+              35:      6(int) Load 34
+              37:     36(ptr) AccessChain 33(@entryPointOutput) 12
+                              Store 37 35
+              40:     25(ptr) AccessChain 11(vsout) 18
+              41:    8(fvec4) Load 40
+                              Store 39(Pos_out) 41
+              42:     16(ptr) AccessChain 11(vsout) 27
+              43:      6(int) Load 42
+              44:     36(ptr) AccessChain 33(@entryPointOutput) 18
+                              Store 44 43
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/hlsl.struct.split.array.geom.out b/Test/baseResults/hlsl.struct.split.array.geom.out
new file mode 100644
index 0000000..e8921b6
--- /dev/null
+++ b/Test/baseResults/hlsl.struct.split.array.geom.out
@@ -0,0 +1,295 @@
+hlsl.struct.split.array.geom
+Shader version: 450
+invocations = -1
+max_vertices = 4
+input primitive = points
+output primitive = triangle_strip
+0:? Sequence
+0:13  Function Definition: main(u1[1];struct-PSInput-vf4-vf2-vf3-u11; (temp void)
+0:13    Function Parameters: 
+0:13      'v' (layout(location=0 ) in 1-element array of uint)
+0:13      'OutputStream' (out structure{temp 4-component vector of float Position Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:?     Sequence
+0:16      Sequence
+0:16        move second child to first child (temp structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:16          'Out' (temp structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:16          Constant:
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0 (const uint)
+0:18      Sequence
+0:18        move second child to first child (temp int)
+0:18          'x' (temp int)
+0:18          Constant:
+0:18            0 (const int)
+0:18        Loop with condition tested first
+0:18          Loop Condition
+0:18          Compare Less Than (temp bool)
+0:18            'x' (temp int)
+0:18            Constant:
+0:18              2 (const int)
+0:18          Loop Body
+0:19          Sequence
+0:19            move second child to first child (temp int)
+0:19              'y' (temp int)
+0:19              Constant:
+0:19                0 (const int)
+0:19            Loop with condition tested first
+0:19              Loop Condition
+0:19              Compare Less Than (temp bool)
+0:19                'y' (temp int)
+0:19                Constant:
+0:19                  2 (const int)
+0:19              Loop Body
+0:20              move second child to first child (temp structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:20                indirect index (temp structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:20                  indirect index (temp 3-element array of structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:20                    'Verts' (temp 2-element array of 3-element array of structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:20                    'x' (temp int)
+0:20                  'y' (temp int)
+0:20                'Out' (temp structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:19              Loop Terminal Expression
+0:19              Pre-Increment (temp int)
+0:19                'y' (temp int)
+0:18          Loop Terminal Expression
+0:18          Pre-Increment (temp int)
+0:18            'x' (temp int)
+0:?   Linker Objects
+0:?     'v' (layout(location=0 ) in 1-element array of uint)
+0:?     'OutputStream' (layout(location=0 ) out structure{temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:?     'OutputStream.Pos' (out 4-component vector of float Position)
+
+
+Linked geometry stage:
+
+
+Shader version: 450
+invocations = 1
+max_vertices = 4
+input primitive = points
+output primitive = triangle_strip
+0:? Sequence
+0:13  Function Definition: main(u1[1];struct-PSInput-vf4-vf2-vf3-u11; (temp void)
+0:13    Function Parameters: 
+0:13      'v' (layout(location=0 ) in 1-element array of uint)
+0:13      'OutputStream' (out structure{temp 4-component vector of float Position Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:?     Sequence
+0:16      Sequence
+0:16        move second child to first child (temp structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:16          'Out' (temp structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:16          Constant:
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0.000000
+0:16            0 (const uint)
+0:18      Sequence
+0:18        move second child to first child (temp int)
+0:18          'x' (temp int)
+0:18          Constant:
+0:18            0 (const int)
+0:18        Loop with condition tested first
+0:18          Loop Condition
+0:18          Compare Less Than (temp bool)
+0:18            'x' (temp int)
+0:18            Constant:
+0:18              2 (const int)
+0:18          Loop Body
+0:19          Sequence
+0:19            move second child to first child (temp int)
+0:19              'y' (temp int)
+0:19              Constant:
+0:19                0 (const int)
+0:19            Loop with condition tested first
+0:19              Loop Condition
+0:19              Compare Less Than (temp bool)
+0:19                'y' (temp int)
+0:19                Constant:
+0:19                  2 (const int)
+0:19              Loop Body
+0:20              move second child to first child (temp structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:20                indirect index (temp structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:20                  indirect index (temp 3-element array of structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:20                    'Verts' (temp 2-element array of 3-element array of structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:20                    'x' (temp int)
+0:20                  'y' (temp int)
+0:20                'Out' (temp structure{temp 4-component vector of float Pos, temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:19              Loop Terminal Expression
+0:19              Pre-Increment (temp int)
+0:19                'y' (temp int)
+0:18          Loop Terminal Expression
+0:18          Pre-Increment (temp int)
+0:18            'x' (temp int)
+0:?   Linker Objects
+0:?     'v' (layout(location=0 ) in 1-element array of uint)
+0:?     'OutputStream' (layout(location=0 ) out structure{temp 2-component vector of float TexCoord, temp 3-component vector of float TerrainPos, temp uint VertexID})
+0:?     'OutputStream.Pos' (out 4-component vector of float Position)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 89
+
+                              Capability Geometry
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Geometry 4  "main" 83 86 88
+                              ExecutionMode 4 InputPoints
+                              ExecutionMode 4 Invocations 1
+                              ExecutionMode 4 OutputTriangleStrip
+                              ExecutionMode 4 OutputVertices 4
+                              Name 4  "main"
+                              Name 11  "PSInput"
+                              MemberName 11(PSInput) 0  "Pos"
+                              MemberName 11(PSInput) 1  "TexCoord"
+                              MemberName 11(PSInput) 2  "TerrainPos"
+                              MemberName 11(PSInput) 3  "VertexID"
+                              Name 13  "Out"
+                              Name 14  "PSInput"
+                              MemberName 14(PSInput) 0  "Pos"
+                              MemberName 14(PSInput) 1  "TexCoord"
+                              MemberName 14(PSInput) 2  "TerrainPos"
+                              MemberName 14(PSInput) 3  "VertexID"
+                              Name 39  "x"
+                              Name 48  "y"
+                              Name 56  "PSInput"
+                              MemberName 56(PSInput) 0  "Pos"
+                              MemberName 56(PSInput) 1  "TexCoord"
+                              MemberName 56(PSInput) 2  "TerrainPos"
+                              MemberName 56(PSInput) 3  "VertexID"
+                              Name 62  "Verts"
+                              Name 83  "v"
+                              Name 84  "PSInput"
+                              MemberName 84(PSInput) 0  "TexCoord"
+                              MemberName 84(PSInput) 1  "TerrainPos"
+                              MemberName 84(PSInput) 2  "VertexID"
+                              Name 86  "OutputStream"
+                              Name 88  "OutputStream.Pos"
+                              MemberDecorate 14(PSInput) 0 BuiltIn Position
+                              Decorate 83(v) Location 0
+                              Decorate 86(OutputStream) Location 0
+                              Decorate 88(OutputStream.Pos) BuiltIn Position
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeVector 6(float) 2
+               9:             TypeVector 6(float) 3
+              10:             TypeInt 32 0
+     11(PSInput):             TypeStruct 7(fvec4) 8(fvec2) 9(fvec3) 10(int)
+              12:             TypePointer Function 11(PSInput)
+     14(PSInput):             TypeStruct 7(fvec4) 8(fvec2) 9(fvec3) 10(int)
+              15:    6(float) Constant 0
+              16:    7(fvec4) ConstantComposite 15 15 15 15
+              17:    8(fvec2) ConstantComposite 15 15
+              18:    9(fvec3) ConstantComposite 15 15 15
+              19:     10(int) Constant 0
+              20: 14(PSInput) ConstantComposite 16 17 18 19
+              22:             TypeInt 32 1
+              23:     22(int) Constant 0
+              24:             TypePointer Function 7(fvec4)
+              27:     22(int) Constant 1
+              28:             TypePointer Function 8(fvec2)
+              31:     22(int) Constant 2
+              32:             TypePointer Function 9(fvec3)
+              35:     22(int) Constant 3
+              36:             TypePointer Function 10(int)
+              38:             TypePointer Function 22(int)
+              46:             TypeBool
+     56(PSInput):             TypeStruct 7(fvec4) 8(fvec2) 9(fvec3) 10(int)
+              57:     10(int) Constant 3
+              58:             TypeArray 56(PSInput) 57
+              59:     10(int) Constant 2
+              60:             TypeArray 58 59
+              61:             TypePointer Function 60
+              66:             TypePointer Function 56(PSInput)
+              80:     10(int) Constant 1
+              81:             TypeArray 10(int) 80
+              82:             TypePointer Input 81
+           83(v):     82(ptr) Variable Input
+     84(PSInput):             TypeStruct 8(fvec2) 9(fvec3) 10(int)
+              85:             TypePointer Output 84(PSInput)
+86(OutputStream):     85(ptr) Variable Output
+              87:             TypePointer Output 7(fvec4)
+88(OutputStream.Pos):     87(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+         13(Out):     12(ptr) Variable Function
+           39(x):     38(ptr) Variable Function
+           48(y):     38(ptr) Variable Function
+       62(Verts):     61(ptr) Variable Function
+              21:    7(fvec4) CompositeExtract 20 0
+              25:     24(ptr) AccessChain 13(Out) 23
+                              Store 25 21
+              26:    8(fvec2) CompositeExtract 20 1
+              29:     28(ptr) AccessChain 13(Out) 27
+                              Store 29 26
+              30:    9(fvec3) CompositeExtract 20 2
+              33:     32(ptr) AccessChain 13(Out) 31
+                              Store 33 30
+              34:     10(int) CompositeExtract 20 3
+              37:     36(ptr) AccessChain 13(Out) 35
+                              Store 37 34
+                              Store 39(x) 23
+                              Branch 40
+              40:             Label
+                              LoopMerge 42 43 None
+                              Branch 44
+              44:             Label
+              45:     22(int) Load 39(x)
+              47:    46(bool) SLessThan 45 31
+                              BranchConditional 47 41 42
+              41:               Label
+                                Store 48(y) 23
+                                Branch 49
+              49:               Label
+                                LoopMerge 51 52 None
+                                Branch 53
+              53:               Label
+              54:     22(int)   Load 48(y)
+              55:    46(bool)   SLessThan 54 31
+                                BranchConditional 55 50 51
+              50:                 Label
+              63:     22(int)     Load 39(x)
+              64:     22(int)     Load 48(y)
+              65: 11(PSInput)     Load 13(Out)
+              67:     66(ptr)     AccessChain 62(Verts) 63 64
+              68:    7(fvec4)     CompositeExtract 65 0
+              69:     24(ptr)     AccessChain 67 23
+                                  Store 69 68
+              70:    8(fvec2)     CompositeExtract 65 1
+              71:     28(ptr)     AccessChain 67 27
+                                  Store 71 70
+              72:    9(fvec3)     CompositeExtract 65 2
+              73:     32(ptr)     AccessChain 67 31
+                                  Store 73 72
+              74:     10(int)     CompositeExtract 65 3
+              75:     36(ptr)     AccessChain 67 35
+                                  Store 75 74
+                                  Branch 52
+              52:                 Label
+              76:     22(int)     Load 48(y)
+              77:     22(int)     IAdd 76 27
+                                  Store 48(y) 77
+                                  Branch 49
+              51:               Label
+                                Branch 43
+              43:               Label
+              78:     22(int)   Load 39(x)
+              79:     22(int)   IAdd 78 27
+                                Store 39(x) 79
+                                Branch 40
+              42:             Label
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/hlsl.struct.split.call.vert.out b/Test/baseResults/hlsl.struct.split.call.vert.out
new file mode 100644
index 0000000..d7a19e4
--- /dev/null
+++ b/Test/baseResults/hlsl.struct.split.call.vert.out
@@ -0,0 +1,317 @@
+hlsl.struct.split.call.vert
+Shader version: 450
+0:? Sequence
+0:17  Function Definition: Fn1(struct-VS_INPUT-i1-vf4-i11;struct-VS_OUTPUT-i1-vf4-i11; (temp void)
+0:17    Function Parameters: 
+0:17      'fn1_in' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:17      'fn1_out' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:?     Sequence
+0:18      add (temp 4-component vector of float)
+0:18        Pos_in: direct index for structure (temp 4-component vector of float)
+0:18          'fn1_in' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:18          Constant:
+0:18            1 (const int)
+0:18        Pos_out: direct index for structure (temp 4-component vector of float)
+0:18          'fn1_out' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:18          Constant:
+0:18            1 (const int)
+0:22  Function Definition: main(struct-VS_INPUT-i1-vf4-i11; (temp structure{temp int x0_out, temp 4-component vector of float Position Pos_out, temp int x1_out})
+0:22    Function Parameters: 
+0:22      'vsin' (in structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:?     Sequence
+0:25      move second child to first child (temp int)
+0:25        x0_out: direct index for structure (temp int)
+0:25          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:25          Constant:
+0:25            0 (const int)
+0:?         'x0_in' (layout(location=0 ) in int)
+0:26      move second child to first child (temp 4-component vector of float)
+0:26        Pos_out: direct index for structure (temp 4-component vector of float)
+0:26          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:26          Constant:
+0:26            1 (const int)
+0:?         'Pos_in' (in 4-component vector of float Position)
+0:27      move second child to first child (temp int)
+0:27        x1_out: direct index for structure (temp int)
+0:27          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:27          Constant:
+0:27            2 (const int)
+0:?         'x1_in' (layout(location=1 ) in int)
+0:29      Function Call: Fn1(struct-VS_INPUT-i1-vf4-i11;struct-VS_OUTPUT-i1-vf4-i11; (temp void)
+0:29        Comma (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:29          Sequence
+0:29            move second child to first child (temp int)
+0:29              x0_in: direct index for structure (temp int)
+0:29                'aggShadow' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:29                Constant:
+0:29                  0 (const int)
+0:?               'x0_in' (layout(location=0 ) in int)
+0:29            move second child to first child (temp 4-component vector of float)
+0:29              Pos_in: direct index for structure (temp 4-component vector of float)
+0:29                'aggShadow' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:29                Constant:
+0:29                  1 (const int)
+0:?               'Pos_in' (in 4-component vector of float Position)
+0:29            move second child to first child (temp int)
+0:29              x1_in: direct index for structure (temp int)
+0:29                'aggShadow' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:29                Constant:
+0:29                  2 (const int)
+0:?               'x1_in' (layout(location=1 ) in int)
+0:29          'aggShadow' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:29        'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:31      Sequence
+0:31        Sequence
+0:31          move second child to first child (temp int)
+0:31            x0_out: direct index for structure (temp int)
+0:31              '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:31              Constant:
+0:31                0 (const int)
+0:31            x0_out: direct index for structure (temp int)
+0:31              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:31              Constant:
+0:31                0 (const int)
+0:31          move second child to first child (temp 4-component vector of float)
+0:?             'Pos_out' (out 4-component vector of float Position)
+0:31            Pos_out: direct index for structure (temp 4-component vector of float)
+0:31              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:31              Constant:
+0:31                1 (const int)
+0:31          move second child to first child (temp int)
+0:31            x1_out: direct index for structure (temp int)
+0:31              '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:31              Constant:
+0:31                1 (const int)
+0:31            x1_out: direct index for structure (temp int)
+0:31              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:31              Constant:
+0:31                2 (const int)
+0:31        Branch: Return
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:?     'x0_in' (layout(location=0 ) in int)
+0:?     'Pos_in' (in 4-component vector of float Position)
+0:?     'x1_in' (layout(location=1 ) in int)
+0:?     'Pos_out' (out 4-component vector of float Position)
+
+
+Linked vertex stage:
+
+
+Shader version: 450
+0:? Sequence
+0:17  Function Definition: Fn1(struct-VS_INPUT-i1-vf4-i11;struct-VS_OUTPUT-i1-vf4-i11; (temp void)
+0:17    Function Parameters: 
+0:17      'fn1_in' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:17      'fn1_out' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:?     Sequence
+0:18      add (temp 4-component vector of float)
+0:18        Pos_in: direct index for structure (temp 4-component vector of float)
+0:18          'fn1_in' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:18          Constant:
+0:18            1 (const int)
+0:18        Pos_out: direct index for structure (temp 4-component vector of float)
+0:18          'fn1_out' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:18          Constant:
+0:18            1 (const int)
+0:22  Function Definition: main(struct-VS_INPUT-i1-vf4-i11; (temp structure{temp int x0_out, temp 4-component vector of float Position Pos_out, temp int x1_out})
+0:22    Function Parameters: 
+0:22      'vsin' (in structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:?     Sequence
+0:25      move second child to first child (temp int)
+0:25        x0_out: direct index for structure (temp int)
+0:25          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:25          Constant:
+0:25            0 (const int)
+0:?         'x0_in' (layout(location=0 ) in int)
+0:26      move second child to first child (temp 4-component vector of float)
+0:26        Pos_out: direct index for structure (temp 4-component vector of float)
+0:26          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:26          Constant:
+0:26            1 (const int)
+0:?         'Pos_in' (in 4-component vector of float Position)
+0:27      move second child to first child (temp int)
+0:27        x1_out: direct index for structure (temp int)
+0:27          'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:27          Constant:
+0:27            2 (const int)
+0:?         'x1_in' (layout(location=1 ) in int)
+0:29      Function Call: Fn1(struct-VS_INPUT-i1-vf4-i11;struct-VS_OUTPUT-i1-vf4-i11; (temp void)
+0:29        Comma (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:29          Sequence
+0:29            move second child to first child (temp int)
+0:29              x0_in: direct index for structure (temp int)
+0:29                'aggShadow' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:29                Constant:
+0:29                  0 (const int)
+0:?               'x0_in' (layout(location=0 ) in int)
+0:29            move second child to first child (temp 4-component vector of float)
+0:29              Pos_in: direct index for structure (temp 4-component vector of float)
+0:29                'aggShadow' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:29                Constant:
+0:29                  1 (const int)
+0:?               'Pos_in' (in 4-component vector of float Position)
+0:29            move second child to first child (temp int)
+0:29              x1_in: direct index for structure (temp int)
+0:29                'aggShadow' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:29                Constant:
+0:29                  2 (const int)
+0:?               'x1_in' (layout(location=1 ) in int)
+0:29          'aggShadow' (temp structure{temp int x0_in, temp 4-component vector of float Pos_in, temp int x1_in})
+0:29        'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:31      Sequence
+0:31        Sequence
+0:31          move second child to first child (temp int)
+0:31            x0_out: direct index for structure (temp int)
+0:31              '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:31              Constant:
+0:31                0 (const int)
+0:31            x0_out: direct index for structure (temp int)
+0:31              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:31              Constant:
+0:31                0 (const int)
+0:31          move second child to first child (temp 4-component vector of float)
+0:?             'Pos_out' (out 4-component vector of float Position)
+0:31            Pos_out: direct index for structure (temp 4-component vector of float)
+0:31              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:31              Constant:
+0:31                1 (const int)
+0:31          move second child to first child (temp int)
+0:31            x1_out: direct index for structure (temp int)
+0:31              '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:31              Constant:
+0:31                1 (const int)
+0:31            x1_out: direct index for structure (temp int)
+0:31              'vsout' (temp structure{temp int x0_out, temp 4-component vector of float Pos_out, temp int x1_out})
+0:31              Constant:
+0:31                2 (const int)
+0:31        Branch: Return
+0:?   Linker Objects
+0:?     '@entryPointOutput' (layout(location=0 ) out structure{temp int x0_out, temp int x1_out})
+0:?     'x0_in' (layout(location=0 ) in int)
+0:?     'Pos_in' (in 4-component vector of float Position)
+0:?     'x1_in' (layout(location=1 ) in int)
+0:?     'Pos_out' (out 4-component vector of float Position)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 69
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Vertex 4  "main" 28 33 37 56 62
+                              Name 4  "main"
+                              Name 9  "VS_INPUT"
+                              MemberName 9(VS_INPUT) 0  "x0_in"
+                              MemberName 9(VS_INPUT) 1  "Pos_in"
+                              MemberName 9(VS_INPUT) 2  "x1_in"
+                              Name 11  "VS_OUTPUT"
+                              MemberName 11(VS_OUTPUT) 0  "x0_out"
+                              MemberName 11(VS_OUTPUT) 1  "Pos_out"
+                              MemberName 11(VS_OUTPUT) 2  "x1_out"
+                              Name 16  "Fn1(struct-VS_INPUT-i1-vf4-i11;struct-VS_OUTPUT-i1-vf4-i11;"
+                              Name 14  "fn1_in"
+                              Name 15  "fn1_out"
+                              Name 25  "vsout"
+                              Name 28  "x0_in"
+                              Name 33  "Pos_in"
+                              Name 37  "x1_in"
+                              Name 40  "VS_INPUT"
+                              MemberName 40(VS_INPUT) 0  "x0_in"
+                              MemberName 40(VS_INPUT) 1  "Pos_in"
+                              MemberName 40(VS_INPUT) 2  "x1_in"
+                              Name 42  "aggShadow"
+                              Name 49  "param"
+                              Name 51  "param"
+                              Name 54  "VS_OUTPUT"
+                              MemberName 54(VS_OUTPUT) 0  "x0_out"
+                              MemberName 54(VS_OUTPUT) 1  "x1_out"
+                              Name 56  "@entryPointOutput"
+                              Name 62  "Pos_out"
+                              Decorate 28(x0_in) Location 0
+                              Decorate 33(Pos_in) BuiltIn Position
+                              Decorate 37(x1_in) Location 1
+                              Decorate 56(@entryPointOutput) Location 0
+                              Decorate 62(Pos_out) BuiltIn Position
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+               7:             TypeFloat 32
+               8:             TypeVector 7(float) 4
+     9(VS_INPUT):             TypeStruct 6(int) 8(fvec4) 6(int)
+              10:             TypePointer Function 9(VS_INPUT)
+   11(VS_OUTPUT):             TypeStruct 6(int) 8(fvec4) 6(int)
+              12:             TypePointer Function 11(VS_OUTPUT)
+              13:             TypeFunction 2 10(ptr) 12(ptr)
+              18:      6(int) Constant 1
+              19:             TypePointer Function 8(fvec4)
+              26:      6(int) Constant 0
+              27:             TypePointer Input 6(int)
+       28(x0_in):     27(ptr) Variable Input
+              30:             TypePointer Function 6(int)
+              32:             TypePointer Input 8(fvec4)
+      33(Pos_in):     32(ptr) Variable Input
+              36:      6(int) Constant 2
+       37(x1_in):     27(ptr) Variable Input
+    40(VS_INPUT):             TypeStruct 6(int) 8(fvec4) 6(int)
+              41:             TypePointer Function 40(VS_INPUT)
+   54(VS_OUTPUT):             TypeStruct 6(int) 6(int)
+              55:             TypePointer Output 54(VS_OUTPUT)
+56(@entryPointOutput):     55(ptr) Variable Output
+              59:             TypePointer Output 6(int)
+              61:             TypePointer Output 8(fvec4)
+     62(Pos_out):     61(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+       25(vsout):     12(ptr) Variable Function
+   42(aggShadow):     41(ptr) Variable Function
+       49(param):     41(ptr) Variable Function
+       51(param):     12(ptr) Variable Function
+              29:      6(int) Load 28(x0_in)
+              31:     30(ptr) AccessChain 25(vsout) 26
+                              Store 31 29
+              34:    8(fvec4) Load 33(Pos_in)
+              35:     19(ptr) AccessChain 25(vsout) 18
+                              Store 35 34
+              38:      6(int) Load 37(x1_in)
+              39:     30(ptr) AccessChain 25(vsout) 36
+                              Store 39 38
+              43:      6(int) Load 28(x0_in)
+              44:     30(ptr) AccessChain 42(aggShadow) 26
+                              Store 44 43
+              45:    8(fvec4) Load 33(Pos_in)
+              46:     19(ptr) AccessChain 42(aggShadow) 18
+                              Store 46 45
+              47:      6(int) Load 37(x1_in)
+              48:     30(ptr) AccessChain 42(aggShadow) 36
+                              Store 48 47
+              50:40(VS_INPUT) Load 42(aggShadow)
+                              Store 49(param) 50
+              52:11(VS_OUTPUT) Load 25(vsout)
+                              Store 51(param) 52
+              53:           2 FunctionCall 16(Fn1(struct-VS_INPUT-i1-vf4-i11;struct-VS_OUTPUT-i1-vf4-i11;) 49(param) 51(param)
+              57:     30(ptr) AccessChain 25(vsout) 26
+              58:      6(int) Load 57
+              60:     59(ptr) AccessChain 56(@entryPointOutput) 26
+                              Store 60 58
+              63:     19(ptr) AccessChain 25(vsout) 18
+              64:    8(fvec4) Load 63
+                              Store 62(Pos_out) 64
+              65:     30(ptr) AccessChain 25(vsout) 36
+              66:      6(int) Load 65
+              67:     59(ptr) AccessChain 56(@entryPointOutput) 18
+                              Store 67 66
+                              Return
+                              FunctionEnd
+16(Fn1(struct-VS_INPUT-i1-vf4-i11;struct-VS_OUTPUT-i1-vf4-i11;):           2 Function None 13
+      14(fn1_in):     10(ptr) FunctionParameter
+     15(fn1_out):     12(ptr) FunctionParameter
+              17:             Label
+              20:     19(ptr) AccessChain 14(fn1_in) 18
+              21:    8(fvec4) Load 20
+              22:     19(ptr) AccessChain 15(fn1_out) 18
+              23:    8(fvec4) Load 22
+              24:    8(fvec4) FAdd 21 23
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/hlsl.struct.split.nested.geom.out b/Test/baseResults/hlsl.struct.split.nested.geom.out
new file mode 100644
index 0000000..3dd8d9f
--- /dev/null
+++ b/Test/baseResults/hlsl.struct.split.nested.geom.out
@@ -0,0 +1,271 @@
+hlsl.struct.split.nested.geom
+Shader version: 450
+invocations = -1
+max_vertices = 3
+input primitive = triangles
+output primitive = triangle_strip
+0:? Sequence
+0:24  Function Definition: main(struct-PS_IN-vf4-vf21[3];struct-GS_OUT-struct-PS_IN-vf4-vf21-struct-STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO-f1[2]-i111; (temp void)
+0:24    Function Parameters: 
+0:24      'tin' (in 3-element array of structure{temp 4-component vector of float Position pos, temp 2-component vector of float tc})
+0:24      'ts' (out structure{temp structure{temp 4-component vector of float Position pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:?     Sequence
+0:27      move second child to first child (temp 4-component vector of float)
+0:27        pos: direct index for structure (temp 4-component vector of float)
+0:27          psIn: direct index for structure (temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc})
+0:27            'o' (temp structure{temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:27            Constant:
+0:27              0 (const int)
+0:27          Constant:
+0:27            0 (const int)
+0:?         Constant:
+0:?           1.000000
+0:?           2.000000
+0:?           3.000000
+0:?           4.000000
+0:28      move second child to first child (temp 2-component vector of float)
+0:28        tc: direct index for structure (temp 2-component vector of float)
+0:28          psIn: direct index for structure (temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc})
+0:28            'o' (temp structure{temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:28            Constant:
+0:28              0 (const int)
+0:28          Constant:
+0:28            1 (const int)
+0:?         Constant:
+0:?           5.000000
+0:?           6.000000
+0:30      Sequence
+0:30        Sequence
+0:30          move second child to first child (temp 4-component vector of float)
+0:?             'ts.psIn.pos' (out 4-component vector of float Position)
+0:30            pos: direct index for structure (temp 4-component vector of float)
+0:30              psIn: direct index for structure (temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc})
+0:30                'o' (temp structure{temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:30                Constant:
+0:30                  0 (const int)
+0:30              Constant:
+0:30                0 (const int)
+0:30          move second child to first child (temp 2-component vector of float)
+0:30            tc: direct index for structure (temp 2-component vector of float)
+0:30              psIn: direct index for structure (temp structure{temp 2-component vector of float tc})
+0:30                'ts' (layout(location=0 ) out structure{temp structure{temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:30                Constant:
+0:30                  0 (const int)
+0:30              Constant:
+0:30                0 (const int)
+0:30            tc: direct index for structure (temp 2-component vector of float)
+0:30              psIn: direct index for structure (temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc})
+0:30                'o' (temp structure{temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:30                Constant:
+0:30                  0 (const int)
+0:30              Constant:
+0:30                1 (const int)
+0:30          move second child to first child (temp structure{temp 2-element array of float m0_array, temp int m1})
+0:30            contains_no_builtin_io: direct index for structure (temp structure{temp 2-element array of float m0_array, temp int m1})
+0:30              'ts' (layout(location=0 ) out structure{temp structure{temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:30              Constant:
+0:30                1 (const int)
+0:30            contains_no_builtin_io: direct index for structure (temp structure{temp 2-element array of float m0_array, temp int m1})
+0:30              'o' (temp structure{temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:30              Constant:
+0:30                1 (const int)
+0:30        EmitVertex (temp void)
+0:?   Linker Objects
+0:?     'tin' (layout(location=0 ) in 3-element array of structure{temp 2-component vector of float tc})
+0:?     'ts' (layout(location=0 ) out structure{temp structure{temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:?     'tin.pos' (in 3-element array of 4-component vector of float Position)
+0:?     'ts.psIn.pos' (out 4-component vector of float Position)
+
+
+Linked geometry stage:
+
+
+Shader version: 450
+invocations = 1
+max_vertices = 3
+input primitive = triangles
+output primitive = triangle_strip
+0:? Sequence
+0:24  Function Definition: main(struct-PS_IN-vf4-vf21[3];struct-GS_OUT-struct-PS_IN-vf4-vf21-struct-STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO-f1[2]-i111; (temp void)
+0:24    Function Parameters: 
+0:24      'tin' (in 3-element array of structure{temp 4-component vector of float Position pos, temp 2-component vector of float tc})
+0:24      'ts' (out structure{temp structure{temp 4-component vector of float Position pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:?     Sequence
+0:27      move second child to first child (temp 4-component vector of float)
+0:27        pos: direct index for structure (temp 4-component vector of float)
+0:27          psIn: direct index for structure (temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc})
+0:27            'o' (temp structure{temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:27            Constant:
+0:27              0 (const int)
+0:27          Constant:
+0:27            0 (const int)
+0:?         Constant:
+0:?           1.000000
+0:?           2.000000
+0:?           3.000000
+0:?           4.000000
+0:28      move second child to first child (temp 2-component vector of float)
+0:28        tc: direct index for structure (temp 2-component vector of float)
+0:28          psIn: direct index for structure (temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc})
+0:28            'o' (temp structure{temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:28            Constant:
+0:28              0 (const int)
+0:28          Constant:
+0:28            1 (const int)
+0:?         Constant:
+0:?           5.000000
+0:?           6.000000
+0:30      Sequence
+0:30        Sequence
+0:30          move second child to first child (temp 4-component vector of float)
+0:?             'ts.psIn.pos' (out 4-component vector of float Position)
+0:30            pos: direct index for structure (temp 4-component vector of float)
+0:30              psIn: direct index for structure (temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc})
+0:30                'o' (temp structure{temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:30                Constant:
+0:30                  0 (const int)
+0:30              Constant:
+0:30                0 (const int)
+0:30          move second child to first child (temp 2-component vector of float)
+0:30            tc: direct index for structure (temp 2-component vector of float)
+0:30              psIn: direct index for structure (temp structure{temp 2-component vector of float tc})
+0:30                'ts' (layout(location=0 ) out structure{temp structure{temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:30                Constant:
+0:30                  0 (const int)
+0:30              Constant:
+0:30                0 (const int)
+0:30            tc: direct index for structure (temp 2-component vector of float)
+0:30              psIn: direct index for structure (temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc})
+0:30                'o' (temp structure{temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:30                Constant:
+0:30                  0 (const int)
+0:30              Constant:
+0:30                1 (const int)
+0:30          move second child to first child (temp structure{temp 2-element array of float m0_array, temp int m1})
+0:30            contains_no_builtin_io: direct index for structure (temp structure{temp 2-element array of float m0_array, temp int m1})
+0:30              'ts' (layout(location=0 ) out structure{temp structure{temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:30              Constant:
+0:30                1 (const int)
+0:30            contains_no_builtin_io: direct index for structure (temp structure{temp 2-element array of float m0_array, temp int m1})
+0:30              'o' (temp structure{temp structure{temp 4-component vector of float pos, temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:30              Constant:
+0:30                1 (const int)
+0:30        EmitVertex (temp void)
+0:?   Linker Objects
+0:?     'tin' (layout(location=0 ) in 3-element array of structure{temp 2-component vector of float tc})
+0:?     'ts' (layout(location=0 ) out structure{temp structure{temp 2-component vector of float tc} psIn, temp structure{temp 2-element array of float m0_array, temp int m1} contains_no_builtin_io})
+0:?     'tin.pos' (in 3-element array of 4-component vector of float Position)
+0:?     'ts.psIn.pos' (out 4-component vector of float Position)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 64
+
+                              Capability Geometry
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Geometry 4  "main" 33 40 60 63
+                              ExecutionMode 4 Triangles
+                              ExecutionMode 4 Invocations 1
+                              ExecutionMode 4 OutputTriangleStrip
+                              ExecutionMode 4 OutputVertices 3
+                              Name 4  "main"
+                              Name 9  "PS_IN"
+                              MemberName 9(PS_IN) 0  "pos"
+                              MemberName 9(PS_IN) 1  "tc"
+                              Name 14  "STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO"
+                              MemberName 14(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 0  "m0_array"
+                              MemberName 14(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 1  "m1"
+                              Name 15  "GS_OUT"
+                              MemberName 15(GS_OUT) 0  "psIn"
+                              MemberName 15(GS_OUT) 1  "contains_no_builtin_io"
+                              Name 17  "o"
+                              Name 33  "ts.psIn.pos"
+                              Name 36  "PS_IN"
+                              MemberName 36(PS_IN) 0  "tc"
+                              Name 37  "STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO"
+                              MemberName 37(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 0  "m0_array"
+                              MemberName 37(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) 1  "m1"
+                              Name 38  "GS_OUT"
+                              MemberName 38(GS_OUT) 0  "psIn"
+                              MemberName 38(GS_OUT) 1  "contains_no_builtin_io"
+                              Name 40  "ts"
+                              Name 56  "PS_IN"
+                              MemberName 56(PS_IN) 0  "tc"
+                              Name 60  "tin"
+                              Name 63  "tin.pos"
+                              Decorate 33(ts.psIn.pos) BuiltIn Position
+                              Decorate 40(ts) Location 0
+                              Decorate 60(tin) Location 0
+                              Decorate 63(tin.pos) BuiltIn Position
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeVector 6(float) 2
+        9(PS_IN):             TypeStruct 7(fvec4) 8(fvec2)
+              10:             TypeInt 32 0
+              11:     10(int) Constant 2
+              12:             TypeArray 6(float) 11
+              13:             TypeInt 32 1
+14(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO):             TypeStruct 12 13(int)
+      15(GS_OUT):             TypeStruct 9(PS_IN) 14(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO)
+              16:             TypePointer Function 15(GS_OUT)
+              18:     13(int) Constant 0
+              19:    6(float) Constant 1065353216
+              20:    6(float) Constant 1073741824
+              21:    6(float) Constant 1077936128
+              22:    6(float) Constant 1082130432
+              23:    7(fvec4) ConstantComposite 19 20 21 22
+              24:             TypePointer Function 7(fvec4)
+              26:     13(int) Constant 1
+              27:    6(float) Constant 1084227584
+              28:    6(float) Constant 1086324736
+              29:    8(fvec2) ConstantComposite 27 28
+              30:             TypePointer Function 8(fvec2)
+              32:             TypePointer Output 7(fvec4)
+ 33(ts.psIn.pos):     32(ptr) Variable Output
+       36(PS_IN):             TypeStruct 8(fvec2)
+37(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO):             TypeStruct 12 13(int)
+      38(GS_OUT):             TypeStruct 36(PS_IN) 37(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO)
+              39:             TypePointer Output 38(GS_OUT)
+          40(ts):     39(ptr) Variable Output
+              43:             TypePointer Output 8(fvec2)
+              45:             TypePointer Function 14(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO)
+              48:             TypePointer Output 37(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO)
+              51:             TypePointer Output 12
+              54:             TypePointer Output 13(int)
+       56(PS_IN):             TypeStruct 8(fvec2)
+              57:     10(int) Constant 3
+              58:             TypeArray 56(PS_IN) 57
+              59:             TypePointer Input 58
+         60(tin):     59(ptr) Variable Input
+              61:             TypeArray 7(fvec4) 57
+              62:             TypePointer Input 61
+     63(tin.pos):     62(ptr) Variable Input
+         4(main):           2 Function None 3
+               5:             Label
+           17(o):     16(ptr) Variable Function
+              25:     24(ptr) AccessChain 17(o) 18 18
+                              Store 25 23
+              31:     30(ptr) AccessChain 17(o) 18 26
+                              Store 31 29
+              34:     24(ptr) AccessChain 17(o) 18 18
+              35:    7(fvec4) Load 34
+                              Store 33(ts.psIn.pos) 35
+              41:     30(ptr) AccessChain 17(o) 18 26
+              42:    8(fvec2) Load 41
+              44:     43(ptr) AccessChain 40(ts) 18 18
+                              Store 44 42
+              46:     45(ptr) AccessChain 17(o) 26
+              47:14(STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO) Load 46
+              49:     48(ptr) AccessChain 40(ts) 26
+              50:          12 CompositeExtract 47 0
+              52:     51(ptr) AccessChain 49 18
+                              Store 52 50
+              53:     13(int) CompositeExtract 47 1
+              55:     54(ptr) AccessChain 49 26
+                              Store 55 53
+                              EmitVertex
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/hlsl.struct.split.trivial.geom.out b/Test/baseResults/hlsl.struct.split.trivial.geom.out
new file mode 100644
index 0000000..8448ac4
--- /dev/null
+++ b/Test/baseResults/hlsl.struct.split.trivial.geom.out
@@ -0,0 +1,175 @@
+hlsl.struct.split.trivial.geom
+Shader version: 450
+invocations = -1
+max_vertices = 3
+input primitive = triangles
+output primitive = triangle_strip
+0:? Sequence
+0:14  Function Definition: main(struct-PS_IN-vf41[3];struct-GS_OUT-vf41; (temp void)
+0:14    Function Parameters: 
+0:14      'i' (in 3-element array of structure{temp 4-component vector of float Position pos})
+0:14      'ts' (out structure{temp 4-component vector of float Position pos})
+0:?     Sequence
+0:17      Sequence
+0:17        move second child to first child (temp int)
+0:17          'x' (temp int)
+0:17          Constant:
+0:17            0 (const int)
+0:17        Loop with condition tested first
+0:17          Loop Condition
+0:17          Compare Less Than (temp bool)
+0:17            'x' (temp int)
+0:17            Constant:
+0:17              3 (const int)
+0:17          Loop Body
+0:?           Sequence
+0:18            move second child to first child (temp 4-component vector of float)
+0:18              pos: direct index for structure (temp 4-component vector of float)
+0:18                'o' (temp structure{temp 4-component vector of float pos})
+0:18                Constant:
+0:18                  0 (const int)
+0:18              indirect index (temp 4-component vector of float Position)
+0:18                'i.pos' (in 3-element array of 4-component vector of float Position)
+0:18                'x' (temp int)
+0:19            Sequence
+0:19              Sequence
+0:19                move second child to first child (temp 4-component vector of float)
+0:?                   'ts.pos' (out 4-component vector of float Position)
+0:19                  pos: direct index for structure (temp 4-component vector of float)
+0:19                    'o' (temp structure{temp 4-component vector of float pos})
+0:19                    Constant:
+0:19                      0 (const int)
+0:19              EmitVertex (temp void)
+0:17          Loop Terminal Expression
+0:17          Pre-Increment (temp int)
+0:17            'x' (temp int)
+0:?   Linker Objects
+0:?     'i.pos' (in 3-element array of 4-component vector of float Position)
+0:?     'ts.pos' (out 4-component vector of float Position)
+
+
+Linked geometry stage:
+
+
+Shader version: 450
+invocations = 1
+max_vertices = 3
+input primitive = triangles
+output primitive = triangle_strip
+0:? Sequence
+0:14  Function Definition: main(struct-PS_IN-vf41[3];struct-GS_OUT-vf41; (temp void)
+0:14    Function Parameters: 
+0:14      'i' (in 3-element array of structure{temp 4-component vector of float Position pos})
+0:14      'ts' (out structure{temp 4-component vector of float Position pos})
+0:?     Sequence
+0:17      Sequence
+0:17        move second child to first child (temp int)
+0:17          'x' (temp int)
+0:17          Constant:
+0:17            0 (const int)
+0:17        Loop with condition tested first
+0:17          Loop Condition
+0:17          Compare Less Than (temp bool)
+0:17            'x' (temp int)
+0:17            Constant:
+0:17              3 (const int)
+0:17          Loop Body
+0:?           Sequence
+0:18            move second child to first child (temp 4-component vector of float)
+0:18              pos: direct index for structure (temp 4-component vector of float)
+0:18                'o' (temp structure{temp 4-component vector of float pos})
+0:18                Constant:
+0:18                  0 (const int)
+0:18              indirect index (temp 4-component vector of float Position)
+0:18                'i.pos' (in 3-element array of 4-component vector of float Position)
+0:18                'x' (temp int)
+0:19            Sequence
+0:19              Sequence
+0:19                move second child to first child (temp 4-component vector of float)
+0:?                   'ts.pos' (out 4-component vector of float Position)
+0:19                  pos: direct index for structure (temp 4-component vector of float)
+0:19                    'o' (temp structure{temp 4-component vector of float pos})
+0:19                    Constant:
+0:19                      0 (const int)
+0:19              EmitVertex (temp void)
+0:17          Loop Terminal Expression
+0:17          Pre-Increment (temp int)
+0:17            'x' (temp int)
+0:?   Linker Objects
+0:?     'i.pos' (in 3-element array of 4-component vector of float Position)
+0:?     'ts.pos' (out 4-component vector of float Position)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 42
+
+                              Capability Geometry
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Geometry 4  "main" 28 36
+                              ExecutionMode 4 Triangles
+                              ExecutionMode 4 Invocations 1
+                              ExecutionMode 4 OutputTriangleStrip
+                              ExecutionMode 4 OutputVertices 3
+                              Name 4  "main"
+                              Name 8  "x"
+                              Name 21  "GS_OUT"
+                              MemberName 21(GS_OUT) 0  "pos"
+                              Name 23  "o"
+                              Name 28  "i.pos"
+                              Name 36  "ts.pos"
+                              Decorate 28(i.pos) BuiltIn Position
+                              Decorate 36(ts.pos) BuiltIn Position
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeInt 32 1
+               7:             TypePointer Function 6(int)
+               9:      6(int) Constant 0
+              16:      6(int) Constant 3
+              17:             TypeBool
+              19:             TypeFloat 32
+              20:             TypeVector 19(float) 4
+      21(GS_OUT):             TypeStruct 20(fvec4)
+              22:             TypePointer Function 21(GS_OUT)
+              24:             TypeInt 32 0
+              25:     24(int) Constant 3
+              26:             TypeArray 20(fvec4) 25
+              27:             TypePointer Input 26
+       28(i.pos):     27(ptr) Variable Input
+              30:             TypePointer Input 20(fvec4)
+              33:             TypePointer Function 20(fvec4)
+              35:             TypePointer Output 20(fvec4)
+      36(ts.pos):     35(ptr) Variable Output
+              40:      6(int) Constant 1
+         4(main):           2 Function None 3
+               5:             Label
+            8(x):      7(ptr) Variable Function
+           23(o):     22(ptr) Variable Function
+                              Store 8(x) 9
+                              Branch 10
+              10:             Label
+                              LoopMerge 12 13 None
+                              Branch 14
+              14:             Label
+              15:      6(int) Load 8(x)
+              18:    17(bool) SLessThan 15 16
+                              BranchConditional 18 11 12
+              11:               Label
+              29:      6(int)   Load 8(x)
+              31:     30(ptr)   AccessChain 28(i.pos) 29
+              32:   20(fvec4)   Load 31
+              34:     33(ptr)   AccessChain 23(o) 9
+                                Store 34 32
+              37:     33(ptr)   AccessChain 23(o) 9
+              38:   20(fvec4)   Load 37
+                                Store 36(ts.pos) 38
+                                EmitVertex
+                                Branch 13
+              13:               Label
+              39:      6(int)   Load 8(x)
+              41:      6(int)   IAdd 39 40
+                                Store 8(x) 41
+                                Branch 10
+              12:             Label
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/hlsl.struct.split.trivial.vert.out b/Test/baseResults/hlsl.struct.split.trivial.vert.out
new file mode 100644
index 0000000..bdf156c
--- /dev/null
+++ b/Test/baseResults/hlsl.struct.split.trivial.vert.out
@@ -0,0 +1,108 @@
+hlsl.struct.split.trivial.vert
+Shader version: 450
+0:? Sequence
+0:16  Function Definition: main(struct-VS_INPUT-vf41;vf4; (temp structure{temp 4-component vector of float Position Pos})
+0:16    Function Parameters: 
+0:16      'vsin' (in structure{temp 4-component vector of float Pos_in})
+0:16      'Pos_loose' (in 4-component vector of float Position)
+0:?     Sequence
+0:19      move second child to first child (temp 4-component vector of float)
+0:19        Pos: direct index for structure (temp 4-component vector of float)
+0:19          'vsout' (temp structure{temp 4-component vector of float Pos})
+0:19          Constant:
+0:19            0 (const int)
+0:19        add (temp 4-component vector of float)
+0:?           'Pos_in' (in 4-component vector of float Position)
+0:19          'Pos_loose' (in 4-component vector of float Position)
+0:21      Sequence
+0:21        Sequence
+0:21          move second child to first child (temp 4-component vector of float)
+0:?             'Pos' (out 4-component vector of float Position)
+0:21            Pos: direct index for structure (temp 4-component vector of float)
+0:21              'vsout' (temp structure{temp 4-component vector of float Pos})
+0:21              Constant:
+0:21                0 (const int)
+0:21        Branch: Return
+0:?   Linker Objects
+0:?     'Pos_in' (in 4-component vector of float Position)
+0:?     'Pos_loose' (in 4-component vector of float Position)
+0:?     'Pos' (out 4-component vector of float Position)
+
+
+Linked vertex stage:
+
+
+Shader version: 450
+0:? Sequence
+0:16  Function Definition: main(struct-VS_INPUT-vf41;vf4; (temp structure{temp 4-component vector of float Position Pos})
+0:16    Function Parameters: 
+0:16      'vsin' (in structure{temp 4-component vector of float Pos_in})
+0:16      'Pos_loose' (in 4-component vector of float Position)
+0:?     Sequence
+0:19      move second child to first child (temp 4-component vector of float)
+0:19        Pos: direct index for structure (temp 4-component vector of float)
+0:19          'vsout' (temp structure{temp 4-component vector of float Pos})
+0:19          Constant:
+0:19            0 (const int)
+0:19        add (temp 4-component vector of float)
+0:?           'Pos_in' (in 4-component vector of float Position)
+0:19          'Pos_loose' (in 4-component vector of float Position)
+0:21      Sequence
+0:21        Sequence
+0:21          move second child to first child (temp 4-component vector of float)
+0:?             'Pos' (out 4-component vector of float Position)
+0:21            Pos: direct index for structure (temp 4-component vector of float)
+0:21              'vsout' (temp structure{temp 4-component vector of float Pos})
+0:21              Constant:
+0:21                0 (const int)
+0:21        Branch: Return
+0:?   Linker Objects
+0:?     'Pos_in' (in 4-component vector of float Position)
+0:?     'Pos_loose' (in 4-component vector of float Position)
+0:?     'Pos' (out 4-component vector of float Position)
+
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 26
+
+                              Capability Shader
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Vertex 4  "main" 14 16 22
+                              Name 4  "main"
+                              Name 8  "VS_OUTPUT"
+                              MemberName 8(VS_OUTPUT) 0  "Pos"
+                              Name 10  "vsout"
+                              Name 14  "Pos_in"
+                              Name 16  "Pos_loose"
+                              Name 22  "Pos"
+                              Decorate 14(Pos_in) BuiltIn Position
+                              Decorate 16(Pos_loose) BuiltIn Position
+                              Decorate 22(Pos) BuiltIn Position
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+    8(VS_OUTPUT):             TypeStruct 7(fvec4)
+               9:             TypePointer Function 8(VS_OUTPUT)
+              11:             TypeInt 32 1
+              12:     11(int) Constant 0
+              13:             TypePointer Input 7(fvec4)
+      14(Pos_in):     13(ptr) Variable Input
+   16(Pos_loose):     13(ptr) Variable Input
+              19:             TypePointer Function 7(fvec4)
+              21:             TypePointer Output 7(fvec4)
+         22(Pos):     21(ptr) Variable Output
+         4(main):           2 Function None 3
+               5:             Label
+       10(vsout):      9(ptr) Variable Function
+              15:    7(fvec4) Load 14(Pos_in)
+              17:    7(fvec4) Load 16(Pos_loose)
+              18:    7(fvec4) FAdd 15 17
+              20:     19(ptr) AccessChain 10(vsout) 12
+                              Store 20 18
+              23:     19(ptr) AccessChain 10(vsout) 12
+              24:    7(fvec4) Load 23
+                              Store 22(Pos) 24
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/hlsl.structarray.flatten.geom.out b/Test/baseResults/hlsl.structarray.flatten.geom.out
index 0994af8..0922bae 100644
--- a/Test/baseResults/hlsl.structarray.flatten.geom.out
+++ b/Test/baseResults/hlsl.structarray.flatten.geom.out
@@ -1,52 +1,82 @@
 hlsl.structarray.flatten.geom
-ERROR: 0:10: 'vin' : recursive type not yet supported in GS input 
-ERROR: 1 compilation errors.  No code generated.
-
-
 Shader version: 450
 invocations = -1
 max_vertices = 4
 input primitive = lines
 output primitive = triangle_strip
-ERROR: node is still EOpNull!
-0:10  Function Definition: main(struct-VertexData-vf4-vf4-vf21[2];struct-VertexData-vf4-vf4-vf21; (temp void)
-0:10    Function Parameters: 
-0:10      'vin' (in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:10      'outStream' (out structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:? Sequence
+0:16  Function Definition: main(struct-VertexData-vf4-vf4-vf21[2];struct-PS_IN-vf4-vf4-vf21; (temp void)
+0:16    Function Parameters: 
+0:16      'vin' (layout(location=0 ) in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:16      'outStream' (out structure{temp 4-component vector of float Position position, temp 4-component vector of float color, temp 2-component vector of float uv})
 0:?     Sequence
-0:13      move second child to first child (temp 4-component vector of float)
-0:13        color: direct index for structure (temp 4-component vector of float)
-0:13          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:13          Constant:
-0:13            1 (const int)
-0:?         'vin[0].color' (layout(location=1 ) in 4-component vector of float)
-0:14      move second child to first child (temp 2-component vector of float)
-0:14        uv: direct index for structure (temp 2-component vector of float)
-0:14          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:14          Constant:
-0:14            2 (const int)
-0:?         'vin[0].uv' (layout(location=2 ) in 2-component vector of float)
-0:15      move second child to first child (temp 4-component vector of float)
-0:15        position: direct index for structure (temp 4-component vector of float)
-0:15          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:15          Constant:
-0:15            0 (const int)
-0:?         'vin[0].position' (layout(location=0 ) in 4-component vector of float)
-0:16      Sequence
-0:16        move second child to first child (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:16          'outStream' (out structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:16          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:16        EmitVertex (temp void)
+0:19      move second child to first child (temp 4-component vector of float)
+0:19        color: direct index for structure (temp 4-component vector of float)
+0:19          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:19          Constant:
+0:19            1 (const int)
+0:19        color: direct index for structure (temp 4-component vector of float)
+0:19          direct index (layout(location=0 ) temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:19            'vin' (layout(location=0 ) in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:19            Constant:
+0:19              1 (const int)
+0:19          Constant:
+0:19            1 (const int)
+0:20      move second child to first child (temp 2-component vector of float)
+0:20        uv: direct index for structure (temp 2-component vector of float)
+0:20          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:20          Constant:
+0:20            2 (const int)
+0:20        uv: direct index for structure (temp 2-component vector of float)
+0:20          direct index (layout(location=0 ) temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:20            'vin' (layout(location=0 ) in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:20            Constant:
+0:20              1 (const int)
+0:20          Constant:
+0:20            2 (const int)
+0:21      move second child to first child (temp 4-component vector of float)
+0:21        position: direct index for structure (temp 4-component vector of float)
+0:21          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:21          Constant:
+0:21            0 (const int)
+0:21        position: direct index for structure (temp 4-component vector of float)
+0:21          direct index (layout(location=0 ) temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:21            'vin' (layout(location=0 ) in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:21            Constant:
+0:21              1 (const int)
+0:21          Constant:
+0:21            0 (const int)
+0:22      Sequence
+0:22        Sequence
+0:22          move second child to first child (temp 4-component vector of float)
+0:?             'outStream.position' (out 4-component vector of float Position)
+0:22            position: direct index for structure (temp 4-component vector of float)
+0:22              'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:22              Constant:
+0:22                0 (const int)
+0:22          move second child to first child (temp 4-component vector of float)
+0:22            color: direct index for structure (temp 4-component vector of float)
+0:22              'outStream' (layout(location=0 ) out structure{temp 4-component vector of float color, temp 2-component vector of float uv})
+0:22              Constant:
+0:22                0 (const int)
+0:22            color: direct index for structure (temp 4-component vector of float)
+0:22              'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:22              Constant:
+0:22                1 (const int)
+0:22          move second child to first child (temp 2-component vector of float)
+0:22            uv: direct index for structure (temp 2-component vector of float)
+0:22              'outStream' (layout(location=0 ) out structure{temp 4-component vector of float color, temp 2-component vector of float uv})
+0:22              Constant:
+0:22                1 (const int)
+0:22            uv: direct index for structure (temp 2-component vector of float)
+0:22              'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:22              Constant:
+0:22                2 (const int)
+0:22        EmitVertex (temp void)
 0:?   Linker Objects
-0:?     'vin[0].position' (layout(location=0 ) in 4-component vector of float)
-0:?     'vin[0].color' (layout(location=1 ) in 4-component vector of float)
-0:?     'vin[0].uv' (layout(location=2 ) in 2-component vector of float)
-0:?     'vin[1].position' (layout(location=3 ) in 4-component vector of float)
-0:?     'vin[1].color' (layout(location=4 ) in 4-component vector of float)
-0:?     'vin[1].uv' (layout(location=5 ) in 2-component vector of float)
-0:?     'position' (layout(location=0 ) out 4-component vector of float)
-0:?     'color' (layout(location=1 ) out 4-component vector of float)
-0:?     'uv' (layout(location=2 ) out 2-component vector of float)
+0:?     'vin' (layout(location=0 ) in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:?     'outStream' (layout(location=0 ) out structure{temp 4-component vector of float color, temp 2-component vector of float uv})
+0:?     'outStream.position' (out 4-component vector of float Position)
 
 
 Linked geometry stage:
@@ -57,44 +87,164 @@
 max_vertices = 4
 input primitive = lines
 output primitive = triangle_strip
-ERROR: node is still EOpNull!
-0:10  Function Definition: main(struct-VertexData-vf4-vf4-vf21[2];struct-VertexData-vf4-vf4-vf21; (temp void)
-0:10    Function Parameters: 
-0:10      'vin' (in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:10      'outStream' (out structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:? Sequence
+0:16  Function Definition: main(struct-VertexData-vf4-vf4-vf21[2];struct-PS_IN-vf4-vf4-vf21; (temp void)
+0:16    Function Parameters: 
+0:16      'vin' (layout(location=0 ) in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:16      'outStream' (out structure{temp 4-component vector of float Position position, temp 4-component vector of float color, temp 2-component vector of float uv})
 0:?     Sequence
-0:13      move second child to first child (temp 4-component vector of float)
-0:13        color: direct index for structure (temp 4-component vector of float)
-0:13          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:13          Constant:
-0:13            1 (const int)
-0:?         'vin[0].color' (layout(location=1 ) in 4-component vector of float)
-0:14      move second child to first child (temp 2-component vector of float)
-0:14        uv: direct index for structure (temp 2-component vector of float)
-0:14          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:14          Constant:
-0:14            2 (const int)
-0:?         'vin[0].uv' (layout(location=2 ) in 2-component vector of float)
-0:15      move second child to first child (temp 4-component vector of float)
-0:15        position: direct index for structure (temp 4-component vector of float)
-0:15          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:15          Constant:
-0:15            0 (const int)
-0:?         'vin[0].position' (layout(location=0 ) in 4-component vector of float)
-0:16      Sequence
-0:16        move second child to first child (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:16          'outStream' (out structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:16          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
-0:16        EmitVertex (temp void)
+0:19      move second child to first child (temp 4-component vector of float)
+0:19        color: direct index for structure (temp 4-component vector of float)
+0:19          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:19          Constant:
+0:19            1 (const int)
+0:19        color: direct index for structure (temp 4-component vector of float)
+0:19          direct index (layout(location=0 ) temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:19            'vin' (layout(location=0 ) in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:19            Constant:
+0:19              1 (const int)
+0:19          Constant:
+0:19            1 (const int)
+0:20      move second child to first child (temp 2-component vector of float)
+0:20        uv: direct index for structure (temp 2-component vector of float)
+0:20          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:20          Constant:
+0:20            2 (const int)
+0:20        uv: direct index for structure (temp 2-component vector of float)
+0:20          direct index (layout(location=0 ) temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:20            'vin' (layout(location=0 ) in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:20            Constant:
+0:20              1 (const int)
+0:20          Constant:
+0:20            2 (const int)
+0:21      move second child to first child (temp 4-component vector of float)
+0:21        position: direct index for structure (temp 4-component vector of float)
+0:21          'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:21          Constant:
+0:21            0 (const int)
+0:21        position: direct index for structure (temp 4-component vector of float)
+0:21          direct index (layout(location=0 ) temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:21            'vin' (layout(location=0 ) in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:21            Constant:
+0:21              1 (const int)
+0:21          Constant:
+0:21            0 (const int)
+0:22      Sequence
+0:22        Sequence
+0:22          move second child to first child (temp 4-component vector of float)
+0:?             'outStream.position' (out 4-component vector of float Position)
+0:22            position: direct index for structure (temp 4-component vector of float)
+0:22              'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:22              Constant:
+0:22                0 (const int)
+0:22          move second child to first child (temp 4-component vector of float)
+0:22            color: direct index for structure (temp 4-component vector of float)
+0:22              'outStream' (layout(location=0 ) out structure{temp 4-component vector of float color, temp 2-component vector of float uv})
+0:22              Constant:
+0:22                0 (const int)
+0:22            color: direct index for structure (temp 4-component vector of float)
+0:22              'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:22              Constant:
+0:22                1 (const int)
+0:22          move second child to first child (temp 2-component vector of float)
+0:22            uv: direct index for structure (temp 2-component vector of float)
+0:22              'outStream' (layout(location=0 ) out structure{temp 4-component vector of float color, temp 2-component vector of float uv})
+0:22              Constant:
+0:22                1 (const int)
+0:22            uv: direct index for structure (temp 2-component vector of float)
+0:22              'vout' (temp structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:22              Constant:
+0:22                2 (const int)
+0:22        EmitVertex (temp void)
 0:?   Linker Objects
-0:?     'vin[0].position' (layout(location=0 ) in 4-component vector of float)
-0:?     'vin[0].color' (layout(location=1 ) in 4-component vector of float)
-0:?     'vin[0].uv' (layout(location=2 ) in 2-component vector of float)
-0:?     'vin[1].position' (layout(location=3 ) in 4-component vector of float)
-0:?     'vin[1].color' (layout(location=4 ) in 4-component vector of float)
-0:?     'vin[1].uv' (layout(location=5 ) in 2-component vector of float)
-0:?     'position' (layout(location=0 ) out 4-component vector of float)
-0:?     'color' (layout(location=1 ) out 4-component vector of float)
-0:?     'uv' (layout(location=2 ) out 2-component vector of float)
+0:?     'vin' (layout(location=0 ) in 2-element array of structure{temp 4-component vector of float position, temp 4-component vector of float color, temp 2-component vector of float uv})
+0:?     'outStream' (layout(location=0 ) out structure{temp 4-component vector of float color, temp 2-component vector of float uv})
+0:?     'outStream.position' (out 4-component vector of float Position)
 
-SPIR-V is not generated for failed compile or link
+// Module Version 10000
+// Generated by (magic number): 80001
+// Id's are bound by 49
+
+                              Capability Geometry
+               1:             ExtInstImport  "GLSL.std.450"
+                              MemoryModel Logical GLSL450
+                              EntryPoint Geometry 4  "main" 19 36 41
+                              ExecutionMode 4 InputLines
+                              ExecutionMode 4 Invocations 1
+                              ExecutionMode 4 OutputTriangleStrip
+                              ExecutionMode 4 OutputVertices 4
+                              Name 4  "main"
+                              Name 9  "PS_IN"
+                              MemberName 9(PS_IN) 0  "position"
+                              MemberName 9(PS_IN) 1  "color"
+                              MemberName 9(PS_IN) 2  "uv"
+                              Name 11  "vout"
+                              Name 14  "VertexData"
+                              MemberName 14(VertexData) 0  "position"
+                              MemberName 14(VertexData) 1  "color"
+                              MemberName 14(VertexData) 2  "uv"
+                              Name 19  "vin"
+                              Name 36  "outStream.position"
+                              Name 39  "PS_IN"
+                              MemberName 39(PS_IN) 0  "color"
+                              MemberName 39(PS_IN) 1  "uv"
+                              Name 41  "outStream"
+                              Decorate 19(vin) Location 0
+                              Decorate 36(outStream.position) BuiltIn Position
+                              Decorate 41(outStream) Location 0
+               2:             TypeVoid
+               3:             TypeFunction 2
+               6:             TypeFloat 32
+               7:             TypeVector 6(float) 4
+               8:             TypeVector 6(float) 2
+        9(PS_IN):             TypeStruct 7(fvec4) 7(fvec4) 8(fvec2)
+              10:             TypePointer Function 9(PS_IN)
+              12:             TypeInt 32 1
+              13:     12(int) Constant 1
+  14(VertexData):             TypeStruct 7(fvec4) 7(fvec4) 8(fvec2)
+              15:             TypeInt 32 0
+              16:     15(int) Constant 2
+              17:             TypeArray 14(VertexData) 16
+              18:             TypePointer Input 17
+         19(vin):     18(ptr) Variable Input
+              20:             TypePointer Input 7(fvec4)
+              23:             TypePointer Function 7(fvec4)
+              25:     12(int) Constant 2
+              26:             TypePointer Input 8(fvec2)
+              29:             TypePointer Function 8(fvec2)
+              31:     12(int) Constant 0
+              35:             TypePointer Output 7(fvec4)
+36(outStream.position):     35(ptr) Variable Output
+       39(PS_IN):             TypeStruct 7(fvec4) 8(fvec2)
+              40:             TypePointer Output 39(PS_IN)
+   41(outStream):     40(ptr) Variable Output
+              47:             TypePointer Output 8(fvec2)
+         4(main):           2 Function None 3
+               5:             Label
+        11(vout):     10(ptr) Variable Function
+              21:     20(ptr) AccessChain 19(vin) 13 13
+              22:    7(fvec4) Load 21
+              24:     23(ptr) AccessChain 11(vout) 13
+                              Store 24 22
+              27:     26(ptr) AccessChain 19(vin) 13 25
+              28:    8(fvec2) Load 27
+              30:     29(ptr) AccessChain 11(vout) 25
+                              Store 30 28
+              32:     20(ptr) AccessChain 19(vin) 13 31
+              33:    7(fvec4) Load 32
+              34:     23(ptr) AccessChain 11(vout) 31
+                              Store 34 33
+              37:     23(ptr) AccessChain 11(vout) 31
+              38:    7(fvec4) Load 37
+                              Store 36(outStream.position) 38
+              42:     23(ptr) AccessChain 11(vout) 13
+              43:    7(fvec4) Load 42
+              44:     35(ptr) AccessChain 41(outStream) 31
+                              Store 44 43
+              45:     29(ptr) AccessChain 11(vout) 25
+              46:    8(fvec2) Load 45
+              48:     47(ptr) AccessChain 41(outStream) 13
+                              Store 48 46
+                              EmitVertex
+                              Return
+                              FunctionEnd
diff --git a/Test/baseResults/hlsl.structin.vert.out b/Test/baseResults/hlsl.structin.vert.out
index a5feea8..5e83ed4 100755
--- a/Test/baseResults/hlsl.structin.vert.out
+++ b/Test/baseResults/hlsl.structin.vert.out
@@ -28,50 +28,42 @@
 0:11          'e' (layout(location=5 ) in 4-component vector of float)
 0:13      Sequence
 0:13        Sequence
-0:13          move second child to first child (temp 4-component vector of float)
-0:?             'm[0]' (layout(location=0 ) out 4-component vector of float)
-0:13            direct index (temp 4-component vector of float)
-0:13              m: direct index for structure (temp 2-element array of 4-component vector of float)
-0:13                'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
-0:13                Constant:
-0:13                  0 (const int)
+0:13          move second child to first child (temp 2-element array of 4-component vector of float)
+0:13            m: direct index for structure (temp 2-element array of 4-component vector of float)
+0:13              '@entryPointOutput' (out structure Position{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, smooth temp 4-component vector of float b})
 0:13              Constant:
 0:13                0 (const int)
-0:13          move second child to first child (temp 4-component vector of float)
-0:?             'm[1]' (layout(location=1 ) out 4-component vector of float)
-0:13            direct index (temp 4-component vector of float)
-0:13              m: direct index for structure (temp 2-element array of 4-component vector of float)
-0:13                'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
-0:13                Constant:
-0:13                  0 (const int)
+0:13            m: direct index for structure (temp 2-element array of 4-component vector of float)
+0:13              'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
+0:13              Constant:
+0:13                0 (const int)
+0:13          move second child to first child (temp 2-component vector of uint)
+0:13            coord: direct index for structure (temp 2-component vector of uint)
+0:13              '@entryPointOutput' (out structure Position{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, smooth temp 4-component vector of float b})
 0:13              Constant:
 0:13                1 (const int)
-0:13          move second child to first child (temp 2-component vector of uint)
-0:?             'coord' (layout(location=2 ) out 2-component vector of uint)
 0:13            coord: direct index for structure (temp 2-component vector of uint)
 0:13              'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
 0:13              Constant:
 0:13                1 (const int)
 0:13          move second child to first child (temp 4-component vector of float)
-0:?             'b' (layout(location=3 ) smooth out 4-component vector of float)
+0:13            b: direct index for structure (smooth temp 4-component vector of float)
+0:13              '@entryPointOutput' (out structure Position{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, smooth temp 4-component vector of float b})
+0:13              Constant:
+0:13                2 (const int)
 0:13            b: direct index for structure (temp 4-component vector of float)
 0:13              'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
 0:13              Constant:
 0:13                2 (const int)
 0:13        Branch: Return
 0:?   Linker Objects
-0:?     'm[0]' (layout(location=0 ) out 4-component vector of float)
-0:?     'm[1]' (layout(location=1 ) out 4-component vector of float)
-0:?     'coord' (layout(location=2 ) out 2-component vector of uint)
-0:?     'b' (layout(location=3 ) smooth out 4-component vector of float)
+0:?     '@entryPointOutput' (out structure Position{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, smooth temp 4-component vector of float b})
 0:?     'd' (layout(location=0 ) in 4-component vector of float)
 0:?     'm[0]' (layout(location=1 ) in 4-component vector of float)
 0:?     'm[1]' (layout(location=2 ) in 4-component vector of float)
 0:?     'coord' (layout(location=3 ) in 2-component vector of uint)
-0:?     'b' (layout(location=4 ) in 4-component vector of float)
+0:?     'b' (layout(location=4 ) smooth in 4-component vector of float)
 0:?     'e' (layout(location=5 ) in 4-component vector of float)
-0:?     'm[0]' (layout(location=0 ) out 4-component vector of float)
-0:?     'm[1]' (layout(location=1 ) out 4-component vector of float)
 0:?     'm[0]' (layout(location=1 ) in 4-component vector of float)
 0:?     'm[1]' (layout(location=2 ) in 4-component vector of float)
 
@@ -108,61 +100,53 @@
 0:11          'e' (layout(location=5 ) in 4-component vector of float)
 0:13      Sequence
 0:13        Sequence
-0:13          move second child to first child (temp 4-component vector of float)
-0:?             'm[0]' (layout(location=0 ) out 4-component vector of float)
-0:13            direct index (temp 4-component vector of float)
-0:13              m: direct index for structure (temp 2-element array of 4-component vector of float)
-0:13                'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
-0:13                Constant:
-0:13                  0 (const int)
+0:13          move second child to first child (temp 2-element array of 4-component vector of float)
+0:13            m: direct index for structure (temp 2-element array of 4-component vector of float)
+0:13              '@entryPointOutput' (out structure Position{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, smooth temp 4-component vector of float b})
 0:13              Constant:
 0:13                0 (const int)
-0:13          move second child to first child (temp 4-component vector of float)
-0:?             'm[1]' (layout(location=1 ) out 4-component vector of float)
-0:13            direct index (temp 4-component vector of float)
-0:13              m: direct index for structure (temp 2-element array of 4-component vector of float)
-0:13                'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
-0:13                Constant:
-0:13                  0 (const int)
+0:13            m: direct index for structure (temp 2-element array of 4-component vector of float)
+0:13              'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
+0:13              Constant:
+0:13                0 (const int)
+0:13          move second child to first child (temp 2-component vector of uint)
+0:13            coord: direct index for structure (temp 2-component vector of uint)
+0:13              '@entryPointOutput' (out structure Position{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, smooth temp 4-component vector of float b})
 0:13              Constant:
 0:13                1 (const int)
-0:13          move second child to first child (temp 2-component vector of uint)
-0:?             'coord' (layout(location=2 ) out 2-component vector of uint)
 0:13            coord: direct index for structure (temp 2-component vector of uint)
 0:13              'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
 0:13              Constant:
 0:13                1 (const int)
 0:13          move second child to first child (temp 4-component vector of float)
-0:?             'b' (layout(location=3 ) smooth out 4-component vector of float)
+0:13            b: direct index for structure (smooth temp 4-component vector of float)
+0:13              '@entryPointOutput' (out structure Position{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, smooth temp 4-component vector of float b})
+0:13              Constant:
+0:13                2 (const int)
 0:13            b: direct index for structure (temp 4-component vector of float)
 0:13              'local' (temp structure{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, temp 4-component vector of float b})
 0:13              Constant:
 0:13                2 (const int)
 0:13        Branch: Return
 0:?   Linker Objects
-0:?     'm[0]' (layout(location=0 ) out 4-component vector of float)
-0:?     'm[1]' (layout(location=1 ) out 4-component vector of float)
-0:?     'coord' (layout(location=2 ) out 2-component vector of uint)
-0:?     'b' (layout(location=3 ) smooth out 4-component vector of float)
+0:?     '@entryPointOutput' (out structure Position{temp 2-element array of 4-component vector of float m, temp 2-component vector of uint coord, smooth temp 4-component vector of float b})
 0:?     'd' (layout(location=0 ) in 4-component vector of float)
 0:?     'm[0]' (layout(location=1 ) in 4-component vector of float)
 0:?     'm[1]' (layout(location=2 ) in 4-component vector of float)
 0:?     'coord' (layout(location=3 ) in 2-component vector of uint)
-0:?     'b' (layout(location=4 ) in 4-component vector of float)
+0:?     'b' (layout(location=4 ) smooth in 4-component vector of float)
 0:?     'e' (layout(location=5 ) in 4-component vector of float)
-0:?     'm[0]' (layout(location=0 ) out 4-component vector of float)
-0:?     'm[1]' (layout(location=1 ) out 4-component vector of float)
 0:?     'm[0]' (layout(location=1 ) in 4-component vector of float)
 0:?     'm[1]' (layout(location=2 ) in 4-component vector of float)
 
 // Module Version 10000
 // Generated by (magic number): 80001
-// Id's are bound by 59
+// Id's are bound by 61
 
                               Capability Shader
                1:             ExtInstImport  "GLSL.std.450"
                               MemoryModel Logical GLSL450
-                              EntryPoint Vertex 4  "main" 18 20 24 32 35 41 45 50 54 58
+                              EntryPoint Vertex 4  "main" 18 20 24 32 35 42 60
                               Name 4  "main"
                               Name 12  "VI"
                               MemberName 12(VI) 0  "m"
@@ -174,21 +158,19 @@
                               Name 24  "coord"
                               Name 32  "d"
                               Name 35  "e"
-                              Name 41  "m[0]"
-                              Name 45  "m[1]"
-                              Name 50  "coord"
-                              Name 54  "b"
-                              Name 58  "b"
+                              Name 40  "VI"
+                              MemberName 40(VI) 0  "m"
+                              MemberName 40(VI) 1  "coord"
+                              MemberName 40(VI) 2  "b"
+                              Name 42  "@entryPointOutput"
+                              Name 60  "b"
                               Decorate 18(m[1]) Location 2
                               Decorate 20(m[0]) Location 1
                               Decorate 24(coord) Location 3
                               Decorate 32(d) Location 0
                               Decorate 35(e) Location 5
-                              Decorate 41(m[0]) Location 0
-                              Decorate 45(m[1]) Location 1
-                              Decorate 50(coord) Location 2
-                              Decorate 54(b) Location 3
-                              Decorate 58(b) Location 4
+                              Decorate 42(@entryPointOutput) BuiltIn Position
+                              Decorate 60(b) Location 4
                2:             TypeVoid
                3:             TypeFunction 2
                6:             TypeFloat 32
@@ -211,16 +193,17 @@
            32(d):     17(ptr) Variable Input
            35(e):     17(ptr) Variable Input
               38:             TypePointer Function 7(fvec4)
-              40:             TypePointer Output 7(fvec4)
-        41(m[0]):     40(ptr) Variable Output
-              42:     15(int) Constant 0
-        45(m[1]):     40(ptr) Variable Output
-              46:     15(int) Constant 1
-              49:             TypePointer Output 11(ivec2)
-       50(coord):     49(ptr) Variable Output
-              51:             TypePointer Function 11(ivec2)
-           54(b):     40(ptr) Variable Output
-           58(b):     17(ptr) Variable Input
+          40(VI):             TypeStruct 10 11(ivec2) 7(fvec4)
+              41:             TypePointer Output 40(VI)
+42(@entryPointOutput):     41(ptr) Variable Output
+              43:     15(int) Constant 0
+              44:             TypePointer Function 10
+              47:             TypePointer Output 10
+              49:     15(int) Constant 1
+              50:             TypePointer Function 11(ivec2)
+              53:             TypePointer Output 11(ivec2)
+              57:             TypePointer Output 7(fvec4)
+           60(b):     17(ptr) Variable Input
          4(main):           2 Function None 3
                5:             Label
        14(local):     13(ptr) Variable Function
@@ -238,17 +221,17 @@
               37:    7(fvec4) FAdd 34 36
               39:     38(ptr) AccessChain 14(local) 16
                               Store 39 37
-              43:     38(ptr) AccessChain 14(local) 42 42
-              44:    7(fvec4) Load 43
-                              Store 41(m[0]) 44
-              47:     38(ptr) AccessChain 14(local) 42 46
-              48:    7(fvec4) Load 47
-                              Store 45(m[1]) 48
-              52:     51(ptr) AccessChain 14(local) 46
-              53:   11(ivec2) Load 52
-                              Store 50(coord) 53
+              45:     44(ptr) AccessChain 14(local) 43
+              46:          10 Load 45
+              48:     47(ptr) AccessChain 42(@entryPointOutput) 43
+                              Store 48 46
+              51:     50(ptr) AccessChain 14(local) 49
+              52:   11(ivec2) Load 51
+              54:     53(ptr) AccessChain 42(@entryPointOutput) 49
+                              Store 54 52
               55:     38(ptr) AccessChain 14(local) 16
               56:    7(fvec4) Load 55
-                              Store 54(b) 56
+              58:     57(ptr) AccessChain 42(@entryPointOutput) 16
+                              Store 58 56
                               Return
                               FunctionEnd
diff --git a/Test/hlsl.flatten.return.frag b/Test/hlsl.flatten.return.frag
index c633e67..4aa3f50 100644
--- a/Test/hlsl.flatten.return.frag
+++ b/Test/hlsl.flatten.return.frag
@@ -9,7 +9,7 @@
 
 PS_OUTPUT Func1()
 {
-    return PS_OUTPUT(float4(1), 2, 3, 4);
+    return PS_OUTPUT(float4(1,1,1,1), 2, 3, 4);
 }
 
 PS_OUTPUT main()
diff --git a/Test/hlsl.pp.tokenpasting.frag b/Test/hlsl.pp.tokenpasting.frag
new file mode 100644
index 0000000..5415670
--- /dev/null
+++ b/Test/hlsl.pp.tokenpasting.frag
@@ -0,0 +1,18 @@
+
+#define foobarblee zzzz
+
+#define ar qqqq
+
+#define MACRO1(x,y) foo##x##y
+// #define MACRO2 abc##def
+
+// #define SPACE_IN_MACRO int var1
+
+float4 main() : SV_Target0
+{
+    // float MACRO2 = 10;
+    float MACRO1(b##ar,blee) = 3;
+
+    return float4(foobarblee,0,0,0);
+}
+
diff --git a/Test/hlsl.struct.split-1.vert b/Test/hlsl.struct.split-1.vert
new file mode 100644
index 0000000..ce5f51f
--- /dev/null
+++ b/Test/hlsl.struct.split-1.vert
@@ -0,0 +1,25 @@
+
+struct VS_INPUT
+{
+    int    x0_in  : foo0;
+    float4 Pos_in : SV_Position;
+    int    x1_in  : foo1;
+};
+
+struct VS_OUTPUT
+{
+    int    x0_out  : foo0;
+    float4 Pos_out : SV_Position;
+    int    x1_out  : foo1;
+};
+
+VS_OUTPUT main(VS_INPUT vsin, float4 Pos_loose : SV_Position)
+{
+    VS_OUTPUT vsout;
+
+    vsout.x0_out  = vsin.x0_in;
+    vsout.Pos_out = vsin.Pos_in + Pos_loose;
+    vsout.x1_out  = vsin.x1_in;
+
+    return vsout;
+}
diff --git a/Test/hlsl.struct.split.array.geom b/Test/hlsl.struct.split.array.geom
new file mode 100644
index 0000000..9008df1
--- /dev/null
+++ b/Test/hlsl.struct.split.array.geom
@@ -0,0 +1,21 @@
+struct PSInput
+{
+    float4 Pos      : SV_POSITION;
+    float2 TexCoord : TEXCOORD;
+    float3 TerrainPos : TERRAINPOS;
+    uint VertexID : VertexID;
+};
+
+typedef PSInput foo_t[2][3];
+
+[maxvertexcount(4)]
+void main(point uint v[1] : VertexID, inout TriangleStream<PSInput> OutputStream)
+{
+    foo_t Verts;
+
+    PSInput Out = (PSInput) 0;
+
+    for (int x=0; x<2; ++x)
+        for (int y=0; y<2; ++y)
+            Verts[x][y] = Out;
+}
diff --git a/Test/hlsl.struct.split.call.vert b/Test/hlsl.struct.split.call.vert
new file mode 100644
index 0000000..543adeb
--- /dev/null
+++ b/Test/hlsl.struct.split.call.vert
@@ -0,0 +1,32 @@
+// Test passing split structs to functions.
+
+struct VS_INPUT
+{
+    int    x0_in  : foo0;
+    float4 Pos_in : SV_Position;
+    int    x1_in  : foo1;
+};
+
+struct VS_OUTPUT
+{
+    int    x0_out  : foo0;
+    float4 Pos_out : SV_Position;
+    int    x1_out  : foo1;
+};
+
+void Fn1(VS_INPUT fn1_in, VS_OUTPUT fn1_out) {
+    fn1_in.Pos_in + fn1_out.Pos_out;
+}
+
+VS_OUTPUT main(VS_INPUT vsin)
+{
+    VS_OUTPUT vsout;
+
+    vsout.x0_out  = vsin.x0_in;
+    vsout.Pos_out = vsin.Pos_in;
+    vsout.x1_out  = vsin.x1_in;
+
+    Fn1(vsin, vsout);
+
+    return vsout;
+}
diff --git a/Test/hlsl.struct.split.nested.geom b/Test/hlsl.struct.split.nested.geom
new file mode 100644
index 0000000..03bf38f
--- /dev/null
+++ b/Test/hlsl.struct.split.nested.geom
@@ -0,0 +1,31 @@
+
+struct STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO
+{
+    float m0_array[2];
+    int   m1;
+};
+
+struct PS_IN 
+{ 
+    float4 pos : SV_Position; 
+    float2 tc  : TEXCOORD0;
+    // float  c           : SV_ClipDistance0;
+}; 
+
+struct GS_OUT
+{ 
+    PS_IN psIn;
+    STRUCT_WITH_NO_BUILTIN_INTERSTAGE_IO contains_no_builtin_io;
+};
+
+
+[maxvertexcount(3)] 
+void main(triangle PS_IN tin[3], inout TriangleStream <GS_OUT> ts ) 
+{
+    GS_OUT o;
+
+    o.psIn.pos = float4(1,2,3,4);
+    o.psIn.tc  = float2(5,6);
+
+    ts.Append(o);
+}
diff --git a/Test/hlsl.struct.split.trivial.geom b/Test/hlsl.struct.split.trivial.geom
new file mode 100644
index 0000000..343da38
--- /dev/null
+++ b/Test/hlsl.struct.split.trivial.geom
@@ -0,0 +1,21 @@
+
+struct PS_IN 
+{ 
+    float4 pos : SV_Position; 
+}; 
+
+struct GS_OUT
+{ 
+    float4 pos : SV_Position; 
+};
+
+[maxvertexcount(3)] 
+void main(triangle PS_IN i[3], inout TriangleStream <GS_OUT> ts)
+{
+    GS_OUT o;
+
+    for (int x=0; x<3; ++x) {
+        o.pos = i[x].pos;
+        ts.Append(o);
+    }
+}
diff --git a/Test/hlsl.struct.split.trivial.vert b/Test/hlsl.struct.split.trivial.vert
new file mode 100644
index 0000000..351e418
--- /dev/null
+++ b/Test/hlsl.struct.split.trivial.vert
@@ -0,0 +1,22 @@
+
+// Test trivial case for structure splitting: the IN and OUT structs have ONLY an interstage IO.
+// This should fall back to flattening, and not produce any empty structures.
+
+struct VS_INPUT
+{
+    float4 Pos_in : SV_Position;
+};
+
+struct VS_OUTPUT
+{
+    float4 Pos : SV_Position;
+};
+
+VS_OUTPUT main(VS_INPUT vsin, float4 Pos_loose : SV_Position)
+{
+    VS_OUTPUT vsout;
+
+    vsout.Pos = vsin.Pos_in + Pos_loose;
+
+    return vsout;
+}
diff --git a/Test/hlsl.structarray.flatten.geom b/Test/hlsl.structarray.flatten.geom
index 1b05dc1..990532d 100644
--- a/Test/hlsl.structarray.flatten.geom
+++ b/Test/hlsl.structarray.flatten.geom
@@ -1,17 +1,23 @@
 
 struct VertexData {
-	float4 position : POSITION;
-	float4 color    : COLOR0;
-	float2 uv       : TEXCOORD0;
+    float4 position : POSITION;
+    float4 color    : COLOR0;
+    float2 uv       : TEXCOORD0;
+};
+
+struct PS_IN {
+    float4 position : SV_POSITION;
+    float4 color    : COLOR0;
+    float2 uv       : TEXCOORD0;
 };
 
 [maxvertexcount(4)]
-void main(line VertexData vin[2], inout TriangleStream<VertexData> outStream)
+void main(line VertexData vin[2], inout TriangleStream<PS_IN> outStream)
 {
-    VertexData vout;
+    PS_IN vout;
 
-    vout.color = vin[0].color;
-    vout.uv = vin[0].uv;
-    vout.position = vin[0].position;
+    vout.color = vin[1].color;
+    vout.uv = vin[1].uv;
+    vout.position = vin[1].position;
     outStream.Append(vout);
 }
diff --git a/glslang/Include/Types.h b/glslang/Include/Types.h
index ae40465..6bd201d 100644
--- a/glslang/Include/Types.h
+++ b/glslang/Include/Types.h
@@ -1223,6 +1223,16 @@
             typeName = NewPoolTString(copyOf.typeName->c_str());
     }
 
+    // Recursively make temporary
+    void makeTemporary()
+    {
+        getQualifier().makeTemporary();
+
+        if (isStruct())
+            for (unsigned int i = 0; i < structure->size(); ++i)
+                (*structure)[i].type->makeTemporary();
+    }
+
     TType* clone() const
     {
         TType *newType = new TType();
@@ -1309,6 +1319,20 @@
     virtual bool isImage() const   { return basicType == EbtSampler && getSampler().isImage(); }
     virtual bool isSubpass() const { return basicType == EbtSampler && getSampler().isSubpass(); }
 
+    // Return true if this is interstage IO
+    virtual bool isBuiltInInterstageIO() const
+    {
+        switch (getQualifier().builtIn) {
+        case EbvPosition:
+        case EbvPointSize:
+        case EbvClipDistance:
+        case EbvCullDistance:
+            return true;
+        default:
+            return false;
+        }
+    }
+ 
     // Recursively checks if the type contains the given basic type
     virtual bool containsBasicType(TBasicType checkType) const
     {
@@ -1376,6 +1400,34 @@
         return false;
     }
 
+    // Recursively checks if the type contains an interstage IO builtin
+    virtual bool containsBuiltInInterstageIO() const
+    {
+        if (isBuiltInInterstageIO())
+            return true;
+
+        if (! structure)
+            return false;
+        for (unsigned int i = 0; i < structure->size(); ++i) {
+            if ((*structure)[i].type->containsBuiltInInterstageIO())
+                return true;
+        }
+        return false;
+    }
+
+    // Recursively checks whether a struct contains only interstage IO
+    virtual bool containsOnlyBuiltInInterstageIO() const
+    {
+        if (! structure)
+            return isBuiltInInterstageIO();
+
+        for (unsigned int i = 0; i < structure->size(); ++i) {
+            if (!(*structure)[i].type->containsOnlyBuiltInInterstageIO())
+                return false;
+        }
+        return true;
+    }
+
     virtual bool containsNonOpaque() const
     {
         // list all non-opaque types
diff --git a/gtests/Hlsl.FromFile.cpp b/gtests/Hlsl.FromFile.cpp
index 41372f6..fd35af3 100644
--- a/gtests/Hlsl.FromFile.cpp
+++ b/gtests/Hlsl.FromFile.cpp
@@ -207,6 +207,12 @@
         {"hlsl.shapeConvRet.frag", "main"},
         {"hlsl.stringtoken.frag", "main"},
         {"hlsl.string.frag", "main"},
+        {"hlsl.struct.split-1.vert", "main"},
+        {"hlsl.struct.split.array.geom", "main"},
+        {"hlsl.struct.split.call.vert", "main"},
+        {"hlsl.struct.split.nested.geom", "main"},
+        {"hlsl.struct.split.trivial.geom", "main"},
+        {"hlsl.struct.split.trivial.vert", "main"},
         {"hlsl.structarray.flatten.frag", "main"},
         {"hlsl.structarray.flatten.geom", "main"},
         {"hlsl.structin.vert", "main"},
diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp
index d0f3b00..22f4c0d 100755
--- a/hlsl/hlslGrammar.cpp
+++ b/hlsl/hlslGrammar.cpp
@@ -478,7 +478,7 @@
     // type_specifier
     if (! acceptType(type)) {
         // If this is not a type, we may have inadvertently gone down a wrong path
-        // py parsing "sample", which can be treated like either an identifier or a
+        // by parsing "sample", which can be treated like either an identifier or a
         // qualifier.  Back it out, if we did.
         if (qualifier.sample)
             recedeToken();
diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp
index 8791d4c..613b18a 100755
--- a/hlsl/hlslParseHelper.cpp
+++ b/hlsl/hlslParseHelper.cpp
@@ -59,9 +59,12 @@
     loopNestingLevel(0), annotationNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
     postEntryPointReturn(false),
     limits(resources.limits),
+    inEntryPoint(false),
     entryPointOutput(nullptr),
     nextInLocation(0), nextOutLocation(0),
-    sourceEntryPointName(sourceEntryPointName)
+    sourceEntryPointName(sourceEntryPointName),
+    builtInIoIndex(nullptr),
+    builtInIoBase(nullptr)
 {
     globalUniformDefaults.clear();
     globalUniformDefaults.layoutMatrix = ElmRowMajor;
@@ -656,11 +659,13 @@
 
         if (base->getAsSymbolNode() && (wasFlattened(base) || shouldFlatten(base->getType()))) {
             if (index->getQualifier().storage != EvqConst)
-                error(loc, "Invalid variable index to flattened uniform array", base->getAsSymbolNode()->getName().c_str(), "");
+                error(loc, "Invalid variable index to flattened array", base->getAsSymbolNode()->getName().c_str(), "");
 
-            result = flattenAccess(loc, base, indexValue);
+            result = flattenAccess(base, indexValue);
             flattened = (result != base);
         } else {
+            splitAccessArray(loc, base, index);
+
             if (index->getQualifier().storage == EvqConst) {
                 if (base->getType().isImplicitlySizedArray())
                     updateImplicitArraySize(loc, base, indexValue);
@@ -765,11 +770,9 @@
         }
     } else if (field == "Append" ||
                field == "RestartStrip") {
-        // These methods only valid on stage in variables
-        // TODO: ... which are stream out types, if there's any way to test that here.
-        if (base->getType().getQualifier().storage == EvqVaryingOut) {
-            return intermediate.addMethod(base, TType(EbtVoid), &field, loc);
-        }
+        // We cannot check the type here: it may be sanitized if we're not compiling a geometry shader, but
+        // the code is around in the shader source.
+        return intermediate.addMethod(base, TType(EbtVoid), &field, loc);
     }
 
     // It's not .length() if we get to here.
@@ -834,15 +837,21 @@
             }
         }
         if (fieldFound) {
-            if (base->getAsSymbolNode() && (wasFlattened(base) || shouldFlatten(base->getType())))
-                result = flattenAccess(loc, base, member);
-            else {
-                if (base->getType().getQualifier().storage == EvqConst)
-                    result = intermediate.foldDereference(base, member, loc);
-                else {
-                    TIntermTyped* index = intermediate.addConstantUnion(member, loc);
-                    result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc);
-                    result->setType(*(*fields)[member].type);
+            if (base->getAsSymbolNode() && (wasFlattened(base) || shouldFlatten(base->getType()))) {
+                result = flattenAccess(base, member);
+            } else {
+                // Update the base and member to access if this was a split structure.
+                result = splitAccessStruct(loc, base, member);
+                fields = base->getType().getStruct();
+
+                if (result == nullptr) {
+                    if (base->getType().getQualifier().storage == EvqConst)
+                        result = intermediate.foldDereference(base, member, loc);
+                    else {
+                        TIntermTyped* index = intermediate.addConstantUnion(member, loc);
+                        result = intermediate.addIndex(EOpIndexDirectStruct, base, index, loc);
+                        result->setType(*(*fields)[member].type);
+                    }
                 }
             }
         } else
@@ -853,6 +862,102 @@
     return result;
 }
 
+// Determine whether we should split this type
+bool HlslParseContext::shouldSplit(const TType& type)
+{
+    if (! inEntryPoint)
+        return false;
+
+    const TStorageQualifier qualifier = type.getQualifier().storage;
+
+    // If it contains interstage IO, but not ONLY interstage IO, split the struct.
+    return type.isStruct() && type.containsBuiltInInterstageIO() &&
+        (qualifier == EvqVaryingIn || qualifier == EvqVaryingOut);
+}
+
+// Split the type of the given node into two structs:
+//   1. interstage IO
+//   2. everything else
+// IO members are put into the ioStruct.  The type is modified to remove them.
+void HlslParseContext::split(TIntermTyped* node)
+{
+    if (node == nullptr)
+        return;
+
+    TIntermSymbol* symNode = node->getAsSymbolNode();
+
+    if (symNode == nullptr)
+        return;
+
+    // Create a new variable:
+    TType& splitType = split(*symNode->getType().clone(), symNode->getName());
+
+    splitIoVars[symNode->getId()] = makeInternalVariable(symNode->getName(), splitType);
+}
+
+// Split the type of the given variable into two structs:
+void HlslParseContext::split(const TVariable& variable)
+{
+    const TType& type = variable.getType();
+
+    TString name = (&variable == entryPointOutput) ? "" : variable.getName();
+
+    // Create a new variable:
+    TType& splitType = split(*type.clone(), name);
+
+    splitIoVars[variable.getUniqueId()] = makeInternalVariable(variable.getName(), splitType);
+}
+
+// Recursive implementation of split(const TVariable& variable).
+// Returns reference to the modified type.
+TType& HlslParseContext::split(TType& type, TString name, const TType* outerStructType)
+{
+    const TArraySizes* arraySizes = nullptr;
+
+    // At the outer-most scope, remember the struct type so we can examine its storage class
+    // at deeper levels.
+    if (outerStructType == nullptr)
+        outerStructType = &type;
+
+    if (type.isArray())
+        arraySizes = &type.getArraySizes();
+
+    // We can ignore arrayness: it's uninvolved.
+    if (type.isStruct()) {
+        TTypeList* userStructure = type.getWritableStruct();
+ 
+        // Get iterator to (now at end) set of builtin iterstage IO members
+        const auto firstIo = std::stable_partition(userStructure->begin(), userStructure->end(),
+                                                   [](const TTypeLoc& t) {return !t.type->isBuiltInInterstageIO();});
+
+        // Move those to the builtin IO.  However, we also propagate arrayness (just one level is handled
+        // now) to this variable.
+        for (auto ioType = firstIo; ioType != userStructure->end(); ++ioType) {
+            const TType& memberType = *ioType->type;
+            TVariable* ioVar = makeInternalVariable(name + (name.empty() ? "" : ".") + memberType.getFieldName(), memberType);
+
+            if (arraySizes)
+                ioVar->getWritableType().newArraySizes(*arraySizes);
+
+            interstageBuiltInIo[tInterstageIoData(memberType, *outerStructType)] = ioVar;
+
+            // Merge qualifier from the user structure
+            mergeQualifiers(ioVar->getWritableType().getQualifier(), outerStructType->getQualifier());
+        }
+
+        // Erase the IO vars from the user structure.
+        userStructure->erase(firstIo, userStructure->end());
+
+        // Recurse further into the members.
+        for (unsigned int i = 0; i < userStructure->size(); ++i)
+            split(*(*userStructure)[i].type,
+                  name + (name.empty() ? "" : ".") + (*userStructure)[i].type->getFieldName(),
+                  outerStructType);
+    }
+
+    return type;
+}
+
 // Determine whether we should flatten an arbitrary type.
 bool HlslParseContext::shouldFlatten(const TType& type) const
 {
@@ -868,9 +973,11 @@
 
     const TStorageQualifier qualifier = type.getQualifier().storage;
 
-    return type.isStruct() &&
-           (qualifier == EvqVaryingIn ||
-            qualifier == EvqVaryingOut);
+    if (!type.isStruct())
+        return false;
+
+    return ((language == EShLangVertex   && qualifier == EvqVaryingIn) ||
+            (language == EShLangFragment && qualifier == EvqVaryingOut));
 }
 
 // Is this a uniform array which should be flattened?
@@ -891,7 +998,7 @@
     // emplace gives back a pair whose .first is an iterator to the item...
     auto entry = flattenMap.emplace(variable.getUniqueId(), 
                                     TFlattenData(type.getQualifier().layoutBinding));
-        
+
     // ... and the item is a map pair, so first->second is the TFlattenData itself.
     flatten(loc, variable, type, entry.first->second, "");
 }
@@ -926,13 +1033,6 @@
 int HlslParseContext::flatten(const TSourceLoc& loc, const TVariable& variable, const TType& type,
                               TFlattenData& flattenData, TString name)
 {
-    // TODO: when struct splitting is in place we can remove this restriction.
-    if (language == EShLangGeometry) {
-        const TType derefType(type, 0);
-        if (!isFinalFlattening(derefType) && type.getQualifier().storage == EvqVaryingIn)
-            error(loc, "recursive type not yet supported in GS input", variable.getName().c_str(), "");
-    }
-
     // If something is an arrayed struct, the array flattener will recursively call flatten()
     // to then flatten the struct, so this is an "if else": we don't do both.
     if (type.isArray())
@@ -953,7 +1053,7 @@
 {
     if (isFinalFlattening(type)) {
         // This is as far as we flatten.  Insert the variable.
-        TVariable* memberVariable = makeInternalVariable(memberName.c_str(), type);
+        TVariable* memberVariable = makeInternalVariable(memberName, type);
         mergeQualifiers(memberVariable->getWritableType().getQualifier(), variable.getType().getQualifier());
 
         if (flattenData.nextBinding != TQualifier::layoutBindingEnd)
@@ -1043,16 +1143,22 @@
 // Return true if we have flattened this node.
 bool HlslParseContext::wasFlattened(const TIntermTyped* node) const
 {
-    return node != nullptr &&
-        node->getAsSymbolNode() != nullptr &&
+    return node != nullptr && node->getAsSymbolNode() != nullptr &&
         wasFlattened(node->getAsSymbolNode()->getId());
 }
 
+// Return true if we have split this structure
+bool HlslParseContext::wasSplit(const TIntermTyped* node) const
+{
+    return node != nullptr && node->getAsSymbolNode() != nullptr &&
+        wasSplit(node->getAsSymbolNode()->getId());
+}
+
 
 // Turn an access into an aggregate that was flattened to instead be
 // an access to the individual variable the member was flattened to.
 // Assumes shouldFlatten() or equivalent was called first.
-TIntermTyped* HlslParseContext::flattenAccess(const TSourceLoc&, TIntermTyped* base, int member)
+TIntermTyped* HlslParseContext::flattenAccess(TIntermTyped* base, int member)
 {
     const TType dereferencedType(base->getType(), member);  // dereferenced type
 
@@ -1078,6 +1184,115 @@
     }
 }
 
+// Find and return the split IO TVariable for id, or nullptr if none.
+TVariable* HlslParseContext::getSplitIoVar(int id) const
+{
+    const auto splitIoVar = splitIoVars.find(id);
+
+    if (splitIoVar == splitIoVars.end())
+        return nullptr;
+
+    return splitIoVar->second;
+}
+
+// Find and return the split IO TVariable for variable, or nullptr if none.
+TVariable* HlslParseContext::getSplitIoVar(const TVariable* var) const
+{
+    if (var == nullptr)
+        return nullptr;
+
+    return getSplitIoVar(var->getUniqueId());
+}
+
+// Find and return the split IO TVariable for symbol in this node, or nullptr if none.
+TVariable* HlslParseContext::getSplitIoVar(const TIntermTyped* node) const
+{
+    if (node == nullptr)
+        return nullptr;
+
+    const TIntermSymbol* symbolNode = node->getAsSymbolNode();
+
+    if (symbolNode == nullptr)
+        return nullptr;
+
+    return getSplitIoVar(symbolNode->getId());
+}
+
+// Remember the index used to dereference into this structure, in case it has to be moved to a
+// split-off builtin IO member.
+void HlslParseContext::splitAccessArray(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index)
+{
+    const TVariable* splitIoVar = getSplitIoVar(base);
+
+    // Not a split structure
+    if (splitIoVar == nullptr)
+        return;
+
+    if (builtInIoBase) {
+        error(loc, "only one array dimension supported for builtIn IO variable", "", "");
+        return;
+    }
+
+    builtInIoBase  = base;
+    builtInIoIndex = index;
+}
+
+
+// Turn an access into an struct that was split to instead be an
+// access to either the modified structure, or a direct reference to
+// one of the split member variables.
+TIntermTyped* HlslParseContext::splitAccessStruct(const TSourceLoc& loc, TIntermTyped*& base, int& member)
+{
+    // nothing to do
+    if (base == nullptr)
+        return nullptr;
+
+    // We have a pending bracket reference to an outer struct that we may want to move to an inner member.
+    if (builtInIoBase)
+        base = builtInIoBase;
+
+    const TVariable* splitIoVar = getSplitIoVar(base);
+
+    if (splitIoVar == nullptr)
+        return nullptr;
+
+    const TTypeList& members = *base->getType().getStruct();
+
+    const TType& memberType = *members[member].type;
+
+    if (memberType.isBuiltInInterstageIO()) {
+        // It's one of the interstage IO variables we split off.
+        TIntermTyped* builtIn = intermediate.addSymbol(*interstageBuiltInIo[tInterstageIoData(memberType, base->getType())], loc);
+
+        // If there's an array reference to an outer split struct, we re-apply it here.
+        if (builtInIoIndex != nullptr) {
+            if (builtInIoIndex->getQualifier().storage == EvqConst)
+                builtIn = intermediate.addIndex(EOpIndexDirect, builtIn, builtInIoIndex, loc);
+            else
+                builtIn = intermediate.addIndex(EOpIndexIndirect, builtIn, builtInIoIndex, loc);
+
+            builtIn->setType(memberType);
+
+            builtInIoIndex = nullptr;
+            builtInIoBase  = nullptr;
+        }
+
+        return builtIn;
+    } else {
+        // It's not an IO variable.  Find the equivalent index into the new variable.
+        base = intermediate.addSymbol(*splitIoVar, loc);
+
+        int newMember = 0;
+        for (int m=0; m<member; ++m)
+            if (!members[m].type->isBuiltInInterstageIO())
+                ++newMember;
+
+        member = newMember;
+
+        return nullptr;
+    }
+}
+
 // Variables that correspond to the user-interface in and out of a stage
 // (not the built-in interface) are assigned locations and
 // registered as a linkage node (part of the stage's external interface).
@@ -1105,8 +1320,17 @@
         auto& memberList = flattenMap[variable.getUniqueId()].members;
         for (auto member = memberList.begin(); member != memberList.end(); ++member)
             assignLocation(**member);
-    } else
+    } else if (wasSplit(variable.getUniqueId())) {
+        TVariable* splitIoVar = getSplitIoVar(&variable);
+        const TTypeList* structure = splitIoVar->getType().getStruct();
+        // Struct splitting can produce empty structures if the only members of the
+        // struct were builtin interstage IO types.  Only assign locations if it
+        // isn't a struct, or is a non-empty struct.
+        if (structure == nullptr || !structure->empty())
+            assignLocation(*splitIoVar);
+    } else {
         assignLocation(variable);
+    }
 }
 
 //
@@ -1150,6 +1374,23 @@
     return function;
 }
 
+
+// Add interstage IO variables to the linkage in canonical order.
+void HlslParseContext::addInterstageIoToLinkage()
+{
+    std::vector<tInterstageIoData> io;
+    io.reserve(interstageBuiltInIo.size());
+
+    for (auto ioVar = interstageBuiltInIo.begin(); ioVar != interstageBuiltInIo.end(); ++ioVar)
+        io.push_back(ioVar->first);
+
+    // Our canonical order is the TBuiltInVariable numeric order.
+    std::sort(io.begin(), io.end());
+
+    for (int idx = 0; idx < int(io.size()); ++idx)
+        trackLinkageDeferred(*interstageBuiltInIo[io[idx]]);
+}
+
 //
 // Handle seeing the function prototype in front of a function definition in the grammar.  
 // The body is handled after this function returns.
@@ -1188,6 +1429,8 @@
         if (entryPointOutput) {
             if (shouldFlatten(entryPointOutput->getType()))
                 flatten(loc, *entryPointOutput);
+            if (shouldSplit(entryPointOutput->getType()))
+                split(*entryPointOutput);
             assignLocations(*entryPointOutput);
         }
     } else
@@ -1215,7 +1458,15 @@
     for (int i = 0; i < function.getParamCount(); i++) {
         TParameter& param = function[i];
         if (param.name != nullptr) {
-            TVariable *variable = new TVariable(param.name, *param.type);
+            TType* sanitizedType;
+
+            // If we're not in the entry point, parameters are sanitized types.
+            if (inEntryPoint)
+                sanitizedType = param.type;
+            else
+                sanitizedType = sanitizeType(param.type);
+
+            TVariable *variable = new TVariable(param.name, *sanitizedType);
 
             // Insert the parameters with name in the symbol table.
             if (! symbolTable.insert(*variable))
@@ -1225,6 +1476,8 @@
                 if (inEntryPoint) {
                     if (shouldFlatten(*param.type))
                         flatten(loc, *variable);
+                    if (shouldSplit(*param.type))
+                        split(*variable);
                     assignLocations(*variable);
                 }
 
@@ -1239,6 +1492,7 @@
         } else
             paramNodes = intermediate.growAggregate(paramNodes, intermediate.addSymbol(*param.type, loc), loc);
     }
+
     intermediate.setAggregateOperator(paramNodes, EOpParameters, TType(EbtVoid), loc);
     loopNestingLevel = 0;
     controlFlowNestingLevel = 0;
@@ -1373,10 +1627,12 @@
         return intermediate.addBranch(EOpReturn, value, loc);
 }
 
-void HlslParseContext::handleFunctionArgument(TFunction* function, TIntermTyped*& arguments, TIntermTyped* newArg)
+void HlslParseContext::handleFunctionArgument(TFunction* function,
+                                              TIntermTyped*& arguments, TIntermTyped* newArg)
 {
     TParameter param = { 0, new TType, nullptr };
     param.type->shallowCopy(newArg->getType());
+
     function->addParameter(param);
     if (arguments)
         arguments = intermediate.growAggregate(arguments, newArg);
@@ -1392,14 +1648,15 @@
     if (left == nullptr || right == nullptr)
         return nullptr;
 
-    const auto mustFlatten = [&](const TIntermTyped& node) {
-        return wasFlattened(&node) && node.getAsSymbolNode() &&
-               flattenMap.find(node.getAsSymbolNode()->getId()) != flattenMap.end();
-    };
+    const bool isSplitLeft    = wasSplit(left);
+    const bool isSplitRight   = wasSplit(right);
 
-    const bool flattenLeft = mustFlatten(*left);
-    const bool flattenRight = mustFlatten(*right);
-    if (! flattenLeft && ! flattenRight)
+    const bool isFlattenLeft  = wasFlattened(left);
+    const bool isFlattenRight = wasFlattened(right);
+
+    // OK to do a single assign if both are split, or both are unsplit.  But if one is and the other
+    // isn't, we fall back to a memberwise copy.
+    if (! isFlattenLeft && ! isFlattenRight && !isSplitLeft && !isSplitRight)
         return intermediate.addAssign(op, left, right, loc);
 
     TIntermAggregate* assignList = nullptr;
@@ -1425,10 +1682,10 @@
     if (left->getType().isArray())
         memberCount = left->getType().getCumulativeArraySize();
 
-    if (flattenLeft)
+    if (isFlattenLeft)
         leftVariables = &flattenMap.find(left->getAsSymbolNode()->getId())->second.members;
 
-    if (flattenRight) {
+    if (isFlattenRight) {
         rightVariables = &flattenMap.find(right->getAsSymbolNode()->getId())->second.members;
     } else {
         // The RHS is not flattened.  There are several cases:
@@ -1456,73 +1713,118 @@
 
     int memberIdx = 0;
 
-    const auto getMember = [&](bool flatten, TIntermTyped* node,
-                               const TVector<TVariable*>& memberVariables, int member,
-                               TOperator op, const TType& memberType) -> TIntermTyped * {
+    // We track the outer-most aggregate, so that we can use its storage class later.
+    const TIntermTyped* outerLeft  = left;
+    const TIntermTyped* outerRight = right;
+
+    const auto getMember = [&](bool isLeft, TIntermTyped* node, int member, TIntermTyped* splitNode, int splitMember) -> TIntermTyped * {
         TIntermTyped* subTree;
-        if (flatten && isFinalFlattening(memberType)) {
-            subTree = intermediate.addSymbol(*memberVariables[memberIdx++]);
+
+        const bool flattened      = isLeft ? isFlattenLeft : isFlattenRight;
+        const bool split          = isLeft ? isSplitLeft : isSplitRight;
+        const TIntermTyped* outer = isLeft ? outerLeft   : outerRight;
+        const TVector<TVariable*>& flatVariables      = isLeft ? *leftVariables : *rightVariables;
+        const TOperator op = node->getType().isArray() ? EOpIndexDirect : EOpIndexDirectStruct;
+        const TType derefType(node->getType(), member);
+
+        if (split && derefType.isBuiltInInterstageIO()) {
+            // copy from interstage IO builtin if needed
+            subTree = intermediate.addSymbol(*interstageBuiltInIo.find(tInterstageIoData(derefType, outer->getType()))->second);
+        } else if (flattened && isFinalFlattening(derefType)) {
+            subTree = intermediate.addSymbol(*flatVariables[memberIdx++]);
         } else {
-            subTree = intermediate.addIndex(op, node, intermediate.addConstantUnion(member, loc), loc);
-            subTree->setType(memberType);
+            const TType splitDerefType(splitNode->getType(), splitMember);
+
+            subTree = intermediate.addIndex(op, splitNode, intermediate.addConstantUnion(splitMember, loc), loc);
+            subTree->setType(splitDerefType);
         }
 
         return subTree;
     };
 
-    // Cannot use auto here, because this is recursive, and auto can't work out the type without seeing the
-    // whole thing.  So, we'll resort to an explicit type via std::function.
-    const std::function<void(TIntermTyped* left, TIntermTyped* right)>
-    traverse = [&](TIntermTyped* left, TIntermTyped* right) -> void {
-        // If we get here, we are assigning to or from a whole array or struct that must be
-        // flattened, so have to do member-by-member assignment:
-
-        if (left->getType().isArray()) {
-            // array case
-            const TType dereferencedType(left->getType(), 0);
-
-            for (int element=0; element < left->getType().getOuterArraySize(); ++element) {
-                    // Add a new AST symbol node if we have a temp variable holding a complex RHS.
-                TIntermTyped* subRight = getMember(flattenRight, right, *rightVariables, element,
-                                                   EOpIndexDirect, dereferencedType);
-                TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, element,
-                                                  EOpIndexDirect, dereferencedType);
-
-                if (isFinalFlattening(dereferencedType))
-                    assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc);
-                else
-                    traverse(subLeft, subRight);
-            }
-        } else if (left->getType().isStruct()) {
-            // struct case
-            const auto& members = *left->getType().getStruct();
-
-            for (int member = 0; member < (int)members.size(); ++member) {
-                TIntermTyped* subRight = getMember(flattenRight, right, *rightVariables, member,
-                                                   EOpIndexDirectStruct, *members[member].type);
-                TIntermTyped* subLeft = getMember(flattenLeft, left, *leftVariables, member,
-                                                  EOpIndexDirectStruct, *members[member].type);
-
-                if (isFinalFlattening(*members[member].type))
-                    assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc);
-                else
-                    traverse(subLeft, subRight);
-            }
-        } else {
-            assert(0);  // we should never be called on a non-flattenable thing, because
-                        // that case bails out above to a simple copy.
-        }
-
-    };
-
     // Use the proper RHS node: a new symbol from a TVariable, copy
     // of an TIntermSymbol node, or sometimes the right node directly.
     right = rhsTempVar   ? intermediate.addSymbol(*rhsTempVar, loc) :
             cloneSymNode ? intermediate.addSymbol(*cloneSymNode) :
             right;
 
+    // Cannot use auto here, because this is recursive, and auto can't work out the type without seeing the
+    // whole thing.  So, we'll resort to an explicit type via std::function.
+    const std::function<void(TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight)>
+    traverse = [&](TIntermTyped* left, TIntermTyped* right, TIntermTyped* splitLeft, TIntermTyped* splitRight) -> void {
+        // If we get here, we are assigning to or from a whole array or struct that must be
+        // flattened, so have to do member-by-member assignment:
+
+        if (left->getType().isArray()) {
+            const TType dereferencedType(left->getType(), 0);
+
+            // array case
+            for (int element=0; element < left->getType().getOuterArraySize(); ++element) {
+                    // Add a new AST symbol node if we have a temp variable holding a complex RHS.
+                TIntermTyped* subLeft  = getMember(true,  left,  element, left, element);
+                TIntermTyped* subRight = getMember(false, right, element, right, element);
+
+                if (isFinalFlattening(dereferencedType))
+                    assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subLeft, subRight, loc), loc);
+                else
+                    traverse(subLeft, subRight, splitLeft, splitRight);
+            }
+        } else if (left->getType().isStruct()) {
+            // struct case
+            const auto& membersL = *left->getType().getStruct();
+            const auto& membersR = *right->getType().getStruct();
+
+            // These track the members in the split structures corresponding to the same in the unsplit structures,
+            // which we traverse in parallel.
+            int memberL = 0;
+            int memberR = 0;
+
+            for (int member = 0; member < int(membersL.size()); ++member) {
+                const TType& typeL = *membersL[member].type;
+                const TType& typeR = *membersR[member].type;
+
+                TIntermTyped* subLeft  = getMember(true,  left, member, left, member);
+                TIntermTyped* subRight = getMember(false, right, member, right, member);
+
+                // If there is no splitting, use the same values to avoid inefficiency.
+                TIntermTyped* subSplitLeft =  isSplitLeft  ? getMember(true,  left,  member, splitLeft, memberL) : subLeft;
+                TIntermTyped* subSplitRight = isSplitRight ? getMember(false, right, member, splitRight, memberR) : subRight;
+
+                // If this is the final flattening (no nested types below to flatten) we'll copy the member, else
+                // recurse into the type hierarchy.  However, if splitting the struct, that means we can copy a whole
+                // subtree here IFF it does not itself contain any interstage built-in IO variables, so we only have to
+                // recurse into it if there's something for splitting to do.  That can save a lot of AST verbosity for
+                // a bunch of memberwise copies.
+                if (isFinalFlattening(typeL) || (!isFlattenLeft && !isFlattenRight && 
+                                                 !typeL.containsBuiltInInterstageIO() && !typeR.containsBuiltInInterstageIO())) {
+                    assignList = intermediate.growAggregate(assignList, intermediate.addAssign(op, subSplitLeft, subSplitRight, loc), loc);
+                } else {
+                    traverse(subLeft, subRight, subSplitLeft, subSplitRight);
+                }
+
+                memberL += (typeL.isBuiltInInterstageIO() ? 0 : 1);
+                memberR += (typeR.isBuiltInInterstageIO() ? 0 : 1);
+            }
+        } else {
+            assert(0);  // we should never be called on a non-flattenable thing, because
+                        // that case bails out above to a simple copy.
+        }
+
+    };
+
+    TIntermTyped* splitLeft  = left;
+    TIntermTyped* splitRight = right;
+
+    // If either left or right was a split structure, we must read or write it, but still have to
+    // parallel-recurse through the unsplit structure to identify the builtin IO vars.
+    if (isSplitLeft)
+        splitLeft = intermediate.addSymbol(*getSplitIoVar(left), loc);
+
+    if (isSplitRight)
+        splitRight = intermediate.addSymbol(*getSplitIoVar(right), loc);
+
     // This makes the whole assignment, recursing through subtypes as needed.
-    traverse(left, right);
+    traverse(left, right, splitLeft, splitRight);
 
     assert(assignList != nullptr);
     assignList->setOperator(EOpSequence);
@@ -2214,9 +2516,9 @@
             emit->setType(TType(EbtVoid));
 
             sequence = intermediate.growAggregate(sequence,
-                                                  intermediate.addAssign(EOpAssign, 
-                                                                         argAggregate->getSequence()[0]->getAsTyped(),
-                                                                         argAggregate->getSequence()[1]->getAsTyped(), loc),
+                                                  handleAssign(loc, EOpAssign, 
+                                                               argAggregate->getSequence()[0]->getAsTyped(),
+                                                               argAggregate->getSequence()[1]->getAsTyped()),
                                                   loc);
 
             sequence = intermediate.growAggregate(sequence, emit);
@@ -2840,7 +3142,7 @@
             else
                 error(arg->getLoc(), "cannot convert input argument, argument", "", "%d", i);
         } else {
-            if (wasFlattened(arg)) {
+            if (wasFlattened(arg) || wasSplit(arg)) {
                 // Will make a two-level subtree.
                 // The deepest will copy member-by-member to build the structure to pass.
                 // The level above that will be a two-operand EOpComma sequence that follows the copy by the
@@ -4781,6 +5083,43 @@
         error(loc, "name already defined", "typedef", identifier.c_str());
 }
 
+// Type sanitization: return existing sanitized (temporary) type if there is one, else make new one.
+TType* HlslParseContext::sanitizeType(TType* type)
+{
+    // We only do this for structs.
+    if (!type->isStruct())
+        return type;
+
+    // Type sanitization: if this is declaring a variable of a type that contains
+    // interstage IO, we want to make it a temporary.
+    const auto sanitizedTypeIter = sanitizedTypeMap.find(type->getStruct());
+
+    if (sanitizedTypeIter != sanitizedTypeMap.end()) {
+        // We've sanitized this before.  Use that one.
+        TType* sanitizedType = new TType();
+        sanitizedType->shallowCopy(*sanitizedTypeIter->second);
+
+        // Arrayness is not part of the sanitized type.  Use the input type's arrayness.
+        if (type->isArray())
+            sanitizedType->newArraySizes(type->getArraySizes());
+        else
+            sanitizedType->clearArraySizes();
+        return sanitizedType;
+    } else {
+        if (type->containsBuiltInInterstageIO()) {
+            // This means the type contains interstage IO, but we've never encountered it before.
+            // Copy it, sanitize it, and remember it in the sanitizedTypeMap
+            TType* sanitizedType = type->clone();
+            sanitizedType->makeTemporary();
+            sanitizedTypeMap[type->getStruct()] = sanitizedType;
+            return sanitizedType;
+        } else {
+            // This means the type has no interstage IO, so we can use it as is.
+            return type;
+        }
+    }
+}
+
 //
 // Do everything necessary to handle a variable (non-block) declaration.
 // Either redeclaring a variable, or making a new one, updating the symbol
@@ -4806,15 +5145,20 @@
     inheritGlobalDefaults(type.getQualifier());
 
     const bool flattenVar = shouldFlatten(type);
+    const bool splitVar   = shouldSplit(type);
+
+    // Type sanitization: if this is declaring a variable of a type that contains
+    // interstage IO, we want to make it a temporary.
+    TType* sanitizedType = sanitizeType(&type);
 
     // Declare the variable
     if (type.isArray()) {
         // array case
-        declareArray(loc, identifier, type, symbol, !flattenVar);
+        declareArray(loc, identifier, *sanitizedType, symbol, !flattenVar);
     } else {
         // non-array case
         if (! symbol)
-            symbol = declareNonArray(loc, identifier, type, !flattenVar);
+            symbol = declareNonArray(loc, identifier, *sanitizedType, !flattenVar);
         else if (type != symbol->getType())
             error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str());
     }
@@ -4822,6 +5166,9 @@
     if (flattenVar)
         flatten(loc, *symbol->getAsVariable());
 
+    if (splitVar)
+        split(*symbol->getAsVariable());
+
     if (! symbol)
         return nullptr;
 
@@ -5863,4 +6210,13 @@
         name = new TString(intermediate.getEntryPointName().c_str());
 }
 
+// post-processing
+void HlslParseContext::finish()
+{
+    addInterstageIoToLinkage();
+
+    TParseContextBase::finish();
+}
+
+
 } // end namespace glslang
diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h
index 229f697..47ea5aa 100755
--- a/hlsl/hlslParseHelper.h
+++ b/hlsl/hlslParseHelper.h
@@ -186,6 +186,9 @@
     void fixConstInit(const TSourceLoc&, TString& identifier, TType& type, TIntermTyped*& initializer);
     void inheritGlobalDefaults(TQualifier& dst) const;
     TVariable* makeInternalVariable(const char* name, const TType&) const;
+    TVariable* makeInternalVariable(const TString& name, const TType& type) const {
+        return makeInternalVariable(name.c_str(), type);
+    }
     TVariable* declareNonArray(const TSourceLoc&, TString& identifier, TType&, bool track);
     void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&, bool track);
     TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable);
@@ -198,7 +201,7 @@
 
     // Array and struct flattening
     bool shouldFlatten(const TType& type) const;
-    TIntermTyped* flattenAccess(const TSourceLoc&, TIntermTyped* base, int member);
+    TIntermTyped* flattenAccess(TIntermTyped* base, int member);
     bool shouldFlattenIO(const TType&) const;
     bool shouldFlattenUniform(const TType&) const;
     bool wasFlattened(const TIntermTyped* node) const;
@@ -206,11 +209,30 @@
     int  addFlattenedMember(const TSourceLoc& loc, const TVariable&, const TType&, TFlattenData&, const TString& name, bool track);
     bool isFinalFlattening(const TType& type) const { return !(type.isStruct() || type.isArray()); }
 
+    // Structure splitting (splits interstage builtin types into its own struct)
+    bool shouldSplit(const TType&);
+    TIntermTyped* splitAccessStruct(const TSourceLoc& loc, TIntermTyped*& base, int& member);
+    void splitAccessArray(const TSourceLoc& loc, TIntermTyped* base, TIntermTyped* index);
+    TType& split(TType& type, TString name, const TType* outerStructType = nullptr);
+    void split(TIntermTyped*);
+    void split(const TVariable&);
+    bool wasSplit(const TIntermTyped* node) const;
+    bool wasSplit(int id) const { return splitIoVars.find(id) != splitIoVars.end(); }
+    TVariable* getSplitIoVar(const TIntermTyped* node) const;
+    TVariable* getSplitIoVar(const TVariable* var) const;
+    TVariable* getSplitIoVar(int id) const;
+    void addInterstageIoToLinkage();
+
     void flatten(const TSourceLoc& loc, const TVariable& variable);
     int flatten(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
     int flattenStruct(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
     int flattenArray(const TSourceLoc& loc, const TVariable& variable, const TType&, TFlattenData&, TString name);
 
+    // Type sanitization: return existing sanitized (temporary) type if there is one, else make new one.
+    TType* sanitizeType(TType*);
+
+    void finish(); // post-processing
+
     // Current state of parsing
     struct TPragma contextPragma;
     int loopNestingLevel;        // 0 if outside all loops
@@ -276,6 +298,38 @@
     TVector<int> flattenLevel;  // nested postfix operator level for flattening
     TVector<int> flattenOffset; // cumulative offset for flattening
 
+    // Sanitized type map.  During declarations we use the sanitized form of the type
+    // if it exists.
+    TMap<const TTypeList*, TType*> sanitizedTypeMap;
+
+    // Structure splitting data:
+    TMap<int, TVariable*>              splitIoVars;  // variables with the builtin interstage IO removed, indexed by unique ID.
+
+    // The builtin interstage IO map considers e.g, EvqPosition on input and output separately, so that we
+    // can build the linkage correctly if position appears on both sides.  Otherwise, multiple positions
+    // are considered identical.
+    struct tInterstageIoData {
+        tInterstageIoData(const TType& memberType, const TType& storageType) :
+            builtIn(memberType.getQualifier().builtIn),
+            storage(storageType.getQualifier().storage) { }
+
+        TBuiltInVariable  builtIn;
+        TStorageQualifier storage;
+
+        // ordering for maps
+        bool operator<(const tInterstageIoData d) const {
+            return (builtIn != d.builtIn) ? (builtIn < d.builtIn) : (storage < d.storage);
+        }
+    };
+
+    TMap<tInterstageIoData, TVariable*> interstageBuiltInIo; // individual builtin interstage IO vars, inxed by builtin type.
+
+    // We have to move array references to structs containing builtin interstage IO to the split variables.
+    // This is only handled for one level.  This stores the index, because we'll need it in the future, since
+    // unlike normal array references, here the index happens before we discover what it applies to.
+    TIntermTyped* builtInIoIndex;
+    TIntermTyped* builtInIoBase;
+
     unsigned int nextInLocation;
     unsigned int nextOutLocation;