int ForLoopUnroll::getLoopIncrement(TIntermLoop* node) { TIntermNode* expr = node->getExpression(); ASSERT(expr != NULL); // for expression has one of the following forms: // loop_index++ // loop_index-- // loop_index += constant_expression // loop_index -= constant_expression // ++loop_index // --loop_index // The last two forms are not specified in the spec, but I am assuming // its an oversight. TIntermUnary* unOp = expr->getAsUnaryNode(); TIntermBinary* binOp = unOp ? NULL : expr->getAsBinaryNode(); TOperator op = EOpNull; TIntermConstantUnion* incrementNode = NULL; if (unOp != NULL) { op = unOp->getOp(); } else if (binOp != NULL) { op = binOp->getOp(); ASSERT(binOp->getRight() != NULL); incrementNode = binOp->getRight()->getAsConstantUnion(); ASSERT(incrementNode != NULL); } int increment = 0; // The operator is one of: ++ -- += -=. switch (op) { case EOpPostIncrement: case EOpPreIncrement: ASSERT((unOp != NULL) && (binOp == NULL)); increment = 1; break; case EOpPostDecrement: case EOpPreDecrement: ASSERT((unOp != NULL) && (binOp == NULL)); increment = -1; break; case EOpAddAssign: ASSERT((unOp == NULL) && (binOp != NULL)); increment = evaluateIntConstant(incrementNode); break; case EOpSubAssign: ASSERT((unOp == NULL) && (binOp != NULL)); increment = - evaluateIntConstant(incrementNode); break; default: ASSERT(false); } return increment; }
// Check if the tree starting at node corresponds to exp2(y * log2(x)) // If the tree matches, set base to the node corresponding to x. bool IsPowWorkaround(TIntermNode *node, TIntermNode **base) { TIntermUnary *exp = node->getAsUnaryNode(); if (exp != nullptr && exp->getOp() == EOpExp2) { TIntermBinary *mul = exp->getOperand()->getAsBinaryNode(); if (mul != nullptr && mul->isMultiplication()) { TIntermUnary *log = mul->getRight()->getAsUnaryNode(); if (mul->getLeft()->getAsConstantUnion() && log != nullptr) { if (log->getOp() == EOpLog2) { if (base) *base = log->getOperand(); return true; } } } } return false; }
// Add one node as the parent of another that it operates on. TIntermTyped* ir_add_unary_math(TOperator op, TIntermNode* childNode, TSourceLoc line, TParseContext& ctx) { TIntermUnary* node; TIntermTyped* child = childNode->getAsTyped(); if (child == 0) { ctx.infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line); return 0; } switch (op) { case EOpLogicalNot: if (!child->isScalar()) return 0; break; case EOpPostIncrement: case EOpPreIncrement: case EOpPostDecrement: case EOpPreDecrement: case EOpNegative: if (child->getType().getBasicType() == EbtStruct || child->getType().isArray()) return 0; default: break; } // // Do we need to promote the operand? // // Note: Implicit promotions were removed from the language. // TBasicType newType = EbtVoid; switch (op) { case EOpConstructInt: newType = EbtInt; break; case EOpConstructBool: newType = EbtBool; break; case EOpConstructFloat: newType = EbtFloat; break; case EOpLogicalNot: newType = EbtBool; break; default: break; } if (newType != EbtVoid) { child = ir_add_conversion(op, TType(newType, child->getPrecision(), EvqTemporary, child->getColsCount(), child->getRowsCount(), child->isMatrix(), child->isArray()), child, ctx.infoSink); if (child == 0) return 0; } // // For constructors, we are now done, it's all in the conversion. // switch (op) { case EOpConstructInt: case EOpConstructBool: case EOpConstructFloat: return child; default: break; } TIntermConstant* childConst = child->getAsConstant(); // // Make a new node for the operator. // node = new TIntermUnary(op); if (line.line == 0) line = child->getLine(); node->setLine(line); node->setOperand(child); if (! node->promote(ctx)) return 0; // // See if we can fold constants if (childConst) { TIntermConstant* FoldUnaryConstantExpression(TOperator op, TIntermConstant* node); TIntermConstant* res = FoldUnaryConstantExpression(node->getOp(), childConst); if (res) { delete node; return res; } } return node; }
bool ValidateLimitations::validateForLoopExpr(TIntermLoop *node, int indexSymbolId) { TIntermNode *expr = node->getExpression(); if (expr == NULL) { error(node->getLine(), "Missing expression", "for"); return false; } // for expression has one of the following forms: // loop_index++ // loop_index-- // loop_index += constant_expression // loop_index -= constant_expression // ++loop_index // --loop_index // The last two forms are not specified in the spec, but I am assuming // its an oversight. TIntermUnary *unOp = expr->getAsUnaryNode(); TIntermBinary *binOp = unOp ? NULL : expr->getAsBinaryNode(); TOperator op = EOpNull; TIntermSymbol *symbol = NULL; if (unOp != NULL) { op = unOp->getOp(); symbol = unOp->getOperand()->getAsSymbolNode(); } else if (binOp != NULL) { op = binOp->getOp(); symbol = binOp->getLeft()->getAsSymbolNode(); } // The operand must be loop index. if (symbol == NULL) { error(expr->getLine(), "Invalid expression", "for"); return false; } if (symbol->getId() != indexSymbolId) { error(symbol->getLine(), "Expected loop index", symbol->getSymbol().c_str()); return false; } // The operator is one of: ++ -- += -=. switch (op) { case EOpPostIncrement: case EOpPostDecrement: case EOpPreIncrement: case EOpPreDecrement: ASSERT((unOp != NULL) && (binOp == NULL)); break; case EOpAddAssign: case EOpSubAssign: ASSERT((unOp == NULL) && (binOp != NULL)); break; default: error(expr->getLine(), "Invalid operator", GetOperatorString(op)); return false; } // Loop index must be incremented/decremented with a constant. if (binOp != NULL) { if (!isConstExpr(binOp->getRight())) { error(binOp->getLine(), "Loop index cannot be modified by non-constant expression", symbol->getSymbol().c_str()); return false; } } return true; }