HLSL: Wrap the entry-point; need to write 'in' args, and support 'inout' args.

This needs some render testing, but is destined to be part of master.

This also leads to a variety of other simplifications.
 - IO are global symbols, so only need one list of linkage nodes (deferred)
 - no longer need parse-context-wide 'inEntryPoint' state, entry-point is localized
 - several parts of splitting/flattening are now localized
diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp
index 6c20413..9ef296d 100755
--- a/hlsl/hlslGrammar.cpp
+++ b/hlsl/hlslGrammar.cpp
@@ -131,12 +131,15 @@
             continue;
 
         // externalDeclaration
-        TIntermNode* declarationNode;
-        if (! acceptDeclaration(declarationNode))
+        TIntermNode* declarationNode1;
+        TIntermNode* declarationNode2 = nullptr;  // sometimes the grammar for a single declaration creates two
+        if (! acceptDeclaration(declarationNode1, declarationNode2))
             return false;
 
         // hook it up
-        unitNode = intermediate.growAggregate(unitNode, declarationNode);
+        unitNode = intermediate.growAggregate(unitNode, declarationNode1);
+        if (declarationNode2 != nullptr)
+            unitNode = intermediate.growAggregate(unitNode, declarationNode2);
     }
 
     // set root of AST
@@ -292,9 +295,18 @@
 // 'node' could get populated if the declaration creates code, like an initializer
 // or a function body.
 //
+// 'node2' could get populated with a second decoration tree if a single source declaration
+// leads to two subtrees that need to be peers higher up.
+//
 bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
 {
+    TIntermNode* node2;
+    return acceptDeclaration(node, node2);
+}
+bool HlslGrammar::acceptDeclaration(TIntermNode*& node, TIntermNode*& node2)
+{
     node = nullptr;
+    node2 = nullptr;
     bool list = false;
 
     // attributes
@@ -340,7 +352,7 @@
                     parseContext.error(idToken.loc, "function body can't be in a declarator list", "{", "");
                 if (typedefDecl)
                     parseContext.error(idToken.loc, "function body can't be in a typedef", "{", "");
-                return acceptFunctionDefinition(function, node, attributes);
+                return acceptFunctionDefinition(function, node, node2, attributes);
             } else {
                 if (typedefDecl)
                     parseContext.error(idToken.loc, "function typedefs not implemented", "{", "");
@@ -1916,22 +1928,22 @@
 
 // Do the work to create the function definition in addition to
 // parsing the body (compound_statement).
-bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, const TAttributeMap& attributes)
+bool HlslGrammar::acceptFunctionDefinition(TFunction& function, TIntermNode*& node, TIntermNode*& node2, const TAttributeMap& attributes)
 {
     TFunction& functionDeclarator = parseContext.handleFunctionDeclarator(token.loc, function, false /* not prototype */);
     TSourceLoc loc = token.loc;
 
     // This does a pushScope()
-    node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes);
+    node = parseContext.handleFunctionDefinition(loc, functionDeclarator, attributes, node2);
 
     // compound_statement
     TIntermNode* functionBody = nullptr;
-    if (acceptCompoundStatement(functionBody)) {
-        parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
-        return true;
-    }
+    if (! acceptCompoundStatement(functionBody))
+        return false;
 
-    return false;
+    parseContext.handleFunctionBody(loc, functionDeclarator, functionBody, node);
+
+    return true;
 }
 
 // Accept an expression with parenthesis around it, where