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:
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user