diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/IntermNode.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/translator/IntermNode.cpp | 311 |
1 files changed, 181 insertions, 130 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp index aa0f31d170..266e3c8e3d 100644 --- a/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp +++ b/src/3rdparty/angle/src/compiler/translator/IntermNode.cpp @@ -157,26 +157,6 @@ bool TIntermLoop::replaceChildNode( return false; } -void TIntermLoop::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mInit) - { - nodeQueue->push(mInit); - } - if (mCond) - { - nodeQueue->push(mCond); - } - if (mExpr) - { - nodeQueue->push(mExpr); - } - if (mBody) - { - nodeQueue->push(mBody); - } -} - bool TIntermBranch::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -184,14 +164,6 @@ bool TIntermBranch::replaceChildNode( return false; } -void TIntermBranch::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mExpression) - { - nodeQueue->push(mExpression); - } -} - bool TIntermBinary::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -200,18 +172,6 @@ bool TIntermBinary::replaceChildNode( return false; } -void TIntermBinary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mLeft) - { - nodeQueue->push(mLeft); - } - if (mRight) - { - nodeQueue->push(mRight); - } -} - bool TIntermUnary::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -219,14 +179,6 @@ bool TIntermUnary::replaceChildNode( return false; } -void TIntermUnary::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - if (mOperand) - { - nodeQueue->push(mOperand); - } -} - bool TIntermAggregate::replaceChildNode( TIntermNode *original, TIntermNode *replacement) { @@ -237,14 +189,6 @@ bool TIntermAggregate::replaceChildNode( return false; } -void TIntermAggregate::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const -{ - for (size_t childIndex = 0; childIndex < mSequence.size(); childIndex++) - { - nodeQueue->push(mSequence[childIndex]); - } -} - void TIntermAggregate::setPrecisionFromChildren() { if (getBasicType() == EbtBool) @@ -300,20 +244,19 @@ bool TIntermSelection::replaceChildNode( return false; } -void TIntermSelection::enqueueChildren(std::queue<TIntermNode *> *nodeQueue) const +bool TIntermSwitch::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) { - if (mCondition) - { - nodeQueue->push(mCondition); - } - if (mTrueBlock) - { - nodeQueue->push(mTrueBlock); - } - if (mFalseBlock) - { - nodeQueue->push(mFalseBlock); - } + REPLACE_IF_IS(mInit, TIntermTyped, original, replacement); + REPLACE_IF_IS(mStatementList, TIntermAggregate, original, replacement); + return false; +} + +bool TIntermCase::replaceChildNode( + TIntermNode *original, TIntermNode *replacement) +{ + REPLACE_IF_IS(mCondition, TIntermTyped, original, replacement); + return false; } // @@ -336,6 +279,12 @@ bool TIntermOperator::isAssignment() const case EOpMatrixTimesScalarAssign: case EOpMatrixTimesMatrixAssign: case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: return true; default: return false; @@ -379,65 +328,55 @@ bool TIntermOperator::isConstructor() const // Make sure the type of a unary operator is appropriate for its // combination of operation and operand type. // -// Returns false in nothing makes sense. -// -bool TIntermUnary::promote(TInfoSink &) +void TIntermUnary::promote(const TType *funcReturnType) { switch (mOp) { - case EOpLogicalNot: - if (mOperand->getBasicType() != EbtBool) - return false; + case EOpFloatBitsToInt: + case EOpFloatBitsToUint: + case EOpIntBitsToFloat: + case EOpUintBitsToFloat: + case EOpPackSnorm2x16: + case EOpPackUnorm2x16: + case EOpPackHalf2x16: + case EOpUnpackSnorm2x16: + case EOpUnpackUnorm2x16: + mType.setPrecision(EbpHigh); break; - case EOpNegative: - case EOpPositive: - case EOpPostIncrement: - case EOpPostDecrement: - case EOpPreIncrement: - case EOpPreDecrement: - if (mOperand->getBasicType() == EbtBool) - return false; + case EOpUnpackHalf2x16: + mType.setPrecision(EbpMedium); break; - - // operators for built-ins are already type checked against their prototype - case EOpAny: - case EOpAll: - case EOpVectorLogicalNot: - return true; - default: - if (mOperand->getBasicType() != EbtFloat) - return false; + setType(mOperand->getType()); } - setType(mOperand->getType()); - mType.setQualifier(EvqTemporary); + if (funcReturnType != nullptr) + { + if (funcReturnType->getBasicType() == EbtBool) + { + // Bool types should not have precision. + setType(*funcReturnType); + } + else + { + // Precision of the node has been set based on the operand. + setTypePreservePrecision(*funcReturnType); + } + } - return true; + mType.setQualifier(EvqTemporary); } // // Establishes the type of the resultant operation, as well as // makes the operator the correct one for the operands. // -// Returns false if operator can't work on operands. +// For lots of operations it should already be established that the operand +// combination is valid, but returns false if operator can't work on operands. // bool TIntermBinary::promote(TInfoSink &infoSink) { - // This function only handles scalars, vectors, and matrices. - if (mLeft->isArray() || mRight->isArray()) - { - infoSink.info.message(EPrefixInternalError, getLine(), - "Invalid operation for arrays"); - return false; - } - - // GLSL ES 2.0 does not support implicit type casting. - // So the basic type should always match. - if (mLeft->getBasicType() != mRight->getBasicType()) - { - return false; - } + ASSERT(mLeft->isArray() == mRight->isArray()); // // Base assumption: just make the type the same as the left @@ -483,12 +422,9 @@ bool TIntermBinary::promote(TInfoSink &infoSink) // And and Or operate on conditionals // case EOpLogicalAnd: + case EOpLogicalXor: case EOpLogicalOr: - // Both operands must be of type bool. - if (mLeft->getBasicType() != EbtBool || mRight->getBasicType() != EbtBool) - { - return false; - } + ASSERT(mLeft->getBasicType() == EbtBool && mRight->getBasicType() == EbtBool); setType(TType(EbtBool, EbpUndefined)); break; @@ -625,12 +561,28 @@ bool TIntermBinary::promote(TInfoSink &infoSink) case EOpAssign: case EOpInitialize: + // No more additional checks are needed. + ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && + (mLeft->getSecondarySize() == mRight->getSecondarySize())); + break; case EOpAdd: case EOpSub: case EOpDiv: + case EOpIMod: + case EOpBitShiftLeft: + case EOpBitShiftRight: + case EOpBitwiseAnd: + case EOpBitwiseXor: + case EOpBitwiseOr: case EOpAddAssign: case EOpSubAssign: case EOpDivAssign: + case EOpIModAssign: + case EOpBitShiftLeftAssign: + case EOpBitShiftRightAssign: + case EOpBitwiseAndAssign: + case EOpBitwiseXorAssign: + case EOpBitwiseOrAssign: if ((mLeft->isMatrix() && mRight->isVector()) || (mLeft->isVector() && mRight->isMatrix())) { @@ -641,13 +593,19 @@ bool TIntermBinary::promote(TInfoSink &infoSink) if (mLeft->getNominalSize() != mRight->getNominalSize() || mLeft->getSecondarySize() != mRight->getSecondarySize()) { - // If the nominal size of operands do not match: - // One of them must be scalar. + // If the nominal sizes of operands do not match: + // One of them must be a scalar. if (!mLeft->isScalar() && !mRight->isScalar()) return false; - // Operator cannot be of type pure assignment. - if (mOp == EOpAssign || mOp == EOpInitialize) + // In the case of compound assignment other than multiply-assign, + // the right side needs to be a scalar. Otherwise a vector/matrix + // would be assigned to a scalar. A scalar can't be shifted by a + // vector either. + if (!mRight->isScalar() && + (isAssignment() || + mOp == EOpBitShiftLeft || + mOp == EOpBitShiftRight)) return false; } @@ -656,6 +614,11 @@ bool TIntermBinary::promote(TInfoSink &infoSink) mLeft->getSecondarySize(), mRight->getSecondarySize()); setType(TType(basicType, higherPrecision, EvqTemporary, nominalSize, secondarySize)); + if (mLeft->isArray()) + { + ASSERT(mLeft->getArraySize() == mRight->getArraySize()); + mType.setArraySize(mLeft->getArraySize()); + } } break; @@ -665,11 +628,8 @@ bool TIntermBinary::promote(TInfoSink &infoSink) case EOpGreaterThan: case EOpLessThanEqual: case EOpGreaterThanEqual: - if ((mLeft->getNominalSize() != mRight->getNominalSize()) || - (mLeft->getSecondarySize() != mRight->getSecondarySize())) - { - return false; - } + ASSERT((mLeft->getNominalSize() == mRight->getNominalSize()) && + (mLeft->getSecondarySize() == mRight->getSecondarySize())); setType(TType(EbtBool, EbpUndefined)); break; @@ -793,6 +753,7 @@ TIntermTyped *TIntermConstantUnion::fold( break; case EOpDiv: + case EOpIMod: { tempConstArray = new ConstantUnion[objectSize]; for (size_t i = 0; i < objectSize; i++) @@ -810,6 +771,7 @@ TIntermTyped *TIntermConstantUnion::fold( } else { + ASSERT(op == EOpDiv); tempConstArray[i].setFConst( unionArray[i].getFConst() / rightUnionArray[i].getFConst()); @@ -826,9 +788,19 @@ TIntermTyped *TIntermConstantUnion::fold( } else { - tempConstArray[i].setIConst( - unionArray[i].getIConst() / - rightUnionArray[i].getIConst()); + if (op == EOpDiv) + { + tempConstArray[i].setIConst( + unionArray[i].getIConst() / + rightUnionArray[i].getIConst()); + } + else + { + ASSERT(op == EOpIMod); + tempConstArray[i].setIConst( + unionArray[i].getIConst() % + rightUnionArray[i].getIConst()); + } } break; @@ -842,9 +814,19 @@ TIntermTyped *TIntermConstantUnion::fold( } else { - tempConstArray[i].setUConst( - unionArray[i].getUConst() / - rightUnionArray[i].getUConst()); + if (op == EOpDiv) + { + tempConstArray[i].setUConst( + unionArray[i].getUConst() / + rightUnionArray[i].getUConst()); + } + else + { + ASSERT(op == EOpIMod); + tempConstArray[i].setUConst( + unionArray[i].getUConst() % + rightUnionArray[i].getUConst()); + } } break; @@ -968,6 +950,32 @@ TIntermTyped *TIntermConstantUnion::fold( } break; + case EOpBitwiseAnd: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] & rightUnionArray[i]; + break; + case EOpBitwiseXor: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] ^ rightUnionArray[i]; + break; + case EOpBitwiseOr: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] | rightUnionArray[i]; + break; + case EOpBitShiftLeft: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] << rightUnionArray[i]; + break; + case EOpBitShiftRight: + tempConstArray = new ConstantUnion[objectSize]; + for (size_t i = 0; i < objectSize; i++) + tempConstArray[i] = unionArray[i] >> rightUnionArray[i]; + break; + case EOpLessThan: ASSERT(objectSize == 1); tempConstArray = new ConstantUnion[1]; @@ -1160,6 +1168,23 @@ TIntermTyped *TIntermConstantUnion::fold( } break; + case EOpBitwiseNot: + switch (getType().getBasicType()) + { + case EbtInt: + tempConstArray[i].setIConst(~unionArray[i].getIConst()); + break; + case EbtUInt: + tempConstArray[i].setUConst(~unionArray[i].getUConst()); + break; + default: + infoSink.info.message( + EPrefixInternalError, getLine(), + "Unary operation not folded into constant"); + return NULL; + } + break; + default: return NULL; } @@ -1181,3 +1206,29 @@ TString TIntermTraverser::hash(const TString &name, ShHashFunction64 hashFunctio TString hashedName = stream.str(); return hashedName; } + +void TIntermTraverser::updateTree() +{ + for (size_t ii = 0; ii < mReplacements.size(); ++ii) + { + const NodeUpdateEntry& entry = mReplacements[ii]; + ASSERT(entry.parent); + bool replaced = entry.parent->replaceChildNode( + entry.original, entry.replacement); + ASSERT(replaced); + + if (!entry.originalBecomesChildOfReplacement) + { + // In AST traversing, a parent is visited before its children. + // After we replace a node, if an immediate child is to + // be replaced, we need to make sure we don't update the replaced + // node; instead, we update the replacement node. + for (size_t jj = ii + 1; jj < mReplacements.size(); ++jj) + { + NodeUpdateEntry& entry2 = mReplacements[jj]; + if (entry2.parent == entry.original) + entry2.parent = entry.replacement; + } + } + } +} |