HLSL: Hook up constructor expressions through the AST.
authorJohn Kessenich <cepheus@frii.com>
Sun, 13 Mar 2016 17:24:20 +0000 (11:24 -0600)
committerJohn Kessenich <cepheus@frii.com>
Sun, 13 Mar 2016 17:24:20 +0000 (11:24 -0600)
Test/baseResults/hlsl.frag.out
Test/hlsl.frag
Test/runtests
hlsl/hlslGrammar.cpp
hlsl/hlslGrammar.h
hlsl/hlslParseHelper.cpp
hlsl/hlslParseHelper.h

index bb5e5a7..b96e2ac 100644 (file)
@@ -1,8 +1,50 @@
 hlsl.frag
+Shader version: 100
+gl_FragCoord origin is upper left
+0:? Sequence
+0:5  move second child to first child (temp 4-component vector of float)
+0:5    'AmbientColor' (temp 4-component vector of float)
+0:?     Constant:
+0:?       1.000000
+0:?       0.500000
+0:?       0.000000
+0:?       1.000000
+0:6  move second child to first child (temp float)
+0:6    'AmbientIntensity' (temp float)
+0:6    Constant:
+0:6      0.100000
+0:?   Linker Objects
+0:?     'World' (temp 4X4 matrix of float)
+0:?     'View' (temp 4X4 matrix of float)
+0:?     'Projection' (temp 4X4 matrix of float)
+0:?     'AmbientColor' (temp 4-component vector of float)
+0:?     'AmbientIntensity' (temp float)
+
 
 Linked fragment stage:
 
 
+Shader version: 100
+gl_FragCoord origin is upper left
+0:? Sequence
+0:5  move second child to first child (temp 4-component vector of float)
+0:5    'AmbientColor' (temp 4-component vector of float)
+0:?     Constant:
+0:?       1.000000
+0:?       0.500000
+0:?       0.000000
+0:?       1.000000
+0:6  move second child to first child (temp float)
+0:6    'AmbientIntensity' (temp float)
+0:6    Constant:
+0:6      0.100000
+0:?   Linker Objects
+0:?     'World' (temp 4X4 matrix of float)
+0:?     'View' (temp 4X4 matrix of float)
+0:?     'Projection' (temp 4X4 matrix of float)
+0:?     'AmbientColor' (temp 4-component vector of float)
+0:?     'AmbientIntensity' (temp float)
+
 // Module Version 10000
 // Generated by (magic number): 80001
 // Id's are bound by 17
index 8ed18aa..9107248 100644 (file)
@@ -2,7 +2,7 @@ float4x4 World;
 float4x4 View;
 float4x4 Projection;
 
-float4 AmbientColor = float4(1, 1, 1, 1);
+float4 AmbientColor = float4(1, 0.5, 0, 1);
 float AmbientIntensity = 0.1;
 
 //float4 PixelShaderFunction(VertexShaderOutput input) : COLOR0
index 67a374c..d5099a9 100755 (executable)
@@ -66,7 +66,7 @@ while read t; do
     *)
       echo Running HLSL-to-SPIR-V $t...
       b=`basename $t`
-      $EXE -D -e PixelShaderFunction -H $t > $TARGETDIR/$b.out
+      $EXE -D -e PixelShaderFunction -H -i $t > $TARGETDIR/$b.out
       diff -b $BASEDIR/$b.out $TARGETDIR/$b.out || HASERROR=1
       ;;
   esac
index bbf3c99..20d7bb3 100755 (executable)
 //POSSIBILITY OF SUCH DAMAGE.
 //
 
+//
+// This is a set of mutually recursive methods implementing the HLSL grammar.
+// Generally, each returns
+//  - through an argument: a type specifically appropriate to which rule it
+//    recognized
+//  - through the return value: true/false to indicate whether or not it
+//    recognized its rule
+//
+// As much as possible, only grammar recognition should happen in this file,
+// with all other work being farmed out to hlslParseHelper.cpp, which it turn
+// will build the AST.
+//
+// The next token, yet to be "accepted" is always sitting in 'token'.
+// When a method says it accepts a rule, that means all tokens involved
+// in the rule will have been consumed, and none left in 'token'.
+//
+
 #include "hlslTokens.h"
 #include "hlslGrammar.h"
 
