// // 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]); } }
// // 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"; }