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

@ -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;