Add redeclarations of built-in blocks.

Note: lots of test results changed due to listing the members of a block when printing types.

git-svn-id: https://cvs.khronos.org/svn/repos/ogl/trunk/ecosystem/public/sdk/tools/glslang@23682 e7fa87d3-cd2b-0410-9028-fcbf551c1848
This commit is contained in:
John Kessenich 2013-10-24 01:25:40 +00:00
parent 94fdd1117b
commit ab41fe5df6
44 changed files with 528 additions and 324 deletions

View file

@ -755,6 +755,17 @@ public:
TString s(buf);
s.append(getCompleteTypeString());
// Add struct/block members
if (structure) {
s.append("{");
for (size_t i = 0; i < structure->size(); ++i) {
s.append((*structure)[i].type->getFieldName());
if (i < structure->size()-1)
s.append(",");
}
s.append("}");
}
return s;
}

View file

@ -1328,7 +1328,7 @@ void TBuiltIns::initialize(int version, EProfile profile)
);
if (IncludeLegacy(version, profile)) {
if (version < 410)
if (version < 150)
stageBuiltins[EShLangFragment].append(
"in float gl_FogFragCoord;"
"in vec4 gl_TexCoord[];"

View file

@ -1881,7 +1881,7 @@ void TParseContext::nonInitConstCheck(TSourceLoc loc, TString& identifier, TType
//
// Returns a redeclared and type-modified variable if a redeclarated occurred.
//
TSymbol* TParseContext::redeclareBuiltin(TSourceLoc loc, const TString& identifier, bool& newDeclaration)
TSymbol* TParseContext::redeclareBuiltinVariable(TSourceLoc loc, const TString& identifier, bool& newDeclaration)
{
if (profile == EEsProfile || identifier.compare(0, 3, "gl_") != 0 || symbolTable.atBuiltInLevel())
return 0;
@ -1889,8 +1889,6 @@ TSymbol* TParseContext::redeclareBuiltin(TSourceLoc loc, const TString& identifi
// Potentially redeclaring a built-in variable...
if ((identifier == "gl_FragDepth" && version >= 420) ||
(identifier == "gl_PerVertex" && version >= 410) ||
(identifier == "gl_PerFragment" && version >= 410) ||
(identifier == "gl_FragCoord" && version >= 150) ||
(identifier == "gl_ClipDistance" && version >= 130) ||
(identifier == "gl_FrontColor" && version >= 130) ||
@ -1928,6 +1926,90 @@ TSymbol* TParseContext::redeclareBuiltin(TSourceLoc loc, const TString& identifi
return 0;
}
bool TParseContext::redeclareBuiltinBlock(TSourceLoc loc, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes)
{
// just a quick out, not everything that must be checked:
if (symbolTable.atBuiltInLevel() || profile == EEsProfile || blockName.compare(0, 3, "gl_") != 0)
return false;
if (instanceName && instanceName->compare(0, 3, "gl_") != 0) {
error(loc, "cannot redeclare a built-in block with a user name", instanceName->c_str(), "");
return false;
}
profileRequires(loc, ECoreProfile | ECompatibilityProfile, 410, GL_ARB_separate_shader_objects, "built-in block redeclaration");
// Potentially redeclaring a built-in block...
if (blockName != "gl_PerVertex" && blockName != "gl_PerFragment")
return false;
// Blocks with instance names are easy to find, lookup the instance name,
// Anonymous blocks need to be found via a member. copyUp()?? will work
// just fine for either find.
bool builtIn;
TSymbol* block;
if (instanceName)
block = symbolTable.find(*instanceName, &builtIn);
else
block = symbolTable.find(typeList.front().type->getFieldName(), &builtIn);
// If the block was not found, this must be a version/profile/stage
// that doesn't have it.
if (! block)
return false;
// Built-in blocks cannot be redeclared more than once, which if happened,
// we'd be finding the already redeclared one here, rather than the built in.
if (! builtIn) {
error(loc, "can only redeclare a built-in block once", blockName.c_str(), "");
return false;
}
// Copy the to make a writable version, to insert into the block table after editing
block = symbolTable.copyUpDeferredInsert(block);
if (block->getType().getBasicType() != EbtBlock) {
error(loc, "cannot redeclare a non block as a block", blockName.c_str(), "");
return false;
}
// TODO: semantics: block redeclaration: instance array size matching?
// Edit and error check the container against the redeclaration
// - remove unused members
// - ensure remaining qualifiers match
TType& type = block->getWritableType();
TTypeList::iterator member = type.getStruct()->begin();
while (member != type.getStruct()->end()) {
// look for match
bool found = false;
for (TTypeList::iterator newMember = typeList.begin(); newMember != typeList.end(); ++newMember) {
if (member->type->getFieldName() == newMember->type->getFieldName()) {
found = true;
break;
}
}
// remove non-redeclared members
if (found)
++member;
else
member = type.getStruct()->erase(member);
// TODO: semantics: block redeclaration: member type/qualifier matching
}
symbolTable.insert(*block);
// Save it in the AST for linker use.
intermediate.addSymbolLinkageNode(linkage, *block);
return true;
}
void TParseContext::paramCheck(TSourceLoc loc, const TStorageQualifier& qualifier, TType* type)
{
switch (qualifier) {
@ -2418,12 +2500,9 @@ TIntermNode* TParseContext::declareVariable(TSourceLoc loc, TString& identifier,
if (! type.getQualifier().hasStream() && language == EShLangGeometry && type.getQualifier().storage == EvqVaryingOut)
type.getQualifier().layoutStream = globalOutputDefaults.layoutStream;
if (publicType.geometry != ElgNone)
error(loc, "geometry primitive qualifier cannot be applied to a variable declaration", TQualifier::getGeometryString(publicType.geometry), "");
// 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 = redeclareBuiltin(loc, identifier, newDeclaration);
TSymbol* symbol = redeclareBuiltinVariable(loc, identifier, newDeclaration);
if (! symbol)
reservedErrorCheck(loc, identifier);
@ -2848,10 +2927,14 @@ TIntermTyped* TParseContext::constructStruct(TIntermNode* node, const TType& typ
//
// Do everything needed to add an interface block.
//
void TParseContext::addBlock(TSourceLoc loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes)
void TParseContext::declareBlock(TSourceLoc loc, TTypeList& typeList, const TString* instanceName, TArraySizes* arraySizes)
{
// First, error checks
// This might be a redeclaration of a built-in block, find out, and get
// a modifiable copy if so.
if (redeclareBuiltinBlock(loc, typeList, *blockName, instanceName, arraySizes))
return;
// Basic error checks
if (reservedErrorCheck(loc, *blockName))
return;

View file

@ -115,7 +115,8 @@ public:
void precisionQualifierCheck(TSourceLoc, TPublicType&);
void parameterSamplerCheck(TSourceLoc, TStorageQualifier qualifier, const TType& type);
bool containsSampler(const TType& type);
TSymbol* redeclareBuiltin(TSourceLoc, const TString&, bool& newDeclaration);
TSymbol* redeclareBuiltinVariable(TSourceLoc, const TString&, bool& newDeclaration);
bool redeclareBuiltinBlock(TSourceLoc, TTypeList& typeList, const TString& blockName, const TString* instanceName, TArraySizes* arraySizes);
void paramCheck(TSourceLoc, const TStorageQualifier&, TType* type);
void nestedBlockCheck(TSourceLoc);
void nestedStructCheck(TSourceLoc);
@ -137,7 +138,7 @@ public:
TIntermTyped* addConstructor(TSourceLoc, TIntermNode*, const TType&, TOperator);
TIntermTyped* constructStruct(TIntermNode*, const TType&, int, TSourceLoc);
TIntermTyped* constructBuiltIn(const TType&, TOperator, TIntermNode*, TSourceLoc, bool subset);
void addBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
void declareBlock(TSourceLoc, TTypeList& typeList, const TString* instanceName = 0, TArraySizes* arraySizes = 0);
void addQualifierToExisting(TSourceLoc, TQualifier, const TString& identifier);
void addQualifierToExisting(TSourceLoc, TQualifier, TIdentifierList&);
void updateStandaloneQualifierDefaults(TSourceLoc, const TPublicType&);

View file

@ -463,13 +463,11 @@ public:
// to the current level, so it can be modified without impacting other users
// of the shared table.
//
TSymbol* copyUp(TSymbol* shared)
TSymbol* copyUpDeferredInsert(TSymbol* shared)
{
TSymbol* copy;
if (shared->getAsVariable()) {
copy = shared->clone();
TSymbol* copy = shared->clone();
copy->setUniqueId(shared->getUniqueId());
table[currentLevel()]->insert(*copy);
return copy;
} else {
const TAnonMember* anon = shared->getAsAnonMember();
@ -477,7 +475,20 @@ public:
TVariable* container = anon->getAnonContainer().clone();
container->changeName(NewPoolTString(""));
container->setUniqueId(anon->getAnonContainer().getUniqueId());
table[currentLevel()]->insert(*container);
return container;
}
}
TSymbol* copyUp(TSymbol* shared)
{
TSymbol* copy = copyUpDeferredInsert(shared);
table[currentLevel()]->insert(*copy);
if (shared->getAsVariable())
return copy;
else {
// get copy of an anonymous member's container
table[currentLevel()]->insert(*copy);
// return the copy of the anonymous member
return table[currentLevel()]->find(shared->getName());
}
}

View file

@ -761,15 +761,15 @@ declaration
$$ = 0;
}
| block_structure SEMICOLON {
parseContext.addBlock($1.loc, *$1.typeList);
parseContext.declareBlock($1.loc, *$1.typeList);
$$ = 0;
}
| block_structure IDENTIFIER SEMICOLON {
parseContext.addBlock($1.loc, *$1.typeList, $2.string);
parseContext.declareBlock($1.loc, *$1.typeList, $2.string);
$$ = 0;
}
| block_structure IDENTIFIER array_specifier SEMICOLON {
parseContext.addBlock($1.loc, *$1.typeList, $2.string, $3.arraySizes);
parseContext.declareBlock($1.loc, *$1.typeList, $2.string, $3.arraySizes);
$$ = 0;
}
| type_qualifier SEMICOLON {