@@ -74,11 +91,21 @@ bool HlslGrammar::acceptTokenClass(EHlslTokenClass tokenClass)
 //
 bool HlslGrammar::acceptCompilationUnit()
 {
+    TIntermNode* unitNode = nullptr;
+
     while (token.tokenClass != EHTokNone) {
-        if (! acceptDeclaration())
+        // externalDeclaration
+        TIntermNode* declarationNode;
+        if (! acceptDeclaration(declarationNode))
             return false;
+
+        // hook it up
+        unitNode = parseContext.intermediate.growAggregate(unitNode, declarationNode);
     }
 
+    // set root of AST
+    parseContext.intermediate.setTreeRoot(unitNode);
+
     return true;
 }
 
@@ -90,8 +117,13 @@ bool HlslGrammar::acceptCompilationUnit()
 //      | fully_specified_type identifier function_parameters ;         // function prototype
 //      | fully_specified_type function_parameters compound_statement   // function definition
 //
-bool HlslGrammar::acceptDeclaration()
+// 'node' could get created if the declaration creates code, like an initializer
+// or a function body.
+//
+bool HlslGrammar::acceptDeclaration(TIntermNode*& node)
 {
+    node = nullptr;
+
     // fully_specified_type
     TType type;
     if (! acceptFullySpecifiedType(type))
@@ -114,7 +146,7 @@ bool HlslGrammar::acceptDeclaration()
 
         // ;
         if (acceptTokenClass(EHTokSemicolon)) {
-            parseContext.declareVariable(declLoc, *declName, type, 0, expressionNode);
+            node = parseContext.declareVariable(declLoc, *declName, type, 0, expressionNode);
             return true;
         }
     }
@@ -252,9 +284,9 @@ bool HlslGrammar::acceptType(TType& type)
 // expression
 //      : identifier
 //      | ( expression )
-//      | type(...) // constructor
+//      | type(...)                 // constructor
 //      | literal
-//      | identifier + identifier
+//      | identifier operator identifier   // to be generalized to all expressions
 //
 bool HlslGrammar::acceptExpression(TIntermTyped*& node)
 {
@@ -282,19 +314,11 @@ bool HlslGrammar::acceptExpression(TIntermTyped*& node)
     if (acceptLiteral(node))
         return true;
 
-    // type(...) // constructor
-    TType type;
-    if (acceptType(type)) {
-        TIntermSequence* arguments;
-        if (! acceptArguments(arguments)) {
-            expected("constructor arguments");
-            return false;
-        }
-
+    // type(...)     // constructor
+    if (acceptConstructor(node))
         return true;
-    }
 
-    // identifier + identifier
+    // identifier operator identifier
     if (token.tokenClass == EHTokIdentifier) {
         TIntermTyped* left = parseContext.handleVariable(token.loc, token.symbol, token.string);
         advanceToken();
@@ -318,22 +342,61 @@ bool HlslGrammar::acceptExpression(TIntermTyped*& node)
     return true;
 }
 
+// constructor
+//      : type arguments
+//
+bool HlslGrammar::acceptConstructor(TIntermTyped*& node)
+{
+    // type
+    TType type;
+    if (acceptType(type)) {
+        TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type);
+        if (constructorFunction == nullptr)
+            return false;
+
+        // arguments
+        TIntermAggregate* arguments = nullptr;
+        if (! acceptArguments(constructorFunction, arguments)) {
+            expected("constructor arguments");
+            return false;
+        }
+
+        // hook it up
+        node = parseContext.handleFunctionCall(arguments->getLoc(), constructorFunction, arguments);
+
+        return true;
+    }
+
+    return false;
+}
+
 // arguments
 //      : ( expression , expression, ... )
 //
