Skip to content

Commit 89240be

Browse files
committed
[HLSL][RootSignature] Implement multiple diagnostics in RootSignatureParser
1 parent 70448a3 commit 89240be

File tree

3 files changed

+81
-19
lines changed

3 files changed

+81
-19
lines changed

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,13 @@ class RootSignatureParser {
198198
bool tryConsumeExpectedToken(RootSignatureToken::Kind Expected);
199199
bool tryConsumeExpectedToken(ArrayRef<RootSignatureToken::Kind> Expected);
200200

201+
/// Consume tokens until the expected token has been peeked to be next
202+
/// or we have reached the end of the stream. Note that this means the
203+
/// expected token will be the next token not CurToken.
204+
///
205+
/// Returns true if it found a token of the given type.
206+
bool skipUntilExpectedToken(ArrayRef<RootSignatureToken::Kind> Expected);
207+
201208
/// Convert the token's offset in the signature string to its SourceLocation
202209
///
203210
/// This allows to currently retrieve the location for multi-token

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 52 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,15 @@ namespace hlsl {
1717

1818
using TokenKind = RootSignatureToken::Kind;
1919

20+
static const TokenKind RootElementKeywords[] = {
21+
TokenKind::kw_RootFlags,
22+
TokenKind::kw_CBV,
23+
TokenKind::kw_UAV,
24+
TokenKind::kw_SRV,
25+
TokenKind::kw_DescriptorTable,
26+
TokenKind::kw_StaticSampler,
27+
};
28+
2029
RootSignatureParser::RootSignatureParser(
2130
llvm::dxbc::RootSignatureVersion Version,
2231
SmallVector<RootSignatureElement> &Elements, StringLiteral *Signature,
@@ -27,51 +36,63 @@ RootSignatureParser::RootSignatureParser(
2736
bool RootSignatureParser::parse() {
2837
// Iterate as many RootSignatureElements as possible, until we hit the
2938
// end of the stream
39+
bool HadError = false;
3040
while (!peekExpectedToken(TokenKind::end_of_stream)) {
41+
bool HadLocalError = false;
3142
if (tryConsumeExpectedToken(TokenKind::kw_RootFlags)) {
3243
SourceLocation ElementLoc = getTokenLocation(CurToken);
3344
auto Flags = parseRootFlags();
34-
if (!Flags.has_value())
35-
return true;
36-
Elements.emplace_back(RootSignatureElement(ElementLoc, *Flags));
45+
if (Flags.has_value())
46+
Elements.emplace_back(RootSignatureElement(ElementLoc, *Flags));
47+
else
48+
HadLocalError = true;
3749
} else if (tryConsumeExpectedToken(TokenKind::kw_RootConstants)) {
3850
SourceLocation ElementLoc = getTokenLocation(CurToken);
3951
auto Constants = parseRootConstants();
40-
if (!Constants.has_value())
41-
return true;
42-
Elements.emplace_back(RootSignatureElement(ElementLoc, *Constants));
52+
if (Constants.has_value())
53+
Elements.emplace_back(RootSignatureElement(ElementLoc, *Constants));
54+
else
55+
HadLocalError = true;
4356
} else if (tryConsumeExpectedToken(TokenKind::kw_DescriptorTable)) {
4457
SourceLocation ElementLoc = getTokenLocation(CurToken);
4558
auto Table = parseDescriptorTable();
46-
if (!Table.has_value())
47-
return true;
48-
Elements.emplace_back(RootSignatureElement(ElementLoc, *Table));
59+
if (Table.has_value())
60+
Elements.emplace_back(RootSignatureElement(ElementLoc, *Table));
61+
else
62+
HadLocalError = true;
4963
} else if (tryConsumeExpectedToken(
5064
{TokenKind::kw_CBV, TokenKind::kw_SRV, TokenKind::kw_UAV})) {
5165
SourceLocation ElementLoc = getTokenLocation(CurToken);
5266
auto Descriptor = parseRootDescriptor();
53-
if (!Descriptor.has_value())
54-
return true;
55-
Elements.emplace_back(RootSignatureElement(ElementLoc, *Descriptor));
67+
if (Descriptor.has_value())
68+
Elements.emplace_back(RootSignatureElement(ElementLoc, *Descriptor));
69+
else
70+
HadLocalError = true;
5671
} else if (tryConsumeExpectedToken(TokenKind::kw_StaticSampler)) {
5772
SourceLocation ElementLoc = getTokenLocation(CurToken);
5873
auto Sampler = parseStaticSampler();
59-
if (!Sampler.has_value())
60-
return true;
61-
Elements.emplace_back(RootSignatureElement(ElementLoc, *Sampler));
74+
if (Sampler.has_value())
75+
Elements.emplace_back(RootSignatureElement(ElementLoc, *Sampler));
76+
else
77+
HadLocalError = true;
6278
} else {
79+
HadLocalError = true;
6380
consumeNextToken(); // let diagnostic be at the start of invalid token
6481
reportDiag(diag::err_hlsl_invalid_token)
6582
<< /*parameter=*/0 << /*param of*/ TokenKind::kw_RootSignature;
66-
return true;
6783
}
6884

69-
// ',' denotes another element, otherwise, expected to be at end of stream
70-
if (!tryConsumeExpectedToken(TokenKind::pu_comma))
85+
if (HadLocalError) {
86+
HadError = true;
87+
skipUntilExpectedToken(RootElementKeywords);
88+
} else if (!tryConsumeExpectedToken(TokenKind::pu_comma)) {
89+
// ',' denotes another element, otherwise, expected to be at end of stream
7190
break;
91+
}
7292
}
7393

74-
return consumeExpectedToken(TokenKind::end_of_stream,
94+
return HadError ||
95+
consumeExpectedToken(TokenKind::end_of_stream,
7596
diag::err_expected_either, TokenKind::pu_comma);
7697
}
7798

@@ -1371,6 +1392,18 @@ bool RootSignatureParser::tryConsumeExpectedToken(
13711392
return true;
13721393
}
13731394

1395+
bool RootSignatureParser::skipUntilExpectedToken(
1396+
ArrayRef<TokenKind> AnyExpected) {
1397+
1398+
while (!peekExpectedToken(AnyExpected)) {
1399+
if (peekExpectedToken(TokenKind::end_of_stream))
1400+
return false;
1401+
consumeNextToken();
1402+
}
1403+
1404+
return true;
1405+
}
1406+
13741407
SourceLocation RootSignatureParser::getTokenLocation(RootSignatureToken Tok) {
13751408
return Signature->getLocationOfByte(Tok.LocOffset, PP.getSourceManager(),
13761409
PP.getLangOpts(), PP.getTargetInfo());

clang/test/SemaHLSL/RootSignature-err.hlsl

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,3 +103,25 @@ void bad_root_signature_22() {}
103103
// expected-error@+1 {{invalid value of RootFlags}}
104104
[RootSignature("RootFlags(local_root_signature | root_flag_typo)")]
105105
void bad_root_signature_23() {}
106+
107+
#define DemoMultipleErrorsRootSignature \
108+
"CBV(b0, invalid)," \
109+
"StaticSampler()" \
110+
"DescriptorTable(" \
111+
" visibility = SHADER_VISIBILITY_ALL," \
112+
" visibility = SHADER_VISIBILITY_DOMAIN," \
113+
")," \
114+
"SRV(t0, space = 28947298374912374098172)" \
115+
"UAV(u0, flags = 3)" \
116+
"DescriptorTable(Sampler(s0 flags = DATA_VOLATILE))," \
117+
"CBV(b0),,"
118+
119+
// expected-error@+7 {{invalid parameter of CBV}}
120+
// expected-error@+6 {{did not specify mandatory parameter 's register'}}
121+
// expected-error@+5 {{specified the same parameter 'visibility' multiple times}}
122+
// expected-error@+4 {{integer literal is too large to be represented as a 32-bit signed integer type}}
123+
// expected-error@+3 {{flag value is neither a literal 0 nor a named value}}
124+
// expected-error@+2 {{expected ')' or ','}}
125+
// expected-error@+1 {{invalid parameter of RootSignature}}
126+
[RootSignature(DemoMultipleErrorsRootSignature)]
127+
void multiple_errors() {}

0 commit comments

Comments
 (0)