Commit f119a263 by Olli Etuaho Committed by Commit Bot

Clean up unary and aggregate math folding

Prefer asserts instead of adding internal errors to the compiler log when types of arguments are not as expected or the folding function runs into an operation it can't handle. Neither of these cases should be possible, the checks for correct argument types are solid at this point. In the future, when new built-in functions are added, constant folding support for them should be added as well. foldUnaryWithDifferentReturnType and foldUnaryWithSameReturnType are renamed to foldUnaryNonComponentWise and foldUnaryComponentWise respectively. These names better reflect what these functions are doing. The info sink member is removed from TIntermediate, since TDiagnostics is now passed into the functions that may generate warnings instead. BUG=angleproject:1490 TEST=angle_unittests Change-Id: I6a08abbe29cf23f3a318032fdc46dd3dbaf4410e Reviewed-on: https://chromium-review.googlesource.com/377959 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 9df01f8a
......@@ -219,8 +219,7 @@ TIntermNode *TCompiler::compileTreeImpl(const char *const shaderStrings[],
++firstSource;
}
TIntermediate intermediate(infoSink);
TParseContext parseContext(symbolTable, extensionBehavior, intermediate, shaderType, shaderSpec,
TParseContext parseContext(symbolTable, extensionBehavior, shaderType, shaderSpec,
compileOptions, true, infoSink, getResources());
parseContext.setFragmentPrecisionHighOnESSL1(fragmentPrecisionHigh);
......@@ -254,7 +253,7 @@ TIntermNode *TCompiler::compileTreeImpl(const char *const shaderStrings[],
mComputeShaderLocalSize = parseContext.getComputeShaderLocalSize();
root = parseContext.getTreeRoot();
root = intermediate.postProcess(root);
root = TIntermediate::PostProcess(root);
// Highp might have been auto-enabled based on shader version
fragmentPrecisionHigh = parseContext.getFragmentPrecisionHigh();
......
......@@ -44,13 +44,14 @@ TConstantUnion *Vectorize(const TConstantUnion &constant, size_t size)
return constUnion;
}
void UndefinedConstantFoldingError(const TSourceLoc &loc, TOperator op, TBasicType basicType,
TInfoSink &infoSink, TConstantUnion *result)
void UndefinedConstantFoldingError(const TSourceLoc &loc,
TOperator op,
TBasicType basicType,
TDiagnostics *diagnostics,
TConstantUnion *result)
{
std::stringstream constantFoldingErrorStream;
constantFoldingErrorStream << "'" << GetOperatorString(op)
<< "' operation result is undefined for the values passed in";
infoSink.info.message(EPrefixWarning, loc, constantFoldingErrorStream.str().c_str());
diagnostics->warning(loc, "operation result is undefined for the values passed in",
GetOperatorString(op), "");
switch (basicType)
{
......@@ -856,7 +857,7 @@ TIntermTyped *TIntermBinary::fold(TDiagnostics *diagnostics)
return CreateFoldedNode(constArray, this, resultQualifier);
}
TIntermTyped *TIntermUnary::fold(TInfoSink &infoSink)
TIntermTyped *TIntermUnary::fold(TDiagnostics *diagnostics)
{
TIntermConstantUnion *operandConstant = mOperand->getAsConstantUnion();
if (operandConstant == nullptr)
......@@ -879,11 +880,11 @@ TIntermTyped *TIntermUnary::fold(TInfoSink &infoSink)
case EOpUnpackUnorm2x16:
case EOpPackHalf2x16:
case EOpUnpackHalf2x16:
constArray = operandConstant->foldUnaryWithDifferentReturnType(mOp, infoSink);
break;
constArray = operandConstant->foldUnaryNonComponentWise(mOp);
break;
default:
constArray = operandConstant->foldUnaryWithSameReturnType(mOp, infoSink);
break;
constArray = operandConstant->foldUnaryComponentWise(mOp, diagnostics);
break;
}
// Nodes may be constant folded without being qualified as constant.
......@@ -891,7 +892,7 @@ TIntermTyped *TIntermUnary::fold(TInfoSink &infoSink)
return CreateFoldedNode(constArray, this, resultQualifier);
}
TIntermTyped *TIntermAggregate::fold(TInfoSink &infoSink)
TIntermTyped *TIntermAggregate::fold(TDiagnostics *diagnostics)
{
// Make sure that all params are constant before actual constant folding.
for (auto *param : *getSequence())
......@@ -903,9 +904,9 @@ TIntermTyped *TIntermAggregate::fold(TInfoSink &infoSink)
}
TConstantUnion *constArray = nullptr;
if (isConstructor())
constArray = TIntermConstantUnion::FoldAggregateConstructor(this, infoSink);
constArray = TIntermConstantUnion::FoldAggregateConstructor(this);
else
constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, infoSink);
constArray = TIntermConstantUnion::FoldAggregateBuiltIn(this, diagnostics);
// Nodes may be constant folded without being qualified as constant.
TQualifier resultQualifier = areChildrenConstQualified() ? EvqConst : EvqTemporary;
......@@ -925,10 +926,7 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
const TConstantUnion *leftArray = getUnionArrayPointer();
const TConstantUnion *rightArray = rightNode->getUnionArrayPointer();
if (!leftArray)
return nullptr;
if (!rightArray)
return nullptr;
ASSERT(leftArray && rightArray);
size_t objectSize = getType().getObjectSize();
......@@ -1224,29 +1222,22 @@ TConstantUnion *TIntermConstantUnion::foldBinary(TOperator op,
return resultArray;
}
//
// The fold functions see if an operation on a constant can be done in place,
// without generating run-time code.
//
// Returns the constant value to keep using or nullptr.
//
TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink)
// The fold functions do operations on a constant at GLSL compile time, without generating run-time
// code. Returns the constant value to keep using. Nullptr should not be returned.
TConstantUnion *TIntermConstantUnion::foldUnaryNonComponentWise(TOperator op)
{
//
// Do operations where the return type has a different number of components compared to the operand type.
//
// Do operations where the return type may have a different number of components compared to the
// operand type.
const TConstantUnion *operandArray = getUnionArrayPointer();
if (!operandArray)
return nullptr;
ASSERT(operandArray);
size_t objectSize = getType().getObjectSize();
TConstantUnion *resultArray = nullptr;
switch (op)
{
case EOpAny:
if (getType().getBasicType() == EbtBool)
{
case EOpAny:
ASSERT(getType().getBasicType() == EbtBool);
resultArray = new TConstantUnion();
resultArray->setBConst(false);
for (size_t i = 0; i < objectSize; i++)
......@@ -1258,16 +1249,9 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator
}
}
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpAll:
if (getType().getBasicType() == EbtBool)
{
case EOpAll:
ASSERT(getType().getBasicType() == EbtBool);
resultArray = new TConstantUnion();
resultArray->setBConst(true);
for (size_t i = 0; i < objectSize; i++)
......@@ -1279,89 +1263,55 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator
}
}
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpLength:
if (getType().getBasicType() == EbtFloat)
{
case EOpLength:
ASSERT(getType().getBasicType() == EbtFloat);
resultArray = new TConstantUnion();
resultArray->setFConst(VectorLength(operandArray, objectSize));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpTranspose:
if (getType().getBasicType() == EbtFloat)
case EOpTranspose:
{
ASSERT(getType().getBasicType() == EbtFloat);
resultArray = new TConstantUnion[objectSize];
angle::Matrix<float> result =
GetMatrix(operandArray, getType().getRows(), getType().getCols()).transpose();
SetUnionArrayFromMatrix(result, resultArray);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpDeterminant:
if (getType().getBasicType() == EbtFloat)
case EOpDeterminant:
{
ASSERT(getType().getBasicType() == EbtFloat);
unsigned int size = getType().getNominalSize();
ASSERT(size >= 2 && size <= 4);
resultArray = new TConstantUnion();
resultArray->setFConst(GetMatrix(operandArray, size).determinant());
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpInverse:
if (getType().getBasicType() == EbtFloat)
case EOpInverse:
{
ASSERT(getType().getBasicType() == EbtFloat);
unsigned int size = getType().getNominalSize();
ASSERT(size >= 2 && size <= 4);
resultArray = new TConstantUnion[objectSize];
resultArray = new TConstantUnion[objectSize];
angle::Matrix<float> result = GetMatrix(operandArray, size).inverse();
SetUnionArrayFromMatrix(result, resultArray);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpPackSnorm2x16:
if (getType().getBasicType() == EbtFloat)
{
case EOpPackSnorm2x16:
ASSERT(getType().getBasicType() == EbtFloat);
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
resultArray->setUConst(gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
resultArray->setUConst(
gl::packSnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackSnorm2x16:
if (getType().getBasicType() == EbtUInt)
case EOpUnpackSnorm2x16:
{
ASSERT(getType().getBasicType() == EbtUInt);
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackSnorm2x16(operandArray[0].getUConst(), &f1, &f2);
......@@ -1369,29 +1319,18 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator
resultArray[1].setFConst(f2);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpPackUnorm2x16:
if (getType().getBasicType() == EbtFloat)
{
case EOpPackUnorm2x16:
ASSERT(getType().getBasicType() == EbtFloat);
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
resultArray->setUConst(gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
resultArray->setUConst(
gl::packUnorm2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackUnorm2x16:
if (getType().getBasicType() == EbtUInt)
case EOpUnpackUnorm2x16:
{
ASSERT(getType().getBasicType() == EbtUInt);
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackUnorm2x16(operandArray[0].getUConst(), &f1, &f2);
......@@ -1399,29 +1338,18 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator
resultArray[1].setFConst(f2);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpPackHalf2x16:
if (getType().getBasicType() == EbtFloat)
{
case EOpPackHalf2x16:
ASSERT(getType().getBasicType() == EbtFloat);
ASSERT(getType().getNominalSize() == 2);
resultArray = new TConstantUnion();
resultArray->setUConst(gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
resultArray->setUConst(
gl::packHalf2x16(operandArray[0].getFConst(), operandArray[1].getFConst()));
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
case EOpUnpackHalf2x16:
if (getType().getBasicType() == EbtUInt)
case EOpUnpackHalf2x16:
{
ASSERT(getType().getBasicType() == EbtUInt);
resultArray = new TConstantUnion[2];
float f1, f2;
gl::unpackHalf2x16(operandArray[0].getUConst(), &f1, &f2);
......@@ -1429,29 +1357,24 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithDifferentReturnType(TOperator
resultArray[1].setFConst(f2);
break;
}
else
{
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
}
break;
default:
break;
default:
UNREACHABLE();
break;
}
return resultArray;
}
TConstantUnion *TIntermConstantUnion::foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink)
TConstantUnion *TIntermConstantUnion::foldUnaryComponentWise(TOperator op,
TDiagnostics *diagnostics)
{
//
// Do unary operations where the return type is the same as operand type.
//
// Do unary operations where each component of the result is computed based on the corresponding
// component of the operand. Also folds normalize, though the divisor in that case takes all
// components into account.
const TConstantUnion *operandArray = getUnionArrayPointer();
if (!operandArray)
return nullptr;
ASSERT(operandArray);
size_t objectSize = getType().getObjectSize();
......@@ -1460,243 +1383,213 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithSameReturnType(TOperator op,
{
switch(op)
{
case EOpNegative:
switch (getType().getBasicType())
{
case EbtFloat:
resultArray[i].setFConst(-operandArray[i].getFConst());
break;
case EbtInt:
resultArray[i].setIConst(-operandArray[i].getIConst());
break;
case EbtUInt:
resultArray[i].setUConst(static_cast<unsigned int>(
-static_cast<int>(operandArray[i].getUConst())));
case EOpNegative:
switch (getType().getBasicType())
{
case EbtFloat:
resultArray[i].setFConst(-operandArray[i].getFConst());
break;
case EbtInt:
resultArray[i].setIConst(-operandArray[i].getIConst());
break;
case EbtUInt:
resultArray[i].setUConst(static_cast<unsigned int>(
-static_cast<int>(operandArray[i].getUConst())));
break;
default:
UNREACHABLE();
return nullptr;
}
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpPositive:
switch (getType().getBasicType())
{
case EbtFloat:
resultArray[i].setFConst(operandArray[i].getFConst());
break;
case EbtInt:
resultArray[i].setIConst(operandArray[i].getIConst());
break;
case EbtUInt:
resultArray[i].setUConst(static_cast<unsigned int>(
static_cast<int>(operandArray[i].getUConst())));
case EOpPositive:
switch (getType().getBasicType())
{
case EbtFloat:
resultArray[i].setFConst(operandArray[i].getFConst());
break;
case EbtInt:
resultArray[i].setIConst(operandArray[i].getIConst());
break;
case EbtUInt:
resultArray[i].setUConst(static_cast<unsigned int>(
static_cast<int>(operandArray[i].getUConst())));
break;
default:
UNREACHABLE();
return nullptr;
}
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpLogicalNot:
// this code is written for possible future use,
// will not get executed currently
switch (getType().getBasicType())
{
case EbtBool:
resultArray[i].setBConst(!operandArray[i].getBConst());
case EOpLogicalNot:
switch (getType().getBasicType())
{
case EbtBool:
resultArray[i].setBConst(!operandArray[i].getBConst());
break;
default:
UNREACHABLE();
return nullptr;
}
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpBitwiseNot:
switch (getType().getBasicType())
{
case EbtInt:
resultArray[i].setIConst(~operandArray[i].getIConst());
break;
case EbtUInt:
resultArray[i].setUConst(~operandArray[i].getUConst());
case EOpBitwiseNot:
switch (getType().getBasicType())
{
case EbtInt:
resultArray[i].setIConst(~operandArray[i].getIConst());
break;
case EbtUInt:
resultArray[i].setUConst(~operandArray[i].getUConst());
break;
default:
UNREACHABLE();
return nullptr;
}
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpRadians:
if (getType().getBasicType() == EbtFloat)
{
case EOpRadians:
ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setFConst(kDegreesToRadiansMultiplier * operandArray[i].getFConst());
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpDegrees:
if (getType().getBasicType() == EbtFloat)
{
case EOpDegrees:
ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setFConst(kRadiansToDegreesMultiplier * operandArray[i].getFConst());
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpSin:
if (!foldFloatTypeUnary(operandArray[i], &sinf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpCos:
if (!foldFloatTypeUnary(operandArray[i], &cosf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpTan:
if (!foldFloatTypeUnary(operandArray[i], &tanf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpSin:
foldFloatTypeUnary(operandArray[i], &sinf, &resultArray[i]);
break;
case EOpAsin:
// For asin(x), results are undefined if |x| > 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &asinf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpCos:
foldFloatTypeUnary(operandArray[i], &cosf, &resultArray[i]);
break;
case EOpAcos:
// For acos(x), results are undefined if |x| > 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) > 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &acosf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpTan:
foldFloatTypeUnary(operandArray[i], &tanf, &resultArray[i]);
break;
case EOpAtan:
if (!foldFloatTypeUnary(operandArray[i], &atanf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAsin:
// For asin(x), results are undefined if |x| > 1, we are choosing to set result to
// 0.
if (fabsf(operandArray[i].getFConst()) > 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
diagnostics, &resultArray[i]);
else
foldFloatTypeUnary(operandArray[i], &asinf, &resultArray[i]);
break;
case EOpSinh:
if (!foldFloatTypeUnary(operandArray[i], &sinhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAcos:
// For acos(x), results are undefined if |x| > 1, we are choosing to set result to
// 0.
if (fabsf(operandArray[i].getFConst()) > 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
diagnostics, &resultArray[i]);
else
foldFloatTypeUnary(operandArray[i], &acosf, &resultArray[i]);
break;
case EOpCosh:
if (!foldFloatTypeUnary(operandArray[i], &coshf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAtan:
foldFloatTypeUnary(operandArray[i], &atanf, &resultArray[i]);
break;
case EOpTanh:
if (!foldFloatTypeUnary(operandArray[i], &tanhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpSinh:
foldFloatTypeUnary(operandArray[i], &sinhf, &resultArray[i]);
break;
case EOpAsinh:
if (!foldFloatTypeUnary(operandArray[i], &asinhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpCosh:
foldFloatTypeUnary(operandArray[i], &coshf, &resultArray[i]);
break;
case EOpAcosh:
// For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &acoshf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpTanh:
foldFloatTypeUnary(operandArray[i], &tanhf, &resultArray[i]);
break;
case EOpAtanh:
// For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && fabsf(operandArray[i].getFConst()) >= 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &atanhf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpAsinh:
foldFloatTypeUnary(operandArray[i], &asinhf, &resultArray[i]);
break;
case EOpAbs:
switch (getType().getBasicType())
{
case EbtFloat:
resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
case EOpAcosh:
// For acosh(x), results are undefined if x < 1, we are choosing to set result to 0.
if (operandArray[i].getFConst() < 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
diagnostics, &resultArray[i]);
else
foldFloatTypeUnary(operandArray[i], &acoshf, &resultArray[i]);
break;
case EbtInt:
resultArray[i].setIConst(abs(operandArray[i].getIConst()));
case EOpAtanh:
// For atanh(x), results are undefined if |x| >= 1, we are choosing to set result to
// 0.
if (fabsf(operandArray[i].getFConst()) >= 1.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
diagnostics, &resultArray[i]);
else
foldFloatTypeUnary(operandArray[i], &atanhf, &resultArray[i]);
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpSign:
switch (getType().getBasicType())
{
case EbtFloat:
case EOpAbs:
switch (getType().getBasicType())
{
float fConst = operandArray[i].getFConst();
float fResult = 0.0f;
if (fConst > 0.0f)
fResult = 1.0f;
else if (fConst < 0.0f)
fResult = -1.0f;
resultArray[i].setFConst(fResult);
case EbtFloat:
resultArray[i].setFConst(fabsf(operandArray[i].getFConst()));
break;
case EbtInt:
resultArray[i].setIConst(abs(operandArray[i].getIConst()));
break;
default:
UNREACHABLE();
return nullptr;
}
break;
case EbtInt:
case EOpSign:
switch (getType().getBasicType())
{
int iConst = operandArray[i].getIConst();
int iResult = 0;
if (iConst > 0)
iResult = 1;
else if (iConst < 0)
iResult = -1;
resultArray[i].setIConst(iResult);
case EbtFloat:
{
float fConst = operandArray[i].getFConst();
float fResult = 0.0f;
if (fConst > 0.0f)
fResult = 1.0f;
else if (fConst < 0.0f)
fResult = -1.0f;
resultArray[i].setFConst(fResult);
break;
}
case EbtInt:
{
int iConst = operandArray[i].getIConst();
int iResult = 0;
if (iConst > 0)
iResult = 1;
else if (iConst < 0)
iResult = -1;
resultArray[i].setIConst(iResult);
break;
}
default:
UNREACHABLE();
return nullptr;
}
break;
default:
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
}
break;
case EOpFloor:
if (!foldFloatTypeUnary(operandArray[i], &floorf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpFloor:
foldFloatTypeUnary(operandArray[i], &floorf, &resultArray[i]);
break;
case EOpTrunc:
if (!foldFloatTypeUnary(operandArray[i], &truncf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpTrunc:
foldFloatTypeUnary(operandArray[i], &truncf, &resultArray[i]);
break;
case EOpRound:
if (!foldFloatTypeUnary(operandArray[i], &roundf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpRound:
foldFloatTypeUnary(operandArray[i], &roundf, &resultArray[i]);
break;
case EOpRoundEven:
if (getType().getBasicType() == EbtFloat)
case EOpRoundEven:
{
ASSERT(getType().getBasicType() == EbtFloat);
float x = operandArray[i].getFConst();
float result;
float fractPart = modff(x, &result);
......@@ -1707,197 +1600,151 @@ TConstantUnion *TIntermConstantUnion::foldUnaryWithSameReturnType(TOperator op,
resultArray[i].setFConst(result);
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpCeil:
if (!foldFloatTypeUnary(operandArray[i], &ceilf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpCeil:
foldFloatTypeUnary(operandArray[i], &ceilf, &resultArray[i]);
break;
case EOpFract:
if (getType().getBasicType() == EbtFloat)
case EOpFract:
{
ASSERT(getType().getBasicType() == EbtFloat);
float x = operandArray[i].getFConst();
resultArray[i].setFConst(x - floorf(x));
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpIsNan:
if (getType().getBasicType() == EbtFloat)
{
case EOpIsNan:
ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setBConst(gl::isNaN(operandArray[0].getFConst()));
break;
}
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
case EOpIsInf:
if (getType().getBasicType() == EbtFloat)
{
case EOpIsInf:
ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setBConst(gl::isInf(operandArray[0].getFConst()));
break;
}
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
case EOpFloatBitsToInt:
if (getType().getBasicType() == EbtFloat)
{
case EOpFloatBitsToInt:
ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setIConst(gl::bitCast<int32_t>(operandArray[0].getFConst()));
break;
}
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
case EOpFloatBitsToUint:
if (getType().getBasicType() == EbtFloat)
{
case EOpFloatBitsToUint:
ASSERT(getType().getBasicType() == EbtFloat);
resultArray[i].setUConst(gl::bitCast<uint32_t>(operandArray[0].getFConst()));
break;
}
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
case EOpIntBitsToFloat:
if (getType().getBasicType() == EbtInt)
{
case EOpIntBitsToFloat:
ASSERT(getType().getBasicType() == EbtInt);
resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getIConst()));
break;
}
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
case EOpUintBitsToFloat:
if (getType().getBasicType() == EbtUInt)
{
case EOpUintBitsToFloat:
ASSERT(getType().getBasicType() == EbtUInt);
resultArray[i].setFConst(gl::bitCast<float>(operandArray[0].getUConst()));
break;
}
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
case EOpExp:
if (!foldFloatTypeUnary(operandArray[i], &expf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpExp:
foldFloatTypeUnary(operandArray[i], &expf, &resultArray[i]);
break;
case EOpLog:
// For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpLog:
// For log(x), results are undefined if x <= 0, we are choosing to set result to 0.
if (operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
diagnostics, &resultArray[i]);
else
foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
break;
case EOpExp2:
if (!foldFloatTypeUnary(operandArray[i], &exp2f, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpExp2:
foldFloatTypeUnary(operandArray[i], &exp2f, &resultArray[i]);
break;
case EOpLog2:
// For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
// And log2f is not available on some plarforms like old android, so just using log(x)/log(2) here.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &logf, infoSink, &resultArray[i]))
return nullptr;
else
resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
break;
case EOpLog2:
// For log2(x), results are undefined if x <= 0, we are choosing to set result to 0.
// And log2f is not available on some plarforms like old android, so just using
// log(x)/log(2) here.
if (operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
diagnostics, &resultArray[i]);
else
{
foldFloatTypeUnary(operandArray[i], &logf, &resultArray[i]);
resultArray[i].setFConst(resultArray[i].getFConst() / logf(2.0f));
}
break;
case EOpSqrt:
// For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() < 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
return nullptr;
break;
case EOpSqrt:
// For sqrt(x), results are undefined if x < 0, we are choosing to set result to 0.
if (operandArray[i].getFConst() < 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
diagnostics, &resultArray[i]);
else
foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
break;
case EOpInverseSqrt:
// There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
// so getting the square root first using builtin function sqrt() and then taking its inverse.
// Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set result to 0.
if (getType().getBasicType() == EbtFloat && operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink, &resultArray[i]);
else if (!foldFloatTypeUnary(operandArray[i], &sqrtf, infoSink, &resultArray[i]))
return nullptr;
else
resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
break;
case EOpInverseSqrt:
// There is no stdlib built-in function equavalent for GLES built-in inversesqrt(),
// so getting the square root first using builtin function sqrt() and then taking
// its inverse.
// Also, for inversesqrt(x), results are undefined if x <= 0, we are choosing to set
// result to 0.
if (operandArray[i].getFConst() <= 0.0f)
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
diagnostics, &resultArray[i]);
else
{
foldFloatTypeUnary(operandArray[i], &sqrtf, &resultArray[i]);
resultArray[i].setFConst(1.0f / resultArray[i].getFConst());
}
break;
case EOpVectorLogicalNot:
if (getType().getBasicType() == EbtBool)
{
case EOpVectorLogicalNot:
ASSERT(getType().getBasicType() == EbtBool);
resultArray[i].setBConst(!operandArray[i].getBConst());
break;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return nullptr;
case EOpNormalize:
if (getType().getBasicType() == EbtFloat)
case EOpNormalize:
{
float x = operandArray[i].getFConst();
ASSERT(getType().getBasicType() == EbtFloat);
float x = operandArray[i].getFConst();
float length = VectorLength(operandArray, objectSize);
if (length)
resultArray[i].setFConst(x / length);
else
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(), infoSink,
&resultArray[i]);
UndefinedConstantFoldingError(getLine(), op, getType().getBasicType(),
diagnostics, &resultArray[i]);
break;
}
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
case EOpDFdx:
case EOpDFdy:
case EOpFwidth:
if (getType().getBasicType() == EbtFloat)
{
case EOpDFdx:
case EOpDFdy:
case EOpFwidth:
ASSERT(getType().getBasicType() == EbtFloat);
// Derivatives of constant arguments should be 0.
resultArray[i].setFConst(0.0f);
break;
}
infoSink.info.message(EPrefixInternalError, getLine(), "Unary operation not folded into constant");
return nullptr;
default:
return nullptr;
default:
return nullptr;
}
}
return resultArray;
}
bool TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter, FloatTypeUnaryFunc builtinFunc,
TInfoSink &infoSink, TConstantUnion *result) const
void TIntermConstantUnion::foldFloatTypeUnary(const TConstantUnion &parameter,
FloatTypeUnaryFunc builtinFunc,
TConstantUnion *result) const
{
ASSERT(builtinFunc);
if (getType().getBasicType() == EbtFloat)
{
result->setFConst(builtinFunc(parameter.getFConst()));
return true;
}
infoSink.info.message(
EPrefixInternalError, getLine(),
"Unary operation not folded into constant");
return false;
ASSERT(getType().getBasicType() == EbtFloat);
result->setFConst(builtinFunc(parameter.getFConst()));
}
// static
TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate,
TInfoSink &infoSink)
TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate *aggregate)
{
ASSERT(aggregate->getSequence()->size() > 0u);
size_t resultSize = aggregate->getType().getObjectSize();
......@@ -1996,7 +1843,8 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateConstructor(TIntermAggregate
}
// static
TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink)
TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *aggregate,
TDiagnostics *diagnostics)
{
TOperator op = aggregate->getOp();
TIntermSequence *sequence = aggregate->getSequence();
......@@ -2037,284 +1885,298 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
//
switch (op)
{
case EOpAtan:
case EOpAtan:
{
if (basicType == EbtFloat)
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
float y = unionArrays[0][i].getFConst();
float x = unionArrays[1][i].getFConst();
// Results are undefined if x and y are both 0.
if (x == 0.0f && y == 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
else
resultArray[i].setFConst(atan2f(y, x));
}
float y = unionArrays[0][i].getFConst();
float x = unionArrays[1][i].getFConst();
// Results are undefined if x and y are both 0.
if (x == 0.0f && y == 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else
resultArray[i].setFConst(atan2f(y, x));
}
else
UNREACHABLE();
break;
}
break;
case EOpPow:
case EOpPow:
{
if (basicType == EbtFloat)
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
// Results are undefined if x < 0.
// Results are undefined if x = 0 and y <= 0.
if (x < 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
else if (x == 0.0f && y <= 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
else
resultArray[i].setFConst(powf(x, y));
}
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
// Results are undefined if x < 0.
// Results are undefined if x = 0 and y <= 0.
if (x < 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else if (x == 0.0f && y <= 0.0f)
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else
resultArray[i].setFConst(powf(x, y));
}
else
UNREACHABLE();
break;
}
break;
case EOpMod:
case EOpMod:
{
if (basicType == EbtFloat)
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
resultArray[i].setFConst(x - y * floorf(x / y));
}
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
resultArray[i].setFConst(x - y * floorf(x / y));
}
else
UNREACHABLE();
break;
}
break;
case EOpMin:
case EOpMin:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
switch (basicType)
{
case EbtFloat:
resultArray[i].setFConst(std::min(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
break;
case EbtInt:
resultArray[i].setIConst(std::min(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
break;
case EbtUInt:
resultArray[i].setUConst(std::min(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
break;
default:
UNREACHABLE();
break;
case EbtFloat:
resultArray[i].setFConst(std::min(unionArrays[0][i].getFConst(),
unionArrays[1][i].getFConst()));
break;
case EbtInt:
resultArray[i].setIConst(std::min(unionArrays[0][i].getIConst(),
unionArrays[1][i].getIConst()));
break;
case EbtUInt:
resultArray[i].setUConst(std::min(unionArrays[0][i].getUConst(),
unionArrays[1][i].getUConst()));
break;
default:
UNREACHABLE();
break;
}
}
break;
}
break;
case EOpMax:
case EOpMax:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
switch (basicType)
{
case EbtFloat:
resultArray[i].setFConst(std::max(unionArrays[0][i].getFConst(), unionArrays[1][i].getFConst()));
break;
case EbtInt:
resultArray[i].setIConst(std::max(unionArrays[0][i].getIConst(), unionArrays[1][i].getIConst()));
break;
case EbtUInt:
resultArray[i].setUConst(std::max(unionArrays[0][i].getUConst(), unionArrays[1][i].getUConst()));
break;
default:
UNREACHABLE();
break;
case EbtFloat:
resultArray[i].setFConst(std::max(unionArrays[0][i].getFConst(),
unionArrays[1][i].getFConst()));
break;
case EbtInt:
resultArray[i].setIConst(std::max(unionArrays[0][i].getIConst(),
unionArrays[1][i].getIConst()));
break;
case EbtUInt:
resultArray[i].setUConst(std::max(unionArrays[0][i].getUConst(),
unionArrays[1][i].getUConst()));
break;
default:
UNREACHABLE();
break;
}
}
break;
}
break;
case EOpStep:
case EOpStep:
{
if (basicType == EbtFloat)
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
resultArray[i].setFConst(unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f : 1.0f);
}
else
UNREACHABLE();
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
resultArray[i].setFConst(
unionArrays[1][i].getFConst() < unionArrays[0][i].getFConst() ? 0.0f
: 1.0f);
break;
}
break;
case EOpLessThan:
case EOpLessThan:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
switch (basicType)
{
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() < unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() < unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() < unionArrays[1][i].getUConst());
break;
default:
UNREACHABLE();
break;
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() <
unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() <
unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() <
unionArrays[1][i].getUConst());
break;
default:
UNREACHABLE();
break;
}
}
break;
}
break;
case EOpLessThanEqual:
case EOpLessThanEqual:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
switch (basicType)
{
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() <= unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() <= unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() <= unionArrays[1][i].getUConst());
break;
default:
UNREACHABLE();
break;
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() <=
unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() <=
unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() <=
unionArrays[1][i].getUConst());
break;
default:
UNREACHABLE();
break;
}
}
break;
}
break;
case EOpGreaterThan:
case EOpGreaterThan:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
switch (basicType)
{
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() > unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() > unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() > unionArrays[1][i].getUConst());
break;
default:
UNREACHABLE();
break;
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() >
unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() >
unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() >
unionArrays[1][i].getUConst());
break;
default:
UNREACHABLE();
break;
}
}
break;
}
break;
case EOpGreaterThanEqual:
case EOpGreaterThanEqual:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
switch (basicType)
{
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() >= unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() >= unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() >= unionArrays[1][i].getUConst());
break;
default:
UNREACHABLE();
break;
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() >=
unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() >=
unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() >=
unionArrays[1][i].getUConst());
break;
default:
UNREACHABLE();
break;
}
}
}
break;
case EOpVectorEqual:
case EOpVectorEqual:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
switch (basicType)
{
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() == unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() == unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() == unionArrays[1][i].getUConst());
break;
case EbtBool:
resultArray[i].setBConst(unionArrays[0][i].getBConst() == unionArrays[1][i].getBConst());
break;
default:
UNREACHABLE();
break;
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() ==
unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() ==
unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() ==
unionArrays[1][i].getUConst());
break;
case EbtBool:
resultArray[i].setBConst(unionArrays[0][i].getBConst() ==
unionArrays[1][i].getBConst());
break;
default:
UNREACHABLE();
break;
}
}
break;
}
break;
case EOpVectorNotEqual:
case EOpVectorNotEqual:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
switch (basicType)
{
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() != unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() != unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() != unionArrays[1][i].getUConst());
break;
case EbtBool:
resultArray[i].setBConst(unionArrays[0][i].getBConst() != unionArrays[1][i].getBConst());
break;
default:
UNREACHABLE();
break;
case EbtFloat:
resultArray[i].setBConst(unionArrays[0][i].getFConst() !=
unionArrays[1][i].getFConst());
break;
case EbtInt:
resultArray[i].setBConst(unionArrays[0][i].getIConst() !=
unionArrays[1][i].getIConst());
break;
case EbtUInt:
resultArray[i].setBConst(unionArrays[0][i].getUConst() !=
unionArrays[1][i].getUConst());
break;
case EbtBool:
resultArray[i].setBConst(unionArrays[0][i].getBConst() !=
unionArrays[1][i].getBConst());
break;
default:
UNREACHABLE();
break;
}
}
break;
}
break;
case EOpDistance:
if (basicType == EbtFloat)
case EOpDistance:
{
ASSERT(basicType == EbtFloat);
TConstantUnion *distanceArray = new TConstantUnion[maxObjectSize];
resultArray = new TConstantUnion();
resultArray = new TConstantUnion();
for (size_t i = 0; i < maxObjectSize; i++)
{
float x = unionArrays[0][i].getFConst();
......@@ -2322,47 +2184,40 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
distanceArray[i].setFConst(x - y);
}
resultArray->setFConst(VectorLength(distanceArray, maxObjectSize));
break;
}
else
UNREACHABLE();
break;
case EOpDot:
if (basicType == EbtFloat)
{
case EOpDot:
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion();
resultArray->setFConst(VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
}
else
UNREACHABLE();
break;
resultArray->setFConst(
VectorDotProduct(unionArrays[0], unionArrays[1], maxObjectSize));
break;
case EOpCross:
if (basicType == EbtFloat && maxObjectSize == 3)
case EOpCross:
{
ASSERT(basicType == EbtFloat && maxObjectSize == 3);
resultArray = new TConstantUnion[maxObjectSize];
float x0 = unionArrays[0][0].getFConst();
float x1 = unionArrays[0][1].getFConst();
float x2 = unionArrays[0][2].getFConst();
float y0 = unionArrays[1][0].getFConst();
float y1 = unionArrays[1][1].getFConst();
float y2 = unionArrays[1][2].getFConst();
float x0 = unionArrays[0][0].getFConst();
float x1 = unionArrays[0][1].getFConst();
float x2 = unionArrays[0][2].getFConst();
float y0 = unionArrays[1][0].getFConst();
float y1 = unionArrays[1][1].getFConst();
float y2 = unionArrays[1][2].getFConst();
resultArray[0].setFConst(x1 * y2 - y1 * x2);
resultArray[1].setFConst(x2 * y0 - y2 * x0);
resultArray[2].setFConst(x0 * y1 - y0 * x1);
break;
}
else
UNREACHABLE();
break;
case EOpReflect:
if (basicType == EbtFloat)
case EOpReflect:
{
ASSERT(basicType == EbtFloat);
// genType reflect (genType I, genType N) :
// For the incident vector I and surface orientation N, returns the reflection direction:
// For the incident vector I and surface orientation N, returns the reflection
// direction:
// I - 2 * dot(N, I) * N.
resultArray = new TConstantUnion[maxObjectSize];
resultArray = new TConstantUnion[maxObjectSize];
float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
for (size_t i = 0; i < maxObjectSize; i++)
{
......@@ -2370,45 +2225,40 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
2.0f * dotProduct * unionArrays[1][i].getFConst();
resultArray[i].setFConst(result);
}
break;
}
else
UNREACHABLE();
break;
case EOpMul:
if (basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
(*sequence)[1]->getAsTyped()->isMatrix())
case EOpMul:
{
ASSERT(basicType == EbtFloat && (*sequence)[0]->getAsTyped()->isMatrix() &&
(*sequence)[1]->getAsTyped()->isMatrix());
// Perform component-wise matrix multiplication.
resultArray = new TConstantUnion[maxObjectSize];
int size = (*sequence)[0]->getAsTyped()->getNominalSize();
int size = (*sequence)[0]->getAsTyped()->getNominalSize();
angle::Matrix<float> result =
GetMatrix(unionArrays[0], size).compMult(GetMatrix(unionArrays[1], size));
SetUnionArrayFromMatrix(result, resultArray);
break;
}
else
UNREACHABLE();
break;
case EOpOuterProduct:
if (basicType == EbtFloat)
case EOpOuterProduct:
{
ASSERT(basicType == EbtFloat);
size_t numRows = (*sequence)[0]->getAsTyped()->getType().getObjectSize();
size_t numCols = (*sequence)[1]->getAsTyped()->getType().getObjectSize();
resultArray = new TConstantUnion[numRows * numCols];
resultArray = new TConstantUnion[numRows * numCols];
angle::Matrix<float> result =
GetMatrix(unionArrays[0], static_cast<int>(numRows), 1)
.outerProduct(GetMatrix(unionArrays[1], 1, static_cast<int>(numCols)));
SetUnionArrayFromMatrix(result, resultArray);
break;
}
else
UNREACHABLE();
break;
default:
UNREACHABLE();
// TODO: Add constant folding support for other built-in operations that take 2 parameters and not handled above.
return nullptr;
default:
UNREACHABLE();
// TODO: Add constant folding support for other built-in operations that take 2
// parameters and not handled above.
return nullptr;
}
}
else if (paramsCount == 3)
......@@ -2418,124 +2268,123 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
//
switch (op)
{
case EOpClamp:
case EOpClamp:
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
switch (basicType)
{
case EbtFloat:
case EbtFloat:
{
float x = unionArrays[0][i].getFConst();
float x = unionArrays[0][i].getFConst();
float min = unionArrays[1][i].getFConst();
float max = unionArrays[2][i].getFConst();
// Results are undefined if min > max.
if (min > max)
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else
resultArray[i].setFConst(gl::clamp(x, min, max));
break;
}
break;
case EbtInt:
case EbtInt:
{
int x = unionArrays[0][i].getIConst();
int x = unionArrays[0][i].getIConst();
int min = unionArrays[1][i].getIConst();
int max = unionArrays[2][i].getIConst();
// Results are undefined if min > max.
if (min > max)
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else
resultArray[i].setIConst(gl::clamp(x, min, max));
break;
}
break;
case EbtUInt:
case EbtUInt:
{
unsigned int x = unionArrays[0][i].getUConst();
unsigned int x = unionArrays[0][i].getUConst();
unsigned int min = unionArrays[1][i].getUConst();
unsigned int max = unionArrays[2][i].getUConst();
// Results are undefined if min > max.
if (min > max)
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
else
resultArray[i].setUConst(gl::clamp(x, min, max));
break;
}
break;
default:
UNREACHABLE();
break;
default:
UNREACHABLE();
break;
}
}
break;
}
break;
case EOpMix:
case EOpMix:
{
if (basicType == EbtFloat)
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
if (type == EbtFloat)
{
float x = unionArrays[0][i].getFConst();
float y = unionArrays[1][i].getFConst();
TBasicType type = (*sequence)[2]->getAsTyped()->getType().getBasicType();
if (type == EbtFloat)
{
// Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
float a = unionArrays[2][i].getFConst();
resultArray[i].setFConst(x * (1.0f - a) + y * a);
}
else // 3rd parameter is EbtBool
{
ASSERT(type == EbtBool);
// Selects which vector each returned component comes from.
// For a component of a that is false, the corresponding component of x is returned.
// For a component of a that is true, the corresponding component of y is returned.
bool a = unionArrays[2][i].getBConst();
resultArray[i].setFConst(a ? y : x);
}
// Returns the linear blend of x and y, i.e., x * (1 - a) + y * a.
float a = unionArrays[2][i].getFConst();
resultArray[i].setFConst(x * (1.0f - a) + y * a);
}
else // 3rd parameter is EbtBool
{
ASSERT(type == EbtBool);
// Selects which vector each returned component comes from.
// For a component of a that is false, the corresponding component of x is
// returned.
// For a component of a that is true, the corresponding component of y is
// returned.
bool a = unionArrays[2][i].getBConst();
resultArray[i].setFConst(a ? y : x);
}
}
else
UNREACHABLE();
break;
}
break;
case EOpSmoothStep:
case EOpSmoothStep:
{
if (basicType == EbtFloat)
ASSERT(basicType == EbtFloat);
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
{
resultArray = new TConstantUnion[maxObjectSize];
for (size_t i = 0; i < maxObjectSize; i++)
float edge0 = unionArrays[0][i].getFConst();
float edge1 = unionArrays[1][i].getFConst();
float x = unionArrays[2][i].getFConst();
// Results are undefined if edge0 >= edge1.
if (edge0 >= edge1)
{
float edge0 = unionArrays[0][i].getFConst();
float edge1 = unionArrays[1][i].getFConst();
float x = unionArrays[2][i].getFConst();
// Results are undefined if edge0 >= edge1.
if (edge0 >= edge1)
{
UndefinedConstantFoldingError(loc, op, basicType, infoSink, &resultArray[i]);
}
else
{
// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
// Hermite interpolation between 0 and 1 when edge0 < x < edge1.
float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
}
UndefinedConstantFoldingError(loc, op, basicType, diagnostics,
&resultArray[i]);
}
else
{
// Returns 0.0 if x <= edge0 and 1.0 if x >= edge1 and performs smooth
// Hermite interpolation between 0 and 1 when edge0 < x < edge1.
float t = gl::clamp((x - edge0) / (edge1 - edge0), 0.0f, 1.0f);
resultArray[i].setFConst(t * t * (3.0f - 2.0f * t));
}
}
else
UNREACHABLE();
break;
}
break;
case EOpFaceForward:
if (basicType == EbtFloat)
case EOpFaceForward:
{
ASSERT(basicType == EbtFloat);
// genType faceforward(genType N, genType I, genType Nref) :
// If dot(Nref, I) < 0 return N, otherwise return -N.
resultArray = new TConstantUnion[maxObjectSize];
resultArray = new TConstantUnion[maxObjectSize];
float dotProduct = VectorDotProduct(unionArrays[2], unionArrays[1], maxObjectSize);
for (size_t i = 0; i < maxObjectSize; i++)
{
......@@ -2544,43 +2393,42 @@ TConstantUnion *TIntermConstantUnion::FoldAggregateBuiltIn(TIntermAggregate *agg
else
resultArray[i].setFConst(-unionArrays[0][i].getFConst());
}
break;
}
else
UNREACHABLE();
break;
case EOpRefract:
if (basicType == EbtFloat)
case EOpRefract:
{
ASSERT(basicType == EbtFloat);
// genType refract(genType I, genType N, float eta) :
// For the incident vector I and surface normal N, and the ratio of indices of refraction eta,
// For the incident vector I and surface normal N, and the ratio of indices of
// refraction eta,
// return the refraction vector. The result is computed by
// k = 1.0 - eta * eta * (1.0 - dot(N, I) * dot(N, I))
// if (k < 0.0)
// return genType(0.0)
// else
// return eta * I - (eta * dot(N, I) + sqrt(k)) * N
resultArray = new TConstantUnion[maxObjectSize];
resultArray = new TConstantUnion[maxObjectSize];
float dotProduct = VectorDotProduct(unionArrays[1], unionArrays[0], maxObjectSize);
for (size_t i = 0; i < maxObjectSize; i++)
{
float eta = unionArrays[2][i].getFConst();
float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
float k = 1.0f - eta * eta * (1.0f - dotProduct * dotProduct);
if (k < 0.0f)
resultArray[i].setFConst(0.0f);
else
resultArray[i].setFConst(eta * unionArrays[0][i].getFConst() -
(eta * dotProduct + sqrtf(k)) * unionArrays[1][i].getFConst());
(eta * dotProduct + sqrtf(k)) *
unionArrays[1][i].getFConst());
}
break;
}
else
UNREACHABLE();
break;
default:
UNREACHABLE();
// TODO: Add constant folding support for other built-in operations that take 3 parameters and not handled above.
return nullptr;
default:
UNREACHABLE();
// TODO: Add constant folding support for other built-in operations that take 3
// parameters and not handled above.
return nullptr;
}
}
return resultArray;
......
......@@ -319,6 +319,7 @@ class TIntermConstantUnion : public TIntermTyped
TIntermConstantUnion(const TConstantUnion *unionPointer, const TType &type)
: TIntermTyped(type), mUnionArrayPointer(unionPointer)
{
ASSERT(unionPointer);
}
TIntermTyped *deepCopy() const override { return new TIntermConstantUnion(*this); }
......@@ -346,6 +347,7 @@ class TIntermConstantUnion : public TIntermTyped
void replaceConstantUnion(const TConstantUnion *safeConstantUnion)
{
ASSERT(safeConstantUnion);
// Previous union pointer freed on pool deallocation.
mUnionArrayPointer = safeConstantUnion;
}
......@@ -357,12 +359,12 @@ class TIntermConstantUnion : public TIntermTyped
TConstantUnion *foldBinary(TOperator op,
TIntermConstantUnion *rightNode,
TDiagnostics *diagnostics);
TConstantUnion *foldUnaryWithDifferentReturnType(TOperator op, TInfoSink &infoSink);
TConstantUnion *foldUnaryWithSameReturnType(TOperator op, TInfoSink &infoSink);
TConstantUnion *foldUnaryNonComponentWise(TOperator op);
TConstantUnion *foldUnaryComponentWise(TOperator op, TDiagnostics *diagnostics);
static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate,
TInfoSink &infoSink);
static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate, TInfoSink &infoSink);
static TConstantUnion *FoldAggregateConstructor(TIntermAggregate *aggregate);
static TConstantUnion *FoldAggregateBuiltIn(TIntermAggregate *aggregate,
TDiagnostics *diagnostics);
protected:
// Same data may be shared between multiple constant unions, so it can't be modified.
......@@ -370,7 +372,9 @@ class TIntermConstantUnion : public TIntermTyped
private:
typedef float(*FloatTypeUnaryFunc) (float);
bool foldFloatTypeUnary(const TConstantUnion &parameter, FloatTypeUnaryFunc builtinFunc, TInfoSink &infoSink, TConstantUnion *result) const;
void foldFloatTypeUnary(const TConstantUnion &parameter,
FloatTypeUnaryFunc builtinFunc,
TConstantUnion *result) const;
TIntermConstantUnion(const TIntermConstantUnion &node); // Note: not deleted, just private!
};
......@@ -468,6 +472,11 @@ class TIntermUnary : public TIntermOperator
mOperand(NULL),
mUseEmulatedFunction(false) {}
TIntermUnary(TOperator op, TIntermTyped *operand)
: TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
{
}
TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
void traverse(TIntermTraverser *it) override;
......@@ -479,7 +488,7 @@ class TIntermUnary : public TIntermOperator
void setOperand(TIntermTyped *operand) { mOperand = operand; }
TIntermTyped *getOperand() { return mOperand; }
void promote(const TType *funcReturnType);
TIntermTyped *fold(TInfoSink &infoSink);
TIntermTyped *fold(TDiagnostics *diagnostics);
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
......@@ -532,7 +541,7 @@ class TIntermAggregate : public TIntermOperator
bool insertChildNodes(TIntermSequence::size_type position, TIntermSequence insertions);
// Conservatively assume function calls and other aggregate operators have side-effects
bool hasSideEffects() const override { return true; }
TIntermTyped *fold(TInfoSink &infoSink);
TIntermTyped *fold(TDiagnostics *diagnostics);
TIntermSequence *getSequence() { return &mSequence; }
const TIntermSequence *getSequence() const { return &mSequence; }
......
......@@ -58,29 +58,6 @@ TIntermTyped *TIntermediate::addIndex(
}
//
// 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. Sequences
......@@ -388,7 +365,7 @@ TIntermBranch* TIntermediate::addBranch(
// This is to be executed once the final root is put on top by the parsing
// process.
//
TIntermAggregate *TIntermediate::postProcess(TIntermNode *root)
TIntermAggregate *TIntermediate::PostProcess(TIntermNode *root)
{
if (root == nullptr)
return nullptr;
......@@ -411,7 +388,8 @@ TIntermAggregate *TIntermediate::postProcess(TIntermNode *root)
return aggRoot;
}
TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate)
TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate,
TDiagnostics *diagnostics)
{
switch (aggregate->getOp())
{
......@@ -438,12 +416,12 @@ TIntermTyped *TIntermediate::foldAggregateBuiltIn(TIntermAggregate *aggregate)
case EOpFaceForward:
case EOpReflect:
case EOpRefract:
return aggregate->fold(mInfoSink);
return aggregate->fold(diagnostics);
default:
// TODO: Add support for folding array constructors
if (aggregate->isConstructor() && !aggregate->isArray())
{
return aggregate->fold(mInfoSink);
return aggregate->fold(diagnostics);
}
// Constant folding not supported for the built-in.
return nullptr;
......
......@@ -16,15 +16,13 @@ struct TVectorFields
};
//
// Set of helper functions to help parse and build the tree.
// Set of helper functions to help build the tree.
//
class TInfoSink;
class TIntermediate
{
public:
POOL_ALLOCATOR_NEW_DELETE();
TIntermediate(TInfoSink &i)
: mInfoSink(i) { }
TIntermediate() {}
TIntermSymbol *addSymbol(
int id, const TString &, const TType &, const TSourceLoc &);
......@@ -56,16 +54,14 @@ class TIntermediate
TIntermBranch *addBranch(TOperator, const TSourceLoc &);
TIntermBranch *addBranch(TOperator, TIntermTyped *, const TSourceLoc &);
TIntermTyped *addSwizzle(TVectorFields &, const TSourceLoc &);
TIntermAggregate *postProcess(TIntermNode *root);
static TIntermAggregate *PostProcess(TIntermNode *root);
static void outputTree(TIntermNode *, TInfoSinkBase &);
TIntermTyped *foldAggregateBuiltIn(TIntermAggregate *aggregate);
TIntermTyped *foldAggregateBuiltIn(TIntermAggregate *aggregate, TDiagnostics *diagnostics);
private:
void operator=(TIntermediate &); // prevent assignments
TInfoSink & mInfoSink;
};
#endif // COMPILER_TRANSLATOR_INTERMEDIATE_H_
......@@ -2376,7 +2376,7 @@ TIntermTyped *TParseContext::addConstructor(TIntermNode *arguments,
constructor->setType(type);
TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor);
TIntermTyped *constConstructor = intermediate.foldAggregateBuiltIn(constructor, &mDiagnostics);
if (constConstructor)
{
return constConstructor;
......@@ -3425,7 +3425,15 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
break;
}
return intermediate.addUnaryMath(op, child, loc, funcReturnType);
TIntermUnary *node = new TIntermUnary(op, child);
node->setLine(loc);
node->promote(funcReturnType);
TIntermTyped *foldedNode = node->fold(&mDiagnostics);
if (foldedNode)
return foldedNode;
return node;
}
TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
......@@ -4054,7 +4062,8 @@ TIntermTyped *TParseContext::addFunctionCallOrMethod(TFunction *fnCall,
// See if we can constant fold a built-in. Note that this may be possible even
// if it is not const-qualified.
TIntermTyped *foldedNode = intermediate.foldAggregateBuiltIn(aggregate);
TIntermTyped *foldedNode =
intermediate.foldAggregateBuiltIn(aggregate, &mDiagnostics);
if (foldedNode)
{
callNode = foldedNode;
......
......@@ -31,14 +31,13 @@ class TParseContext : angle::NonCopyable
public:
TParseContext(TSymbolTable &symt,
TExtensionBehavior &ext,
TIntermediate &interm,
sh::GLenum type,
ShShaderSpec spec,
int options,
bool checksPrecErrors,
TInfoSink &is,
const ShBuiltInResources &resources)
: intermediate(interm),
: intermediate(),
symbolTable(symt),
mDeferredSingleDeclarationErrorCheck(false),
mShaderType(type),
......@@ -367,7 +366,7 @@ class TParseContext : angle::NonCopyable
TIntermTyped *cond, TIntermTyped *trueBlock, TIntermTyped *falseBlock, const TSourceLoc &line);
// TODO(jmadill): make these private
TIntermediate &intermediate; // to hold and build a parse tree
TIntermediate intermediate; // to build a parse tree
TSymbolTable &symbolTable; // symbol table that goes with the language currently being parsed
private:
......
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