-bool HlslGrammar::acceptArguments(TIntermSequence*& arguments)
+// The arguments are pushed onto the 'function' argument list and
+// onto the 'arguments' aggregate.
+//
+bool HlslGrammar::acceptArguments(TFunction* function, TIntermAggregate*& arguments)
 {
+    // (
     if (! acceptTokenClass(EHTokLeftParen))
         return false;
 
     do {
+        // expression
         TIntermTyped* arg;
         if (! acceptExpression(arg))
             break;
+
+        // hook it up
+        parseContext.handleFunctionArgument(function, arguments, arg);
+
+        // ,
         if (! acceptTokenClass(EHTokComma))
             break;
     } while (true);
 
+    // )
     if (! acceptTokenClass(EHTokRightParen)) {
         expected("right parenthesis");
         return false;
index 3e042ff..8239d3e 100755 (executable)
@@ -55,13 +55,14 @@ namespace glslang {
         bool acceptTokenClass(EHlslTokenClass);
 
         bool acceptCompilationUnit();
-        bool acceptDeclaration();
+        bool acceptDeclaration(TIntermNode*& node);
         bool acceptFullySpecifiedType(TType&);
         void acceptQualifier(TQualifier&);
         bool acceptType(TType&);
         bool acceptCompoundStatement();
         bool acceptExpression(TIntermTyped*&);
-        bool acceptArguments(TIntermSequence*&);
+        bool acceptConstructor(TIntermTyped*&);
+        bool acceptArguments(TFunction*, TIntermAggregate*&);
         bool acceptLiteral(TIntermTyped*&);
         bool acceptOperator(TOperator& op);
 
index 9a0531c..95a266f 100755 (executable)
@@ -754,6 +754,14 @@ TIntermAggregate* HlslParseContext::handleFunctionDefinition(const TSourceLoc& l
     return paramNodes;
 }
 
+void HlslParseContext::handleFunctionArgument(TFunction* function, TIntermAggregate*& arguments, TIntermTyped* arg)
+{
+    TParameter param = { 0, new TType };
+    param.type->shallowCopy(arg->getType());
+    function->addParameter(param);
+    arguments = intermediate.growAggregate(arguments, arg);
+}
+
 //
 // Handle seeing function call syntax in the grammar, which could be any of
 //  - .length() method
@@ -1182,18 +1190,13 @@ void HlslParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fn
 //
 // Handle seeing a built-in constructor in a grammar production.
 //
-TFunction* HlslParseContext::handleConstructorCall(const TSourceLoc& loc, const TPublicType& publicType)
+TFunction* HlslParseContext::handleConstructorCall(const TSourceLoc& loc, const TType& type)
 {
-    TType type(publicType);
-    type.getQualifier().precision = EpqNone;
-
     TOperator op = mapTypeToConstructorOp(type);
 
     if (op == EOpNull) {
         error(loc, "cannot construct this type", type.getBasicString(), "");
-        op = EOpConstructFloat;
-        TType errorType(EbtFloat);
-        type.shallowCopy(errorType);
+        return nullptr;
     }
 
     TString empty("");
index 1537cfc..88a3fe2 100755 (executable)
@@ -83,12 +83,13 @@ public:
     TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field);
     TFunction* handleFunctionDeclarator(const TSourceLoc&, TFunction& function, bool prototype);
     TIntermAggregate* handleFunctionDefinition(const TSourceLoc&, TFunction&);
+    void handleFunctionArgument(TFunction*, TIntermAggregate*&, TIntermTyped*);
     TIntermTyped* handleFunctionCall(const TSourceLoc&, TFunction*, TIntermNode*);
     TIntermTyped* handleLengthMethod(const TSourceLoc&, TFunction*, TIntermNode*);
     void addInputArgumentConversions(const TFunction&, TIntermNode*&) const;
     TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermAggregate&) const;
     void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&);
-    TFunction* handleConstructorCall(const TSourceLoc&, const TPublicType&);
+    TFunction* handleConstructorCall(const TSourceLoc&, const TType&);
 
     bool parseVectorFields(const TSourceLoc&, const TString&, int vecSize, TVectorFields&);
     void assignError(const TSourceLoc&, const char* op, TString left, TString right);