From c633f644da9b069c687df6b187f3f43f20b13eca Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Mon, 3 Apr 2017 21:48:37 -0600 Subject: [PATCH] HLSL: Non-functional: rationalize making constructors. Improves foundation for adding scalar casts. Makes handle/make names more sane, better commented, uses more precise subclass typing, and removes mutual recursion between converting initializer lists and making constructors. --- glslang/Include/revision.h | 2 +- hlsl/hlslGrammar.cpp | 6 +++--- hlsl/hlslParseHelper.cpp | 31 +++++++++++++++++++++++-------- hlsl/hlslParseHelper.h | 5 +++-- 4 files changed, 30 insertions(+), 14 deletions(-) diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 175e4888..df5bcfee 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // For the version, it uses the latest git tag followed by the number of commits. // For the date, it uses the current date (when then script is run). -#define GLSLANG_REVISION "Overload400-PrecQual.1965" +#define GLSLANG_REVISION "Overload400-PrecQual.1971" #define GLSLANG_DATE "03-Apr-2017" diff --git a/hlsl/hlslGrammar.cpp b/hlsl/hlslGrammar.cpp index a1c05cf4..3b4bb4cd 100755 --- a/hlsl/hlslGrammar.cpp +++ b/hlsl/hlslGrammar.cpp @@ -2219,7 +2219,7 @@ bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTy // For initializer lists, we have to const-fold into a constructor for the type, so build // that. - TFunction* constructor = parseContext.handleConstructorCall(token.loc, type); + TFunction* constructor = parseContext.makeConstructorCall(token.loc, type); if (constructor == nullptr) // cannot construct return false; @@ -2628,7 +2628,7 @@ bool HlslGrammar::acceptUnaryExpression(TIntermTyped*& node) return false; // Hook it up like a constructor - TFunction* constructorFunction = parseContext.handleConstructorCall(loc, castType); + TFunction* constructorFunction = parseContext.makeConstructorCall(loc, castType); if (constructorFunction == nullptr) { expected("type that can be constructed"); return false; @@ -2841,7 +2841,7 @@ bool HlslGrammar::acceptConstructor(TIntermTyped*& node) // type TType type; if (acceptType(type)) { - TFunction* constructorFunction = parseContext.handleConstructorCall(token.loc, type); + TFunction* constructorFunction = parseContext.makeConstructorCall(token.loc, type); if (constructorFunction == nullptr) return false; diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index 7f6f7b21..7278dc9c 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -3897,7 +3897,7 @@ TIntermTyped* HlslParseContext::handleFunctionCall(const TSourceLoc& loc, TFunct // // It's a constructor, of type 'type'. // - result = addConstructor(loc, arguments, type); + result = handleConstructor(loc, arguments, type); if (result == nullptr) error(loc, "cannot construct with these arguments", type.getCompleteString().c_str(), ""); } @@ -4308,9 +4308,13 @@ void HlslParseContext::builtInOpCheck(const TSourceLoc& loc, const TFunction& fn } // -// Handle seeing a built-in constructor in a grammar production. +// Handle seeing something in a grammar production that can be done by calling +// a constructor. // -TFunction* HlslParseContext::handleConstructorCall(const TSourceLoc& loc, const TType& type) +// The constructor still must be "handled" by handleFunctionCall(), which will +// then call handleConstructor(). +// +TFunction* HlslParseContext::makeConstructorCall(const TSourceLoc& loc, const TType& type) { TOperator op = intermediate.mapTypeToConstructorOp(type); @@ -6495,9 +6499,9 @@ TIntermTyped* HlslParseContext::convertInitializerList(const TSourceLoc& loc, co // Now that the subtree is processed, process this node as if the // initializer list is a set of arguments to a constructor. - TIntermNode* emulatedConstructorArguments; + TIntermTyped* emulatedConstructorArguments; if (initList->getSequence().size() == 1) - emulatedConstructorArguments = initList->getSequence()[0]; + emulatedConstructorArguments = initList->getSequence()[0]->getAsTyped(); else emulatedConstructorArguments = initList; @@ -6519,15 +6523,26 @@ void HlslParseContext::lengthenList(const TSourceLoc& loc, TIntermSequence& list // // Returns nullptr for an error or the constructed node (aggregate or typed) for no error. // -TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermNode* node, const TType& type) +TIntermTyped* HlslParseContext::handleConstructor(const TSourceLoc& loc, TIntermTyped* node, const TType& type) { - if (node == nullptr || node->getAsTyped() == nullptr) + if (node == nullptr) return nullptr; // Handle the idiom "(struct type)0" + // Sequences (in an aggregate) for initialization are not yet tagged with + // an operator or type, so it is too early to ask if they are scalars. if (type.isStruct() && isZeroConstructor(node)) return convertInitializerList(loc, type, intermediate.makeAggregate(loc)); + return addConstructor(loc, node, type); +} + +// Add a constructor, either from the grammar, or other programmatic reasons. +// +// Return nullptr if it can't be done. +// +TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermTyped* node, const TType& type) +{ TIntermAggregate* aggrNode = node->getAsAggregate(); TOperator op = intermediate.mapTypeToConstructorOp(type); @@ -6565,7 +6580,7 @@ TIntermTyped* HlslParseContext::addConstructor(const TSourceLoc& loc, TIntermNod else if (op == EOpConstructStruct) newNode = constructAggregate(node, *(*memberTypes).type, 1, node->getLoc()); else - newNode = constructBuiltIn(type, op, node->getAsTyped(), node->getLoc(), false); + newNode = constructBuiltIn(type, op, node, node->getLoc(), false); if (newNode && (type.isArray() || op == EOpConstructStruct)) newNode = intermediate.setAggregateOperator(newNode, EOpConstructStruct, type, loc); diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index ff597c28..75468434 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -96,7 +96,7 @@ public: void addInputArgumentConversions(const TFunction&, TIntermTyped*&); TIntermTyped* addOutputArgumentConversions(const TFunction&, TIntermOperator&); void builtInOpCheck(const TSourceLoc&, const TFunction&, TIntermOperator&); - TFunction* handleConstructorCall(const TSourceLoc&, const TType&); + TFunction* makeConstructorCall(const TSourceLoc&, const TType&); void handleSemantic(TSourceLoc, TQualifier&, TBuiltInVariable, const TString& upperCase); void handlePackOffset(const TSourceLoc&, TQualifier&, const glslang::TString& location, const glslang::TString* component); @@ -141,7 +141,8 @@ public: TSymbol* lookupUserType(const TString&, TType&); TIntermNode* declareVariable(const TSourceLoc&, const TString& identifier, TType&, TIntermTyped* initializer = 0); void lengthenList(const TSourceLoc&, TIntermSequence& list, int size); - TIntermTyped* addConstructor(const TSourceLoc&, TIntermNode*, const TType&); + TIntermTyped* handleConstructor(const TSourceLoc&, TIntermTyped*, const TType&); + TIntermTyped* addConstructor(const TSourceLoc&, TIntermTyped*, const TType&); TIntermTyped* constructAggregate(TIntermNode*, const TType&, int, const TSourceLoc&); TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermTyped*, const TSourceLoc&, bool subset); void declareBlock(const TSourceLoc&, TType&, const TString* instanceName = 0, TArraySizes* arraySizes = 0);