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,13 +1519,9 @@ 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())
{
case EOpDeclaration:
if (visit == PreVisit)
{
TIntermSequence *sequence = node->getSequence();
......@@ -1533,8 +1529,8 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
ASSERT(sequence->size() == 1);
if (variable &&
(variable->getQualifier() == EvqTemporary ||
variable->getQualifier() == EvqGlobal || variable->getQualifier() == EvqConst))
(variable->getQualifier() == EvqTemporary || variable->getQualifier() == EvqGlobal ||
variable->getQualifier() == EvqConst))
{
ensureStructDefined(variable->getType());
......@@ -1562,8 +1558,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
}
}
else if (variable->getAsSymbolNode() &&
variable->getAsSymbolNode()->getSymbol() ==
"") // Type (struct) declaration
variable->getAsSymbolNode()->getSymbol() == "") // Type (struct) declaration
{
// Already added to constructor map
}
......@@ -1572,8 +1567,7 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
}
else if (variable && IsVaryingOut(variable->getQualifier()))
{
for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end();
sit++)
for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); sit++)
{
TIntermSymbol *symbol = (*sit)->getAsSymbolNode();
......@@ -1589,14 +1583,16 @@ bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
}
}
}
return false;
}
else if (visit == InVisit)
return false;
}
bool OutputHLSL::visitAggregate(Visit visit, TIntermAggregate *node)
{
TInfoSinkBase &out = getInfoSink();
switch (node->getOp())
{
out << ", ";
}
break;
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,20 +202,20 @@ 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,
TIntermDeclaration *parseSingleDeclaration(TPublicType &publicType,
const TSourceLoc &identifierOrTypeLocation,
const TString &identifier);
TIntermAggregate *parseSingleArrayDeclaration(TPublicType &publicType,
TIntermDeclaration *parseSingleArrayDeclaration(TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &indexLocation,
TIntermTyped *indexExpression);
TIntermAggregate *parseSingleInitDeclaration(const TPublicType &publicType,
TIntermDeclaration *parseSingleInitDeclaration(const TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &initLocation,
......@@ -223,7 +223,7 @@ class TParseContext : angle::NonCopyable
// 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,
TIntermDeclaration *parseSingleArrayInitDeclaration(TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &indexLocation,
......@@ -236,32 +236,32 @@ class TParseContext : angle::NonCopyable
const TString *identifier,
const TSymbol *symbol);
TIntermAggregate *parseDeclarator(TPublicType &publicType,
TIntermAggregate *aggregateDeclaration,
void parseDeclarator(TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier);
TIntermAggregate *parseArrayDeclarator(TPublicType &publicType,
TIntermAggregate *aggregateDeclaration,
const TString &identifier,
TIntermDeclaration *declarationOut);
void parseArrayDeclarator(TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &arrayLocation,
TIntermTyped *indexExpression);
TIntermAggregate *parseInitDeclarator(const TPublicType &publicType,
TIntermAggregate *aggregateDeclaration,
TIntermTyped *indexExpression,
TIntermDeclaration *declarationOut);
void parseInitDeclarator(const TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &initLocation,
TIntermTyped *initializer);
TIntermTyped *initializer,
TIntermDeclaration *declarationOut);
// Parse a declarator like "a[n] = initializer"
TIntermAggregate *parseArrayInitDeclarator(const TPublicType &publicType,
TIntermAggregate *aggregateDeclaration,
void parseArrayInitDeclarator(const TPublicType &publicType,
const TSourceLoc &identifierLocation,
const TString &identifier,
const TSourceLoc &indexLocation,
TIntermTyped *indexExpression,
const TSourceLoc &initLocation,
TIntermTyped *initializer);
TIntermTyped *initializer,
TIntermDeclaration *declarationOut);
void parseGlobalLayoutQualifier(const TTypeQualifierBuilder &typeQualifierBuilder);
TIntermAggregate *addFunctionPrototypeDeclaration(const TFunction &parsedFunction,
......@@ -302,7 +302,7 @@ class TParseContext : angle::NonCopyable
const TString *structName,
TFieldList *fieldList);
TIntermAggregate *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
TIntermDeclaration *addInterfaceBlock(const TTypeQualifierBuilder &typeQualifierBuilder,
const TSourceLoc &nameLine,
const TString &blockName,
TFieldList *fieldList,
......@@ -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,10 +33,8 @@ 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)
{
......@@ -46,20 +44,21 @@ bool PruneEmptyDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *no
{
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:
// 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(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:
// 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();
......@@ -99,8 +98,6 @@ bool PruneEmptyDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *no
}
}
return false;
}
return true;
}
} // 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,10 +44,8 @@ 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)
......@@ -63,9 +61,8 @@ bool SeparateArrayInitTraverser::visitAggregate(Visit, TIntermAggregate *node)
TIntermSequence replacements;
TIntermAggregate *replacementDeclaration = new TIntermAggregate;
replacementDeclaration->setOp(EOpDeclaration);
replacementDeclaration->getSequence()->push_back(symbol);
TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
replacementDeclaration->appendDeclarator(symbol);
replacementDeclaration->setLine(symbol->getLine());
replacements.push_back(replacementDeclaration);
......@@ -79,8 +76,6 @@ bool SeparateArrayInitTraverser::visitAggregate(Visit, TIntermAggregate *node)
}
}
return false;
}
return true;
}
} // 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,10 +41,8 @@ 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)
{
......@@ -54,10 +52,9 @@ bool SeparateDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node
TIntermSequence replacementDeclarations;
for (size_t ii = 0; ii < sequence->size(); ++ii)
{
TIntermAggregate *replacementDeclaration = new TIntermAggregate;
TIntermDeclaration *replacementDeclaration = new TIntermDeclaration();
replacementDeclaration->setOp(EOpDeclaration);
replacementDeclaration->getSequence()->push_back(sequence->at(ii));
replacementDeclaration->appendDeclarator(sequence->at(ii)->getAsTyped());
replacementDeclaration->setLine(sequence->at(ii)->getLine());
replacementDeclarations.push_back(replacementDeclaration);
}
......@@ -66,8 +63,6 @@ bool SeparateDeclarationsTraverser::visitAggregate(Visit, TIntermAggregate *node
NodeReplaceWithMultipleEntry(parentBlock, node, replacementDeclarations));
}
return false;
}
return true;
}
} // 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,14 +559,8 @@ void CollectVariables::visitInfoList(const TIntermSequence &sequence,
}
}
bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
bool CollectVariables::visitDeclaration(Visit, TIntermDeclaration *node)
{
bool visitChildren = true;
switch (node->getOp())
{
case EOpDeclaration:
{
const TIntermSequence &sequence = *(node->getSequence());
ASSERT(!sequence.empty());
......@@ -576,11 +570,10 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
if (typedNode.getBasicType() == EbtInterfaceBlock)
{
visitInfoList(sequence, mInterfaceBlocks);
visitChildren = false;
return false;
}
else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
qualifier == EvqFragmentOut || qualifier == EvqUniform ||
IsVarying(qualifier))
else if (qualifier == EvqAttribute || qualifier == EvqVertexIn || qualifier == EvqFragmentOut ||
qualifier == EvqUniform || IsVarying(qualifier))
{
switch (qualifier)
{
......@@ -599,14 +592,10 @@ bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
break;
}
visitChildren = false;
}
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::visitAggregate(Visit, TIntermAggregate *node)
bool TVersionGLSL::visitDeclaration(Visit, TIntermDeclaration *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;
}
return true;
}
bool TVersionGLSL::visitAggregate(Visit, TIntermAggregate *node)
{
bool visitChildren = true;
switch (node->getOp())
{
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