HLSL: Refactor attribute implementation.

- make it sharable with GLSL
- correct the case insensitivity
- remove the map; queries are not needed, all entries need processing
- make it easier to build bottom up (will help GLSL parsing)
- support semantic checking and reporting
- allow front-end dependent semantics and attribute name mapping
This commit is contained in:
John Kessenich
2018-01-30 11:01:39 -07:00
parent e349af7e20
commit e18fd20d5c
17 changed files with 638 additions and 500 deletions

View File

@@ -396,6 +396,9 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
if (peekTokenClass(EHTokLeftParen)) {
// looks like function parameters
// merge in the attributes into the return type
parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType, true);
// Potentially rename shader entry point function. No-op most of the time.
parseContext.renameShaderFunction(fullName);
@@ -423,7 +426,13 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
parseContext.handleFunctionDeclarator(declarator.loc, *declarator.function, true);
}
} else {
// A variable declaration. Fix the storage qualifier if it's a global.
// A variable declaration.
// merge in the attributes, the first time around, into the shared type
if (! declarator_list)
parseContext.transferTypeAttributes(token.loc, declarator.attributes, declaredType);
// Fix the storage qualifier if it's a global.
if (declaredType.getQualifier().storage == EvqTemporary && parseContext.symbolTable.atGlobalLevel())
declaredType.getQualifier().storage = EvqUniform;
@@ -536,13 +545,16 @@ bool HlslGrammar::acceptDeclaration(TIntermNode*& nodeList)
bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
{
node = nullptr;
TAttributeMap attributes;
TAttributes attributes;
// fully_specified_type
TType type;
if (! acceptFullySpecifiedType(type, attributes))
return false;
if (attributes.size() > 0)
parseContext.warn(token.loc, "attributes don't apply to control declaration", "", "");
// filter out type casts
if (peekTokenClass(EHTokLeftParen)) {
recedeToken();
@@ -578,12 +590,12 @@ bool HlslGrammar::acceptControlDeclaration(TIntermNode*& node)
// : type_specifier
// | type_qualifier type_specifier
//
bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributeMap& attributes)
bool HlslGrammar::acceptFullySpecifiedType(TType& type, const TAttributes& attributes)
{
TIntermNode* nodeList = nullptr;
return acceptFullySpecifiedType(type, nodeList, attributes);
}
bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributeMap& attributes, bool forbidDeclarators)
bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList, const TAttributes& attributes, bool forbidDeclarators)
{
// type_qualifier
TQualifier qualifier;
@@ -608,7 +620,7 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList,
parseContext.mergeQualifiers(type.getQualifier(), qualifier);
// merge in the attributes
parseContext.transferTypeAttributes(attributes, type);
parseContext.transferTypeAttributes(token.loc, attributes, type);
// further, it can create an anonymous instance of the block
// (cbuffer and tbuffer don't consume the next identifier, and
@@ -633,9 +645,6 @@ bool HlslGrammar::acceptFullySpecifiedType(TType& type, TIntermNode*& nodeList,
qualifier.builtIn = type.getQualifier().builtIn;
type.getQualifier() = qualifier;
// merge in the attributes
parseContext.transferTypeAttributes(attributes, type);
}
return true;
@@ -2335,7 +2344,7 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
// struct_declaration
// attributes
TAttributeMap attributes;
TAttributes attributes;
acceptAttributes(attributes);
bool declarator_list = false;
@@ -2346,6 +2355,9 @@ bool HlslGrammar::acceptStructDeclarationList(TTypeList*& typeList, TIntermNode*
expected("member type");
return false;
}
// merge in the attributes
parseContext.transferTypeAttributes(token.loc, attributes, memberType);
// struct_declarator COMMA struct_declarator ...
bool functionDefinitionAccepted = false;
@@ -2542,7 +2554,7 @@ bool HlslGrammar::acceptDefaultParameterDeclaration(const TType& type, TIntermTy
bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
{
// attributes
TAttributeMap attributes;
TAttributes attributes;
acceptAttributes(attributes);
// fully_specified_type
@@ -2550,6 +2562,9 @@ bool HlslGrammar::acceptParameterDeclaration(TFunction& function)
if (! acceptFullySpecifiedType(*type, attributes))
return false;
// merge in the attributes
parseContext.transferTypeAttributes(token.loc, attributes, *type);
// identifier
HlslToken idToken;
acceptIdentifier(idToken);
@@ -3386,7 +3401,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
statement = nullptr;
// attributes
TAttributeMap attributes;
TAttributes attributes;
acceptAttributes(attributes);
// attributed_statement
@@ -3458,7 +3473,7 @@ bool HlslGrammar::acceptStatement(TIntermNode*& statement)
// | PATCHCONSTANTFUNC
// | NUMTHREADS LEFT_PAREN x_size, y_size,z z_size RIGHT_PAREN
//
void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
void HlslGrammar::acceptAttributes(TAttributes& attributes)
{
// For now, accept the [ XXX(X) ] syntax, but drop all but
// numthreads, which is used to set the CS local size.
@@ -3529,9 +3544,16 @@ void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
return;
}
// Add any values we found into the attribute map. This accepts
// (and ignores) values not mapping to a known TAttributeType;
attributes.setAttribute(nameSpace, attributeToken.string, expressions);
// Add any values we found into the attribute map.
if (attributeToken.string != nullptr) {
TAttributeType attributeType = parseContext.attributeFromName(nameSpace, *attributeToken.string);
if (attributeType == EatNone)
parseContext.warn(attributeToken.loc, "unrecognized attribute", attributeToken.string->c_str(), "");
else {
TAttributeArgs attributeArgs = { attributeType, expressions };
attributes.push_back(attributeArgs);
}
}
} while (true);
}
@@ -3539,12 +3561,10 @@ void HlslGrammar::acceptAttributes(TAttributeMap& attributes)
// : IF LEFT_PAREN expression RIGHT_PAREN statement
// : IF LEFT_PAREN expression RIGHT_PAREN statement ELSE statement
//
bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributeMap& attributes)
bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttributes& attributes)
{
TSourceLoc loc = token.loc;
const TSelectionControl control = parseContext.handleSelectionControl(attributes);
// IF
if (! acceptTokenClass(EHTokIf))
return false;
@@ -3582,7 +3602,9 @@ bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttri
}
// Put the pieces together
statement = intermediate.addSelection(condition, thenElse, loc, control);
statement = intermediate.addSelection(condition, thenElse, loc);
parseContext.handleSelectionAttributes(loc, statement->getAsSelectionNode(), attributes);
parseContext.popScope();
--parseContext.controlFlowNestingLevel;
@@ -3592,13 +3614,11 @@ bool HlslGrammar::acceptSelectionStatement(TIntermNode*& statement, const TAttri
// switch_statement
// : SWITCH LEFT_PAREN expression RIGHT_PAREN compound_statement
//
bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributeMap& attributes)
bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttributes& attributes)
{
// SWITCH
TSourceLoc loc = token.loc;
const TSelectionControl control = parseContext.handleSelectionControl(attributes);
if (! acceptTokenClass(EHTokSwitch))
return false;
@@ -3618,7 +3638,8 @@ bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttribut
--parseContext.controlFlowNestingLevel;
if (statementOkay)
statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr, control);
statement = parseContext.addSwitch(loc, switchExpression, statement ? statement->getAsAggregate() : nullptr,
attributes);
parseContext.popSwitchSequence();
parseContext.popScope();
@@ -3632,7 +3653,7 @@ bool HlslGrammar::acceptSwitchStatement(TIntermNode*& statement, const TAttribut
// | FOR LEFT_PAREN for_init_statement for_rest_statement RIGHT_PAREN statement
//
// Non-speculative, only call if it needs to be found; WHILE or DO or FOR already seen.
bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributeMap& attributes)
bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttributes& attributes)
{
TSourceLoc loc = token.loc;
TIntermTyped* condition = nullptr;
@@ -3642,9 +3663,8 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
// WHILE or DO or FOR
advanceToken();
const TLoopControl control = parseContext.handleLoopControl(attributes);
TIntermLoop* loopNode = nullptr;
switch (loop) {
case EHTokWhile:
// so that something declared in the condition is scoped to the lifetime
@@ -3670,9 +3690,9 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
parseContext.popScope();
--parseContext.controlFlowNestingLevel;
statement = intermediate.addLoop(statement, condition, nullptr, true, loc, control);
return true;
loopNode = intermediate.addLoop(statement, condition, nullptr, true, loc);
statement = loopNode;
break;
case EHTokDo:
parseContext.nestLooping(); // this only needs to work right if no errors
@@ -3703,9 +3723,9 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
parseContext.unnestLooping();
--parseContext.controlFlowNestingLevel;
statement = intermediate.addLoop(statement, condition, 0, false, loc, control);
return true;
loopNode = intermediate.addLoop(statement, condition, 0, false, loc);
statement = loopNode;
break;
case EHTokFor:
{
@@ -3747,18 +3767,21 @@ bool HlslGrammar::acceptIterationStatement(TIntermNode*& statement, const TAttri
return false;
}
statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, control);
statement = intermediate.addForLoop(statement, initNode, condition, iterator, true, loc, loopNode);
parseContext.popScope();
parseContext.unnestLooping();
--parseContext.controlFlowNestingLevel;
return true;
break;
}
default:
return false;
}
parseContext.handleLoopAttributes(loc, loopNode, attributes);
return true;
}
// jump_statement