summaryrefslogtreecommitdiffstats
path: root/gfx/angle/src/compiler/translator/Intermediate.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gfx/angle/src/compiler/translator/Intermediate.cpp')
-rwxr-xr-xgfx/angle/src/compiler/translator/Intermediate.cpp222
1 files changed, 143 insertions, 79 deletions
diff --git a/gfx/angle/src/compiler/translator/Intermediate.cpp b/gfx/angle/src/compiler/translator/Intermediate.cpp
index 9e3e455ae..b6fefa45e 100755
--- a/gfx/angle/src/compiler/translator/Intermediate.cpp
+++ b/gfx/angle/src/compiler/translator/Intermediate.cpp
@@ -15,9 +15,6 @@
#include "compiler/translator/Intermediate.h"
#include "compiler/translator/SymbolTable.h"
-namespace sh
-{
-
////////////////////////////////////////////////////////////////////////////
//
// First set of functions are to help build the intermediate representation.
@@ -47,30 +44,52 @@ TIntermSymbol *TIntermediate::addSymbol(
// Returns the added node.
// The caller should set the type of the returned node.
//
-TIntermTyped *TIntermediate::addIndex(TOperator op,
- TIntermTyped *base,
- TIntermTyped *index,
- const TSourceLoc &line,
- TDiagnostics *diagnostics)
+TIntermTyped *TIntermediate::addIndex(
+ TOperator op, TIntermTyped *base, TIntermTyped *index, const TSourceLoc &line)
{
- TIntermBinary *node = new TIntermBinary(op, base, index);
+ TIntermBinary *node = new TIntermBinary(op);
node->setLine(line);
+ node->setLeft(base);
+ node->setRight(index);
- TIntermTyped *folded = node->fold(diagnostics);
- if (folded)
- {
- return folded;
- }
+ // caller should set the type
return node;
}
+//
+// Add one node as the parent of another that it operates on.
+//
+// Returns the added node.
+//
+TIntermTyped *TIntermediate::addUnaryMath(
+ TOperator op, TIntermTyped *child, const TSourceLoc &line, const TType *funcReturnType)
+{
+ //
+ // Make a new node for the operator.
+ //
+ TIntermUnary *node = new TIntermUnary(op);
+ node->setLine(line);
+ node->setOperand(child);
+ node->promote(funcReturnType);
+
+ TIntermTyped *foldedNode = node->fold(mInfoSink);
+ if (foldedNode)
+ return foldedNode;
+
+ return node;
+}
+
+//
// This is the safe way to change the operator on an aggregate, as it
// does lots of error checking and fixing. Especially for establishing
-// a function call's operation on it's set of parameters.
+// a function call's operation on it's set of parameters. Sequences
+// of instructions are also aggregates, but they just direnctly set
+// their operator to EOpSequence.
//
// Returns an aggregate node, which could be the one passed in if
// it was already an aggregate but no operator was set.
+//
TIntermAggregate *TIntermediate::setAggregateOperator(
TIntermNode *node, TOperator op, const TSourceLoc &line)
{
@@ -141,10 +160,11 @@ TIntermAggregate *TIntermediate::growAggregate(
//
// Returns an aggregate, unless NULL was passed in for the existing node.
//
-TIntermAggregate *TIntermediate::MakeAggregate(TIntermNode *node, const TSourceLoc &line)
+TIntermAggregate *TIntermediate::makeAggregate(
+ TIntermNode *node, const TSourceLoc &line)
{
- if (node == nullptr)
- return nullptr;
+ if (node == NULL)
+ return NULL;
TIntermAggregate *aggNode = new TIntermAggregate;
aggNode->getSequence()->push_back(node);
@@ -155,57 +175,70 @@ TIntermAggregate *TIntermediate::MakeAggregate(TIntermNode *node, const TSourceL
}
// If the input node is nullptr, return nullptr.
-// If the input node is a block node, return it.
-// If the input node is not a block node, put it inside a block node and return that.
-TIntermBlock *TIntermediate::EnsureBlock(TIntermNode *node)
+// If the input node is a sequence (block) node, return it.
+// If the input node is not a sequence node, put it inside a sequence node and return that.
+TIntermAggregate *TIntermediate::ensureSequence(TIntermNode *node)
{
if (node == nullptr)
return nullptr;
- TIntermBlock *blockNode = node->getAsBlock();
- if (blockNode != nullptr)
- return blockNode;
-
- blockNode = new TIntermBlock();
- blockNode->setLine(node->getLine());
- blockNode->getSequence()->push_back(node);
- return blockNode;
+ TIntermAggregate *aggNode = node->getAsAggregate();
+ if (aggNode != nullptr && aggNode->getOp() == EOpSequence)
+ return aggNode;
+
+ aggNode = makeAggregate(node, node->getLine());
+ aggNode->setOp(EOpSequence);
+ return aggNode;
}
+//
// For "if" test nodes. There are three children; a condition,
// a true path, and a false path. The two paths are in the
// nodePair.
//
-// Returns the node created.
-TIntermNode *TIntermediate::addIfElse(TIntermTyped *cond,
- TIntermNodePair nodePair,
- const TSourceLoc &line)
+// Returns the selection node created.
+//
+TIntermNode *TIntermediate::addSelection(
+ TIntermTyped *cond, TIntermNodePair nodePair, const TSourceLoc &line)
{
- // For compile time constant conditions, prune the code now.
+ //
+ // For compile time constant selections, prune the code and
+ // test now.
+ //
if (cond->getAsConstantUnion())
{
if (cond->getAsConstantUnion()->getBConst(0) == true)
{
- return EnsureBlock(nodePair.node1);
+ return nodePair.node1 ? setAggregateOperator(
+ nodePair.node1, EOpSequence, nodePair.node1->getLine()) : NULL;
}
else
{
- return EnsureBlock(nodePair.node2);
+ return nodePair.node2 ? setAggregateOperator(
+ nodePair.node2, EOpSequence, nodePair.node2->getLine()) : NULL;
}
}
- TIntermIfElse *node =
- new TIntermIfElse(cond, EnsureBlock(nodePair.node1), EnsureBlock(nodePair.node2));
+ TIntermSelection *node = new TIntermSelection(
+ cond, ensureSequence(nodePair.node1), ensureSequence(nodePair.node2));
node->setLine(line);
return node;
}
-TIntermTyped *TIntermediate::AddComma(TIntermTyped *left,
+TIntermTyped *TIntermediate::addComma(TIntermTyped *left,
TIntermTyped *right,
const TSourceLoc &line,
int shaderVersion)
{
+ TQualifier resultQualifier = EvqConst;
+ // ESSL3.00 section 12.43: The result of a sequence operator is not a constant-expression.
+ if (shaderVersion >= 300 || left->getQualifier() != EvqConst ||
+ right->getQualifier() != EvqConst)
+ {
+ resultQualifier = EvqTemporary;
+ }
+
TIntermTyped *commaNode = nullptr;
if (!left->hasSideEffects())
{
@@ -213,53 +246,58 @@ TIntermTyped *TIntermediate::AddComma(TIntermTyped *left,
}
else
{
- commaNode = new TIntermBinary(EOpComma, left, right);
- commaNode->setLine(line);
+ commaNode = growAggregate(left, right, line);
+ commaNode->getAsAggregate()->setOp(EOpComma);
+ commaNode->setType(right->getType());
}
- TQualifier resultQualifier = TIntermBinary::GetCommaQualifier(shaderVersion, left, right);
commaNode->getTypePointer()->setQualifier(resultQualifier);
return commaNode;
}
+//
// For "?:" test nodes. There are three children; a condition,
// a true path, and a false path. The two paths are specified
// as separate parameters.
//
-// Returns the ternary node created, or one of trueExpression and falseExpression if the expression
-// could be folded.
-TIntermTyped *TIntermediate::AddTernarySelection(TIntermTyped *cond,
- TIntermTyped *trueExpression,
- TIntermTyped *falseExpression,
- const TSourceLoc &line)
+// Returns the selection node created, or one of trueBlock and falseBlock if the expression could be folded.
+//
+TIntermTyped *TIntermediate::addSelection(TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock,
+ const TSourceLoc &line)
{
+ TQualifier resultQualifier = EvqTemporary;
+ if (cond->getQualifier() == EvqConst && trueBlock->getQualifier() == EvqConst &&
+ falseBlock->getQualifier() == EvqConst)
+ {
+ resultQualifier = EvqConst;
+ }
// Note that the node resulting from here can be a constant union without being qualified as
// constant.
if (cond->getAsConstantUnion())
{
- TQualifier resultQualifier =
- TIntermTernary::DetermineQualifier(cond, trueExpression, falseExpression);
if (cond->getAsConstantUnion()->getBConst(0))
{
- trueExpression->getTypePointer()->setQualifier(resultQualifier);
- return trueExpression;
+ trueBlock->getTypePointer()->setQualifier(resultQualifier);
+ return trueBlock;
}
else
{
- falseExpression->getTypePointer()->setQualifier(resultQualifier);
- return falseExpression;
+ falseBlock->getTypePointer()->setQualifier(resultQualifier);
+ return falseBlock;
}
}
- // Make a ternary node.
- TIntermTernary *node = new TIntermTernary(cond, trueExpression, falseExpression);
+ //
+ // Make a selection node.
+ //
+ TIntermSelection *node = new TIntermSelection(cond, trueBlock, falseBlock, trueBlock->getType());
+ node->getTypePointer()->setQualifier(resultQualifier);
node->setLine(line);
return node;
}
-TIntermSwitch *TIntermediate::addSwitch(TIntermTyped *init,
- TIntermBlock *statementList,
- const TSourceLoc &line)
+TIntermSwitch *TIntermediate::addSwitch(
+ TIntermTyped *init, TIntermAggregate *statementList, const TSourceLoc &line)
{
TIntermSwitch *node = new TIntermSwitch(init, statementList);
node->setLine(line);
@@ -292,22 +330,24 @@ TIntermConstantUnion *TIntermediate::addConstantUnion(const TConstantUnion *cons
return node;
}
-TIntermTyped *TIntermediate::AddSwizzle(TIntermTyped *baseExpression,
- const TVectorFields &fields,
- const TSourceLoc &dotLocation)
+TIntermTyped *TIntermediate::addSwizzle(
+ TVectorFields &fields, const TSourceLoc &line)
{
- TVector<int> fieldsVector;
- for (int i = 0; i < fields.num; ++i)
- {
- fieldsVector.push_back(fields.offsets[i]);
- }
- TIntermSwizzle *node = new TIntermSwizzle(baseExpression, fieldsVector);
- node->setLine(dotLocation);
- TIntermTyped *folded = node->fold();
- if (folded)
+ TIntermAggregate *node = new TIntermAggregate(EOpSequence);
+
+ node->setLine(line);
+ TIntermConstantUnion *constIntNode;
+ TIntermSequence *sequenceVector = node->getSequence();
+ TConstantUnion *unionArray;
+
+ for (int i = 0; i < fields.num; i++)
{
- return folded;
+ unionArray = new TConstantUnion[1];
+ unionArray->setIConst(fields.offsets[i]);
+ constIntNode = addConstantUnion(
+ unionArray, TType(EbtInt, EbpUndefined, EvqConst), line);
+ sequenceVector->push_back(constIntNode);
}
return node;
@@ -320,7 +360,7 @@ TIntermNode *TIntermediate::addLoop(
TLoopType type, TIntermNode *init, TIntermTyped *cond, TIntermTyped *expr,
TIntermNode *body, const TSourceLoc &line)
{
- TIntermNode *node = new TIntermLoop(type, init, cond, expr, EnsureBlock(body));
+ TIntermNode *node = new TIntermLoop(type, init, cond, expr, ensureSequence(body));
node->setLine(line);
return node;
@@ -344,8 +384,34 @@ TIntermBranch* TIntermediate::addBranch(
return node;
}
-TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
- TDiagnostics *diagnostics)
+//
+// This is to be executed once the final root is put on top by the parsing
+// process.
+//
+TIntermAggregate *TIntermediate::postProcess(TIntermNode *root)
+{
+ if (root == nullptr)
+ return nullptr;
+
+ //
+ // Finish off the top level sequence, if any
+ //
+ TIntermAggregate *aggRoot = root->getAsAggregate();
+ if (aggRoot != nullptr && aggRoot->getOp() == EOpNull)
+ {
+ aggRoot->setOp(EOpSequence);
+ }
+ else if (aggRoot == nullptr || aggRoot->getOp() != EOpSequence)
+ {
+ aggRoot = new TIntermAggregate(EOpSequence);
+ aggRoot->setLine(root->getLine());
+ aggRoot->getSequence()->push_back(root);
+ }
+
+ return aggRoot;
+}
+
+TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate)
{
switch (aggregate->getOp())
{
@@ -372,16 +438,14 @@ TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
case EOpFaceForward:
case EOpReflect:
case EOpRefract:
- return aggregate->fold(diagnostics);
+ return aggregate->fold(mInfoSink);
default:
// TODO: Add support for folding array constructors
if (aggregate->isConstructor() && !aggregate->isArray())
{
- return aggregate->fold(diagnostics);
+ return aggregate->fold(mInfoSink);
}
// Constant folding not supported for the built-in.
return nullptr;
}
}
-
-} // namespace sh