// // 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. // 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; }
TIntermBinary *MakeNewBinary(TOperator op, TIntermTyped *left, TIntermTyped *right, const TType &resultType) { TIntermBinary *binary = new TIntermBinary(op); binary->setLeft(left); binary->setRight(right); binary->setType(resultType); return binary; }
TIntermBinary *TIntermTraverser::createTempAssignment(TIntermTyped *rightNode) { ASSERT(rightNode != nullptr); TIntermSymbol *tempSymbol = createTempSymbol(rightNode->getType()); TIntermBinary *assignment = new TIntermBinary(EOpAssign); assignment->setLeft(tempSymbol); assignment->setRight(rightNode); assignment->setType(tempSymbol->getType()); return assignment; }
// // Connect two nodes through an index operator, where the left node is the base // of an array or struct, and the right node is a direct or indirect offset. // // Returns the added node. // The caller should set the type of the returned node. // TIntermTyped* TIntermediate::addIndex(TOperator op, TIntermTyped* base, TIntermTyped* index, const TSourceLoc& line) { TIntermBinary* node = new TIntermBinary(op); node->setLine(line); node->setLeft(base); node->setRight(index); // caller should set the type return node; }
TIntermAggregate *TIntermTraverser::createTempInitDeclaration(TIntermTyped *initializer, TQualifier qualifier) { ASSERT(initializer != nullptr); TIntermSymbol *tempSymbol = createTempSymbol(initializer->getType(), qualifier); TIntermAggregate *tempDeclaration = new TIntermAggregate(EOpDeclaration); TIntermBinary *tempInit = new TIntermBinary(EOpInitialize); tempInit->setLeft(tempSymbol); tempInit->setRight(initializer); tempInit->setType(tempSymbol->getType()); tempDeclaration->getSequence()->push_back(tempInit); return tempDeclaration; }
// Connect two nodes through an index operator, where the left node is the base // of an array or struct, and the right node is a direct or indirect offset. // // The caller should set the type of the returned node. TIntermTyped* ir_add_index(TOperator op, TIntermTyped* base, TIntermTyped* index, TSourceLoc line) { TIntermBinary* node = new TIntermBinary(op); if (line.line == 0) line = index->getLine(); node->setLine(line); node->setLeft(base); node->setRight(index); // caller should set the type return node; }
void InitializeVariables::insertInitCode(TIntermSequence *sequence) { for (size_t ii = 0; ii < mVariables.size(); ++ii) { const InitVariableInfo &varInfo = mVariables[ii]; if (varInfo.type.isArray()) { for (int index = varInfo.type.getArraySize() - 1; index >= 0; --index) { TIntermBinary *assign = new TIntermBinary(EOpAssign); sequence->insert(sequence->begin(), assign); TIntermBinary *indexDirect = new TIntermBinary(EOpIndexDirect); TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); indexDirect->setLeft(symbol); TIntermConstantUnion *indexNode = constructIndexNode(index); indexDirect->setRight(indexNode); assign->setLeft(indexDirect); TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type); assign->setRight(zeroConst); } } else { TIntermBinary *assign = new TIntermBinary(EOpAssign); sequence->insert(sequence->begin(), assign); TIntermSymbol *symbol = new TIntermSymbol(0, varInfo.name, varInfo.type); assign->setLeft(symbol); TIntermConstantUnion *zeroConst = constructFloatConstUnionNode(varInfo.type); assign->setRight(zeroConst); } } }
TString ScalarizeVecAndMatConstructorArgs::createTempVariable(TIntermTyped *original) { TString tempVarName = "_webgl_tmp_"; if (original->isScalar()) { tempVarName += "scalar_"; } else if (original->isVector()) { tempVarName += "vec_"; } else { ASSERT(original->isMatrix()); tempVarName += "mat_"; } tempVarName += Str(mTempVarCount).c_str(); mTempVarCount++; ASSERT(original); TType type = original->getType(); type.setQualifier(EvqTemporary); if (mShaderType == GL_FRAGMENT_SHADER && type.getBasicType() == EbtFloat && type.getPrecision() == EbpUndefined) { // We use the highest available precision for the temporary variable // to avoid computing the actual precision using the rules defined // in GLSL ES 1.0 Section 4.5.2. type.setPrecision(mFragmentPrecisionHigh ? EbpHigh : EbpMedium); } TIntermBinary *init = new TIntermBinary(EOpInitialize); TIntermSymbol *symbolNode = new TIntermSymbol(-1, tempVarName, type); init->setLeft(symbolNode); init->setRight(original); init->setType(type); TIntermAggregate *decl = new TIntermAggregate(EOpDeclaration); decl->getSequence()->push_back(init); ASSERT(mSequenceStack.size() > 0); TIntermSequence &sequence = mSequenceStack.back(); sequence.push_back(decl); return tempVarName; }
// // Connect two nodes through an assignment. // // Returns the added node. // TIntermTyped* TIntermediate::addAssign(TOperator op, TIntermTyped* left, TIntermTyped* right, const TSourceLoc& line) { // // Like adding binary math, except the conversion can only go // from right to left. // TIntermBinary* node = new TIntermBinary(op); 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 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 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; }