Always create TVariables for TIntermSymbol nodes
TIntermSymbol nodes are now constructed based on a specific TVariable.
This makes sure that all TIntermSymbol nodes that are created to refer
to a specific temporary in an AST transform will have consistent data.
The TVariable objects are not necessarily added to the symbol table
levels - just those variables that can be referred to by their name
during parsing need to be reachable through there.
In the future this can be taken a step further so that TIntermSymbol
nodes just to point to a TVariable instead of duplicating the
information.
BUG=angleproject:2267
TEST=angle_unittests
Change-Id: I4e7bcdb0637cd3b588d3c202ef02f4b7bd7954a1
Reviewed-on: https://chromium-review.googlesource.com/811925
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
diff --git a/src/compiler/translator/RemoveDynamicIndexing.cpp b/src/compiler/translator/RemoveDynamicIndexing.cpp
index 5fda43f..093f5e5 100644
--- a/src/compiler/translator/RemoveDynamicIndexing.cpp
+++ b/src/compiler/translator/RemoveDynamicIndexing.cpp
@@ -58,29 +58,30 @@
return nameSink.str();
}
-TIntermSymbol *CreateBaseSymbol(const TType &type, TQualifier qualifier, TSymbolTable *symbolTable)
+TIntermSymbol *CreateBaseSymbol(const TType &type, TSymbolTable *symbolTable)
{
- TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), "base", type);
- symbol->setInternal(true);
- symbol->getTypePointer()->setQualifier(qualifier);
- return symbol;
+ TString *baseString = NewPoolTString("base");
+ TVariable *baseVariable =
+ new TVariable(symbolTable, baseString, type, SymbolType::AngleInternal);
+ return new TIntermSymbol(baseVariable);
}
TIntermSymbol *CreateIndexSymbol(TSymbolTable *symbolTable)
{
- TIntermSymbol *symbol =
- new TIntermSymbol(symbolTable->nextUniqueId(), "index", TType(EbtInt, EbpHigh));
- symbol->setInternal(true);
- symbol->getTypePointer()->setQualifier(EvqIn);
- return symbol;
+ TString *indexString = NewPoolTString("index");
+ TVariable *indexVariable = new TVariable(
+ symbolTable, indexString, TType(EbtInt, EbpHigh, EvqIn), SymbolType::AngleInternal);
+ return new TIntermSymbol(indexVariable);
}
TIntermSymbol *CreateValueSymbol(const TType &type, TSymbolTable *symbolTable)
{
- TIntermSymbol *symbol = new TIntermSymbol(symbolTable->nextUniqueId(), "value", type);
- symbol->setInternal(true);
- symbol->getTypePointer()->setQualifier(EvqIn);
- return symbol;
+ TString *valueString = NewPoolTString("value");
+ TType valueType(type);
+ valueType.setQualifier(EvqIn);
+ TVariable *valueVariable =
+ new TVariable(symbolTable, valueString, valueType, SymbolType::AngleInternal);
+ return new TIntermSymbol(valueVariable);
}
TIntermConstantUnion *CreateIntConstantNode(int i)
@@ -157,17 +158,12 @@
// base[1] = value;
// }
// Note that else is not used in above functions to avoid the RewriteElseBlocks transformation.
-TIntermFunctionDefinition *GetIndexFunctionDefinition(TType type,
+TIntermFunctionDefinition *GetIndexFunctionDefinition(const TType &type,
bool write,
const TSymbolUniqueId &functionId,
TSymbolTable *symbolTable)
{
ASSERT(!type.isArray());
- // Conservatively use highp here, even if the indexed type is not highp. That way the code can't
- // end up using mediump version of an indexing function for a highp value, if both mediump and
- // highp values are being indexed in the shader. For HLSL precision doesn't matter, but in
- // principle this code could be used with multiple backends.
- type.setPrecision(EbpHigh);
TType fieldType = GetFieldType(type);
int numCases = 0;
@@ -190,10 +186,17 @@
TIntermFunctionPrototype *prototypeNode =
CreateInternalFunctionPrototypeNode(returnType, functionName.c_str(), functionId);
- TQualifier baseQualifier = EvqInOut;
+ TType baseType(type);
+ // Conservatively use highp here, even if the indexed type is not highp. That way the code can't
+ // end up using mediump version of an indexing function for a highp value, if both mediump and
+ // highp values are being indexed in the shader. For HLSL precision doesn't matter, but in
+ // principle this code could be used with multiple backends.
+ baseType.setPrecision(EbpHigh);
+ baseType.setQualifier(EvqInOut);
if (!write)
- baseQualifier = EvqIn;
- TIntermSymbol *baseParam = CreateBaseSymbol(type, baseQualifier, symbolTable);
+ baseType.setQualifier(EvqIn);
+
+ TIntermSymbol *baseParam = CreateBaseSymbol(baseType, symbolTable);
prototypeNode->getSequence()->push_back(baseParam);
TIntermSymbol *indexParam = CreateIndexSymbol(symbolTable);
prototypeNode->getSequence()->push_back(indexParam);
@@ -361,16 +364,16 @@
}
TIntermAggregate *CreateIndexedWriteFunctionCall(TIntermBinary *node,
- TIntermTyped *index,
- TIntermTyped *writtenValue,
+ TVariable *index,
+ TVariable *writtenValue,
const TSymbolUniqueId &functionId)
{
ASSERT(node->getOp() == EOpIndexIndirect);
TIntermSequence *arguments = new TIntermSequence();
// Deep copy the child nodes so that two pointers to the same node don't end up in the tree.
arguments->push_back(node->getLeft()->deepCopy());
- arguments->push_back(index->deepCopy());
- arguments->push_back(writtenValue);
+ arguments->push_back(CreateTempSymbolNode(index));
+ arguments->push_back(CreateTempSymbolNode(writtenValue));
std::string functionName = GetIndexFunctionName(node->getLeft()->getType(), true);
TIntermAggregate *indexedWriteCall =
@@ -394,15 +397,14 @@
// to this:
// int s0 = index_expr; v_expr[s0];
// Now v_expr[s0] can be safely executed several times without unintended side effects.
- nextTemporaryId();
-
- // Init the temp variable holding the index
- TIntermDeclaration *initIndex = createTempInitDeclaration(node->getRight());
- insertStatementInParentBlock(initIndex);
+ TIntermDeclaration *indexVariableDeclaration = nullptr;
+ TVariable *indexVariable = DeclareTempVariable(mSymbolTable, node->getRight(),
+ EvqTemporary, &indexVariableDeclaration);
+ insertStatementInParentBlock(indexVariableDeclaration);
mUsedTreeInsertion = true;
// Replace the index with the temp variable
- TIntermSymbol *tempIndex = createTempSymbol(node->getRight()->getType());
+ TIntermSymbol *tempIndex = CreateTempSymbolNode(indexVariable);
queueReplacementWithParent(node, node->getRight(), tempIndex, OriginalNode::IS_DROPPED);
}
else if (IntermNodePatternMatcher::IsDynamicIndexingOfVectorOrMatrix(node))
@@ -473,34 +475,34 @@
{
indexedWriteFunctionId = mWrittenVecAndMatrixTypes[type];
}
- TType fieldType = GetFieldType(type);
TIntermSequence insertionsBefore;
TIntermSequence insertionsAfter;
// Store the index in a temporary signed int variable.
- nextTemporaryId();
+ // s0 = index_expr;
TIntermTyped *indexInitializer = EnsureSignedInt(node->getRight());
- TIntermDeclaration *initIndex = createTempInitDeclaration(indexInitializer);
- initIndex->setLine(node->getLine());
- insertionsBefore.push_back(initIndex);
+ TIntermDeclaration *indexVariableDeclaration = nullptr;
+ TVariable *indexVariable = DeclareTempVariable(
+ mSymbolTable, indexInitializer, EvqTemporary, &indexVariableDeclaration);
+ insertionsBefore.push_back(indexVariableDeclaration);
- // Create a node for referring to the index after the nextTemporaryId() call
- // below.
- TIntermSymbol *tempIndex = createTempSymbol(indexInitializer->getType());
+ // s1 = dyn_index(v_expr, s0);
+ TIntermAggregate *indexingCall = CreateIndexFunctionCall(
+ node, CreateTempSymbolNode(indexVariable), *indexingFunctionId);
+ TIntermDeclaration *fieldVariableDeclaration = nullptr;
+ TVariable *fieldVariable = DeclareTempVariable(
+ mSymbolTable, indexingCall, EvqTemporary, &fieldVariableDeclaration);
+ insertionsBefore.push_back(fieldVariableDeclaration);
- TIntermAggregate *indexingCall =
- CreateIndexFunctionCall(node, tempIndex, *indexingFunctionId);
-
- nextTemporaryId(); // From now on, creating temporary symbols that refer to the
- // field value.
- insertionsBefore.push_back(createTempInitDeclaration(indexingCall));
-
+ // dyn_index_write(v_expr, s0, s1);
TIntermAggregate *indexedWriteCall = CreateIndexedWriteFunctionCall(
- node, tempIndex, createTempSymbol(fieldType), *indexedWriteFunctionId);
+ node, indexVariable, fieldVariable, *indexedWriteFunctionId);
insertionsAfter.push_back(indexedWriteCall);
insertStatementsInParentBlock(insertionsBefore, insertionsAfter);
- queueReplacement(createTempSymbol(fieldType), OriginalNode::IS_DROPPED);
+
+ // replace the node with s1
+ queueReplacement(CreateTempSymbolNode(fieldVariable), OriginalNode::IS_DROPPED);
mUsedTreeInsertion = true;
}
else