// // Merge the linker objects from unitLinkerObjects into linkerObjects. // Duplication is expected and filtered out, but contradictions are an error. // void TIntermediate::mergeLinkerObjects(TInfoSink& infoSink, TIntermSequence& linkerObjects, const TIntermSequence& unitLinkerObjects) { // Error check and merge the linker objects (duplicates should not be created) std::size_t initialNumLinkerObjects = linkerObjects.size(); for (unsigned int unitLinkObj = 0; unitLinkObj < unitLinkerObjects.size(); ++unitLinkObj) { bool merge = true; for (std::size_t linkObj = 0; linkObj < initialNumLinkerObjects; ++linkObj) { TIntermSymbol* symbol = linkerObjects[linkObj]->getAsSymbolNode(); TIntermSymbol* unitSymbol = unitLinkerObjects[unitLinkObj]->getAsSymbolNode(); assert(symbol && unitSymbol); if (symbol->getName() == unitSymbol->getName()) { // filter out copy merge = false; // but if one has an initializer and the other does not, update // the initializer if (symbol->getConstArray().empty() && ! unitSymbol->getConstArray().empty()) symbol->setConstArray(unitSymbol->getConstArray()); // Similarly for binding if (! symbol->getQualifier().hasBinding() && unitSymbol->getQualifier().hasBinding()) symbol->getQualifier().layoutBinding = unitSymbol->getQualifier().layoutBinding; // Update implicit array sizes mergeImplicitArraySizes(symbol->getWritableType(), unitSymbol->getType()); // Check for consistent types/qualification/initializers etc. mergeErrorCheck(infoSink, *symbol, *unitSymbol, false); } } if (merge) linkerObjects.push_back(unitLinkerObjects[unitLinkObj]); } }
// Test for and give an error if the node can't be read from. void TParseContextBase::rValueErrorCheck(const TSourceLoc& loc, const char* op, TIntermTyped* node) { if (! node) return; TIntermBinary* binaryNode = node->getAsBinaryNode(); if (binaryNode) { switch(binaryNode->getOp()) { case EOpIndexDirect: case EOpIndexIndirect: case EOpIndexDirectStruct: case EOpVectorSwizzle: case EOpMatrixSwizzle: rValueErrorCheck(loc, op, binaryNode->getLeft()); default: break; } return; } TIntermSymbol* symNode = node->getAsSymbolNode(); if (symNode && symNode->getQualifier().writeonly) error(loc, "can't read from writeonly object: ", op, symNode->getName().c_str()); }
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; }
// // Compare two global objects from two compilation units and see if they match // well enough. Rules can be different for intra- vs. cross-stage matching. // // This function only does one of intra- or cross-stage matching per call. // void TIntermediate::mergeErrorCheck(TInfoSink& infoSink, const TIntermSymbol& symbol, const TIntermSymbol& unitSymbol, bool crossStage) { bool writeTypeComparison = false; // Types have to match if (symbol.getType() != unitSymbol.getType()) { error(infoSink, "Types must match:"); writeTypeComparison = true; } // Qualifiers have to (almost) match // Storage... if (symbol.getQualifier().storage != unitSymbol.getQualifier().storage) { error(infoSink, "Storage qualifiers must match:"); writeTypeComparison = true; } // Precision... if (symbol.getQualifier().precision != unitSymbol.getQualifier().precision) { error(infoSink, "Precision qualifiers must match:"); writeTypeComparison = true; } // Invariance... if (! crossStage && symbol.getQualifier().invariant != unitSymbol.getQualifier().invariant) { error(infoSink, "Presence of invariant qualifier must match:"); writeTypeComparison = true; } // Precise... if (! crossStage && symbol.getQualifier().noContraction != unitSymbol.getQualifier().noContraction) { error(infoSink, "Presence of precise qualifier must match:"); writeTypeComparison = true; } // Auxiliary and interpolation... if (symbol.getQualifier().centroid != unitSymbol.getQualifier().centroid || symbol.getQualifier().smooth != unitSymbol.getQualifier().smooth || symbol.getQualifier().flat != unitSymbol.getQualifier().flat || symbol.getQualifier().sample != unitSymbol.getQualifier().sample || symbol.getQualifier().patch != unitSymbol.getQualifier().patch || symbol.getQualifier().nopersp != unitSymbol.getQualifier().nopersp) { error(infoSink, "Interpolation and auxiliary storage qualifiers must match:"); writeTypeComparison = true; } // Memory... if (symbol.getQualifier().coherent != unitSymbol.getQualifier().coherent || symbol.getQualifier().volatil != unitSymbol.getQualifier().volatil || symbol.getQualifier().restrict != unitSymbol.getQualifier().restrict || symbol.getQualifier().readonly != unitSymbol.getQualifier().readonly || symbol.getQualifier().writeonly != unitSymbol.getQualifier().writeonly) { error(infoSink, "Memory qualifiers must match:"); writeTypeComparison = true; } // Layouts... // TODO: 4.4 enhanced layouts: Generalize to include offset/align: current spec // requires separate user-supplied offset from actual computed offset, but // current implementation only has one offset. if (symbol.getQualifier().layoutMatrix != unitSymbol.getQualifier().layoutMatrix || symbol.getQualifier().layoutPacking != unitSymbol.getQualifier().layoutPacking || symbol.getQualifier().layoutLocation != unitSymbol.getQualifier().layoutLocation || symbol.getQualifier().layoutComponent != unitSymbol.getQualifier().layoutComponent || symbol.getQualifier().layoutIndex != unitSymbol.getQualifier().layoutIndex || symbol.getQualifier().layoutBinding != unitSymbol.getQualifier().layoutBinding || (symbol.getQualifier().hasBinding() && (symbol.getQualifier().layoutOffset != unitSymbol.getQualifier().layoutOffset))) { error(infoSink, "Layout qualification must match:"); writeTypeComparison = true; } // Initializers have to match, if both are present, and if we don't already know the types don't match if (! writeTypeComparison) { if (! symbol.getConstArray().empty() && ! unitSymbol.getConstArray().empty()) { if (symbol.getConstArray() != unitSymbol.getConstArray()) { error(infoSink, "Initializers must match:"); infoSink.info << " " << symbol.getName() << "\n"; } } } if (writeTypeComparison) infoSink.info << " " << symbol.getName() << ": \"" << symbol.getType().getCompleteString() << "\" versus \"" << unitSymbol.getType().getCompleteString() << "\"\n"; }