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
//
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;
if (mOperand->getQualifier() == EvqConst)
resultQualifier = EvqConst;
......@@ -1355,36 +1362,49 @@ TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
{
TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
if (operandConstant == nullptr)
TConstantUnion *constArray = nullptr;
if (mOp == EOpArrayLength)
{
return this;
if (mOperand->hasSideEffects())
{
return this;
}
constArray = new TConstantUnion[1];
constArray->setIConst(mOperand->getOutermostArraySize());
}
TConstantUnion *constArray = nullptr;
switch (mOp)
else
{
case EOpAny:
case EOpAll:
case EOpLength:
case EOpTranspose:
case EOpDeterminant:
case EOpInverse:
case EOpPackSnorm2x16:
case EOpUnpackSnorm2x16:
case EOpPackUnorm2x16:
case EOpUnpackUnorm2x16:
case EOpPackHalf2x16:
case EOpUnpackHalf2x16:
case EOpPackUnorm4x8:
case EOpPackSnorm4x8:
case EOpUnpackUnorm4x8:
case EOpUnpackSnorm4x8:
constArray = operandConstant->foldUnaryNonComponentWise(mOp);
break;
default:
constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
break;
TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
if (operandConstant == nullptr)
{
return this;
}
switch (mOp)
{
case EOpAny:
case EOpAll:
case EOpLength:
case EOpTranspose:
case EOpDeterminant:
case EOpInverse:
case EOpPackSnorm2x16:
case EOpUnpackSnorm2x16:
case EOpPackUnorm2x16:
case EOpUnpackUnorm2x16:
case EOpPackHalf2x16:
case EOpUnpackHalf2x16:
case EOpPackUnorm4x8:
case EOpPackSnorm4x8:
case EOpUnpackUnorm4x8:
case EOpUnpackSnorm4x8:
constArray = operandConstant->foldUnaryNonComponentWise(mOp);
break;
default:
constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
break;
}
}
if (constArray == nullptr)
{
......
......@@ -30,6 +30,9 @@ const char *GetOperatorString(TOperator op)
case EOpPreDecrement:
return "--";
case EOpArrayLength:
return ".length()";
case EOpAdd:
return "+";
case EOpSub:
......
......@@ -42,6 +42,8 @@ enum TOperator
EOpPreIncrement,
EOpPreDecrement,
EOpArrayLength,
//
// binary operations (ones with special GLSL syntax are used in TIntermBinary nodes, others in
// TIntermAggregate nodes)
......
......@@ -318,6 +318,10 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
mOut << "Pre-Decrement";
break;
case EOpArrayLength:
mOut << "Array length";
break;
case EOpLogicalNotComponentWise:
mOut << "component-wise not";
break;
......
......@@ -5447,8 +5447,6 @@ TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
TIntermNode *thisNode,
const TSourceLoc &loc)
{
TConstantUnion *unionArray = new TConstantUnion[1];
int arraySize = 0;
TIntermTyped *typedThis = thisNode->getAsTyped();
// 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
......@@ -5471,29 +5469,18 @@ TIntermTyped *TParseContext::addMethod(TFunction *fnCall,
{
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
{
arraySize = typedThis->getOutermostArraySize();
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");
}
}
unionArray->setIConst(arraySize);
TIntermConstantUnion *node =
new TIntermConstantUnion(unionArray, TType(EbtInt, EbpUndefined, EvqConst));
node->setLine(loc);
return node;
TIntermUnary *node = new TIntermUnary(EOpArrayLength, typedThis);
node->setLine(loc);
return node->fold(mDiagnostics);
}
return CreateZeroNode(TType(EbtInt, EbpUndefined, EvqConst));
}
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