// // Connect two nodes through an assignment. // // Returns the added node. // TIntermTyped *TIntermediate::addAssign( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) { if (left->getType().getStruct() || right->getType().getStruct()) { if (left->getType() != right->getType()) { return NULL; } } TIntermBinary *node = new TIntermBinary(op); node->setLine(line); node->setLeft(left); node->setRight(right); if (!node->promote(mInfoSink)) return NULL; return node; }
// Connect two nodes through an assignment. TIntermTyped* ir_add_assign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TParseContext& ctx) { // // Like adding binary math, except the conversion can only go // from right to left. // TIntermBinary* node = new TIntermBinary(op); if (line.line == 0) line = left->getLine(); node->setLine(line); TIntermTyped* child = ir_add_conversion(op, left->getType(), right, ctx.infoSink); if (child == 0) return 0; node->setLeft(left); node->setRight(child); if (! node->promote(ctx)) return 0; return node; }
// // Connect two nodes through an assignment. // // Returns the added node. // TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line) { // // Like adding binary math, except the conversion can only go // from right to left. // TIntermBinary* node = new TIntermBinary(op); if (line == 0) line = left->getLine(); node->setLine(line); TIntermTyped* child = addConversion(op, left->getType(), right); if (child == 0) return 0; node->setLeft(left); node->setRight(child); if (! node->promote(infoSink)) return 0; return node; }
// // Connect two nodes with a new parent that does a binary operation on the nodes. // // Returns the added node. // TIntermTyped *TIntermediate::addBinaryMath( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) { // // Need a new node holding things together then. Make // one and promote it to the right type. // TIntermBinary *node = new TIntermBinary(op); node->setLine(line); node->setLeft(left); node->setRight(right); if (!node->promote(mInfoSink)) return NULL; // See if we can fold constants. TIntermTyped *foldedNode = node->fold(mInfoSink); if (foldedNode) return foldedNode; return node; }
// // Connect two nodes with a new parent that does a binary operation on the nodes. // // Returns the added node. // TIntermTyped *TIntermediate::addBinaryMath( TOperator op, TIntermTyped *left, TIntermTyped *right, const TSourceLoc &line) { switch (op) { case EOpEqual: case EOpNotEqual: if (left->isArray()) return NULL; break; case EOpLessThan: case EOpGreaterThan: case EOpLessThanEqual: case EOpGreaterThanEqual: if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { return NULL; } break; case EOpLogicalOr: case EOpLogicalXor: case EOpLogicalAnd: if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { return NULL; } break; case EOpAdd: case EOpSub: case EOpDiv: case EOpMul: if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) return NULL; default: break; } if (left->getBasicType() != right->getBasicType()) { return NULL; } // // Need a new node holding things together then. Make // one and promote it to the right type. // TIntermBinary *node = new TIntermBinary(op); node->setLine(line); node->setLeft(left); node->setRight(right); if (!node->promote(mInfoSink)) return NULL; // // See if we can fold constants. // TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); if (leftTempConstant && rightTempConstant) { TIntermTyped *typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, mInfoSink); if (typedReturnNode) return typedReturnNode; } return node; }
// Connect two nodes with a new parent that does a binary operation on the nodes. TIntermTyped* ir_add_binary_math(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TParseContext& ctx) { if (!left || !right) return 0; switch (op) { case EOpLessThan: case EOpGreaterThan: case EOpLessThanEqual: case EOpGreaterThanEqual: if (left->getType().isMatrix() || left->getType().isArray() || left->getType().getBasicType() == EbtStruct) { return 0; } break; case EOpLogicalOr: case EOpLogicalXor: case EOpLogicalAnd: if (left->getType().isMatrix() || left->getType().isArray()) return 0; if ( left->getBasicType() != EbtBool ) { if ( left->getType().getBasicType() != EbtInt && left->getType().getBasicType() != EbtFloat ) return 0; else { // If the left is a float or int, convert to a bool. This is the conversion that HLSL // does left = ir_add_conversion(EOpConstructBool, TType ( EbtBool, left->getPrecision(), left->getQualifier(), left->getColsCount(), left->getRowsCount(), left->isMatrix(), left->isArray()), left, ctx.infoSink); if ( left == 0 ) return 0; } } if (right->getType().isMatrix() || right->getType().isArray() || right->getType().isVector()) return 0; if ( right->getBasicType() != EbtBool ) { if ( right->getType().getBasicType() != EbtInt && right->getType().getBasicType() != EbtFloat ) return 0; else { // If the right is a float or int, convert to a bool. This is the conversion that HLSL // does right = ir_add_conversion(EOpConstructBool, TType ( EbtBool, right->getPrecision(), right->getQualifier(), right->getColsCount(), right->getRowsCount(), right->isMatrix(), right->isArray()), right, ctx.infoSink); if ( right == 0 ) return 0; } } break; case EOpAdd: case EOpSub: case EOpDiv: case EOpMul: case EOpMod: { TBasicType ltype = left->getType().getBasicType(); TBasicType rtype = right->getType().getBasicType(); if (ltype == EbtStruct) return 0; // If left or right type is a bool, convert to float. bool leftToFloat = (ltype == EbtBool); bool rightToFloat = (rtype == EbtBool); // For modulus, if either is an integer, convert to float as well. if (op == EOpMod) { leftToFloat |= (ltype == EbtInt); rightToFloat |= (rtype == EbtInt); } if (leftToFloat) { left = ir_add_conversion (EOpConstructFloat, TType (EbtFloat, left->getPrecision(), left->getQualifier(), left->getColsCount(), left->getRowsCount(), left->isMatrix(), left->isArray()), left, ctx.infoSink); if (left == 0) return 0; } if (rightToFloat) { right = ir_add_conversion (EOpConstructFloat, TType (EbtFloat, right->getPrecision(), right->getQualifier(), right->getColsCount(), right->getRowsCount(), right->isMatrix(), right->isArray()), right, ctx.infoSink); if (right == 0) return 0; } } break; default: break; } // // First try converting the children to compatible types. // if (!(left->getType().getStruct() && right->getType().getStruct())) { TIntermTyped* child = 0; bool useLeft = true; //default to using the left child as the type to promote to //need to always convert up if ( left->getType().getBasicType() != EbtFloat) { if ( right->getType().getBasicType() == EbtFloat) { useLeft = false; } else { if ( left->getType().getBasicType() != EbtInt) { if ( right->getType().getBasicType() == EbtInt) useLeft = false; } } } if (useLeft) { child = ir_add_conversion(op, left->getType(), right, ctx.infoSink); if (child) right = child; else { child = ir_add_conversion(op, right->getType(), left, ctx.infoSink); if (child) left = child; else return 0; } } else { child = ir_add_conversion(op, right->getType(), left, ctx.infoSink); if (child) left = child; else { child = ir_add_conversion(op, left->getType(), right, ctx.infoSink); if (child) right = child; else return 0; } } } else { if (left->getType() != right->getType()) return 0; } // // Need a new node holding things together then. Make // one and promote it to the right type. // TIntermBinary* node = new TIntermBinary(op); if (line.line == 0) line = right->getLine(); node->setLine(line); node->setLeft(left); node->setRight(right); if (! node->promote(ctx)) return 0; // // See if we can fold constants TIntermConstant* constA = left->getAsConstant(); TIntermConstant* constB = right->getAsConstant(); if (constA && constB) { TIntermConstant* FoldBinaryConstantExpression(TOperator op, TIntermConstant* nodeA, TIntermConstant* nodeB); TIntermConstant* res = FoldBinaryConstantExpression(node->getOp(), constA, constB); if (res) { delete node; return res; } } return node; }
// // Connect two nodes with a new parent that does a binary operation on the nodes. // // Returns the added node. // TIntermTyped* TIntermediate::addBinaryMath(TOperator op, TIntermTyped* left, TIntermTyped* right, TSourceLoc line, TSymbolTable& symbolTable) { switch (op) { case EOpEqual: case EOpNotEqual: if (left->isArray()) return 0; break; case EOpLessThan: case EOpGreaterThan: case EOpLessThanEqual: case EOpGreaterThanEqual: if (left->isMatrix() || left->isArray() || left->isVector() || left->getBasicType() == EbtStruct) { return 0; } break; case EOpLogicalOr: case EOpLogicalXor: case EOpLogicalAnd: if (left->getBasicType() != EbtBool || left->isMatrix() || left->isArray() || left->isVector()) { return 0; } break; case EOpAdd: case EOpSub: case EOpDiv: case EOpMul: if (left->getBasicType() == EbtStruct || left->getBasicType() == EbtBool) return 0; default: break; } // // First try converting the children to compatible types. // if (left->getType().getStruct() && right->getType().getStruct()) { if (left->getType() != right->getType()) return 0; } else { TIntermTyped* child = addConversion(op, left->getType(), right); if (child) right = child; else { child = addConversion(op, right->getType(), left); if (child) left = child; else return 0; } } // // Need a new node holding things together then. Make // one and promote it to the right type. // TIntermBinary* node = new TIntermBinary(op); if (line == 0) line = right->getLine(); node->setLine(line); node->setLeft(left); node->setRight(right); if (!node->promote(infoSink)) return 0; // // See if we can fold constants. // TIntermTyped* typedReturnNode = 0; TIntermConstantUnion *leftTempConstant = left->getAsConstantUnion(); TIntermConstantUnion *rightTempConstant = right->getAsConstantUnion(); if (leftTempConstant && rightTempConstant) { typedReturnNode = leftTempConstant->fold(node->getOp(), rightTempConstant, infoSink); if (typedReturnNode) return typedReturnNode; } return node; }