Commit 13389b66 by Olli Etuaho Committed by Commit Bot

Split TIntermDeclaration from TIntermAggregate

The new class TIntermDeclaration is now used for struct, interface block and variable declarations. TIntermDeclaration nodes do not have a type - rather the type is stored in each child node. The types may differ in case the declaration is a series of array declarators with mismatching sizes. TIntermAggregate is still used for function calls, function prototypes, function parameter lists and invariant declarations. BUG=angleproject:1490 TEST=angle_unittests Change-Id: I0457188f354481470855f61ac1c878fc2579b1d1 Reviewed-on: https://chromium-review.googlesource.com/400023 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 3feb3ff5
...@@ -111,7 +111,7 @@ bool DeferGlobalInitializersTraverser::visitBinary(Visit visit, TIntermBinary *n ...@@ -111,7 +111,7 @@ bool DeferGlobalInitializersTraverser::visitBinary(Visit visit, TIntermBinary *n
if (symbolNode->getQualifier() == EvqConst) if (symbolNode->getQualifier() == EvqConst)
{ {
// All of the siblings in the same declaration need to have consistent qualifiers. // All of the siblings in the same declaration need to have consistent qualifiers.
auto *siblings = getParentNode()->getAsAggregate()->getSequence(); auto *siblings = getParentNode()->getAsDeclarationNode()->getSequence();
for (TIntermNode *siblingNode : *siblings) for (TIntermNode *siblingNode : *siblings)
{ {
TIntermBinary *siblingBinary = siblingNode->getAsBinaryNode(); TIntermBinary *siblingBinary = siblingNode->getAsBinaryNode();
......
...@@ -598,6 +598,24 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node) ...@@ -598,6 +598,24 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
return visitChildren; return visitChildren;
} }
bool EmulatePrecision::visitDeclaration(Visit visit, TIntermDeclaration *node)
{
// Variable or interface block declaration.
if (visit == PreVisit)
{
mDeclaringVariables = true;
}
else if (visit == InVisit)
{
mDeclaringVariables = true;
}
else
{
mDeclaringVariables = false;
}
return true;
}
bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
{ {
bool visitChildren = true; bool visitChildren = true;
...@@ -614,21 +632,6 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -614,21 +632,6 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpInvariantDeclaration: case EOpInvariantDeclaration:
visitChildren = false; visitChildren = false;
break; break;
case EOpDeclaration:
// Variable declaration.
if (visit == PreVisit)
{
mDeclaringVariables = true;
}
else if (visit == InVisit)
{
mDeclaringVariables = true;
}
else
{
mDeclaringVariables = false;
}
break;
case EOpFunctionCall: case EOpFunctionCall:
{ {
// Function call. // Function call.
......
...@@ -27,6 +27,7 @@ class EmulatePrecision : public TLValueTrackingTraverser ...@@ -27,6 +27,7 @@ class EmulatePrecision : public TLValueTrackingTraverser
bool visitBinary(Visit visit, TIntermBinary *node) override; bool visitBinary(Visit visit, TIntermBinary *node) override;
bool visitUnary(Visit visit, TIntermUnary *node) override; bool visitUnary(Visit visit, TIntermUnary *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
void writeEmulationHelpers(TInfoSinkBase &sink, void writeEmulationHelpers(TInfoSinkBase &sink,
const int shaderVersion, const int shaderVersion,
......
...@@ -116,7 +116,7 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -116,7 +116,7 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
TIntermTyped *lhs = sequence->at(0)->getAsTyped(); TIntermTyped *lhs = sequence->at(0)->getAsTyped();
ASSERT(lhs); ASSERT(lhs);
TIntermAggregate *init = createTempInitDeclaration(lhs); TIntermDeclaration *init = createTempInitDeclaration(lhs);
TIntermTyped *current = createTempSymbol(lhs->getType()); TIntermTyped *current = createTempSymbol(lhs->getType());
insertStatementInParentBlock(init); insertStatementInParentBlock(init);
......
...@@ -51,7 +51,7 @@ bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node) ...@@ -51,7 +51,7 @@ bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node)
// Check if loop index type is integer. // Check if loop index type is integer.
// This is called after ValidateLimitations pass, so the loop has the limited form specified // This is called after ValidateLimitations pass, so the loop has the limited form specified
// in ESSL 1.00 appendix A. // in ESSL 1.00 appendix A.
TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence(); TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); TIntermSymbol *symbol = (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
if (symbol->getBasicType() == EbtInt) if (symbol->getBasicType() == EbtInt)
node->setUnrollFlag(true); node->setUnrollFlag(true);
......
...@@ -222,6 +222,11 @@ bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacem ...@@ -222,6 +222,11 @@ bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacem
return replaceChildNodeInternal(original, replacement); return replaceChildNodeInternal(original, replacement);
} }
bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
return replaceChildNodeInternal(original, replacement);
}
bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement) bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement)
{ {
for (size_t ii = 0; ii < getSequence()->size(); ++ii) for (size_t ii = 0; ii < getSequence()->size(); ++ii)
...@@ -320,12 +325,26 @@ void TIntermAggregate::setBuiltInFunctionPrecision() ...@@ -320,12 +325,26 @@ void TIntermAggregate::setBuiltInFunctionPrecision()
void TIntermBlock::appendStatement(TIntermNode *statement) void TIntermBlock::appendStatement(TIntermNode *statement)
{ {
if (statement != nullptr) // Declaration nodes with no children can appear if all the declarators just added constants to
// the symbol table instead of generating code. They're no-ops so they aren't added to blocks.
if (statement != nullptr && (statement->getAsDeclarationNode() == nullptr ||
!statement->getAsDeclarationNode()->getSequence()->empty()))
{ {
mStatements.push_back(statement); mStatements.push_back(statement);
} }
} }
void TIntermDeclaration::appendDeclarator(TIntermTyped *declarator)
{
ASSERT(declarator != nullptr);
ASSERT(declarator->getAsSymbolNode() != nullptr ||
(declarator->getAsBinaryNode() != nullptr &&
declarator->getAsBinaryNode()->getOp() == EOpInitialize));
ASSERT(mDeclarators.empty() ||
declarator->getType().sameElementType(mDeclarators.back()->getAsTyped()->getType()));
mDeclarators.push_back(declarator);
}
bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement) bool TIntermTernary::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{ {
REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
......
...@@ -32,6 +32,7 @@ class TDiagnostics; ...@@ -32,6 +32,7 @@ class TDiagnostics;
class TIntermTraverser; class TIntermTraverser;
class TIntermAggregate; class TIntermAggregate;
class TIntermBlock; class TIntermBlock;
class TIntermDeclaration;
class TIntermFunctionDefinition; class TIntermFunctionDefinition;
class TIntermSwizzle; class TIntermSwizzle;
class TIntermBinary; class TIntermBinary;
...@@ -98,6 +99,7 @@ class TIntermNode : angle::NonCopyable ...@@ -98,6 +99,7 @@ class TIntermNode : angle::NonCopyable
virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; } virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; }
virtual TIntermAggregate *getAsAggregate() { return 0; } virtual TIntermAggregate *getAsAggregate() { return 0; }
virtual TIntermBlock *getAsBlock() { return nullptr; } virtual TIntermBlock *getAsBlock() { return nullptr; }
virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; }
virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; } virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; }
virtual TIntermBinary *getAsBinaryNode() { return 0; } virtual TIntermBinary *getAsBinaryNode() { return 0; }
virtual TIntermUnary *getAsUnaryNode() { return 0; } virtual TIntermUnary *getAsUnaryNode() { return 0; }
...@@ -710,6 +712,28 @@ class TIntermBlock : public TIntermNode, public TIntermAggregateBase ...@@ -710,6 +712,28 @@ class TIntermBlock : public TIntermNode, public TIntermAggregateBase
TIntermSequence mStatements; TIntermSequence mStatements;
}; };
// Struct, interface block or variable declaration. Can contain multiple variable declarators.
class TIntermDeclaration : public TIntermNode, public TIntermAggregateBase
{
public:
TIntermDeclaration() : TIntermNode() {}
~TIntermDeclaration() {}
TIntermDeclaration *getAsDeclarationNode() override { return this; }
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
// Only intended for initially building the declaration.
// The declarator node should be either TIntermSymbol or TIntermBinary with op set to
// EOpInitialize.
void appendDeclarator(TIntermTyped *declarator);
TIntermSequence *getSequence() override { return &mDeclarators; }
const TIntermSequence *getSequence() const override { return &mDeclarators; }
protected:
TIntermSequence mDeclarators;
};
// For ternary operators like a ? b : c. // For ternary operators like a ? b : c.
class TIntermTernary : public TIntermTyped class TIntermTernary : public TIntermTyped
{ {
...@@ -858,6 +882,7 @@ class TIntermTraverser : angle::NonCopyable ...@@ -858,6 +882,7 @@ class TIntermTraverser : angle::NonCopyable
} }
virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; } virtual bool visitAggregate(Visit visit, TIntermAggregate *node) { return true; }
virtual bool visitBlock(Visit visit, TIntermBlock *node) { return true; } virtual bool visitBlock(Visit visit, TIntermBlock *node) { return true; }
virtual bool visitDeclaration(Visit visit, TIntermDeclaration *node) { return true; }
virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; } virtual bool visitLoop(Visit visit, TIntermLoop *node) { return true; }
virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; } virtual bool visitBranch(Visit visit, TIntermBranch *node) { return true; }
...@@ -877,6 +902,7 @@ class TIntermTraverser : angle::NonCopyable ...@@ -877,6 +902,7 @@ class TIntermTraverser : angle::NonCopyable
virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node); virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node);
virtual void traverseAggregate(TIntermAggregate *node); virtual void traverseAggregate(TIntermAggregate *node);
virtual void traverseBlock(TIntermBlock *node); virtual void traverseBlock(TIntermBlock *node);
virtual void traverseDeclaration(TIntermDeclaration *node);
virtual void traverseLoop(TIntermLoop *node); virtual void traverseLoop(TIntermLoop *node);
virtual void traverseBranch(TIntermBranch *node); virtual void traverseBranch(TIntermBranch *node);
...@@ -987,11 +1013,11 @@ class TIntermTraverser : angle::NonCopyable ...@@ -987,11 +1013,11 @@ class TIntermTraverser : angle::NonCopyable
// Helper to create a temporary symbol node. // Helper to create a temporary symbol node.
TIntermSymbol *createTempSymbol(const TType &type); TIntermSymbol *createTempSymbol(const TType &type);
// Create a node that declares but doesn't initialize a temporary symbol. // Create a node that declares but doesn't initialize a temporary symbol.
TIntermAggregate *createTempDeclaration(const TType &type); TIntermDeclaration *createTempDeclaration(const TType &type);
// Create a node that initializes the current temporary symbol with initializer having the given qualifier. // Create a node that initializes the current temporary symbol with initializer having the given qualifier.
TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier); TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier);
// Create a node that initializes the current temporary symbol with initializer. // Create a node that initializes the current temporary symbol with initializer.
TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer); TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer);
// Create a node that assigns rightNode to the current temporary symbol. // Create a node that assigns rightNode to the current temporary symbol.
TIntermBinary *createTempAssignment(TIntermTyped *rightNode); TIntermBinary *createTempAssignment(TIntermTyped *rightNode);
// Increment temporary symbol index. // Increment temporary symbol index.
......
...@@ -68,6 +68,11 @@ void TIntermBlock::traverse(TIntermTraverser *it) ...@@ -68,6 +68,11 @@ void TIntermBlock::traverse(TIntermTraverser *it)
it->traverseBlock(this); it->traverseBlock(this);
} }
void TIntermDeclaration::traverse(TIntermTraverser *it)
{
it->traverseDeclaration(this);
}
void TIntermAggregate::traverse(TIntermTraverser *it) void TIntermAggregate::traverse(TIntermTraverser *it)
{ {
it->traverseAggregate(this); it->traverseAggregate(this);
...@@ -155,24 +160,25 @@ TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type) ...@@ -155,24 +160,25 @@ TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
return createTempSymbol(type, EvqTemporary); return createTempSymbol(type, EvqTemporary);
} }
TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type) TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
{ {
TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration); TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
tempDeclaration->getSequence()->push_back(createTempSymbol(type)); tempDeclaration->appendDeclarator(createTempSymbol(type));
return tempDeclaration; return tempDeclaration;
} }
TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier) TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
TQualifier qualifier)
{ {
ASSERT(initializer != nullptr); ASSERT(initializer != nullptr);
TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier); TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration); TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer); TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
tempDeclaration->getSequence()->push_back(tempInit); tempDeclaration->appendDeclarator(tempInit);
return tempDeclaration; return tempDeclaration;
} }
TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer) TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
{ {
return createTempInitDeclaration(initializer, EvqTemporary); return createTempInitDeclaration(initializer, EvqTemporary);
} }
...@@ -490,6 +496,37 @@ void TIntermTraverser::traverseBlock(TIntermBlock *node) ...@@ -490,6 +496,37 @@ void TIntermTraverser::traverseBlock(TIntermBlock *node)
visitBlock(PostVisit, node); visitBlock(PostVisit, node);
} }
// Traverse a declaration node.
void TIntermTraverser::traverseDeclaration(TIntermDeclaration *node)
{
bool visit = true;
TIntermSequence *sequence = node->getSequence();
if (preVisit)
visit = visitDeclaration(PreVisit, node);
if (visit)
{
incrementDepth(node);
for (auto *child : *sequence)
{
child->traverse(this);
if (visit && inVisit)
{
if (child != sequence->back())
visit = visitDeclaration(InVisit, node);
}
}
decrementDepth();
}
if (visit && postVisit)
visitDeclaration(PostVisit, node);
}
// Traverse an aggregate node. Same comments in binary node apply here. // Traverse an aggregate node. Same comments in binary node apply here.
void TIntermTraverser::traverseAggregate(TIntermAggregate *node) void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
{ {
......
...@@ -93,8 +93,7 @@ void TLoopIndexInfo::fillInfo(TIntermLoop *node) ...@@ -93,8 +93,7 @@ void TLoopIndexInfo::fillInfo(TIntermLoop *node)
// Here we assume all the operations are valid, because the loop node is // Here we assume all the operations are valid, because the loop node is
// already validated in ValidateLimitations. // already validated in ValidateLimitations.
TIntermSequence *declSeq = TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
node->getInit()->getAsAggregate()->getSequence();
TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode();
TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
......
...@@ -16,7 +16,6 @@ enum TOperator ...@@ -16,7 +16,6 @@ enum TOperator
EOpFunctionCall, EOpFunctionCall,
EOpParameters, // an aggregate listing the parameters to a function EOpParameters, // an aggregate listing the parameters to a function
EOpDeclaration,
EOpInvariantDeclaration, // Specialized declarations for attributing invariance EOpInvariantDeclaration, // Specialized declarations for attributing invariance
EOpPrototype, EOpPrototype,
......
...@@ -916,27 +916,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -916,27 +916,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
out << ")"; out << ")";
visitChildren = false; visitChildren = false;
break; break;
case EOpDeclaration:
// Variable declaration.
if (visit == PreVisit)
{
const TIntermSequence &sequence = *(node->getSequence());
const TIntermTyped *variable = sequence.front()->getAsTyped();
writeLayoutQualifier(variable->getType());
writeVariableType(variable->getType());
out << " ";
mDeclaringVariables = true;
}
else if (visit == InVisit)
{
out << ", ";
mDeclaringVariables = true;
}
else
{
mDeclaringVariables = false;
}
break;
case EOpInvariantDeclaration: case EOpInvariantDeclaration:
// Invariant declaration. // Invariant declaration.
ASSERT(visit == PreVisit); ASSERT(visit == PreVisit);
...@@ -1059,6 +1038,32 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -1059,6 +1038,32 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
return visitChildren; return visitChildren;
} }
bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node)
{
TInfoSinkBase &out = objSink();
// Variable declaration.
if (visit == PreVisit)
{
const TIntermSequence &sequence = *(node->getSequence());
const TIntermTyped *variable = sequence.front()->getAsTyped();
writeLayoutQualifier(variable->getType());
writeVariableType(variable->getType());
out << " ";
mDeclaringVariables = true;
}
else if (visit == InVisit)
{
out << ", ";
mDeclaringVariables = true;
}
else
{
mDeclaringVariables = false;
}
return true;
}
bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
{ {
TInfoSinkBase &out = objSink(); TInfoSinkBase &out = objSink();
...@@ -1092,8 +1097,7 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) ...@@ -1092,8 +1097,7 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
else else
{ {
// Need to put a one-iteration loop here to handle break. // Need to put a one-iteration loop here to handle break.
TIntermSequence *declSeq = TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
node->getInit()->getAsAggregate()->getSequence();
TIntermSymbol *indexSymbol = TIntermSymbol *indexSymbol =
(*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
TString name = hashVariableName(indexSymbol->getSymbol()); TString name = hashVariableName(indexSymbol->getSymbol());
......
...@@ -52,6 +52,7 @@ class TOutputGLSLBase : public TIntermTraverser ...@@ -52,6 +52,7 @@ class TOutputGLSLBase : public TIntermTraverser
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitBlock(Visit visit, TIntermBlock *node) override; bool visitBlock(Visit visit, TIntermBlock *node) override;
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
bool visitLoop(Visit visit, TIntermLoop *node) override; bool visitLoop(Visit visit, TIntermLoop *node) override;
bool visitBranch(Visit visit, TIntermBranch *node) override; bool visitBranch(Visit visit, TIntermBranch *node) override;
......
...@@ -1519,84 +1519,80 @@ bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition ...@@ -1519,84 +1519,80 @@ bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition
return false; return false;
} }
bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node) bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node)
{ {
TInfoSinkBase &out = getInfoSink(); TInfoSinkBase &out = getInfoSink();
if (visit == PreVisit)
switch (node->getOp())
{ {
case EOpDeclaration: TIntermSequence *sequence = node->getSequence();
if (visit == PreVisit) TIntermTyped *variable = (*sequence)[0]->getAsTyped();
{ ASSERT(sequence->size() == 1);
TIntermSequence *sequence = node->getSequence();
TIntermTyped *variable = (*sequence)[0]->getAsTyped();
ASSERT(sequence->size() == 1);
if (variable && if (variable &&
(variable->getQualifier() == EvqTemporary || (variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal ||
variable->getQualifier() == EvqGlobal || variable->getQualifier() == EvqConst)) variable->getQualifier() == EvqConst))
{ {
ensureStructDefined(variable->getType()); ensureStructDefined(variable->getType());
if (!variable->getAsSymbolNode() || if (!variable->getAsSymbolNode() ||
variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
{ {
if (!mInsideFunction) if (!mInsideFunction)
{ {
out << "static "; out << "static ";
} }
out << TypeString(variable->getType()) + " "; out << TypeString(variable->getType()) + " ";
TIntermSymbol *symbol = variable->getAsSymbolNode(); TIntermSymbol *symbol = variable->getAsSymbolNode();
if (symbol) if (symbol)
{ {
symbol->traverse(this); symbol->traverse(this);
out << ArrayString(symbol->getType()); out << ArrayString(symbol->getType());
out << " = " + initializer(symbol->getType()); out << " = " + initializer(symbol->getType());
}
else
{
variable->traverse(this);
}
}
else if (variable->getAsSymbolNode() &&
variable->getAsSymbolNode()->getSymbol() ==
"") // Type (struct) declaration
{
// Already added to constructor map
}
else
UNREACHABLE();
} }
else if (variable && IsVaryingOut(variable->getQualifier())) else
{ {
for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); variable->traverse(this);
sit++)
{
TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
if (symbol)
{
// Vertex (output) varyings which are declared but not written to should
// still be declared to allow successful linking
mReferencedVaryings[symbol->getSymbol()] = symbol;
}
else
{
(*sit)->traverse(this);
}
}
} }
return false;
} }
else if (visit == InVisit) else if (variable->getAsSymbolNode() &&
variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration
{ {
out << ", "; // Already added to constructor map
} }
break; else
UNREACHABLE();
}
else if (variable && IsVaryingOut(variable->getQualifier()))
{
for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
{
TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
if (symbol)
{
// Vertex (output) varyings which are declared but not written to should
// still be declared to allow successful linking
mReferencedVaryings[symbol->getSymbol()] = symbol;
}
else
{
(*sit)->traverse(this);
}
}
}
}
return false;
}
bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
TInfoSinkBase &out = getInfoSink();
switch (node->getOp())
{
case EOpInvariantDeclaration: case EOpInvariantDeclaration:
// Do not do any translation // Do not do any translation
return false; return false;
...@@ -2177,39 +2173,6 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node) ...@@ -2177,39 +2173,6 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
return true; return true;
} }
bool OutputHLSL::isSingleStatement(TIntermNode *node)
{
if (node->getAsBlock())
{
return false;
}
TIntermAggregate *aggregate = node->getAsAggregate();
if (aggregate)
{
if (aggregate->getOp() == EOpDeclaration)
{
// Declaring multiple comma-separated variables must be considered multiple statements
// because each individual declaration has side effects which are visible in the next.
return false;
}
else
{
for (TIntermSequence::iterator sit = aggregate->getSequence()->begin(); sit != aggregate->getSequence()->end(); sit++)
{
if (!isSingleStatement(*sit))
{
return false;
}
}
return true;
}
}
return true;
}
// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them // Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254). // (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node) bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
...@@ -2227,7 +2190,7 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node) ...@@ -2227,7 +2190,7 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
// Parse index name and intial value // Parse index name and intial value
if (node->getInit()) if (node->getInit())
{ {
TIntermAggregate *init = node->getInit()->getAsAggregate(); TIntermDeclaration *init = node->getInit()->getAsDeclarationNode();
if (init) if (init)
{ {
......
...@@ -69,10 +69,10 @@ class OutputHLSL : public TIntermTraverser ...@@ -69,10 +69,10 @@ class OutputHLSL : public TIntermTraverser
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate*); bool visitAggregate(Visit visit, TIntermAggregate*);
bool visitBlock(Visit visit, TIntermBlock *node); bool visitBlock(Visit visit, TIntermBlock *node);
bool visitDeclaration(Visit visit, TIntermDeclaration *node);
bool visitLoop(Visit visit, TIntermLoop*); bool visitLoop(Visit visit, TIntermLoop*);
bool visitBranch(Visit visit, TIntermBranch*); bool visitBranch(Visit visit, TIntermBranch*);
bool isSingleStatement(TIntermNode *node);
bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node); bool handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node);
// Emit one of three strings depending on traverse phase. Called with literal strings so using const char* instead of TString. // Emit one of three strings depending on traverse phase. Called with literal strings so using const char* instead of TString.
......
...@@ -202,66 +202,66 @@ class TParseContext : angle::NonCopyable ...@@ -202,66 +202,66 @@ class TParseContext : angle::NonCopyable
const TString &identifier, const TString &identifier,
const TPublicType &pType, const TPublicType &pType,
TIntermTyped *initializer, TIntermTyped *initializer,
TIntermNode **intermNode); TIntermBinary **initNode);
TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder, TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
const TPublicType &typeSpecifier); const TPublicType &typeSpecifier);
TIntermAggregate *parseSingleDeclaration(TPublicType &publicType, TIntermDeclaration *parseSingleDeclaration(TPublicType &publicType,
const TSourceLoc &identifierOrTypeLocation, const TSourceLoc &identifierOrTypeLocation,
const TString &identifier); const TString &identifier);
TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType, TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &publicType,
const TSourceLoc &identifierLocation, const TSourceLoc &identifierLocation,
const TString &identifier, const TString &identifier,
const TSourceLoc &indexLocation, const TSourceLoc &indexLocation,
TIntermTyped *indexExpression); TIntermTyped *indexExpression);
TIntermAggregate *parseSingleInitDeclaration(const TPublicType &publicType, TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType,
const TSourceLoc &identifierLocation, const TSourceLoc &identifierLocation,
const TString &identifier, const TString &identifier,
const TSourceLoc &initLocation, const TSourceLoc &initLocation,
TIntermTyped *initializer); TIntermTyped *initializer);
// Parse a declaration like "type a[n] = initializer" // Parse a declaration like "type a[n] = initializer"
// Note that this does not apply to declarations like "type[n] a = initializer" // Note that this does not apply to declarations like "type[n] a = initializer"
TIntermAggregate *parseSingleArrayInitDeclaration(TPublicType &publicType, TIntermDeclaration *parseSingleArrayInitDeclaration(TPublicType &publicType,
const TSourceLoc &identifierLocation, const TSourceLoc &identifierLocation,
const TString &identifier, const TString &identifier,
const TSourceLoc &indexLocation, const TSourceLoc &indexLocation,
TIntermTyped *indexExpression, TIntermTyped *indexExpression,
const TSourceLoc &initLocation, const TSourceLoc &initLocation,
TIntermTyped *initializer); TIntermTyped *initializer);
TIntermAggregate *parseInvariantDeclaration(const TTypeQualifierBuilder &typeQualifierBuilder, TIntermAggregate *parseInvariantDeclaration(const TTypeQualifierBuilder &typeQualifierBuilder,
const TSourceLoc &identifierLoc, const TSourceLoc &identifierLoc,
const TString *identifier, const TString *identifier,
const TSymbol *symbol); const TSymbol *symbol);
TIntermAggregate *parseDeclarator(TPublicType &publicType, void parseDeclarator(TPublicType &publicType,
TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
const TSourceLoc &identifierLocation, const TString &identifier,
const TString &identifier); TIntermDeclaration *declarationOut);
TIntermAggregate *parseArrayDeclarator(TPublicType &publicType, void parseArrayDeclarator(TPublicType &publicType,
TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
const TSourceLoc &identifierLocation, const TString &identifier,
const TString &identifier, const TSourceLoc &arrayLocation,
const TSourceLoc &arrayLocation, TIntermTyped *indexExpression,
TIntermTyped *indexExpression); TIntermDeclaration *declarationOut);
TIntermAggregate *parseInitDeclarator(const TPublicType &publicType, void parseInitDeclarator(const TPublicType &publicType,
TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
const TSourceLoc &identifierLocation, const TString &identifier,
const TString &identifier, const TSourceLoc &initLocation,
const TSourceLoc &initLocation, TIntermTyped *initializer,
TIntermTyped *initializer); TIntermDeclaration *declarationOut);
// Parse a declarator like "a[n] = initializer" // Parse a declarator like "a[n] = initializer"
TIntermAggregate *parseArrayInitDeclarator(const TPublicType &publicType, void parseArrayInitDeclarator(const TPublicType &publicType,
TIntermAggregate *aggregateDeclaration, const TSourceLoc &identifierLocation,
const TSourceLoc &identifierLocation, const TString &identifier,
const TString &identifier, const TSourceLoc &indexLocation,
const TSourceLoc &indexLocation, TIntermTyped *indexExpression,
TIntermTyped *indexExpression, const TSourceLoc &initLocation,
const TSourceLoc &initLocation, TIntermTyped *initializer,
TIntermTyped *initializer); TIntermDeclaration *declarationOut);
void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder); void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder);
TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &parsedFunction, TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &parsedFunction,
...@@ -302,14 +302,14 @@ class TParseContext : angle::NonCopyable ...@@ -302,14 +302,14 @@ class TParseContext : angle::NonCopyable
const TString *structName, const TString *structName,
TFieldList *fieldList); TFieldList *fieldList);
TIntermAggregate *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder, TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
const TSourceLoc &nameLine, const TSourceLoc &nameLine,
const TString &blockName, const TString &blockName,
TFieldList *fieldList, TFieldList *fieldList,
const TString *instanceName, const TString *instanceName,
const TSourceLoc &instanceLine, const TSourceLoc &instanceLine,
TIntermTyped *arrayIndex, TIntermTyped *arrayIndex,
const TSourceLoc &arrayIndexLine); const TSourceLoc &arrayIndexLine);
void parseLocalSize(const TString &qualifierType, void parseLocalSize(const TString &qualifierType,
const TSourceLoc &qualifierTypeLine, const TSourceLoc &qualifierTypeLine,
...@@ -409,8 +409,10 @@ class TParseContext : angle::NonCopyable ...@@ -409,8 +409,10 @@ class TParseContext : angle::NonCopyable
TIntermTyped *addBinaryMathInternal( TIntermTyped *addBinaryMathInternal(
TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
TIntermTyped *createAssign( TIntermBinary *createAssign(TOperator op,
TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc); TIntermTyped *left,
TIntermTyped *right,
const TSourceLoc &loc);
// The funcReturnType parameter is expected to be non-null when the operation is a built-in function. // The funcReturnType parameter is expected to be non-null when the operation is a built-in function.
// It is expected to be null for other unary operators. // It is expected to be null for other unary operators.
TIntermTyped *createUnaryMath( TIntermTyped *createUnaryMath(
......
...@@ -18,7 +18,7 @@ class PruneEmptyDeclarationsTraverser : private TIntermTraverser ...@@ -18,7 +18,7 @@ class PruneEmptyDeclarationsTraverser : private TIntermTraverser
static void apply(TIntermNode *root); static void apply(TIntermNode *root);
private: private:
PruneEmptyDeclarationsTraverser(); PruneEmptyDeclarationsTraverser();
bool visitAggregate(Visit, TIntermAggregate *node) override; bool visitDeclaration(Visit, TIntermDeclaration *node) override;
}; };
void PruneEmptyDeclarationsTraverser::apply(TIntermNode *root) void PruneEmptyDeclarationsTraverser::apply(TIntermNode *root)
...@@ -33,74 +33,71 @@ PruneEmptyDeclarationsTraverser::PruneEmptyDeclarationsTraverser() ...@@ -33,74 +33,71 @@ PruneEmptyDeclarationsTraverser::PruneEmptyDeclarationsTraverser()
{ {
} }
bool PruneEmptyDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node) bool PruneEmptyDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
{ {
if (node->getOp() == EOpDeclaration) TIntermSequence *sequence = node->getSequence();
if (sequence->size() >= 1)
{ {
TIntermSequence *sequence = node->getSequence(); TIntermSymbol *sym = sequence->front()->getAsSymbolNode();
if (sequence->size() >= 1) // Prune declarations without a variable name, unless it's an interface block declaration.
if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock())
{ {
TIntermSymbol *sym = sequence->front()->getAsSymbolNode(); if (sequence->size() > 1)
// Prune declarations without a variable name, unless it's an interface block declaration.
if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock())
{ {
if (sequence->size() > 1) // Generate a replacement that will remove the empty declarator in the beginning of
// a declarator list. Example of a declaration that will be changed:
// float, a;
// will be changed to
// float a;
// This applies also to struct declarations.
TIntermSequence emptyReplacement;
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(node, sym, emptyReplacement));
}
else if (sym->getBasicType() != EbtStruct)
{
// Single struct declarations may just declare the struct type and no variables, so
// they should not be pruned. All other single empty declarations can be pruned
// entirely. Example of an empty declaration that will be pruned:
// float;
TIntermSequence emptyReplacement;
TIntermBlock *parentAsBlock = getParentNode()->getAsBlock();
// The declaration may be inside a block or in a loop init expression.
ASSERT(parentAsBlock != nullptr || getParentNode()->getAsLoopNode() != nullptr);
if (parentAsBlock)
{ {
// Generate a replacement that will remove the empty declarator in the beginning of a declarator mMultiReplacements.push_back(
// list. Example of a declaration that will be changed: NodeReplaceWithMultipleEntry(parentAsBlock, node, emptyReplacement));
// float, a;
// will be changed to
// float a;
// This applies also to struct declarations.
TIntermSequence emptyReplacement;
mMultiReplacements.push_back(NodeReplaceWithMultipleEntry(node, sym, emptyReplacement));
} }
else if (sym->getBasicType() != EbtStruct) else
{ {
// Single struct declarations may just declare the struct type and no variables, so they should queueReplacement(node, nullptr, OriginalNode::IS_DROPPED);
// not be pruned. All other single empty declarations can be pruned entirely. Example of an empty
// declaration that will be pruned:
// float;
TIntermSequence emptyReplacement;
TIntermBlock *parentAsBlock = getParentNode()->getAsBlock();
// The declaration may be inside a block or in a loop init expression.
ASSERT(parentAsBlock != nullptr || getParentNode()->getAsLoopNode() != nullptr);
if (parentAsBlock)
{
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentAsBlock, node, emptyReplacement));
}
else
{
queueReplacement(node, nullptr, OriginalNode::IS_DROPPED);
}
} }
else if (sym->getType().getQualifier() != EvqGlobal && }
sym->getType().getQualifier() != EvqTemporary) else if (sym->getType().getQualifier() != EvqGlobal &&
{ sym->getType().getQualifier() != EvqTemporary)
// We've hit an empty struct declaration with a qualifier, for example like {
// this: // We've hit an empty struct declaration with a qualifier, for example like
// const struct a { int i; }; // this:
// NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so // const struct a { int i; };
// we convert the declaration to a regular struct declaration. This is okay, // NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so
// since ESSL 1.00 spec section 4.1.8 says about structs that "The optional // we convert the declaration to a regular struct declaration. This is okay,
// qualifiers only apply to any declarators, and are not part of the type being // since ESSL 1.00 spec section 4.1.8 says about structs that "The optional
// defined for name." // qualifiers only apply to any declarators, and are not part of the type being
// defined for name."
if (mInGlobalScope) if (mInGlobalScope)
{ {
sym->getTypePointer()->setQualifier(EvqGlobal); sym->getTypePointer()->setQualifier(EvqGlobal);
} }
else else
{ {
sym->getTypePointer()->setQualifier(EvqTemporary); sym->getTypePointer()->setQualifier(EvqTemporary);
}
} }
} }
} }
return false;
} }
return true; return false;
} }
} // namespace } // namespace
......
...@@ -390,7 +390,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod ...@@ -390,7 +390,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
// Now v_expr[s0] can be safely executed several times without unintended side effects. // Now v_expr[s0] can be safely executed several times without unintended side effects.
// Init the temp variable holding the index // Init the temp variable holding the index
TIntermAggregate *initIndex = createTempInitDeclaration(node->getRight()); TIntermDeclaration *initIndex = createTempInitDeclaration(node->getRight());
insertStatementInParentBlock(initIndex); insertStatementInParentBlock(initIndex);
mUsedTreeInsertion = true; mUsedTreeInsertion = true;
...@@ -441,7 +441,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod ...@@ -441,7 +441,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
// Store the index in a temporary signed int variable. // Store the index in a temporary signed int variable.
TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight()); TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight());
TIntermAggregate *initIndex = createTempInitDeclaration(indexInitializer); TIntermDeclaration *initIndex = createTempInitDeclaration(indexInitializer);
initIndex->setLine(node->getLine()); initIndex->setLine(node->getLine());
insertionsBefore.push_back(initIndex); insertionsBefore.push_back(initIndex);
......
...@@ -67,7 +67,7 @@ class DoWhileRewriter : public TIntermTraverser ...@@ -67,7 +67,7 @@ class DoWhileRewriter : public TIntermTraverser
TType boolType = TType(EbtBool); TType boolType = TType(EbtBool);
// bool temp = false; // bool temp = false;
TIntermAggregate *tempDeclaration = nullptr; TIntermDeclaration *tempDeclaration = nullptr;
{ {
TConstantUnion *falseConstant = new TConstantUnion(); TConstantUnion *falseConstant = new TConstantUnion();
falseConstant->setBConst(false); falseConstant->setBConst(false);
......
...@@ -70,8 +70,7 @@ TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse) ...@@ -70,8 +70,7 @@ TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
nextTemporaryIndex(); nextTemporaryIndex();
TIntermTyped *typedCondition = ifElse->getCondition()->getAsTyped(); TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition());
TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition);
TIntermBlock *falseBlock = nullptr; TIntermBlock *falseBlock = nullptr;
......
...@@ -265,8 +265,8 @@ TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *orig ...@@ -265,8 +265,8 @@ TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *orig
TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type); TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type);
TIntermBinary *init = new TIntermBinary(EOpInitialize, symbolNode, original); TIntermBinary *init = new TIntermBinary(EOpInitialize, symbolNode, original);
TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration); TIntermDeclaration *decl = new TIntermDeclaration();
decl->getSequence()->push_back(init); decl->appendDeclarator(init);
ASSERT(mBlockStack.size() > 0); ASSERT(mBlockStack.size() > 0);
TIntermSequence &sequence = mBlockStack.back(); TIntermSequence &sequence = mBlockStack.back();
......
...@@ -29,7 +29,7 @@ class SeparateArrayInitTraverser : private TIntermTraverser ...@@ -29,7 +29,7 @@ class SeparateArrayInitTraverser : private TIntermTraverser
static void apply(TIntermNode *root); static void apply(TIntermNode *root);
private: private:
SeparateArrayInitTraverser(); SeparateArrayInitTraverser();
bool visitAggregate(Visit, TIntermAggregate *node) override; bool visitDeclaration(Visit, TIntermDeclaration *node) override;
}; };
void SeparateArrayInitTraverser::apply(TIntermNode *root) void SeparateArrayInitTraverser::apply(TIntermNode *root)
...@@ -44,43 +44,38 @@ SeparateArrayInitTraverser::SeparateArrayInitTraverser() ...@@ -44,43 +44,38 @@ SeparateArrayInitTraverser::SeparateArrayInitTraverser()
{ {
} }
bool SeparateArrayInitTraverser::visitAggregate(Visit, TIntermAggregate *node) bool SeparateArrayInitTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
{ {
if (node->getOp() == EOpDeclaration) TIntermSequence *sequence = node->getSequence();
TIntermBinary *initNode = sequence->back()->getAsBinaryNode();
if (initNode != nullptr && initNode->getOp() == EOpInitialize)
{ {
TIntermSequence *sequence = node->getSequence(); TIntermTyped *initializer = initNode->getRight();
TIntermBinary *initNode = sequence->back()->getAsBinaryNode(); if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer))
if (initNode != nullptr && initNode->getOp() == EOpInitialize)
{ {
TIntermTyped *initializer = initNode->getRight(); // We rely on that array declarations have been isolated to single declarations.
if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer)) ASSERT(sequence->size() == 1);
{ TIntermTyped *symbol = initNode->getLeft();
// We rely on that array declarations have been isolated to single declarations. TIntermBlock *parentBlock = getParentNode()->getAsBlock();
ASSERT(sequence->size() == 1); ASSERT(parentBlock != nullptr);
TIntermTyped *symbol = initNode->getLeft();
TIntermBlock *parentBlock = getParentNode()->getAsBlock();
ASSERT(parentBlock != nullptr);
TIntermSequence replacements; TIntermSequence replacements;
TIntermAggregate *replacementDeclaration = new TIntermAggregate; TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
replacementDeclaration->setOp(EOpDeclaration); replacementDeclaration->appendDeclarator(symbol);
replacementDeclaration->getSequence()->push_back(symbol); replacementDeclaration->setLine(symbol->getLine());
replacementDeclaration->setLine(symbol->getLine()); replacements.push_back(replacementDeclaration);
replacements.push_back(replacementDeclaration);
TIntermBinary *replacementAssignment = TIntermBinary *replacementAssignment =
new TIntermBinary(EOpAssign, symbol, initializer); new TIntermBinary(EOpAssign, symbol, initializer);
replacementAssignment->setLine(symbol->getLine()); replacementAssignment->setLine(symbol->getLine());
replacements.push_back(replacementAssignment); replacements.push_back(replacementAssignment);
mMultiReplacements.push_back( mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentBlock, node, replacements)); NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
}
} }
return false;
} }
return true; return false;
} }
} // namespace } // namespace
......
...@@ -26,7 +26,7 @@ class SeparateDeclarationsTraverser : private TIntermTraverser ...@@ -26,7 +26,7 @@ class SeparateDeclarationsTraverser : private TIntermTraverser
static void apply(TIntermNode *root); static void apply(TIntermNode *root);
private: private:
SeparateDeclarationsTraverser(); SeparateDeclarationsTraverser();
bool visitAggregate(Visit, TIntermAggregate *node) override; bool visitDeclaration(Visit, TIntermDeclaration *node) override;
}; };
void SeparateDeclarationsTraverser::apply(TIntermNode *root) void SeparateDeclarationsTraverser::apply(TIntermNode *root)
...@@ -41,33 +41,28 @@ SeparateDeclarationsTraverser::SeparateDeclarationsTraverser() ...@@ -41,33 +41,28 @@ SeparateDeclarationsTraverser::SeparateDeclarationsTraverser()
{ {
} }
bool SeparateDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node) bool SeparateDeclarationsTraverser::visitDeclaration(Visit, TIntermDeclaration *node)
{ {
if (node->getOp() == EOpDeclaration) TIntermSequence *sequence = node->getSequence();
if (sequence->size() > 1)
{ {
TIntermSequence *sequence = node->getSequence(); TIntermBlock *parentBlock = getParentNode()->getAsBlock();
if (sequence->size() > 1) ASSERT(parentBlock != nullptr);
{
TIntermBlock *parentBlock = getParentNode()->getAsBlock();
ASSERT(parentBlock != nullptr);
TIntermSequence replacementDeclarations;
for (size_t ii = 0; ii < sequence->size(); ++ii)
{
TIntermAggregate *replacementDeclaration = new TIntermAggregate;
replacementDeclaration->setOp(EOpDeclaration); TIntermSequence replacementDeclarations;
replacementDeclaration->getSequence()->push_back(sequence->at(ii)); for (size_t ii = 0; ii < sequence->size(); ++ii)
replacementDeclaration->setLine(sequence->at(ii)->getLine()); {
replacementDeclarations.push_back(replacementDeclaration); TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
}
mMultiReplacements.push_back( replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped());
NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations)); replacementDeclaration->setLine(sequence->at(ii)->getLine());
replacementDeclarations.push_back(replacementDeclaration);
} }
return false;
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations));
} }
return true; return false;
} }
} // namespace } // namespace
......
...@@ -134,9 +134,7 @@ bool UnfoldShortCircuitTraverser::visitTernary(Visit visit, TIntermTernary *node ...@@ -134,9 +134,7 @@ bool UnfoldShortCircuitTraverser::visitTernary(Visit visit, TIntermTernary *node
// Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;" // Unfold "b ? x : y" into "type s; if(b) s = x; else s = y;"
TIntermSequence insertions; TIntermSequence insertions;
TIntermSymbol *tempSymbol = createTempSymbol(node->getType()); TIntermDeclaration *tempDeclaration = createTempDeclaration(node->getType());
TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
tempDeclaration->getSequence()->push_back(tempSymbol);
insertions.push_back(tempDeclaration); insertions.push_back(tempDeclaration);
TIntermBlock *trueBlock = new TIntermBlock(); TIntermBlock *trueBlock = new TIntermBlock();
......
...@@ -213,8 +213,8 @@ int ValidateLimitations::validateForLoopInit(TIntermLoop *node) ...@@ -213,8 +213,8 @@ int ValidateLimitations::validateForLoopInit(TIntermLoop *node)
// init-declaration has the form: // init-declaration has the form:
// type-specifier identifier = constant-expression // type-specifier identifier = constant-expression
// //
TIntermAggregate *decl = init->getAsAggregate(); TIntermDeclaration *decl = init->getAsDeclarationNode();
if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) if (decl == nullptr)
{ {
error(init->getLine(), "Invalid init declaration", "for"); error(init->getLine(), "Invalid init declaration", "for");
return -1; return -1;
......
...@@ -559,54 +559,43 @@ void CollectVariables::visitInfoList(const TIntermSequence &sequence, ...@@ -559,54 +559,43 @@ void CollectVariables::visitInfoList(const TIntermSequence &sequence,
} }
} }
bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node) bool CollectVariables::visitDeclaration(Visit, TIntermDeclaration *node)
{ {
bool visitChildren = true; const TIntermSequence &sequence = *(node->getSequence());
ASSERT(!sequence.empty());
switch (node->getOp()) const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
TQualifier qualifier = typedNode.getQualifier();
if (typedNode.getBasicType() == EbtInterfaceBlock)
{ {
case EOpDeclaration: visitInfoList(sequence, mInterfaceBlocks);
return false;
}
else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqFragmentOut ||
qualifier == EvqUniform || IsVarying(qualifier))
{
switch (qualifier)
{ {
const TIntermSequence &sequence = *(node->getSequence()); case EvqAttribute:
ASSERT(!sequence.empty()); case EvqVertexIn:
visitInfoList(sequence, mAttribs);
const TIntermTyped &typedNode = *(sequence.front()->getAsTyped()); break;
TQualifier qualifier = typedNode.getQualifier(); case EvqFragmentOut:
visitInfoList(sequence, mOutputVariables);
if (typedNode.getBasicType() == EbtInterfaceBlock) break;
{ case EvqUniform:
visitInfoList(sequence, mInterfaceBlocks); visitInfoList(sequence, mUniforms);
visitChildren = false; break;
} default:
else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || visitInfoList(sequence, mVaryings);
qualifier == EvqFragmentOut || qualifier == EvqUniform || break;
IsVarying(qualifier))
{
switch (qualifier)
{
case EvqAttribute:
case EvqVertexIn:
visitInfoList(sequence, mAttribs);
break;
case EvqFragmentOut:
visitInfoList(sequence, mOutputVariables);
break;
case EvqUniform:
visitInfoList(sequence, mUniforms);
break;
default:
visitInfoList(sequence, mVaryings);
break;
}
visitChildren = false;
}
break;
} }
default: break;
return false;
} }
return visitChildren; return true;
} }
bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode) bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
......
...@@ -31,7 +31,7 @@ class CollectVariables : public TIntermTraverser ...@@ -31,7 +31,7 @@ class CollectVariables : public TIntermTraverser
const TExtensionBehavior &extensionBehavior); const TExtensionBehavior &extensionBehavior);
void visitSymbol(TIntermSymbol *symbol) override; void visitSymbol(TIntermSymbol *symbol) override;
bool visitAggregate(Visit, TIntermAggregate *node) override; bool visitDeclaration(Visit, TIntermDeclaration *node) override;
bool visitBinary(Visit visit, TIntermBinary *binaryNode) override; bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
private: private:
......
...@@ -62,21 +62,22 @@ void TVersionGLSL::visitSymbol(TIntermSymbol *node) ...@@ -62,21 +62,22 @@ void TVersionGLSL::visitSymbol(TIntermSymbol *node)
} }
} }
bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *node)
{
const TIntermSequence &sequence = *(node->getSequence());
if (sequence.front()->getAsTyped()->getType().isInvariant())
{
ensureVersionIsAtLeast(GLSL_VERSION_120);
}
return true;
}
bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node) bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)
{ {
bool visitChildren = true; bool visitChildren = true;
switch (node->getOp()) switch (node->getOp())
{ {
case EOpDeclaration:
{
const TIntermSequence &sequence = *(node->getSequence());
if (sequence.front()->getAsTyped()->getType().isInvariant())
{
ensureVersionIsAtLeast(GLSL_VERSION_120);
}
break;
}
case EOpInvariantDeclaration: case EOpInvariantDeclaration:
ensureVersionIsAtLeast(GLSL_VERSION_120); ensureVersionIsAtLeast(GLSL_VERSION_120);
break; break;
......
...@@ -58,6 +58,7 @@ class TVersionGLSL : public TIntermTraverser ...@@ -58,6 +58,7 @@ class TVersionGLSL : public TIntermTraverser
void visitSymbol(TIntermSymbol *) override; void visitSymbol(TIntermSymbol *) override;
bool visitAggregate(Visit, TIntermAggregate *) override; bool visitAggregate(Visit, TIntermAggregate *) override;
bool visitDeclaration(Visit, TIntermDeclaration *node) override;
private: private:
void ensureVersionIsAtLeast(int version); void ensureVersionIsAtLeast(int version);
......
...@@ -77,6 +77,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h). ...@@ -77,6 +77,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
TIntermTyped* intermTypedNode; TIntermTyped* intermTypedNode;
TIntermAggregate* intermAggregate; TIntermAggregate* intermAggregate;
TIntermBlock* intermBlock; TIntermBlock* intermBlock;
TIntermDeclaration* intermDeclaration;
TIntermSwitch* intermSwitch; TIntermSwitch* intermSwitch;
TIntermCase* intermCase; TIntermCase* intermCase;
}; };
...@@ -606,10 +607,7 @@ declaration ...@@ -606,10 +607,7 @@ declaration
$$ = context->addFunctionPrototypeDeclaration(*($1.function), @1); $$ = context->addFunctionPrototypeDeclaration(*($1.function), @1);
} }
| init_declarator_list SEMICOLON { | init_declarator_list SEMICOLON {
TIntermAggregate *aggNode = $1.intermAggregate; $$ = $1.intermDeclaration;
if (aggNode && aggNode->getOp() == EOpNull)
aggNode->setOp(EOpDeclaration);
$$ = aggNode;
} }
| PRECISION precision_qualifier type_specifier_no_prec SEMICOLON { | PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
if (($2 == EbpHigh) && (context->getShaderType() == GL_FRAGMENT_SHADER) && !context->getFragmentPrecisionHigh()) { if (($2 == EbpHigh) && (context->getShaderType() == GL_FRAGMENT_SHADER) && !context->getFragmentPrecisionHigh()) {
...@@ -762,54 +760,54 @@ init_declarator_list ...@@ -762,54 +760,54 @@ init_declarator_list
} }
| init_declarator_list COMMA identifier { | init_declarator_list COMMA identifier {
$$ = $1; $$ = $1;
$$.intermAggregate = context->parseDeclarator($$.type, $1.intermAggregate, @3, *$3.string); context->parseDeclarator($$.type, @3, *$3.string, $$.intermDeclaration);
} }
| init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
$$ = $1; $$ = $1;
$$.intermAggregate = context->parseArrayDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5); context->parseArrayDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration);
} }
| init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET EQUAL initializer { | init_declarator_list COMMA identifier LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
ES3_OR_NEWER("[]", @3, "implicitly sized array"); ES3_OR_NEWER("[]", @3, "implicitly sized array");
$$ = $1; $$ = $1;
$$.intermAggregate = context->parseArrayInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, nullptr, @6, $7); context->parseArrayInitDeclarator($$.type, @3, *$3.string, @4, nullptr, @6, $7, $$.intermDeclaration);
} }
| init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer { | init_declarator_list COMMA identifier LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer {
ES3_OR_NEWER("=", @7, "first-class arrays (array initializer)"); ES3_OR_NEWER("=", @7, "first-class arrays (array initializer)");
$$ = $1; $$ = $1;
$$.intermAggregate = context->parseArrayInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5, @7, $8); context->parseArrayInitDeclarator($$.type, @3, *$3.string, @4, $5, @7, $8, $$.intermDeclaration);
} }
| init_declarator_list COMMA identifier EQUAL initializer { | init_declarator_list COMMA identifier EQUAL initializer {
$$ = $1; $$ = $1;
$$.intermAggregate = context->parseInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5); context->parseInitDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration);
} }
; ;
single_declaration single_declaration
: fully_specified_type { : fully_specified_type {
$$.type = $1; $$.type = $1;
$$.intermAggregate = context->parseSingleDeclaration($$.type, @1, ""); $$.intermDeclaration = context->parseSingleDeclaration($$.type, @1, "");
} }
| fully_specified_type identifier { | fully_specified_type identifier {
$$.type = $1; $$.type = $1;
$$.intermAggregate = context->parseSingleDeclaration($$.type, @2, *$2.string); $$.intermDeclaration = context->parseSingleDeclaration($$.type, @2, *$2.string);
} }
| fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET { | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET {
$$.type = $1; $$.type = $1;
$$.intermAggregate = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, $4); $$.intermDeclaration = context->parseSingleArrayDeclaration($$.type, @2, *$2.string, @3, $4);
} }
| fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET EQUAL initializer { | fully_specified_type identifier LEFT_BRACKET RIGHT_BRACKET EQUAL initializer {
ES3_OR_NEWER("[]", @3, "implicitly sized array"); ES3_OR_NEWER("[]", @3, "implicitly sized array");
$$.type = $1; $$.type = $1;
$$.intermAggregate = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, nullptr, @5, $6); $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, nullptr, @5, $6);
} }
| fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer { | fully_specified_type identifier LEFT_BRACKET constant_expression RIGHT_BRACKET EQUAL initializer {
ES3_OR_NEWER("=", @6, "first-class arrays (array initializer)"); ES3_OR_NEWER("=", @6, "first-class arrays (array initializer)");
$$.type = $1; $$.type = $1;
$$.intermAggregate = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, $4, @6, $7); $$.intermDeclaration = context->parseSingleArrayInitDeclaration($$.type, @2, *$2.string, @3, $4, @6, $7);
} }
| fully_specified_type identifier EQUAL initializer { | fully_specified_type identifier EQUAL initializer {
$$.type = $1; $$.type = $1;
$$.intermAggregate = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4); $$.intermDeclaration = context->parseSingleInitDeclaration($$.type, @2, *$2.string, @3, $4);
} }
; ;
...@@ -1416,10 +1414,10 @@ condition ...@@ -1416,10 +1414,10 @@ condition
context->checkIsScalarBool($1->getLine(), $1); context->checkIsScalarBool($1->getLine(), $1);
} }
| fully_specified_type identifier EQUAL initializer { | fully_specified_type identifier EQUAL initializer {
TIntermNode *intermNode; TIntermBinary *initNode = nullptr;
context->checkIsScalarBool(@2, $1); context->checkIsScalarBool(@2, $1);
if (!context->executeInitializer(@2, *$2.string, $1, $4, &intermNode)) if (!context->executeInitializer(@2, *$2.string, $1, $4, &initNode))
$$ = $4; $$ = $4;
else { else {
$$ = 0; $$ = 0;
......
...@@ -219,6 +219,7 @@ union YYSTYPE ...@@ -219,6 +219,7 @@ union YYSTYPE
TIntermTyped* intermTypedNode; TIntermTyped* intermTypedNode;
TIntermAggregate* intermAggregate; TIntermAggregate* intermAggregate;
TIntermBlock *intermBlock; TIntermBlock *intermBlock;
TIntermDeclaration *intermDeclaration;
TIntermSwitch* intermSwitch; TIntermSwitch* intermSwitch;
TIntermCase* intermCase; TIntermCase* intermCase;
}; };
......
...@@ -53,6 +53,7 @@ class TOutputTraverser : public TIntermTraverser ...@@ -53,6 +53,7 @@ class TOutputTraverser : public TIntermTraverser
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override; bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *) override; bool visitAggregate(Visit visit, TIntermAggregate *) override;
bool visitBlock(Visit visit, TIntermBlock *) override; bool visitBlock(Visit visit, TIntermBlock *) override;
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
bool visitLoop(Visit visit, TIntermLoop *) override; bool visitLoop(Visit visit, TIntermLoop *) override;
bool visitBranch(Visit visit, TIntermBranch *) override; bool visitBranch(Visit visit, TIntermBranch *) override;
}; };
...@@ -467,7 +468,6 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -467,7 +468,6 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpOuterProduct: out << "outer product"; break; case EOpOuterProduct: out << "outer product"; break;
case EOpDeclaration: out << "Declaration: "; break;
case EOpInvariantDeclaration: out << "Invariant Declaration: "; break; case EOpInvariantDeclaration: out << "Invariant Declaration: "; break;
default: default:
...@@ -493,6 +493,16 @@ bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node) ...@@ -493,6 +493,16 @@ bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
return true; return true;
} }
bool TOutputTraverser::visitDeclaration(Visit visit, TIntermDeclaration *node)
{
TInfoSinkBase &out = sink;
OutputTreeText(out, node, mDepth);
out << "Declaration\n";
return true;
}
bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node) bool TOutputTraverser::visitTernary(Visit visit, TIntermTernary *node)
{ {
TInfoSinkBase &out = sink; TInfoSinkBase &out = sink;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment