diff --git a/Test/baseResults/hlsl.frag.out b/Test/baseResults/hlsl.frag.out index bb5e5a7c..b96e2acd 100644 --- a/Test/baseResults/hlsl.frag.out +++ b/Test/baseResults/hlsl.frag.out @@ -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 diff --git a/Test/hlsl.frag b/Test/hlsl.frag index 8ed18aa8..9107248f 100644 --- a/Test/hlsl.frag +++ b/Test/hlsl.frag @@ -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 diff --git a/Test/runtests b/Test/runtests index 67a374cf..d5099a91 100755 --- a/Test/runtests +++ b/Test/runtests @@ -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 diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index bbf3c999..20d7bb3f 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -33,6 +33,23 @@ //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; diff --git a/hlsl/hlslGrammar.h b/hlsl/hlslGrammar.h index 3e042ffe..8239d3e9 100755 --- a/hlsl/hlslGrammar.h +++ b/hlsl/hlslGrammar.h @@ -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); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 9a0531c7..95a266fd 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -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(""); diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index 1537cfc8..88a3fe2f 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -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);