Commit 1dded803 by Olli Etuaho Committed by Commit Bot

Check multiplication validity in ParseContext

This improves separation of responsibilities in the code: ParseContext should handle operand type validation, while TIntermBinary::promote should ideally only determine the type of the node based on the operation and operands. BUG=angleproject:952 TEST=angle_unittests Change-Id: I9a8d8ede21cdf35de631623a62194c0da5c604d2 Reviewed-on: https://chromium-review.googlesource.com/372622 Commit-Queue: Olli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org>
parent 9949f04d
......@@ -417,6 +417,9 @@ class TIntermBinary : public TIntermOperator
TIntermTyped *deepCopy() const override { return new TIntermBinary(*this); }
static TOperator GetMulOpBasedOnOperands(const TType &left, const TType &right);
static TOperator GetMulAssignOpBasedOnOperands(const TType &left, const TType &right);
TIntermBinary *getAsBinaryNode() override { return this; };
void traverse(TIntermTraverser *it) override;
bool replaceChildNode(TIntermNode *original, TIntermNode *replacement) override;
......
......@@ -3574,6 +3574,49 @@ bool TParseContext::binaryOpCommonCheck(TOperator op,
return true;
}
bool TParseContext::isMultiplicationTypeCombinationValid(TOperator op,
const TType &left,
const TType &right)
{
switch (op)
{
case EOpMul:
case EOpMulAssign:
return left.getNominalSize() == right.getNominalSize() &&
left.getSecondarySize() == right.getSecondarySize();
case EOpVectorTimesScalar:
return true;
case EOpVectorTimesScalarAssign:
ASSERT(!left.isMatrix() && !right.isMatrix());
return left.isVector() && !right.isVector();
case EOpVectorTimesMatrix:
return left.getNominalSize() == right.getRows();
case EOpVectorTimesMatrixAssign:
ASSERT(!left.isMatrix() && right.isMatrix());
return left.isVector() && left.getNominalSize() == right.getRows() &&
left.getNominalSize() == right.getCols();
case EOpMatrixTimesVector:
return left.getCols() == right.getNominalSize();
case EOpMatrixTimesScalar:
return true;
case EOpMatrixTimesScalarAssign:
ASSERT(left.isMatrix() && !right.isMatrix());
return !right.isVector();
case EOpMatrixTimesMatrix:
return left.getCols() == right.getRows();
case EOpMatrixTimesMatrixAssign:
ASSERT(left.isMatrix() && right.isMatrix());
// We need to check two things:
// 1. The matrix multiplication step is valid.
// 2. The result will have the same number of columns as the lvalue.
return left.getCols() == right.getRows() && left.getCols() == right.getCols();
default:
UNREACHABLE();
return false;
}
}
TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
TIntermTyped *left,
TIntermTyped *right,
......@@ -3634,6 +3677,15 @@ TIntermTyped *TParseContext::addBinaryMathInternal(TOperator op,
break;
}
if (op == EOpMul)
{
op = TIntermBinary::GetMulOpBasedOnOperands(left->getType(), right->getType());
if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
{
return nullptr;
}
}
TIntermBinary *node = new TIntermBinary(op, left, right);
node->setLine(loc);
......@@ -3688,6 +3740,14 @@ TIntermTyped *TParseContext::createAssign(TOperator op,
{
if (binaryOpCommonCheck(op, left, right, loc))
{
if (op == EOpMulAssign)
{
op = TIntermBinary::GetMulAssignOpBasedOnOperands(left->getType(), right->getType());
if (!isMultiplicationTypeCombinationValid(op, left->getType(), right->getType()))
{
return nullptr;
}
}
TIntermBinary *node = new TIntermBinary(op, left, right);
node->setLine(loc);
......
......@@ -389,6 +389,9 @@ class TParseContext : angle::NonCopyable
bool checkIsValidTypeAndQualifierForArray(const TSourceLoc &indexLocation,
const TPublicType &elementType);
// Assumes that multiplication op has already been set based on the types.
bool isMultiplicationTypeCombinationValid(TOperator op, const TType &left, const TType &right);
TIntermTyped *addBinaryMathInternal(
TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &loc);
TIntermTyped *createAssign(
......
......@@ -60,7 +60,8 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
log->setLine(node->getLine());
log->setType(x->getType());
TIntermBinary *mul = new TIntermBinary(EOpMul, y, log);
TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType());
TIntermBinary *mul = new TIntermBinary(op, y, log);
mul->setLine(node->getLine());
bool valid = mul->promote();
UNUSED_ASSERTION_VARIABLE(valid);
......
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