Whole stack: Fix stale types in the AST linker object nodes, fixing #557.

Rationalizes the entire tracking of the linker object nodes, effecting
GLSL, HLSL, and SPIR-V, to allow tracked objects to be fully edited before
their type snapshot for linker objects.

Should only effect things when the rest of the AST contained no reference to
the symbol, because normal AST nodes were not stale. Also will only effect such
objects when their types were edited.
This commit is contained in:
John Kessenich
2016-11-05 10:15:53 -06:00
parent e5e58cfee3
commit d3f1122a44
107 changed files with 630 additions and 560 deletions

View File

@@ -48,10 +48,10 @@
namespace glslang {
HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool /*parsingBuiltins*/,
HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& interm, bool parsingBuiltins,
int version, EProfile profile, const SpvVersion& spvVersion, EShLanguage language, TInfoSink& infoSink,
bool forwardCompatible, EShMessages messages) :
TParseContextBase(symbolTable, interm, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
TParseContextBase(symbolTable, interm, parsingBuiltins, version, profile, spvVersion, language, infoSink, forwardCompatible, messages),
contextPragma(true, false),
loopNestingLevel(0), annotationNestingLevel(0), structNestingLevel(0), controlFlowNestingLevel(0),
postMainReturn(false),
@@ -59,9 +59,6 @@ HlslParseContext::HlslParseContext(TSymbolTable& symbolTable, TIntermediate& int
entryPointOutput(nullptr),
nextInLocation(0), nextOutLocation(0)
{
// ensure we always have a linkage node, even if empty, to simplify tree topology algorithms
linkage = new TIntermAggregate;
globalUniformDefaults.clear();
globalUniformDefaults.layoutMatrix = ElmRowMajor;
globalUniformDefaults.layoutPacking = ElpStd140;
@@ -128,6 +125,8 @@ bool HlslParseContext::parseShaderStrings(TPpContext& ppContext, TInputScanner&
return false;
}
finish();
return numErrors == 0;
}
@@ -950,9 +949,9 @@ void HlslParseContext::flattenArray(const TSourceLoc& loc, const TVariable& vari
++binding;
memberVariables.push_back(memberVariable);
intermediate.addSymbolLinkageNode(linkage, *memberVariable);
trackLinkageDeferred(*memberVariable);
}
flattenMap[variable.getUniqueId()] = memberVariables;
}
@@ -989,7 +988,7 @@ void HlslParseContext::assignLocations(TVariable& variable)
nextOutLocation += intermediate.computeTypeLocationSize(variable.getType());
}
}
intermediate.addSymbolLinkageNode(linkage, variable);
trackLinkage(variable);
}
};
@@ -3588,7 +3587,7 @@ void HlslParseContext::arrayDimMerge(TType& type, const TArraySizes* sizes)
// Do all the semantic checking for declaring or redeclaring an array, with and
// without a size, and make the right changes to the symbol table.
//
void HlslParseContext::declareArray(const TSourceLoc& loc, TString& identifier, const TType& type, TSymbol*& symbol, bool& newDeclaration)
void HlslParseContext::declareArray(const TSourceLoc& loc, TString& identifier, const TType& type, TSymbol*& symbol, bool track)
{
if (! symbol) {
bool currentScope;
@@ -3605,7 +3604,8 @@ void HlslParseContext::declareArray(const TSourceLoc& loc, TString& identifier,
//
symbol = new TVariable(&identifier, type);
symbolTable.insert(*symbol);
newDeclaration = true;
if (track && symbolTable.atGlobalLevel())
trackLinkageDeferred(*symbol);
return;
}
@@ -3628,7 +3628,6 @@ void HlslParseContext::declareArray(const TSourceLoc& loc, TString& identifier,
// redeclareBuiltinVariable() should have already done the copyUp()
TType& existingType = symbol->getWritableType();
if (existingType.isExplicitlySizedArray()) {
// be more lenient for input arrays to geometry shaders and tessellation control outputs, where the redeclaration is the same size
return;
@@ -3695,7 +3694,7 @@ void HlslParseContext::updateImplicitArraySize(const TSourceLoc& loc, TIntermNod
//
TSymbol* HlslParseContext::redeclareBuiltinVariable(const TSourceLoc& /*loc*/, const TString& identifier,
const TQualifier& /*qualifier*/,
const TShaderQualifiers& /*publicType*/, bool& /*newDeclaration*/)
const TShaderQualifiers& /*publicType*/)
{
if (! builtInName(identifier) || symbolTable.atBuiltInLevel() || ! symbolTable.atGlobalLevel())
return nullptr;
@@ -3820,7 +3819,7 @@ void HlslParseContext::redeclareBuiltinBlock(const TSourceLoc& loc, TTypeList& n
symbolTable.insert(*block);
// Save it in the AST for linker use.
intermediate.addSymbolLinkageNode(linkage, *block);
trackLinkageDeferred(*block);
}
void HlslParseContext::paramFix(TType& type)
@@ -4413,8 +4412,7 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
return nullptr;
// Check for redeclaration of built-ins and/or attempting to declare a reserved name
bool newDeclaration = false; // true if a new entry gets added to the symbol table
TSymbol* symbol = nullptr; // = redeclareBuiltinVariable(loc, identifier, type.getQualifier(), parseType.shaderQualifiers, newDeclaration);
TSymbol* symbol = nullptr;
inheritGlobalDefaults(type.getQualifier());
@@ -4423,14 +4421,14 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
// Declare the variable
if (type.isArray()) {
// array case
declareArray(loc, identifier, type, symbol, newDeclaration);
flattenVar = shouldFlatten(type);
declareArray(loc, identifier, type, symbol, !flattenVar);
if (flattenVar)
flatten(loc, *symbol->getAsVariable());
} else {
// non-array case
if (! symbol)
symbol = declareNonArray(loc, identifier, type, newDeclaration);
symbol = declareNonArray(loc, identifier, type);
else if (type != symbol->getType())
error(loc, "cannot change the type of", "redeclaration", symbol->getName().c_str());
}
@@ -4452,13 +4450,6 @@ TIntermNode* HlslParseContext::declareVariable(const TSourceLoc& loc, TString& i
initNode = executeInitializer(loc, initializer, variable);
}
// see if it's a linker-level object to track. if it's flattened above,
// that process added linkage objects for the flattened symbols, we don't
// add the aggregate here.
if (!flattenVar)
if (newDeclaration && symbolTable.atGlobalLevel())
intermediate.addSymbolLinkageNode(linkage, *symbol);
return initNode;
}
@@ -4494,19 +4485,20 @@ TVariable* HlslParseContext::makeInternalVariable(const char* name, const TType&
//
// Return the successfully declared variable.
//
TVariable* HlslParseContext::declareNonArray(const TSourceLoc& loc, TString& identifier, TType& type, bool& newDeclaration)
TVariable* HlslParseContext::declareNonArray(const TSourceLoc& loc, TString& identifier, TType& type)
{
// make a new variable
TVariable* variable = new TVariable(&identifier, type);
// add variable to symbol table
if (! symbolTable.insert(*variable)) {
error(loc, "redefinition", variable->getName().c_str(), "");
return nullptr;
} else {
newDeclaration = true;
if (symbolTable.insert(*variable)) {
if (symbolTable.atGlobalLevel())
trackLinkageDeferred(*variable);
return variable;
}
error(loc, "redefinition", variable->getName().c_str(), "");
return nullptr;
}
//
@@ -5019,7 +5011,7 @@ void HlslParseContext::declareBlock(const TSourceLoc& loc, TType& type, const TS
}
// Save it in the AST for linker use.
intermediate.addSymbolLinkageNode(linkage, variable);
trackLinkageDeferred(variable);
}
void HlslParseContext::finalizeGlobalUniformBlockLayout(TVariable& block)

View File

@@ -114,7 +114,7 @@ public:
bool structQualifierErrorCheck(const TSourceLoc&, const TPublicType& pType);
void mergeQualifiers(TQualifier& dst, const TQualifier& src);
int computeSamplerTypeIndex(TSampler&);
TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&, bool& newDeclaration);
TSymbol* redeclareBuiltinVariable(const TSourceLoc&, const TString&, const TQualifier&, const TShaderQualifiers&);
void redeclareBuiltinBlock(const TSourceLoc&, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
void paramFix(TType& type);
void specializationCheck(const TSourceLoc&, const TType&, const char* op);
@@ -163,8 +163,8 @@ public:
protected:
void inheritGlobalDefaults(TQualifier& dst) const;
TVariable* makeInternalVariable(const char* name, const TType&) const;
TVariable* declareNonArray(const TSourceLoc&, TString& identifier, TType&, bool& newDeclaration);
void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&, bool& newDeclaration);
TVariable* declareNonArray(const TSourceLoc&, TString& identifier, TType&);
void declareArray(const TSourceLoc&, TString& identifier, const TType&, TSymbol*&, bool track);
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);