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,36 +1362,49 @@ TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics) ...@@ -1355,36 +1362,49 @@ TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics) TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
{ {
TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion(); TConstantUnion *constArray = nullptr;
if (operandConstant == nullptr)
if (mOp == EOpArrayLength)
{ {
return this; if (mOperand->hasSideEffects())
{
return this;
}
constArray = new TConstantUnion[1];
constArray->setIConst(mOperand->getOutermostArraySize());
} }
else
TConstantUnion *constArray = nullptr;
switch (mOp)
{ {
case EOpAny: TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
case EOpAll: if (operandConstant == nullptr)
case EOpLength: {
case EOpTranspose: return this;
case EOpDeterminant: }
case EOpInverse:
case EOpPackSnorm2x16: switch (mOp)
case EOpUnpackSnorm2x16: {
case EOpPackUnorm2x16: case EOpAny:
case EOpUnpackUnorm2x16: case EOpAll:
case EOpPackHalf2x16: case EOpLength:
case EOpUnpackHalf2x16: case EOpTranspose:
case EOpPackUnorm4x8: case EOpDeterminant:
case EOpPackSnorm4x8: case EOpInverse:
case EOpUnpackUnorm4x8: case EOpPackSnorm2x16:
case EOpUnpackSnorm4x8: case EOpUnpackSnorm2x16:
constArray = operandConstant->foldUnaryNonComponentWise(mOp); case EOpPackUnorm2x16:
break; case EOpUnpackUnorm2x16:
default: case EOpPackHalf2x16:
constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics); case EOpUnpackHalf2x16:
break; case EOpPackUnorm4x8:
case EOpPackSnorm4x8:
case EOpUnpackUnorm4x8:
case EOpUnpackSnorm4x8:
constArray = operandConstant->foldUnaryNonComponentWise(mOp);
break;
default:
constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
break;
}
} }
if (constArray == nullptr) if (constArray == nullptr)
{ {
......
...@@ -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 if (typedThis->hasSideEffects())
{
error(loc, "length method not supported on expressions with possible side effects",
"length");
}
else else
{ {
arraySize = typedThis->getOutermostArraySize(); TIntermUnary *node = new TIntermUnary(EOpArrayLength, typedThis);
if (typedThis->getAsSymbolNode() == nullptr) node->setLine(loc);
{ return node->fold(mDiagnostics);
// This code path can be hit with expressions like these: }
// (a = b).length() return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
// (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");
}
}
unionArray->setIConst(arraySize);
TIntermConstantUnion *node =
new TIntermConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst));
node->setLine(loc);
return node;
} }
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