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
if (symbolNode->getQualifier() == EvqConst)
{
// 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)
{
TIntermBinary *siblingBinary = siblingNode->getAsBinaryNode();
......
......@@ -598,6 +598,24 @@ bool EmulatePrecision::visitBinary(Visit visit, TIntermBinary *node)
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 visitChildren = true;
......@@ -614,21 +632,6 @@ bool EmulatePrecision::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpInvariantDeclaration:
visitChildren = false;
break;
case EOpDeclaration:
// Variable declaration.
if (visit == PreVisit)
{
mDeclaringVariables = true;
}
else if (visit == InVisit)
{
mDeclaringVariables = true;
}
else
{
mDeclaringVariables = false;
}
break;
case EOpFunctionCall:
{
// Function call.
......
......@@ -27,6 +27,7 @@ class EmulatePrecision : public TLValueTrackingTraverser
bool visitBinary(Visit visit, TIntermBinary *node) override;
bool visitUnary(Visit visit, TIntermUnary *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
void writeEmulationHelpers(TInfoSinkBase &sink,
const int shaderVersion,
......
......@@ -116,7 +116,7 @@ bool Traverser::visitAggregate(Visit visit, TIntermAggregate *node)
TIntermTyped *lhs = sequence->at(0)->getAsTyped();
ASSERT(lhs);
TIntermAggregate *init = createTempInitDeclaration(lhs);
TIntermDeclaration *init = createTempInitDeclaration(lhs);
TIntermTyped *current = createTempSymbol(lhs->getType());
insertStatementInParentBlock(init);
......
......@@ -51,7 +51,7 @@ bool ForLoopUnrollMarker::visitLoop(Visit, TIntermLoop *node)
// Check if loop index type is integer.
// This is called after ValidateLimitations pass, so the loop has the limited form specified
// 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();
if (symbol->getBasicType() == EbtInt)
node->setUnrollFlag(true);
......
......@@ -222,6 +222,11 @@ bool TIntermBlock::replaceChildNode(TIntermNode *original, TIntermNode *replacem
return replaceChildNodeInternal(original, replacement);
}
bool TIntermDeclaration::replaceChildNode(TIntermNode *original, TIntermNode *replacement)
{
return replaceChildNodeInternal(original, replacement);
}
bool TIntermAggregateBase::replaceChildNodeInternal(TIntermNode *original, TIntermNode *replacement)
{
for (size_t ii = 0; ii < getSequence()->size(); ++ii)
......@@ -320,12 +325,26 @@ void TIntermAggregate::setBuiltInFunctionPrecision()
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);
}
}
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)
{
REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement);
......
......@@ -32,6 +32,7 @@ class TDiagnostics;
class TIntermTraverser;
class TIntermAggregate;
class TIntermBlock;
class TIntermDeclaration;
class TIntermFunctionDefinition;
class TIntermSwizzle;
class TIntermBinary;
......@@ -98,6 +99,7 @@ class TIntermNode : angle::NonCopyable
virtual TIntermFunctionDefinition *getAsFunctionDefinition() { return nullptr; }
virtual TIntermAggregate *getAsAggregate() { return 0; }
virtual TIntermBlock *getAsBlock() { return nullptr; }
virtual TIntermDeclaration *getAsDeclarationNode() { return nullptr; }
virtual TIntermSwizzle *getAsSwizzleNode() { return nullptr; }
virtual TIntermBinary *getAsBinaryNode() { return 0; }
virtual TIntermUnary *getAsUnaryNode() { return 0; }
......@@ -710,6 +712,28 @@ class TIntermBlock : public TIntermNode, public TIntermAggregateBase
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.
class TIntermTernary : public TIntermTyped
{
......@@ -858,6 +882,7 @@ class TIntermTraverser : angle::NonCopyable
}
virtual bool visitAggregate(Visit visit, TIntermAggregate *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 visitBranch(Visit visit, TIntermBranch *node) { return true; }
......@@ -877,6 +902,7 @@ class TIntermTraverser : angle::NonCopyable
virtual void traverseFunctionDefinition(TIntermFunctionDefinition *node);
virtual void traverseAggregate(TIntermAggregate *node);
virtual void traverseBlock(TIntermBlock *node);
virtual void traverseDeclaration(TIntermDeclaration *node);
virtual void traverseLoop(TIntermLoop *node);
virtual void traverseBranch(TIntermBranch *node);
......@@ -987,11 +1013,11 @@ class TIntermTraverser : angle::NonCopyable
// Helper to create a temporary symbol node.
TIntermSymbol *createTempSymbol(const TType &type);
// 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.
TIntermAggregate *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier);
TIntermDeclaration *createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier);
// 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.
TIntermBinary *createTempAssignment(TIntermTyped *rightNode);
// Increment temporary symbol index.
......
......@@ -68,6 +68,11 @@ void TIntermBlock::traverse(TIntermTraverser *it)
it->traverseBlock(this);
}
void TIntermDeclaration::traverse(TIntermTraverser *it)
{
it->traverseDeclaration(this);
}
void TIntermAggregate::traverse(TIntermTraverser *it)
{
it->traverseAggregate(this);
......@@ -155,24 +160,25 @@ TIntermSymbol *TIntermTraverser::createTempSymbol(const TType &type)
return createTempSymbol(type, EvqTemporary);
}
TIntermAggregate *TIntermTraverser::createTempDeclaration(const TType &type)
TIntermDeclaration *TIntermTraverser::createTempDeclaration(const TType &type)
{
TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
tempDeclaration->getSequence()->push_back(createTempSymbol(type));
TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
tempDeclaration->appendDeclarator(createTempSymbol(type));
return tempDeclaration;
}
TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier)
TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer,
TQualifier qualifier)
{
ASSERT(initializer != nullptr);
TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier);
TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
TIntermDeclaration *tempDeclaration = new TIntermDeclaration();
TIntermBinary *tempInit = new TIntermBinary(EOpInitialize, tempSymbol, initializer);
tempDeclaration->getSequence()->push_back(tempInit);
tempDeclaration->appendDeclarator(tempInit);
return tempDeclaration;
}
TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
TIntermDeclaration *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer)
{
return createTempInitDeclaration(initializer, EvqTemporary);
}
......@@ -490,6 +496,37 @@ void TIntermTraverser::traverseBlock(TIntermBlock *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.
void TIntermTraverser::traverseAggregate(TIntermAggregate *node)
{
......
......@@ -93,8 +93,7 @@ void TLoopIndexInfo::fillInfo(TIntermLoop *node)
// Here we assume all the operations are valid, because the loop node is
// already validated in ValidateLimitations.
TIntermSequence *declSeq =
node->getInit()->getAsAggregate()->getSequence();
TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode();
TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode();
......
......@@ -16,7 +16,6 @@ enum TOperator
EOpFunctionCall,
EOpParameters, // an aggregate listing the parameters to a function
EOpDeclaration,
EOpInvariantDeclaration, // Specialized declarations for attributing invariance
EOpPrototype,
......
......@@ -916,27 +916,6 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
out << ")";
visitChildren = false;
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:
// Invariant declaration.
ASSERT(visit == PreVisit);
......@@ -1059,6 +1038,32 @@ bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
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)
{
TInfoSinkBase &out = objSink();
......@@ -1092,8 +1097,7 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
else
{
// Need to put a one-iteration loop here to handle break.
TIntermSequence *declSeq =
node->getInit()->getAsAggregate()->getSequence();
TIntermSequence *declSeq = node->getInit()->getAsDeclarationNode()->getSequence();
TIntermSymbol *indexSymbol =
(*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode();
TString name = hashVariableName(indexSymbol->getSymbol());
......
......@@ -52,6 +52,7 @@ class TOutputGLSLBase : public TIntermTraverser
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
bool visitBlock(Visit visit, TIntermBlock *node) override;
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
bool visitLoop(Visit visit, TIntermLoop *node) override;
bool visitBranch(Visit visit, TIntermBranch *node) override;
......
......@@ -1519,84 +1519,80 @@ bool OutputHLSL::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition
return false;
}
bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
bool OutputHLSL::visitDeclaration(Visit visit, TIntermDeclaration *node)
{
TInfoSinkBase &out = getInfoSink();
switch (node->getOp())
if (visit == PreVisit)
{
case EOpDeclaration:
if (visit == PreVisit)
{
TIntermSequence *sequence = node->getSequence();
TIntermTyped *variable = (*sequence)[0]->getAsTyped();
ASSERT(sequence->size() == 1);
TIntermSequence *sequence = node->getSequence();
TIntermTyped *variable = (*sequence)[0]->getAsTyped();
ASSERT(sequence->size() == 1);
if (variable &&
(variable->getQualifier() == EvqTemporary ||
variable->getQualifier() == EvqGlobal || variable->getQualifier() == EvqConst))
{
ensureStructDefined(variable->getType());
if (variable &&
(variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal ||
variable->getQualifier() == EvqConst))
{
ensureStructDefined(variable->getType());
if (!variable->getAsSymbolNode() ||
variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
{
if (!mInsideFunction)
{
out << "static ";
}
if (!variable->getAsSymbolNode() ||
variable->getAsSymbolNode()->getSymbol() != "") // Variable declaration
{
if (!mInsideFunction)
{
out << "static ";
}
out << TypeString(variable->getType()) + " ";
out << TypeString(variable->getType()) + " ";
TIntermSymbol *symbol = variable->getAsSymbolNode();
TIntermSymbol *symbol = variable->getAsSymbolNode();
if (symbol)
{
symbol->traverse(this);
out << ArrayString(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();
if (symbol)
{
symbol->traverse(this);
out << ArrayString(symbol->getType());
out << " = " + initializer(symbol->getType());
}
else if (variable && IsVaryingOut(variable->getQualifier()))
else
{
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);
}
}
variable->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:
// Do not do any translation
return false;
......@@ -2177,39 +2173,6 @@ bool OutputHLSL::visitBranch(Visit visit, TIntermBranch *node)
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
// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
......@@ -2227,7 +2190,7 @@ bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
// Parse index name and intial value
if (node->getInit())
{
TIntermAggregate *init = node->getInit()->getAsAggregate();
TIntermDeclaration *init = node->getInit()->getAsDeclarationNode();
if (init)
{
......
......@@ -69,10 +69,10 @@ class OutputHLSL : public TIntermTraverser
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate*);
bool visitBlock(Visit visit, TIntermBlock *node);
bool visitDeclaration(Visit visit, TIntermDeclaration *node);
bool visitLoop(Visit visit, TIntermLoop*);
bool visitBranch(Visit visit, TIntermBranch*);
bool isSingleStatement(TIntermNode *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.
......
......@@ -202,66 +202,66 @@ class TParseContext : angle::NonCopyable
const TString &identifier,
const TPublicType &pType,
TIntermTyped *initializer,
TIntermNode **intermNode);
TIntermBinary **initNode);
TPublicType addFullySpecifiedType(const TTypeQualifierBuilder &typeQualifierBuilder,
const TPublicType &typeSpecifier);
TIntermAggregate *parseSingleDeclaration(TPublicType &publicType,
const TSourceLoc &identifierOrTypeLocation,
const TString &identifier);
TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &indexLocation,
TIntermTyped *indexExpression);
TIntermAggregate *parseSingleInitDeclaration(const TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &initLocation,
TIntermTyped *initializer);
TIntermDeclaration *parseSingleDeclaration(TPublicType &publicType,
const TSourceLoc &identifierOrTypeLocation,
const TString &identifier);
TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &indexLocation,
TIntermTyped *indexExpression);
TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &initLocation,
TIntermTyped *initializer);
// Parse a declaration like "type a[n] = initializer"
// Note that this does not apply to declarations like "type[n] a = initializer"
TIntermAggregate *parseSingleArrayInitDeclaration(TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &indexLocation,
TIntermTyped *indexExpression,
const TSourceLoc &initLocation,
TIntermTyped *initializer);
TIntermDeclaration *parseSingleArrayInitDeclaration(TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &indexLocation,
TIntermTyped *indexExpression,
const TSourceLoc &initLocation,
TIntermTyped *initializer);
TIntermAggregate *parseInvariantDeclaration(const TTypeQualifierBuilder &typeQualifierBuilder,
const TSourceLoc &identifierLoc,
const TString *identifier,
const TSymbol *symbol);
TIntermAggregate *parseDeclarator(TPublicType &publicType,
TIntermAggregate *aggregateDeclaration,
const TSourceLoc &identifierLocation,
const TString &identifier);
TIntermAggregate *parseArrayDeclarator(TPublicType &publicType,
TIntermAggregate *aggregateDeclaration,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &arrayLocation,
TIntermTyped *indexExpression);
TIntermAggregate *parseInitDeclarator(const TPublicType &publicType,
TIntermAggregate *aggregateDeclaration,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &initLocation,
TIntermTyped *initializer);
void parseDeclarator(TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
TIntermDeclaration *declarationOut);
void parseArrayDeclarator(TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &arrayLocation,
TIntermTyped *indexExpression,
TIntermDeclaration *declarationOut);
void parseInitDeclarator(const TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &initLocation,
TIntermTyped *initializer,
TIntermDeclaration *declarationOut);
// Parse a declarator like "a[n] = initializer"
TIntermAggregate *parseArrayInitDeclarator(const TPublicType &publicType,
TIntermAggregate *aggregateDeclaration,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &indexLocation,
TIntermTyped *indexExpression,
const TSourceLoc &initLocation,
TIntermTyped *initializer);
void parseArrayInitDeclarator(const TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &indexLocation,
TIntermTyped *indexExpression,
const TSourceLoc &initLocation,
TIntermTyped *initializer,
TIntermDeclaration *declarationOut);
void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder);
TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &parsedFunction,
......@@ -302,14 +302,14 @@ class TParseContext : angle::NonCopyable
const TString *structName,
TFieldList *fieldList);
TIntermAggregate *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
const TSourceLoc &nameLine,
const TString &blockName,
TFieldList *fieldList,
const TString *instanceName,
const TSourceLoc &instanceLine,
TIntermTyped *arrayIndex,
const TSourceLoc &arrayIndexLine);
TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
const TSourceLoc &nameLine,
const TString &blockName,
TFieldList *fieldList,
const TString *instanceName,
const TSourceLoc &instanceLine,
TIntermTyped *arrayIndex,
const TSourceLoc &arrayIndexLine);
void parseLocalSize(const TString &qualifierType,
const TSourceLoc &qualifierTypeLine,
......@@ -409,8 +409,10 @@ class TParseContext : angle::NonCopyable
TIntermTyped *addBinaryMathInternal(
TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
TIntermTyped *createAssign(
TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
TIntermBinary *createAssign(TOperator op,
TIntermTyped *left,
TIntermTyped *right,
const TSourceLoc &loc);
// 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.
TIntermTyped *createUnaryMath(
......
......@@ -18,7 +18,7 @@ class PruneEmptyDeclarationsTraverser : private TIntermTraverser
static void apply(TIntermNode *root);
private:
PruneEmptyDeclarationsTraverser();
bool visitAggregate(Visit, TIntermAggregate *node) override;
bool visitDeclaration(Visit, TIntermDeclaration *node) override;
};
void PruneEmptyDeclarationsTraverser::apply(TIntermNode *root)
......@@ -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();
if (sequence->size() >= 1)
TIntermSymbol *sym = sequence->front()->getAsSymbolNode();
// 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();
// Prune declarations without a variable name, unless it's an interface block declaration.
if (sym != nullptr && sym->getSymbol() == "" && !sym->isInterfaceBlock())
if (sequence->size() > 1)
{
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
// 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));
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentAsBlock, node, emptyReplacement));
}
else if (sym->getBasicType() != EbtStruct)
else
{
// 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)
{
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentAsBlock, node, emptyReplacement));
}
else
{
queueReplacement(node, nullptr, OriginalNode::IS_DROPPED);
}
queueReplacement(node, nullptr, OriginalNode::IS_DROPPED);
}
else if (sym->getType().getQualifier() != EvqGlobal &&
sym->getType().getQualifier() != EvqTemporary)
{
// We've hit an empty struct declaration with a qualifier, for example like
// this:
// const struct a { int i; };
// NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so
// we convert the declaration to a regular struct declaration. This is okay,
// since ESSL 1.00 spec section 4.1.8 says about structs that "The optional
// qualifiers only apply to any declarators, and are not part of the type being
// defined for name."
}
else if (sym->getType().getQualifier() != EvqGlobal &&
sym->getType().getQualifier() != EvqTemporary)
{
// We've hit an empty struct declaration with a qualifier, for example like
// this:
// const struct a { int i; };
// NVIDIA GL driver version 367.27 doesn't accept this kind of declarations, so
// we convert the declaration to a regular struct declaration. This is okay,
// since ESSL 1.00 spec section 4.1.8 says about structs that "The optional
// qualifiers only apply to any declarators, and are not part of the type being
// defined for name."
if (mInGlobalScope)
{
sym->getTypePointer()->setQualifier(EvqGlobal);
}
else
{
sym->getTypePointer()->setQualifier(EvqTemporary);
}
if (mInGlobalScope)
{
sym->getTypePointer()->setQualifier(EvqGlobal);
}
else
{
sym->getTypePointer()->setQualifier(EvqTemporary);
}
}
}
return false;
}
return true;
return false;
}
} // namespace
......
......@@ -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.
// Init the temp variable holding the index
TIntermAggregate *initIndex = createTempInitDeclaration(node->getRight());
TIntermDeclaration *initIndex = createTempInitDeclaration(node->getRight());
insertStatementInParentBlock(initIndex);
mUsedTreeInsertion = true;
......@@ -441,7 +441,7 @@ bool RemoveDynamicIndexingTraverser::visitBinary(Visit visit, TIntermBinary *nod
// Store the index in a temporary signed int variable.
TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight());
TIntermAggregate *initIndex = createTempInitDeclaration(indexInitializer);
TIntermDeclaration *initIndex = createTempInitDeclaration(indexInitializer);
initIndex->setLine(node->getLine());
insertionsBefore.push_back(initIndex);
......
......@@ -67,7 +67,7 @@ class DoWhileRewriter : public TIntermTraverser
TType boolType = TType(EbtBool);
// bool temp = false;
TIntermAggregate *tempDeclaration = nullptr;
TIntermDeclaration *tempDeclaration = nullptr;
{
TConstantUnion *falseConstant = new TConstantUnion();
falseConstant->setBConst(false);
......
......@@ -70,8 +70,7 @@ TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
nextTemporaryIndex();
TIntermTyped *typedCondition = ifElse->getCondition()->getAsTyped();
TIntermAggregate *storeCondition = createTempInitDeclaration(typedCondition);
TIntermDeclaration *storeCondition = createTempInitDeclaration(ifElse->getCondition());
TIntermBlock *falseBlock = nullptr;
......
......@@ -265,8 +265,8 @@ TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *orig
TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type);
TIntermBinary *init = new TIntermBinary(EOpInitialize, symbolNode, original);
TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration);
decl->getSequence()->push_back(init);
TIntermDeclaration *decl = new TIntermDeclaration();
decl->appendDeclarator(init);
ASSERT(mBlockStack.size() > 0);
TIntermSequence &sequence = mBlockStack.back();
......
......@@ -29,7 +29,7 @@ class SeparateArrayInitTraverser : private TIntermTraverser
static void apply(TIntermNode *root);
private:
SeparateArrayInitTraverser();
bool visitAggregate(Visit, TIntermAggregate *node) override;
bool visitDeclaration(Visit, TIntermDeclaration *node) override;
};
void SeparateArrayInitTraverser::apply(TIntermNode *root)
......@@ -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();
TIntermBinary *initNode = sequence->back()->getAsBinaryNode();
if (initNode != nullptr && initNode->getOp() == EOpInitialize)
TIntermTyped *initializer = initNode->getRight();
if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer))
{
TIntermTyped *initializer = initNode->getRight();
if (initializer->isArray() && !sh::OutputHLSL::canWriteAsHLSLLiteral(initializer))
{
// We rely on that array declarations have been isolated to single declarations.
ASSERT(sequence->size() == 1);
TIntermTyped *symbol = initNode->getLeft();
TIntermBlock *parentBlock = getParentNode()->getAsBlock();
ASSERT(parentBlock != nullptr);
// We rely on that array declarations have been isolated to single declarations.
ASSERT(sequence->size() == 1);
TIntermTyped *symbol = initNode->getLeft();
TIntermBlock *parentBlock = getParentNode()->getAsBlock();
ASSERT(parentBlock != nullptr);
TIntermSequence replacements;
TIntermSequence replacements;
TIntermAggregate *replacementDeclaration = new TIntermAggregate;
replacementDeclaration->setOp(EOpDeclaration);
replacementDeclaration->getSequence()->push_back(symbol);
replacementDeclaration->setLine(symbol->getLine());
replacements.push_back(replacementDeclaration);
TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
replacementDeclaration->appendDeclarator(symbol);
replacementDeclaration->setLine(symbol->getLine());
replacements.push_back(replacementDeclaration);
TIntermBinary *replacementAssignment =
new TIntermBinary(EOpAssign, symbol, initializer);
replacementAssignment->setLine(symbol->getLine());
replacements.push_back(replacementAssignment);
TIntermBinary *replacementAssignment =
new TIntermBinary(EOpAssign, symbol, initializer);
replacementAssignment->setLine(symbol->getLine());
replacements.push_back(replacementAssignment);
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
}
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentBlock, node, replacements));
}
return false;
}
return true;
return false;
}
} // namespace
......
......@@ -26,7 +26,7 @@ class SeparateDeclarationsTraverser : private TIntermTraverser
static void apply(TIntermNode *root);
private:
SeparateDeclarationsTraverser();
bool visitAggregate(Visit, TIntermAggregate *node) override;
bool visitDeclaration(Visit, TIntermDeclaration *node) override;
};
void SeparateDeclarationsTraverser::apply(TIntermNode *root)
......@@ -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();
if (sequence->size() > 1)
{
TIntermBlock *parentBlock = getParentNode()->getAsBlock();
ASSERT(parentBlock != nullptr);
TIntermSequence replacementDeclarations;
for (size_t ii = 0; ii < sequence->size(); ++ii)
{
TIntermAggregate *replacementDeclaration = new TIntermAggregate;
TIntermBlock *parentBlock = getParentNode()->getAsBlock();
ASSERT(parentBlock != nullptr);
replacementDeclaration->setOp(EOpDeclaration);
replacementDeclaration->getSequence()->push_back(sequence->at(ii));
replacementDeclaration->setLine(sequence->at(ii)->getLine());
replacementDeclarations.push_back(replacementDeclaration);
}
TIntermSequence replacementDeclarations;
for (size_t ii = 0; ii < sequence->size(); ++ii)
{
TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations));
replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped());
replacementDeclaration->setLine(sequence->at(ii)->getLine());
replacementDeclarations.push_back(replacementDeclaration);
}
return false;
mMultiReplacements.push_back(
NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations));
}
return true;
return false;
}
} // namespace
......
......@@ -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;"
TIntermSequence insertions;
TIntermSymbol *tempSymbol = createTempSymbol(node->getType());
TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration);
tempDeclaration->getSequence()->push_back(tempSymbol);
TIntermDeclaration *tempDeclaration = createTempDeclaration(node->getType());
insertions.push_back(tempDeclaration);
TIntermBlock *trueBlock = new TIntermBlock();
......
......@@ -213,8 +213,8 @@ int ValidateLimitations::validateForLoopInit(TIntermLoop *node)
// init-declaration has the form:
// type-specifier identifier = constant-expression
//
TIntermAggregate *decl = init->getAsAggregate();
if ((decl == NULL) || (decl->getOp() != EOpDeclaration))
TIntermDeclaration *decl = init->getAsDeclarationNode();
if (decl == nullptr)
{
error(init->getLine(), "Invalid init declaration", "for");
return -1;
......
......@@ -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());
ASSERT(!sequence.empty());
const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
TQualifier qualifier = typedNode.getQualifier();
if (typedNode.getBasicType() == EbtInterfaceBlock)
{
visitInfoList(sequence, mInterfaceBlocks);
visitChildren = false;
}
else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
qualifier == EvqFragmentOut || qualifier == EvqUniform ||
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;
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;
}
default: break;
return false;
}
return visitChildren;
return true;
}
bool CollectVariables::visitBinary(Visit, TIntermBinary *binaryNode)
......
......@@ -31,7 +31,7 @@ class CollectVariables : public TIntermTraverser
const TExtensionBehavior &extensionBehavior);
void visitSymbol(TIntermSymbol *symbol) override;
bool visitAggregate(Visit, TIntermAggregate *node) override;
bool visitDeclaration(Visit, TIntermDeclaration *node) override;
bool visitBinary(Visit visit, TIntermBinary *binaryNode) override;
private:
......
......@@ -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 visitChildren = true;
switch (node->getOp())
{
case EOpDeclaration:
{
const TIntermSequence &sequence = *(node->getSequence());
if (sequence.front()->getAsTyped()->getType().isInvariant())
{
ensureVersionIsAtLeast(GLSL_VERSION_120);
}
break;
}
case EOpInvariantDeclaration:
ensureVersionIsAtLeast(GLSL_VERSION_120);
break;
......
......@@ -58,6 +58,7 @@ class TVersionGLSL : public TIntermTraverser
void visitSymbol(TIntermSymbol *) override;
bool visitAggregate(Visit, TIntermAggregate *) override;
bool visitDeclaration(Visit, TIntermDeclaration *node) override;
private:
void ensureVersionIsAtLeast(int version);
......
......@@ -77,6 +77,7 @@ WHICH GENERATES THE GLSL ES PARSER (glslang_tab.cpp AND glslang_tab.h).
TIntermTyped* intermTypedNode;
TIntermAggregate* intermAggregate;
TIntermBlock* intermBlock;
TIntermDeclaration* intermDeclaration;
TIntermSwitch* intermSwitch;
TIntermCase* intermCase;
};
......@@ -606,10 +607,7 @@ declaration
$$ = context->addFunctionPrototypeDeclaration(*($1.function), @1);
}
| init_declarator_list SEMICOLON {
TIntermAggregate *aggNode = $1.intermAggregate;
if (aggNode && aggNode->getOp() == EOpNull)
aggNode->setOp(EOpDeclaration);
$$ = aggNode;
$$ = $1.intermDeclaration;
}
| PRECISION precision_qualifier type_specifier_no_prec SEMICOLON {
if (($2 == EbpHigh) && (context->getShaderType() == GL_FRAGMENT_SHADER) && !context->getFragmentPrecisionHigh()) {
......@@ -762,54 +760,54 @@ init_declarator_list
}
| init_declarator_list COMMA identifier {
$$ = $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 {
$$ = $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 {
ES3_OR_NEWER("[]", @3, "implicitly sized array");
$$ = $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 {
ES3_OR_NEWER("=", @7, "first-class arrays (array initializer)");
$$ = $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 {
$$ = $1;
$$.intermAggregate = context->parseInitDeclarator($$.type, $1.intermAggregate, @3, *$3.string, @4, $5);
context->parseInitDeclarator($$.type, @3, *$3.string, @4, $5, $$.intermDeclaration);
}
;
single_declaration
: fully_specified_type {
$$.type = $1;
$$.intermAggregate = context->parseSingleDeclaration($$.type, @1, "");
$$.intermDeclaration = context->parseSingleDeclaration($$.type, @1, "");
}
| fully_specified_type identifier {
$$.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 {
$$.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 {
ES3_OR_NEWER("[]", @3, "implicitly sized array");
$$.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 {
ES3_OR_NEWER("=", @6, "first-class arrays (array initializer)");
$$.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 {
$$.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
context->checkIsScalarBool($1->getLine(), $1);
}
| fully_specified_type identifier EQUAL initializer {
TIntermNode *intermNode;
TIntermBinary *initNode = nullptr;
context->checkIsScalarBool(@2, $1);
if (!context->executeInitializer(@2, *$2.string, $1, $4, &intermNode))
if (!context->executeInitializer(@2, *$2.string, $1, $4, &initNode))
$$ = $4;
else {
$$ = 0;
......
......@@ -219,6 +219,7 @@ union YYSTYPE
TIntermTyped* intermTypedNode;
TIntermAggregate* intermAggregate;
TIntermBlock *intermBlock;
TIntermDeclaration *intermDeclaration;
TIntermSwitch* intermSwitch;
TIntermCase* intermCase;
};
......
......@@ -53,6 +53,7 @@ class TOutputTraverser : public TIntermTraverser
bool visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node) override;
bool visitAggregate(Visit visit, TIntermAggregate *) override;
bool visitBlock(Visit visit, TIntermBlock *) override;
bool visitDeclaration(Visit visit, TIntermDeclaration *node) override;
bool visitLoop(Visit visit, TIntermLoop *) override;
bool visitBranch(Visit visit, TIntermBranch *) override;
};
......@@ -467,7 +468,6 @@ bool TOutputTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
case EOpOuterProduct: out << "outer product"; break;
case EOpDeclaration: out << "Declaration: "; break;
case EOpInvariantDeclaration: out << "Invariant Declaration: "; break;
default:
......@@ -493,6 +493,16 @@ bool TOutputTraverser::visitBlock(Visit visit, TIntermBlock *node)
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)
{
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