Commit bb2bbfbb by Olli Etuaho Committed by Commit Bot

Refactor GLSL array length method parsing

This prepares for accepting arbitrary expressions as the "this" node of the array length method. BUG=angleproject:2142 TEST=angle_unittests Change-Id: I728adb6e76d2779dedbabfaeec7d096872e0d00d Reviewed-on: https://chromium-review.googlesource.com/633945Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent 561ed3ae
...@@ -803,6 +803,13 @@ TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const ...@@ -803,6 +803,13 @@ TOperator TIntermBinary::GetMulAssignOpBasedOnOperands(const TType &left, const
// //
void TIntermUnary::promote() void TIntermUnary::promote()
{ {
if (mOp == EOpArrayLength)
{
// Special case: the qualifier of .length() doesn't depend on the operand qualifier.
setType(TType(EbtInt, EbpUndefined, EvqConst));
return;
}
TQualifier resultQualifier = EvqTemporary; TQualifier resultQualifier = EvqTemporary;
if (mOperand->getQualifier() == EvqConst) if (mOperand->getQualifier() == EvqConst)
resultQualifier = EvqConst; resultQualifier = EvqConst;
...@@ -1355,13 +1362,25 @@ TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics) ...@@ -1355,13 +1362,25 @@ TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics) TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
{ {
TConstantUnion *constArray = nullptr;
if (mOp == EOpArrayLength)
{
if (mOperand->hasSideEffects())
{
return this;
}
constArray = new TConstantUnion[1];
constArray->setIConst(mOperand->getOutermostArraySize());
}
else
{
TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
if (operandConstant == nullptr) if (operandConstant == nullptr)
{ {
return this; return this;
} }
TConstantUnion *constArray = nullptr;
switch (mOp) switch (mOp)
{ {
case EOpAny: case EOpAny:
...@@ -1386,6 +1405,7 @@ TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics) ...@@ -1386,6 +1405,7 @@ TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics); constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
break; break;
} }
}
if (constArray == nullptr) if (constArray == nullptr)
{ {
return this; return this;
......
...@@ -30,6 +30,9 @@ const char *GetOperatorString(TOperator op) ...@@ -30,6 +30,9 @@ const char *GetOperatorString(TOperator op)
case EOpPreDecrement: case EOpPreDecrement:
return "--"; return "--";
case EOpArrayLength:
return ".length()";
case EOpAdd: case EOpAdd:
return "+"; return "+";
case EOpSub: case EOpSub:
......
...@@ -42,6 +42,8 @@ enum TOperator ...@@ -42,6 +42,8 @@ enum TOperator
EOpPreIncrement, EOpPreIncrement,
EOpPreDecrement, EOpPreDecrement,
EOpArrayLength,
// //
// binary operations (ones with special GLSL syntax are used in TIntermBinary nodes, others in // binary operations (ones with special GLSL syntax are used in TIntermBinary nodes, others in
// TIntermAggregate nodes) // TIntermAggregate nodes)
......
...@@ -318,6 +318,10 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) ...@@ -318,6 +318,10 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
mOut << "Pre-Decrement"; mOut << "Pre-Decrement";
break; break;
case EOpArrayLength:
mOut << "Array length";
break;
case EOpLogicalNotComponentWise: case EOpLogicalNotComponentWise:
mOut << "component-wise not"; mOut << "component-wise not";
break; break;
......
...@@ -5447,8 +5447,6 @@ TIntermTyped *TParseContext::addMethod(TFunction *fnCall, ...@@ -5447,8 +5447,6 @@ TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
TIntermNode *thisNode, TIntermNode *thisNode,
const TSourceLoc &loc) const TSourceLoc &loc)
{ {
TConstantUnion *unionArray = new TConstantUnion[1];
int arraySize = 0;
TIntermTyped *typedThis = thisNode->getAsTyped(); TIntermTyped *typedThis = thisNode->getAsTyped();
// It's possible for the name pointer in the TFunction to be null in case it gets parsed as // It's possible for the name pointer in the TFunction to be null in case it gets parsed as
// a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS // a constructor. But such a TFunction can't reach here, since the lexer goes into FIELDS
...@@ -5471,29 +5469,18 @@ TIntermTyped *TParseContext::addMethod(TFunction *fnCall, ...@@ -5471,29 +5469,18 @@ TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
{ {
error(loc, "missing input primitive declaration before calling length on gl_in", "length"); error(loc, "missing input primitive declaration before calling length on gl_in", "length");
} }
else else if (typedThis->hasSideEffects())
{ {
arraySize = typedThis->getOutermostArraySize(); error(loc, "length method not supported on expressions with possible side effects",
if (typedThis->getAsSymbolNode() == nullptr)
{
// This code path can be hit with expressions like these:
// (a = b).length()
// (func()).length()
// (int[3](0, 1, 2)).length()
// ESSL 3.00 section 5.9 defines expressions so that this is not actually a valid
// expression.
// It allows "An array name with the length method applied" in contrast to GLSL 4.4
// spec section 5.9 which allows "An array, vector or matrix expression with the
// length method applied".
error(loc, "length can only be called on array names, not on array expressions",
"length"); "length");
} }
} else
unionArray->setIConst(arraySize); {
TIntermConstantUnion *node = TIntermUnary *node = new TIntermUnary(EOpArrayLength, typedThis);
new TIntermConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst));
node->setLine(loc); node->setLine(loc);
return node; return node->fold(mDiagnostics);
}
return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
} }
TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall, TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunction *fnCall,
......
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