From de97fe0ad433d71f699834fcf45a329d6f41679a Mon Sep 17 00:00:00 2001 From: John Kessenich Date: Sat, 1 Oct 2016 18:44:38 -0600 Subject: [PATCH] Non-functional: Rationalizing parse helper hierarchy, step 3 (effected editable symbols and IO resize). --- glslang/Include/revision.h | 2 +- .../MachineIndependent/ParseContextBase.cpp | 32 +++ glslang/MachineIndependent/ParseHelper.cpp | 32 +-- glslang/MachineIndependent/ParseHelper.h | 25 +-- hlsl/hlslParseHelper.cpp | 185 ------------------ hlsl/hlslParseHelper.h | 12 -- 6 files changed, 51 insertions(+), 237 deletions(-) diff --git a/glslang/Include/revision.h b/glslang/Include/revision.h index 72d7d687..21914247 100644 --- a/glslang/Include/revision.h +++ b/glslang/Include/revision.h @@ -2,5 +2,5 @@ // For the version, it uses the latest git tag followed by the number of commits. // For the date, it uses the current date (when then script is run). -#define GLSLANG_REVISION "Overload400-PrecQual.1547" +#define GLSLANG_REVISION "Overload400-PrecQual.1548" #define GLSLANG_DATE "01-Oct-2016" diff --git a/glslang/MachineIndependent/ParseContextBase.cpp b/glslang/MachineIndependent/ParseContextBase.cpp index 2d78714d..b92effce 100644 --- a/glslang/MachineIndependent/ParseContextBase.cpp +++ b/glslang/MachineIndependent/ParseContextBase.cpp @@ -113,6 +113,38 @@ void C_DECL TParseContextBase::ppWarn(const TSourceLoc& loc, const char* szReaso va_end(args); } +// Make a shared symbol have a non-shared version that can be edited by the current +// compile, such that editing its type will not change the shared version and will +// effect all nodes sharing it. +void TParseContextBase::makeEditable(TSymbol*& symbol) +{ + // copyUp() does a deep copy of the type. + symbol = symbolTable.copyUp(symbol); + + // Save it in the AST for linker use. + intermediate.addSymbolLinkageNode(linkage, *symbol); +} + +// Return a writable version of the variable 'name'. +// +// Return nullptr if 'name' is not found. This should mean +// something is seriously wrong (e.g., compiler asking self for +// built-in that doesn't exist). +TVariable* TParseContextBase::getEditableVariable(const char* name) +{ + bool builtIn; + TSymbol* symbol = symbolTable.find(name, &builtIn); + + assert(symbol != nullptr); + if (symbol == nullptr) + return nullptr; + + if (builtIn) + makeEditable(symbol); + + return symbol->getAsVariable(); +} + // Select the best matching function for 'call' from 'candidateList'. // // Assumptions diff --git a/glslang/MachineIndependent/ParseHelper.cpp b/glslang/MachineIndependent/ParseHelper.cpp index dd58ef14..13f277d7 100644 --- a/glslang/MachineIndependent/ParseHelper.cpp +++ b/glslang/MachineIndependent/ParseHelper.cpp @@ -381,7 +381,9 @@ TIntermTyped* TParseContext::handleVariable(const TSourceLoc& loc, TSymbol* symb // If this is a variable or a block, check it and all it contains, but if this // is a member of an anonymous block, check the whole block, as the whole block // will need to be copied up if it contains an implicitly-sized array. - if (symbol->getType().containsImplicitlySizedArray() || (symbol->getAsAnonMember() && symbol->getAsAnonMember()->getAnonContainer().getType().containsImplicitlySizedArray())) + if (symbol->getType().containsImplicitlySizedArray() || + (symbol->getAsAnonMember() && + symbol->getAsAnonMember()->getAnonContainer().getType().containsImplicitlySizedArray())) makeEditable(symbol); } @@ -564,35 +566,11 @@ void TParseContext::handleIndexLimits(const TSourceLoc& /*loc*/, TIntermTyped* b // effect all nodes sharing it. void TParseContext::makeEditable(TSymbol*& symbol) { - // copyUp() does a deep copy of the type. - symbol = symbolTable.copyUp(symbol); + TParseContextBase::makeEditable(symbol); - // Also, see if it's tied to IO resizing + // See if it's tied to IO resizing if (isIoResizeArray(symbol->getType())) ioArraySymbolResizeList.push_back(symbol); - - // Also, save it in the AST for linker use. - intermediate.addSymbolLinkageNode(linkage, *symbol); -} - -// Return a writable version of the variable 'name'. -// -// Return nullptr if 'name' is not found. This should mean -// something is seriously wrong (e.g., compiler asking self for -// built-in that doesn't exist). -TVariable* TParseContext::getEditableVariable(const char* name) -{ - bool builtIn; - TSymbol* symbol = symbolTable.find(name, &builtIn); - - assert(symbol != nullptr); - if (symbol == nullptr) - return nullptr; - - if (builtIn) - makeEditable(symbol); - - return symbol->getAsVariable(); } // Return true if this is a geometry shader input array or tessellation control output array. diff --git a/glslang/MachineIndependent/ParseHelper.h b/glslang/MachineIndependent/ParseHelper.h index fba09eeb..eab78359 100644 --- a/glslang/MachineIndependent/ParseHelper.h +++ b/glslang/MachineIndependent/ParseHelper.h @@ -82,14 +82,14 @@ public: globalUniformBlock(nullptr) { } virtual ~TParseContextBase() { } - void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...); - void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...); - void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...); - void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, ...); + virtual void C_DECL error(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL warn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppError(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); + virtual void C_DECL ppWarn(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, ...); virtual void setLimits(const TBuiltInResource&) = 0; @@ -171,9 +171,11 @@ protected: // override this to set the language-specific name virtual const char* getGlobalUniformBlockName() { return ""; } virtual void finalizeGlobalUniformBlockLayout(TVariable&) { } - void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, TPrefixType prefix, - va_list args); + virtual void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, + const char* szExtraInfoFormat, TPrefixType prefix, + va_list args); + virtual void makeEditable(TSymbol*&); + virtual TVariable* getEditableVariable(const char* name); }; // @@ -241,7 +243,6 @@ public: void handleIndexLimits(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); void makeEditable(TSymbol*&); - TVariable* getEditableVariable(const char* name); bool isIoResizeArray(const TType&) const; void fixIoArraySize(const TSourceLoc&, TType&); void ioArrayCheck(const TSourceLoc&, const TType&, const TString& identifier); diff --git a/hlsl/hlslParseHelper.cpp b/hlsl/hlslParseHelper.cpp index be1e23c1..b462e92f 100755 --- a/hlsl/hlslParseHelper.cpp +++ b/hlsl/hlslParseHelper.cpp @@ -249,19 +249,6 @@ TIntermTyped* HlslParseContext::handleVariable(const TSourceLoc& loc, TSymbol* s if (symbol && symbol->getNumExtensions()) requireExtensions(loc, symbol->getNumExtensions(), symbol->getExtensions(), symbol->getName().c_str()); - if (symbol && symbol->isReadOnly()) { - // All shared things containing an implicitly sized array must be copied up - // on first use, so that all future references will share its array structure, - // so that editing the implicit size will effect all nodes consuming it, - // and so that editing the implicit size won't change the shared one. - // - // If this is a variable or a block, check it and all it contains, but if this - // is a member of an anonymous block, check the whole block, as the whole block - // will need to be copied up if it contains an implicitly-sized array. - if (symbol->getType().containsImplicitlySizedArray() || (symbol->getAsAnonMember() && symbol->getAsAnonMember()->getAnonContainer().getType().containsImplicitlySizedArray())) - makeEditable(symbol); - } - const TVariable* variable; const TAnonMember* anon = symbol ? symbol->getAsAnonMember() : nullptr; TIntermTyped* node = nullptr; @@ -335,9 +322,6 @@ TIntermTyped* HlslParseContext::handleBracketDereference(const TSourceLoc& loc, else { // at least one of base and index is variable... - if (base->getAsSymbolNode() && isIoResizeArray(base->getType())) - handleIoResizeArrayAccess(loc, base); - if (base->getAsSymbolNode() && shouldFlatten(base->getType())) { if (index->getQualifier().storage != EvqConst) error(loc, "Invalid variable index to flattened uniform array", base->getAsSymbolNode()->getName().c_str(), ""); @@ -381,125 +365,6 @@ void HlslParseContext::checkIndex(const TSourceLoc& /*loc*/, const TType& /*type // HLSL todo: any rules for index fixups? } -// Make a shared symbol have a non-shared version that can be edited by the current -// compile, such that editing its type will not change the shared version and will -// effect all nodes sharing it. -void HlslParseContext::makeEditable(TSymbol*& symbol) -{ - // copyUp() does a deep copy of the type. - symbol = symbolTable.copyUp(symbol); - - // Also, see if it's tied to IO resizing - if (isIoResizeArray(symbol->getType())) - ioArraySymbolResizeList.push_back(symbol); - - // Also, save it in the AST for linker use. - intermediate.addSymbolLinkageNode(linkage, *symbol); -} - -TVariable* HlslParseContext::getEditableVariable(const char* name) -{ - bool builtIn; - TSymbol* symbol = symbolTable.find(name, &builtIn); - if (builtIn) - makeEditable(symbol); - - return symbol->getAsVariable(); -} - -// Return true if this is a geometry shader input array or tessellation control output array. -bool HlslParseContext::isIoResizeArray(const TType& type) const -{ - return type.isArray() && - ((language == EShLangGeometry && type.getQualifier().storage == EvqVaryingIn) || - (language == EShLangTessControl && type.getQualifier().storage == EvqVaryingOut && ! type.getQualifier().patch)); -} - -// If an array is not isIoResizeArray() but is an io array, make sure it has the right size -void HlslParseContext::fixIoArraySize(const TSourceLoc& loc, TType& type) -{ - if (! type.isArray() || type.getQualifier().patch || symbolTable.atBuiltInLevel()) - return; - - assert(! isIoResizeArray(type)); - - if (type.getQualifier().storage != EvqVaryingIn || type.getQualifier().patch) - return; - - if (language == EShLangTessControl || language == EShLangTessEvaluation) { - if (type.getOuterArraySize() != resources.maxPatchVertices) { - if (type.isExplicitlySizedArray()) - error(loc, "tessellation input array size must be gl_MaxPatchVertices or implicitly sized", "[]", ""); - type.changeOuterArraySize(resources.maxPatchVertices); - } - } -} - -// Handle a dereference of a geometry shader input array or tessellation control output array. -// See ioArraySymbolResizeList comment in ParseHelper.h. -// -void HlslParseContext::handleIoResizeArrayAccess(const TSourceLoc& /*loc*/, TIntermTyped* base) -{ - TIntermSymbol* symbolNode = base->getAsSymbolNode(); - assert(symbolNode); - if (! symbolNode) - return; - - // fix array size, if it can be fixed and needs to be fixed (will allow variable indexing) - if (symbolNode->getType().isImplicitlySizedArray()) { - int newSize = getIoArrayImplicitSize(); - if (newSize > 0) - symbolNode->getWritableType().changeOuterArraySize(newSize); - } -} - -// If there has been an input primitive declaration (geometry shader) or an output -// number of vertices declaration(tessellation shader), make sure all input array types -// match it in size. Types come either from nodes in the AST or symbols in the -// symbol table. -// -// Types without an array size will be given one. -// Types already having a size that is wrong will get an error. -// -void HlslParseContext::checkIoArraysConsistency(const TSourceLoc& loc, bool tailOnly) -{ - int requiredSize = getIoArrayImplicitSize(); - if (requiredSize == 0) - return; - - const char* feature; - if (language == EShLangGeometry) - feature = TQualifier::getGeometryString(intermediate.getInputPrimitive()); - else if (language == EShLangTessControl) - feature = "vertices"; - else - feature = "unknown"; - - if (tailOnly) { - checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList.back()->getWritableType(), ioArraySymbolResizeList.back()->getName()); - return; - } - - for (size_t i = 0; i < ioArraySymbolResizeList.size(); ++i) - checkIoArrayConsistency(loc, requiredSize, feature, ioArraySymbolResizeList[i]->getWritableType(), ioArraySymbolResizeList[i]->getName()); -} - -int HlslParseContext::getIoArrayImplicitSize() const -{ - if (language == EShLangGeometry) - return TQualifier::mapGeometryToSize(intermediate.getInputPrimitive()); - else if (language == EShLangTessControl) - return intermediate.getVertices() != TQualifier::layoutNotSet ? intermediate.getVertices() : 0; - else - return 0; -} - -void HlslParseContext::checkIoArrayConsistency(const TSourceLoc& /*loc*/, int requiredSize, const char* /*feature*/, TType& type, const TString& /*name*/) -{ - if (type.isImplicitlySizedArray()) - type.changeOuterArraySize(requiredSize); -} - // Handle seeing a binary node with a math operation. TIntermTyped* HlslParseContext::handleBinaryMath(const TSourceLoc& loc, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right) { @@ -2253,22 +2118,6 @@ TIntermTyped* HlslParseContext::handleLengthMethod(const TSourceLoc& loc, TFunct if (type.isRuntimeSizedArray()) { // Create a unary op and let the back end handle it return intermediate.addBuiltInFunctionCall(loc, EOpArrayLength, true, intermNode, TType(EbtInt)); - } else if (type.isImplicitlySizedArray()) { - if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) { - // We could be between a layout declaration that gives a built-in io array implicit size and - // a user redeclaration of that array, meaning we have to substitute its implicit size here - // without actually redeclaring the array. (It is an error to use a member before the - // redeclaration, but not an error to use the array name itself.) - const TString& name = intermNode->getAsSymbolNode()->getName(); - if (name == "gl_in" || name == "gl_out") - length = getIoArrayImplicitSize(); - } - if (length == 0) { - if (intermNode->getAsSymbolNode() && isIoResizeArray(type)) - error(loc, "", function->getName().c_str(), "array must first be sized by a redeclaration or layout qualifier"); - else - error(loc, "", function->getName().c_str(), "array must be declared with a size before using this method"); - } } else length = type.getOuterArraySize(); } else if (type.isMatrix()) @@ -3294,14 +3143,6 @@ void HlslParseContext::declareArray(const TSourceLoc& loc, TString& identifier, symbolTable.insert(*symbol); newDeclaration = true; - if (! symbolTable.atBuiltInLevel()) { - if (isIoResizeArray(type)) { - ioArraySymbolResizeList.push_back(symbol); - checkIoArraysConsistency(loc, true); - } else - fixIoArraySize(loc, symbol->getWritableType()); - } - return; } if (symbol->getAsAnonMember()) { @@ -3326,15 +3167,10 @@ void HlslParseContext::declareArray(const TSourceLoc& loc, TString& identifier, if (existingType.isExplicitlySizedArray()) { // be more lenient for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size - if (! (isIoResizeArray(type) && existingType.getOuterArraySize() == type.getOuterArraySize())) - error(loc, "redeclaration of array with size", identifier.c_str(), ""); return; } existingType.updateArraySizes(type); - - if (isIoResizeArray(type)) - checkIoArraysConsistency(loc); } void HlslParseContext::updateImplicitArraySize(const TSourceLoc& loc, TIntermNode *node, int index) @@ -3519,13 +3355,6 @@ void HlslParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& n symbolTable.insert(*block); - // Tracking for implicit sizing of array - if (isIoResizeArray(block->getType())) { - ioArraySymbolResizeList.push_back(block); - checkIoArraysConsistency(loc, true); - } else if (block->getType().isArray()) - fixIoArraySize(loc, block->getWritableType()); - // Save it in the AST for linker use. intermediate.addSymbolLinkageNode(linkage, *block); } @@ -4723,12 +4552,6 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TS return; } - if (isIoResizeArray(blockType)) { - ioArraySymbolResizeList.push_back(&variable); - checkIoArraysConsistency(loc, true); - } else - fixIoArraySize(loc, variable.getWritableType()); - // Save it in the AST for linker use. intermediate.addSymbolLinkageNode(linkage, variable); } @@ -4933,9 +4756,6 @@ void HlslParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, if (publicType.shaderQualifiers.vertices != TQualifier::layoutNotSet) { assert(language == EShLangTessControl || language == EShLangGeometry); // const char* id = (language == EShLangTessControl) ? "vertices" : "max_vertices"; - - if (language == EShLangTessControl) - checkIoArraysConsistency(loc); } if (publicType.shaderQualifiers.invocations != TQualifier::layoutNotSet) { if (! intermediate.setInvocations(publicType.shaderQualifiers.invocations)) @@ -4951,11 +4771,6 @@ void HlslParseContext::updateStandaloneQualifierDefaults(const TSourceLoc& loc, case ElgTrianglesAdjacency: case ElgQuads: case ElgIsolines: - if (intermediate.setInputPrimitive(publicType.shaderQualifiers.geometry)) { - if (language == EShLangGeometry) - checkIoArraysConsistency(loc); - } else - error(loc, "cannot change previously set input primitive", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); break; default: error(loc, "cannot apply to input", TQualifier::getGeometryString(publicType.shaderQualifiers.geometry), ""); diff --git a/hlsl/hlslParseHelper.h b/hlsl/hlslParseHelper.h index c7568b2a..c8ebdbe8 100755 --- a/hlsl/hlslParseHelper.h +++ b/hlsl/hlslParseHelper.h @@ -63,15 +63,6 @@ public: TIntermTyped* handleBracketDereference(const TSourceLoc&, TIntermTyped* base, TIntermTyped* index); void checkIndex(const TSourceLoc&, const TType&, int& index); - void makeEditable(TSymbol*&); - TVariable* getEditableVariable(const char* name); - bool isIoResizeArray(const TType&) const; - void fixIoArraySize(const TSourceLoc&, TType&); - void handleIoResizeArrayAccess(const TSourceLoc&, TIntermTyped* base); - void checkIoArraysConsistency(const TSourceLoc&, bool tailOnly = false); - int getIoArrayImplicitSize() const; - void checkIoArrayConsistency(const TSourceLoc&, int requiredSize, const char* feature, TType&, const TString&); - TIntermTyped* handleBinaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* left, TIntermTyped* right); TIntermTyped* handleUnaryMath(const TSourceLoc&, const char* str, TOperator op, TIntermTyped* childNode); TIntermTyped* handleDotDereference(const TSourceLoc&, TIntermTyped* base, const TString& field); @@ -168,9 +159,6 @@ protected: TIntermNode* executeInitializer(const TSourceLoc&, TIntermTyped* initializer, TVariable* variable); TIntermTyped* convertInitializerList(const TSourceLoc&, const TType&, TIntermTyped* initializer); TOperator mapAtomicOp(const TSourceLoc& loc, TOperator op, bool isImage); - void outputMessage(const TSourceLoc&, const char* szReason, const char* szToken, - const char* szExtraInfoFormat, TPrefixType prefix, - va_list args); // Array and struct flattening bool shouldFlatten(const TType& type) const { return shouldFlattenIO(type) || shouldFlattenUniform(type); }