void TLoopIndexInfo::fillInfo(TIntermLoop *node) { if (node == NULL) return; // Here we assume all the operations are valid, because the loop node is // already validated in ValidateLimitations. TIntermSequence *declSeq = node->getInit()->getAsAggregate()->getSequence(); TIntermBinary *declInit = (*declSeq)[0]->getAsBinaryNode(); TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); mId = symbol->getId(); mType = symbol->getBasicType(); if (mType == EbtInt) { TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion(); mInitValue = EvaluateIntConstant(initNode); mCurrentValue = mInitValue; mIncrementValue = GetLoopIntIncrement(node); TIntermBinary* binOp = node->getCondition()->getAsBinaryNode(); mStopValue = EvaluateIntConstant( binOp->getRight()->getAsConstantUnion()); mOp = binOp->getOp(); } }
int ValidateLimitations::validateForLoopInit(TIntermLoop *node) { TIntermNode *init = node->getInit(); if (init == NULL) { error(node->getLine(), "Missing init declaration", "for"); return -1; } // // init-declaration has the form: // type-specifier identifier = constant-expression // TIntermAggregate *decl = init->getAsAggregate(); if ((decl == NULL) || (decl->getOp() != EOpDeclaration)) { error(init->getLine(), "Invalid init declaration", "for"); return -1; } // To keep things simple do not allow declaration list. TIntermSequence &declSeq = decl->getSequence(); if (declSeq.size() != 1) { error(decl->getLine(), "Invalid init declaration", "for"); return -1; } TIntermBinary *declInit = declSeq[0]->getAsBinaryNode(); if ((declInit == NULL) || (declInit->getOp() != EOpInitialize)) { error(decl->getLine(), "Invalid init declaration", "for"); return -1; } TIntermSymbol *symbol = declInit->getLeft()->getAsSymbolNode(); if (symbol == NULL) { error(declInit->getLine(), "Invalid init declaration", "for"); return -1; } // The loop index has type int or float. TBasicType type = symbol->getBasicType(); if ((type != EbtInt) && (type != EbtFloat)) { error(symbol->getLine(), "Invalid type for loop index", getBasicString(type)); return -1; } // The loop index is initialized with constant expression. if (!isConstExpr(declInit->getRight())) { error(declInit->getLine(), "Loop index cannot be initialized with non-constant expression", symbol->getSymbol().c_str()); return -1; } return symbol->getId(); }
bool TGlslOutputTraverser::parseInitializer( TIntermBinary *node ) { TIntermTyped *left, *right; left = node->getLeft(); right = node->getRight(); if (!left->getAsSymbolNode()) return false; //Something is likely seriously wrong TIntermSymbol *symNode = left->getAsSymbolNode(); if (symNode->getBasicType() == EbtStruct) return false; GlslSymbol * sym = NULL; if ( !current->hasSymbol( symNode->getId() ) ) { int array = symNode->getTypePointer()->isArray() ? symNode->getTypePointer()->getArraySize() : 0; const char* semantic = ""; if (symNode->getInfo()) semantic = symNode->getInfo()->getSemantic().c_str(); sym = new GlslSymbol( symNode->getSymbol().c_str(), semantic, symNode->getId(), translateType(symNode->getTypePointer()), m_UsePrecision?node->getPrecision():EbpUndefined, translateQualifier(symNode->getQualifier()), array); current->addSymbol(sym); } else return false; //can't init already declared variable if (right->getAsTyped()) { std::stringstream ss; std::stringstream* oldOut = ¤t->getActiveOutput(); current->pushDepth(0); current->setActiveOutput(&ss); right->getAsTyped()->traverse(this); current->setActiveOutput(oldOut); current->popDepth(); sym->setInitializer(ss.str()); } return true; }
void ForLoopUnroll::FillLoopIndexInfo(TIntermLoop* node, TLoopIndexInfo& info) { ASSERT(node->getType() == ELoopFor); ASSERT(node->getUnrollFlag()); TIntermNode* init = node->getInit(); ASSERT(init != NULL); TIntermAggregate* decl = init->getAsAggregate(); ASSERT((decl != NULL) && (decl->getOp() == EOpDeclaration)); TIntermSequence& declSeq = decl->getSequence(); ASSERT(declSeq.size() == 1); TIntermBinary* declInit = declSeq[0]->getAsBinaryNode(); ASSERT((declInit != NULL) && (declInit->getOp() == EOpInitialize)); TIntermSymbol* symbol = declInit->getLeft()->getAsSymbolNode(); ASSERT(symbol != NULL); ASSERT(symbol->getBasicType() == EbtInt); info.id = symbol->getId(); ASSERT(declInit->getRight() != NULL); TIntermConstantUnion* initNode = declInit->getRight()->getAsConstantUnion(); ASSERT(initNode != NULL); info.initValue = evaluateIntConstant(initNode); info.currentValue = info.initValue; TIntermNode* cond = node->getCondition(); ASSERT(cond != NULL); TIntermBinary* binOp = cond->getAsBinaryNode(); ASSERT(binOp != NULL); ASSERT(binOp->getRight() != NULL); ASSERT(binOp->getRight()->getAsConstantUnion() != NULL); info.incrementValue = getLoopIncrement(node); info.stopValue = evaluateIntConstant( binOp->getRight()->getAsConstantUnion()); info.op = binOp->getOp(); }
bool ValidateLimitations::visitBinary(Visit, TIntermBinary* node) { // Check if loop index is modified in the loop body. validateOperation(node, node->getLeft()); // Check indexing. switch (node->getOp()) { case EOpIndexDirect: validateIndexing(node); break; case EOpIndexIndirect: #if defined(__APPLE__) // Loop unrolling is a work-around for a Mac Cg compiler bug where it // crashes when a sampler array's index is also the loop index. // Once Apple fixes this bug, we should remove the code in this CL. // See http://codereview.appspot.com/4331048/. if ((node->getLeft() != NULL) && (node->getRight() != NULL) && (node->getLeft()->getAsSymbolNode())) { TIntermSymbol* symbol = node->getLeft()->getAsSymbolNode(); if (IsSampler(symbol->getBasicType()) && symbol->isArray()) { ValidateLoopIndexExpr validate(mLoopStack); node->getRight()->traverse(&validate); if (validate.usesFloatLoopIndex()) { error(node->getLine(), "sampler array index is float loop index", "for"); } } } #endif validateIndexing(node); break; default: break; } return true; }
bool TSamplerTraverser::traverseAggregate( bool preVisit, TIntermAggregate *node, TIntermTraverser *it) { TSamplerTraverser* sit = static_cast<TSamplerTraverser*>(it); TInfoSink &infoSink = sit->infoSink; if (sit->abort) return false; if (! (sit->typing) ) { switch (node->getOp()) { case EOpFunction: // Store the current function name to use to setup the parameters sit->currentFunction = node->getName().c_str(); break; case EOpParameters: // Store the parameters to the function in the map sit->functionMap[sit->currentFunction.c_str()] = &(node->getSequence()); break; case EOpFunctionCall: { // This is a bit tricky. Find the function in the map. Loop over the parameters // and see if the parameters have been marked as a typed sampler. If so, propagate // the sampler type to the caller if ( sit->functionMap.find ( node->getName().c_str() ) != sit->functionMap.end() ) { // Get the sequence of function parameters TIntermSequence *funcSequence = sit->functionMap[node->getName().c_str()]; // Get the sequence of parameters being passed to function TIntermSequence &sequence = node->getSequence(); // Grab iterators to both sequences TIntermSequence::iterator it = sequence.begin(); TIntermSequence::iterator funcIt = funcSequence->begin(); assert ( sequence.size() == funcSequence->size() ); if ( sequence.size() == funcSequence->size() ) { while ( it != sequence.end() ) { TIntermSymbol *sym = (*it)->getAsSymbolNode(); TIntermSymbol *funcSym = (*funcIt)->getAsSymbolNode(); if ( sym != NULL && funcSym != NULL) { // If the parameter is generic, and the sampler to which // it is being passed has been marked, propogate its sampler // type to the caller. if ( sym->getBasicType() == EbtSamplerGeneric && funcSym->getBasicType() != EbtSamplerGeneric ) { sit->typeSampler ( sym, funcSym->getBasicType() ); } } it++; funcIt++; } } } } break; //HLSL texture functions case EOpTex1D: case EOpTex1DProj: case EOpTex1DLod: case EOpTex1DBias: case EOpTex1DGrad: { TIntermSequence &sequence = node->getSequence(); assert( sequence.size()); TIntermTyped *sampArg = sequence[0]->getAsTyped(); if ( sampArg) { if (sampArg->getBasicType() == EbtSamplerGeneric) { //type the sampler sit->typeSampler( sampArg, EbtSampler1D); } else if (sampArg->getBasicType() != EbtSampler1D) { //We have a sampler mismatch error infoSink.info << "Error: " << node->getLine() << ": Sampler type mismatch, likely using a generic sampler as two types\n"; } } else { assert(0); } } // We need to continue the traverse here, because the calls could be nested break; case EOpTex2D: case EOpTex2DProj: case EOpTex2DLod: case EOpTex2DBias: case EOpTex2DGrad: { TIntermSequence &sequence = node->getSequence(); assert( sequence.size()); TIntermTyped *sampArg = sequence[0]->getAsTyped(); if ( sampArg) { if (sampArg->getBasicType() == EbtSamplerGeneric) { //type the sampler sit->typeSampler( sampArg, EbtSampler2D); } else if (sampArg->getBasicType() != EbtSampler2D) { //We have a sampler mismatch error infoSink.info << "Error: " << node->getLine() << ": Sampler type mismatch, likely using a generic sampler as two types\n"; } } else { assert(0); } } // We need to continue the traverse here, because the calls could be nested break; case EOpTexRect: case EOpTexRectProj: { TIntermSequence &sequence = node->getSequence(); assert( sequence.size()); TIntermTyped *sampArg = sequence[0]->getAsTyped(); if ( sampArg) { if (sampArg->getBasicType() == EbtSamplerGeneric) { //type the sampler sit->typeSampler( sampArg, EbtSamplerRect); } else if (sampArg->getBasicType() != EbtSamplerRect) { //We have a sampler mismatch error infoSink.info << "Error: " << node->getLine() << ": Sampler type mismatch, likely using a generic sampler as two types\n"; } } else { assert(0); } } // We need to continue the traverse here, because the calls could be nested break; case EOpTex3D: case EOpTex3DProj: case EOpTex3DLod: case EOpTex3DBias: case EOpTex3DGrad: { TIntermSequence &sequence = node->getSequence(); assert( sequence.size()); TIntermTyped *sampArg = sequence[0]->getAsTyped(); if ( sampArg) { if (sampArg->getBasicType() == EbtSamplerGeneric) { //type the sampler sit->typeSampler( sampArg, EbtSampler3D); } else if (sampArg->getBasicType() != EbtSampler3D) { //We have a sampler mismatch error infoSink.info << "Error: " << node->getLine() << ": Sampler type mismatch, likely using a generic sampler as two types\n"; } } else { assert(0); } } // We need to continue the traverse here, because the calls could be nested break; case EOpTexCube: case EOpTexCubeProj: case EOpTexCubeLod: case EOpTexCubeBias: case EOpTexCubeGrad: { TIntermSequence &sequence = node->getSequence(); assert( sequence.size()); TIntermTyped *sampArg = sequence[0]->getAsTyped(); if ( sampArg) { if (sampArg->getBasicType() == EbtSamplerGeneric) { //type the sampler sit->typeSampler( sampArg, EbtSamplerCube); } else if (sampArg->getBasicType() != EbtSamplerCube) { //We have a sampler mismatch error infoSink.info << "Error: " << node->getLine() << ": Sampler type mismatch, likely using a generic sampler as two types\n"; } } else { assert(0); } } // We need to continue the traverse here, because the calls could be nested break; default: break; } } return !(sit->abort); }