bool ValidateLimitations::validateIndexing(TIntermBinary *node) { ASSERT((node->getOp() == EOpIndexDirect) || (node->getOp() == EOpIndexIndirect)); bool valid = true; TIntermTyped *index = node->getRight(); // The index expression must have integral type. if (!index->isScalarInt()) { error(index->getLine(), "Index expression must have integral type", index->getCompleteString().c_str()); valid = false; } // The index expession must be a constant-index-expression unless // the operand is a uniform in a vertex shader. TIntermTyped *operand = node->getLeft(); bool skip = (mShaderType == GL_VERTEX_SHADER) && (operand->getQualifier() == EvqUniform); if (!skip && !isConstIndexExpr(index)) { error(index->getLine(), "Index expression must be constant", "[]"); valid = false; } return valid; }
bool TIntermSelection::promoteTernary(TInfoSink& infoSink) { if (!condition->isVector()) return true; int size = condition->getRowsCount(); TIntermTyped* trueb = trueBlock->getAsTyped(); TIntermTyped* falseb = falseBlock->getAsTyped(); if (!trueb || !falseb) return false; if (trueb->getRowsCount() == size && falseb->getRowsCount() == size) return true; // Base assumption: just make the type a float vector TPrecision higherPrecision = GetHigherPrecision(trueb->getPrecision(), falseb->getPrecision()); setType(TType(EbtFloat, higherPrecision, EvqTemporary, 1, size, condition->isMatrix())); TOperator convert = EOpNull; { convert = TOperator( EOpConstructVec2 + size - 2); TIntermAggregate *node = new TIntermAggregate(convert); node->setLine(trueb->getLine()); node->setType(TType(condition->getBasicType(), higherPrecision, trueb->getQualifier() == EvqConst ? EvqConst : EvqTemporary, 1, size, condition->isMatrix())); node->getNodes().push_back(trueb); trueBlock = node; } { convert = TOperator( EOpConstructVec2 + size - 2); TIntermAggregate *node = new TIntermAggregate(convert); node->setLine(falseb->getLine()); node->setType(TType(condition->getBasicType(), higherPrecision, falseb->getQualifier() == EvqConst ? EvqConst : EvqTemporary, 1, size, condition->isMatrix())); node->getNodes().push_back(falseb); falseBlock = node; } return true; }
static TOperator getMatrixConstructOp(const TIntermTyped& intermediate, TParseContext& ctx) { // before GLSL 1.20, only square matrices if (ctx.targetVersion < ETargetGLSL_120) { const int c = intermediate.getColsCount(); const int r = intermediate.getRowsCount(); if (c == 2 && r == 2) return EOpConstructMat2x2FromMat; if (c == 3 && r == 3) return EOpConstructMat3x3FromMat; if (c == 4 && r == 4) return EOpConstructMat4x4; ctx.error(intermediate.getLine(), " non-square matrices not supported", "", "(%ix%i)", r, c); return EOpNull; } switch (intermediate.getColsCount()) { case 2: switch (intermediate.getRowsCount()) { case 2: return EOpConstructMat2x2; case 3: return EOpConstructMat2x3; case 4: return EOpConstructMat2x4; } break; case 3: switch (intermediate.getRowsCount()) { case 2: return EOpConstructMat3x2; case 3: return EOpConstructMat3x3; case 4: return EOpConstructMat3x4; } break; case 4: switch (intermediate.getRowsCount()) { case 2: return EOpConstructMat4x2; case 3: return EOpConstructMat4x3; case 4: return EOpConstructMat4x4; } break; } assert(false); return EOpNull; }
TIntermDeclaration* ir_grow_declaration(TIntermDeclaration* declaration, TIntermSymbol *symbol, TIntermTyped *initializer, TInfoSink& infoSink) { TIntermTyped* added_decl = symbol; if (initializer) added_decl = ir_add_assign(EOpAssign, symbol, initializer, symbol->getLine(), infoSink); if (declaration->isSingleDeclaration()) { TIntermTyped* current = declaration->getDeclaration(); TIntermAggregate* aggregate = ir_make_aggregate(current, current->getLine()); aggregate->setOperator(EOpComma); declaration->getDeclaration() = aggregate; } TIntermAggregate* aggregate = ir_grow_aggregate(declaration->getDeclaration(), added_decl, added_decl->getLine()); aggregate->setOperator(EOpComma); declaration->getDeclaration() = aggregate; return declaration; }
// 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; }
// // Add one node as the parent of another that it operates on. // // Returns the added node. // TIntermTyped* TIntermediate::addUnaryMath(TOperator op, TIntermNode* childNode, TSourceLoc line, TSymbolTable& symbolTable) { TIntermUnary* node; TIntermTyped* child = childNode->getAsTyped(); if (child == 0) { infoSink.info.message(EPrefixInternalError, "Bad type in AddUnaryMath", line); return 0; } switch (op) { case EOpLogicalNot: if (child->getType().getBasicType() != EbtBool || child->getType().isMatrix() || child->getType().isArray() || child->getType().isVector()) { 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; default: break; } if (newType != EbtVoid) { child = addConversion(op, TType(newType, child->getPrecision(), EvqTemporary, child->getNominalSize(), child->isMatrix(), child->isArray()), child); 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; } TIntermConstantUnion *childTempConstant = 0; if (child->getAsConstantUnion()) childTempConstant = child->getAsConstantUnion(); // // Make a new node for the operator. // node = new TIntermUnary(op); if (line == 0) line = child->getLine(); node->setLine(line); node->setOperand(child); if (! node->promote(infoSink)) return 0; if (childTempConstant) { TIntermTyped* newChild = childTempConstant->fold(op, 0, infoSink); if (newChild) return newChild; } return node; }