Commit 31b5fc62 by Olli Etuaho

Add support for bitwise operations in ESSL3

Add support for <<, >>, &, |, ^, and their compound assignment variants <<=, >>=, &=, |=, ^=. Also add support for bitwise not (~). BUG=angle:870 Change-Id: I5e6a835409589556d5d58d58078fdf505cfd8da5 Reviewed-on: https://chromium-review.googlesource.com/241850Tested-by: 's avatarOlli Etuaho <oetuaho@nvidia.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 3940a453
...@@ -258,6 +258,11 @@ inline bool IsShadowSampler(TBasicType type) ...@@ -258,6 +258,11 @@ inline bool IsShadowSampler(TBasicType type)
return false; return false;
} }
inline bool IsInteger(TBasicType type)
{
return type == EbtInt || type == EbtUInt;
}
inline bool SupportsPrecision(TBasicType type) inline bool SupportsPrecision(TBasicType type)
{ {
return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type); return type == EbtFloat || type == EbtInt || type == EbtUInt || IsSampler(type);
......
...@@ -254,7 +254,10 @@ public: ...@@ -254,7 +254,10 @@ public:
ConstantUnion operator<<(const ConstantUnion& constant) const ConstantUnion operator<<(const ConstantUnion& constant) const
{ {
ConstantUnion returnValue; ConstantUnion returnValue;
assert(type == constant.type); // The signedness of the second parameter might be different, but we
// don't care, since the result is undefined if the second parameter is
// negative, and aliasing should not be a problem with unions.
assert(constant.type == EbtInt || constant.type == EbtUInt);
switch (type) { switch (type) {
case EbtInt: returnValue.setIConst(iConst << constant.iConst); break; case EbtInt: returnValue.setIConst(iConst << constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break; case EbtUInt: returnValue.setUConst(uConst << constant.uConst); break;
...@@ -267,7 +270,7 @@ public: ...@@ -267,7 +270,7 @@ public:
ConstantUnion operator&(const ConstantUnion& constant) const ConstantUnion operator&(const ConstantUnion& constant) const
{ {
ConstantUnion returnValue; ConstantUnion returnValue;
assert(type == constant.type); assert(constant.type == EbtInt || constant.type == EbtUInt);
switch (type) { switch (type) {
case EbtInt: returnValue.setIConst(iConst & constant.iConst); break; case EbtInt: returnValue.setIConst(iConst & constant.iConst); break;
case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break; case EbtUInt: returnValue.setUConst(uConst & constant.uConst); break;
......
...@@ -265,6 +265,11 @@ bool TIntermOperator::isAssignment() const ...@@ -265,6 +265,11 @@ bool TIntermOperator::isAssignment() const
case EOpMatrixTimesMatrixAssign: case EOpMatrixTimesMatrixAssign:
case EOpDivAssign: case EOpDivAssign:
case EOpModAssign: case EOpModAssign:
case EOpBitShiftLeftAssign:
case EOpBitShiftRightAssign:
case EOpBitwiseAndAssign:
case EOpBitwiseXorAssign:
case EOpBitwiseOrAssign:
return true; return true;
default: default:
return false; return false;
...@@ -318,6 +323,10 @@ bool TIntermUnary::promote(TInfoSink &) ...@@ -318,6 +323,10 @@ bool TIntermUnary::promote(TInfoSink &)
if (mOperand->getBasicType() != EbtBool) if (mOperand->getBasicType() != EbtBool)
return false; return false;
break; break;
// bit-wise not is already checked
case EOpBitwiseNot:
break;
case EOpNegative: case EOpNegative:
case EOpPositive: case EOpPositive:
case EOpPostIncrement: case EOpPostIncrement:
...@@ -367,8 +376,42 @@ bool TIntermBinary::promote(TInfoSink &infoSink) ...@@ -367,8 +376,42 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
} }
// GLSL ES 2.0 does not support implicit type casting. // GLSL ES 2.0 does not support implicit type casting.
// So the basic type should always match. // So the basic type should usually match.
if (mLeft->getBasicType() != mRight->getBasicType()) bool basicTypesMustMatch = true;
// Check ops which require integer / ivec parameters
switch (mOp)
{
case EOpBitShiftLeft:
case EOpBitShiftRight:
case EOpBitShiftLeftAssign:
case EOpBitShiftRightAssign:
// Unsigned can be bit-shifted by signed and vice versa, but we need to
// check that the basic type is an integer type.
basicTypesMustMatch = false;
if (!IsInteger(mLeft->getBasicType()) || !IsInteger(mRight->getBasicType()))
{
return false;
}
break;
case EOpBitwiseAnd:
case EOpBitwiseXor:
case EOpBitwiseOr:
case EOpBitwiseAndAssign:
case EOpBitwiseXorAssign:
case EOpBitwiseOrAssign:
// It is enough to check the type of only one operand, since later it
// is checked that the operand types match.
if (!IsInteger(mLeft->getBasicType()))
{
return false;
}
break;
default:
break;
}
if (basicTypesMustMatch && mLeft->getBasicType() != mRight->getBasicType())
{ {
return false; return false;
} }
...@@ -563,10 +606,20 @@ bool TIntermBinary::promote(TInfoSink &infoSink) ...@@ -563,10 +606,20 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
case EOpSub: case EOpSub:
case EOpDiv: case EOpDiv:
case EOpMod: case EOpMod:
case EOpBitShiftLeft:
case EOpBitShiftRight:
case EOpBitwiseAnd:
case EOpBitwiseXor:
case EOpBitwiseOr:
case EOpAddAssign: case EOpAddAssign:
case EOpSubAssign: case EOpSubAssign:
case EOpDivAssign: case EOpDivAssign:
case EOpModAssign: case EOpModAssign:
case EOpBitShiftLeftAssign:
case EOpBitShiftRightAssign:
case EOpBitwiseAndAssign:
case EOpBitwiseXorAssign:
case EOpBitwiseOrAssign:
if ((mLeft->isMatrix() && mRight->isVector()) || if ((mLeft->isMatrix() && mRight->isVector()) ||
(mLeft->isVector() && mRight->isMatrix())) (mLeft->isVector() && mRight->isMatrix()))
{ {
...@@ -582,13 +635,14 @@ bool TIntermBinary::promote(TInfoSink &infoSink) ...@@ -582,13 +635,14 @@ bool TIntermBinary::promote(TInfoSink &infoSink)
if (!mLeft->isScalar() && !mRight->isScalar()) if (!mLeft->isScalar() && !mRight->isScalar())
return false; return false;
// In the case of compound assignment, the right side needs to be a // In the case of compound assignment other than multiply-assign,
// scalar. Otherwise a vector/matrix would be assigned to a scalar. // 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() && if (!mRight->isScalar() &&
(mOp == EOpAddAssign || (isAssignment() ||
mOp == EOpSubAssign || mOp == EOpBitShiftLeft ||
mOp == EOpDivAssign || mOp == EOpBitShiftRight))
mOp == EOpModAssign))
return false; return false;
// Operator cannot be of type pure assignment. // Operator cannot be of type pure assignment.
...@@ -914,6 +968,32 @@ TIntermTyped *TIntermConstantUnion::fold( ...@@ -914,6 +968,32 @@ TIntermTyped *TIntermConstantUnion::fold(
} }
break; 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: case EOpLessThan:
ASSERT(objectSize == 1); ASSERT(objectSize == 1);
tempConstArray = new ConstantUnion[1]; tempConstArray = new ConstantUnion[1];
...@@ -1106,6 +1186,23 @@ TIntermTyped *TIntermConstantUnion::fold( ...@@ -1106,6 +1186,23 @@ TIntermTyped *TIntermConstantUnion::fold(
} }
break; 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: default:
return NULL; return NULL;
} }
......
...@@ -49,6 +49,7 @@ enum TOperator ...@@ -49,6 +49,7 @@ enum TOperator
EOpPositive, EOpPositive,
EOpLogicalNot, EOpLogicalNot,
EOpVectorLogicalNot, EOpVectorLogicalNot,
EOpBitwiseNot,
EOpPostIncrement, EOpPostIncrement,
EOpPostDecrement, EOpPostDecrement,
...@@ -82,6 +83,13 @@ enum TOperator ...@@ -82,6 +83,13 @@ enum TOperator
EOpLogicalXor, EOpLogicalXor,
EOpLogicalAnd, EOpLogicalAnd,
EOpBitShiftLeft,
EOpBitShiftRight,
EOpBitwiseAnd,
EOpBitwiseXor,
EOpBitwiseOr,
EOpIndexDirect, EOpIndexDirect,
EOpIndexIndirect, EOpIndexIndirect,
EOpIndexDirectStruct, EOpIndexDirectStruct,
...@@ -213,7 +221,12 @@ enum TOperator ...@@ -213,7 +221,12 @@ enum TOperator
EOpMatrixTimesScalarAssign, EOpMatrixTimesScalarAssign,
EOpMatrixTimesMatrixAssign, EOpMatrixTimesMatrixAssign,
EOpDivAssign, EOpDivAssign,
EOpModAssign EOpModAssign,
EOpBitShiftLeftAssign,
EOpBitShiftRightAssign,
EOpBitwiseAndAssign,
EOpBitwiseXorAssign,
EOpBitwiseOrAssign
}; };
class TIntermTraverser; class TIntermTraverser;
......
...@@ -87,11 +87,14 @@ TIntermTyped *TIntermediate::addBinaryMath( ...@@ -87,11 +87,14 @@ TIntermTyped *TIntermediate::addBinaryMath(
return NULL; return NULL;
} }
break; break;
// Note that for bitwise ops, type checking is done in promote() to
// share code between ops and compound assignment
default: default:
break; break;
} }
if (left->getBasicType() != right->getBasicType()) // This check is duplicated between here and node->promote() as an optimization.
if (left->getBasicType() != right->getBasicType() && op != EOpBitShiftLeft && op != EOpBitShiftRight)
{ {
return NULL; return NULL;
} }
...@@ -193,23 +196,30 @@ TIntermTyped *TIntermediate::addUnaryMath( ...@@ -193,23 +196,30 @@ TIntermTyped *TIntermediate::addUnaryMath(
switch (op) switch (op)
{ {
case EOpLogicalNot: case EOpLogicalNot:
if (child->getType().getBasicType() != EbtBool || if (child->getBasicType() != EbtBool ||
child->getType().isMatrix() || child->isMatrix() ||
child->getType().isArray() || child->isArray() ||
child->getType().isVector()) child->isVector())
{
return NULL;
}
break;
case EOpBitwiseNot:
if ((child->getBasicType() != EbtInt && child->getBasicType() != EbtUInt) ||
child->isMatrix() ||
child->isArray())
{ {
return NULL; return NULL;
} }
break; break;
case EOpPostIncrement: case EOpPostIncrement:
case EOpPreIncrement: case EOpPreIncrement:
case EOpPostDecrement: case EOpPostDecrement:
case EOpPreDecrement: case EOpPreDecrement:
case EOpNegative: case EOpNegative:
case EOpPositive: case EOpPositive:
if (child->getType().getBasicType() == EbtStruct || if (child->getBasicType() == EbtStruct ||
child->getType().isArray()) child->isArray())
{ {
return NULL; return NULL;
} }
......
...@@ -234,6 +234,21 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) ...@@ -234,6 +234,21 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
case EOpMatrixTimesMatrixAssign: case EOpMatrixTimesMatrixAssign:
writeTriplet(visit, "(", " *= ", ")"); writeTriplet(visit, "(", " *= ", ")");
break; break;
case EOpBitShiftLeftAssign:
writeTriplet(visit, "(", " <<= ", ")");
break;
case EOpBitShiftRightAssign:
writeTriplet(visit, "(", " >>= ", ")");
break;
case EOpBitwiseAndAssign:
writeTriplet(visit, "(", " &= ", ")");
break;
case EOpBitwiseXorAssign:
writeTriplet(visit, "(", " ^= ", ")");
break;
case EOpBitwiseOrAssign:
writeTriplet(visit, "(", " |= ", ")");
break;
case EOpIndexDirect: case EOpIndexDirect:
writeTriplet(visit, NULL, "[", "]"); writeTriplet(visit, NULL, "[", "]");
...@@ -346,6 +361,22 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) ...@@ -346,6 +361,22 @@ bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
case EOpMod: case EOpMod:
writeTriplet(visit, "(", " % ", ")"); writeTriplet(visit, "(", " % ", ")");
break; break;
case EOpBitShiftLeft:
writeTriplet(visit, "(", " << ", ")");
break;
case EOpBitShiftRight:
writeTriplet(visit, "(", " >> ", ")");
break;
case EOpBitwiseAnd:
writeTriplet(visit, "(", " & ", ")");
break;
case EOpBitwiseXor:
writeTriplet(visit, "(", " ^ ", ")");
break;
case EOpBitwiseOr:
writeTriplet(visit, "(", " | ", ")");
break;
case EOpEqual: case EOpEqual:
writeTriplet(visit, "(", " == ", ")"); writeTriplet(visit, "(", " == ", ")");
break; break;
...@@ -401,6 +432,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) ...@@ -401,6 +432,7 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node)
case EOpPositive: preString = "(+"; break; case EOpPositive: preString = "(+"; break;
case EOpVectorLogicalNot: preString = "not("; break; case EOpVectorLogicalNot: preString = "not("; break;
case EOpLogicalNot: preString = "(!"; break; case EOpLogicalNot: preString = "(!"; break;
case EOpBitwiseNot: preString = "(~"; break;
case EOpPostIncrement: preString = "("; postString = "++)"; break; case EOpPostIncrement: preString = "("; postString = "++)"; break;
case EOpPostDecrement: preString = "("; postString = "--)"; break; case EOpPostDecrement: preString = "("; postString = "--)"; break;
......
...@@ -1396,6 +1396,11 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) ...@@ -1396,6 +1396,11 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
break; break;
case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break; case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break;
case EOpModAssign: outputTriplet(visit, "(", " %= ", ")"); break; case EOpModAssign: outputTriplet(visit, "(", " %= ", ")"); break;
case EOpBitShiftLeftAssign: outputTriplet(visit, "(", " <<= ", ")"); break;
case EOpBitShiftRightAssign: outputTriplet(visit, "(", " >>= ", ")"); break;
case EOpBitwiseAndAssign: outputTriplet(visit, "(", " &= ", ")"); break;
case EOpBitwiseXorAssign: outputTriplet(visit, "(", " ^= ", ")"); break;
case EOpBitwiseOrAssign: outputTriplet(visit, "(", " |= ", ")"); break;
case EOpIndexDirect: case EOpIndexDirect:
{ {
const TType& leftType = node->getLeft()->getType(); const TType& leftType = node->getLeft()->getType();
...@@ -1484,6 +1489,11 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node) ...@@ -1484,6 +1489,11 @@ bool OutputHLSL::visitBinary(Visit visit, TIntermBinary *node)
case EOpMul: outputTriplet(visit, "(", " * ", ")"); break; case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break; case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break;
case EOpMod: outputTriplet(visit, "(", " % ", ")"); break; case EOpMod: outputTriplet(visit, "(", " % ", ")"); break;
case EOpBitShiftLeft: outputTriplet(visit, "(", " << ", ")"); break;
case EOpBitShiftRight: outputTriplet(visit, "(", " >> ", ")"); break;
case EOpBitwiseAnd: outputTriplet(visit, "(", " & ", ")"); break;
case EOpBitwiseXor: outputTriplet(visit, "(", " ^ ", ")"); break;
case EOpBitwiseOr: outputTriplet(visit, "(", " | ", ")"); break;
case EOpEqual: case EOpEqual:
case EOpNotEqual: case EOpNotEqual:
if (node->getLeft()->isScalar()) if (node->getLeft()->isScalar())
...@@ -1593,6 +1603,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node) ...@@ -1593,6 +1603,7 @@ bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
case EOpPositive: outputTriplet(visit, "(+", "", ")"); break; case EOpPositive: outputTriplet(visit, "(+", "", ")"); break;
case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break; case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break; case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
case EOpBitwiseNot: outputTriplet(visit, "(~", "", ")"); break;
case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break; case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break;
case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break; case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break;
case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break; case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break;
......
...@@ -515,10 +515,11 @@ unary_expression ...@@ -515,10 +515,11 @@ unary_expression
if ($$ == 0) { if ($$ == 0) {
const char* errorOp = ""; const char* errorOp = "";
switch($1.op) { switch($1.op) {
case EOpNegative: errorOp = "-"; break; case EOpNegative: errorOp = "-"; break;
case EOpPositive: errorOp = "+"; break; case EOpPositive: errorOp = "+"; break;
case EOpLogicalNot: errorOp = "!"; break; case EOpLogicalNot: errorOp = "!"; break;
default: break; case EOpBitwiseNot: errorOp = "~"; break;
default: break;
} }
context->unaryOpError(@1, errorOp, $2->getCompleteString()); context->unaryOpError(@1, errorOp, $2->getCompleteString());
context->recover(); context->recover();
...@@ -534,6 +535,10 @@ unary_operator ...@@ -534,6 +535,10 @@ unary_operator
: PLUS { $$.op = EOpPositive; } : PLUS { $$.op = EOpPositive; }
| DASH { $$.op = EOpNegative; } | DASH { $$.op = EOpNegative; }
| BANG { $$.op = EOpLogicalNot; } | BANG { $$.op = EOpLogicalNot; }
| TILDE {
ES3_ONLY("~", @$, "bit-wise operator");
$$.op = EOpBitwiseNot;
}
; ;
// Grammar Note: No '*' or '&' unary ops. Pointers are not supported. // Grammar Note: No '*' or '&' unary ops. Pointers are not supported.
...@@ -588,6 +593,24 @@ additive_expression ...@@ -588,6 +593,24 @@ additive_expression
shift_expression shift_expression
: additive_expression { $$ = $1; } : additive_expression { $$ = $1; }
| shift_expression LEFT_OP additive_expression {
ES3_ONLY("<<", @2, "bit-wise operator");
$$ = context->intermediate.addBinaryMath(EOpBitShiftLeft, $1, $3, @2);
if ($$ == 0) {
context->binaryOpError(@2, "<<", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $1;
}
}
| shift_expression RIGHT_OP additive_expression {
ES3_ONLY(">>", @2, "bit-wise operator");
$$ = context->intermediate.addBinaryMath(EOpBitShiftRight, $1, $3, @2);
if ($$ == 0) {
context->binaryOpError(@2, ">>", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $1;
}
}
; ;
relational_expression relational_expression
...@@ -660,14 +683,41 @@ equality_expression ...@@ -660,14 +683,41 @@ equality_expression
and_expression and_expression
: equality_expression { $$ = $1; } : equality_expression { $$ = $1; }
| and_expression AMPERSAND equality_expression {
ES3_ONLY("&", @2, "bit-wise operator");
$$ = context->intermediate.addBinaryMath(EOpBitwiseAnd, $1, $3, @2);
if ($$ == 0) {
context->binaryOpError(@2, "&", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $1;
}
}
; ;
exclusive_or_expression exclusive_or_expression
: and_expression { $$ = $1; } : and_expression { $$ = $1; }
| exclusive_or_expression CARET and_expression {
ES3_ONLY("^", @2, "bit-wise operator");
$$ = context->intermediate.addBinaryMath(EOpBitwiseXor, $1, $3, @2);
if ($$ == 0) {
context->binaryOpError(@2, "^", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $1;
}
}
; ;
inclusive_or_expression inclusive_or_expression
: exclusive_or_expression { $$ = $1; } : exclusive_or_expression { $$ = $1; }
| inclusive_or_expression VERTICAL_BAR exclusive_or_expression {
ES3_ONLY("|", @2, "bit-wise operator");
$$ = context->intermediate.addBinaryMath(EOpBitwiseOr, $1, $3, @2);
if ($$ == 0) {
context->binaryOpError(@2, "|", $1->getCompleteString(), $3->getCompleteString());
context->recover();
$$ = $1;
}
}
; ;
logical_and_expression logical_and_expression
...@@ -754,6 +804,26 @@ assignment_operator ...@@ -754,6 +804,26 @@ assignment_operator
} }
| ADD_ASSIGN { $$.op = EOpAddAssign; } | ADD_ASSIGN { $$.op = EOpAddAssign; }
| SUB_ASSIGN { $$.op = EOpSubAssign; } | SUB_ASSIGN { $$.op = EOpSubAssign; }
| LEFT_ASSIGN {
ES3_ONLY("<<=", @$, "bit-wise operator");
$$.op = EOpBitShiftLeftAssign;
}
| RIGHT_ASSIGN {
ES3_ONLY(">>=", @$, "bit-wise operator");
$$.op = EOpBitShiftRightAssign;
}
| AND_ASSIGN {
ES3_ONLY("&=", @$, "bit-wise operator");
$$.op = EOpBitwiseAndAssign;
}
| XOR_ASSIGN {
ES3_ONLY("^=", @$, "bit-wise operator");
$$.op = EOpBitwiseXorAssign;
}
| OR_ASSIGN {
ES3_ONLY("|=", @$, "bit-wise operator");
$$.op = EOpBitwiseOrAssign;
}
; ;
expression expression
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -134,6 +134,22 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) ...@@ -134,6 +134,22 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
case EOpModAssign: case EOpModAssign:
out << "modulo second child into first child"; out << "modulo second child into first child";
break; break;
case EOpBitShiftLeftAssign:
out << "bit-wise shift first child left by second child";
break;
case EOpBitShiftRightAssign:
out << "bit-wise shift first child right by second child";
break;
case EOpBitwiseAndAssign:
out << "bit-wise and second child into first child";
break;
case EOpBitwiseXorAssign:
out << "bit-wise xor second child into first child";
break;
case EOpBitwiseOrAssign:
out << "bit-wise or second child into first child";
break;
case EOpIndexDirect: case EOpIndexDirect:
out << "direct index"; out << "direct index";
break; break;
...@@ -165,6 +181,22 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node) ...@@ -165,6 +181,22 @@ bool TOutputTraverser::visitBinary(Visit visit, TIntermBinary *node)
case EOpMod: case EOpMod:
out << "modulo"; out << "modulo";
break; break;
case EOpBitShiftLeft:
out << "bit-wise shift left";
break;
case EOpBitShiftRight:
out << "bit-wise shift right";
break;
case EOpBitwiseAnd:
out << "bit-wise and";
break;
case EOpBitwiseXor:
out << "bit-wise xor";
break;
case EOpBitwiseOr:
out << "bit-wise or";
break;
case EOpEqual: case EOpEqual:
out << "Compare Equal"; out << "Compare Equal";
break; break;
...@@ -262,6 +294,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node) ...@@ -262,6 +294,7 @@ bool TOutputTraverser::visitUnary(Visit visit, TIntermUnary *node)
case EOpPositive: out << "Positive sign"; break; case EOpPositive: out << "Positive sign"; break;
case EOpVectorLogicalNot: case EOpVectorLogicalNot:
case EOpLogicalNot: out << "Negate conditional"; break; case EOpLogicalNot: out << "Negate conditional"; break;
case EOpBitwiseNot: out << "bit-wise not"; break;
case EOpPostIncrement: out << "Post-Increment"; break; case EOpPostIncrement: out << "Post-Increment"; break;
case EOpPostDecrement: out << "Post-Decrement"; break; case EOpPostDecrement: out << "Post-Decrement"; break;
......
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