Skip to content

Commit 03c5dfe

Browse files
committed
add support for an empty descriptor table
1 parent 650d65b commit 03c5dfe

File tree

4 files changed

+144
-2
lines changed

4 files changed

+144
-2
lines changed

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,27 @@ class RootSignatureParser {
9898
// can sucessfully reach the end of the tokens.
9999
bool Parse();
100100

101+
private:
102+
// Root Element helpers
103+
bool ParseRootElement(bool First);
104+
bool ParseDescriptorTable();
105+
106+
// Increment the token iterator if we have not reached the end.
107+
// Return value denotes if we were already at the last token.
108+
bool ConsumeNextToken();
109+
110+
// Is the current token one of the expected kinds
111+
bool EnsureExpectedToken(TokenKind AnyExpected);
112+
bool EnsureExpectedToken(ArrayRef<TokenKind> AnyExpected);
113+
114+
// Consume the next token and report an error if it is not of the expected
115+
// kind.
116+
//
117+
// Return value denotes if it failed to match the expected kind, either it is
118+
// the end of the stream or it didn't match any of the expected kinds.
119+
bool ConsumeExpectedToken(TokenKind Expected);
120+
bool ConsumeExpectedToken(ArrayRef<TokenKind> AnyExpected);
121+
101122
private:
102123
SmallVector<rs::RootElement> &Elements;
103124
SmallVector<RootSignatureToken>::const_iterator CurTok;

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,91 @@ bool RootSignatureParser::Parse() {
186186
if (CurTok == LastTok)
187187
return false;
188188

189+
bool First = true;
190+
// Iterate as many RootElements as possible
191+
while (!ParseRootElement(First)) {
192+
First = false;
193+
// Avoid use of ConsumeNextToken here to skip incorrect end of tokens error
194+
CurTok++;
195+
if (CurTok == LastTok)
196+
return false;
197+
if (EnsureExpectedToken(TokenKind::pu_comma))
198+
return true;
199+
}
200+
201+
return true;
202+
}
203+
204+
bool RootSignatureParser::ParseRootElement(bool First) {
205+
if (First && EnsureExpectedToken(TokenKind::kw_DescriptorTable))
206+
return true;
207+
if (!First && ConsumeExpectedToken(TokenKind::kw_DescriptorTable))
208+
return true;
209+
210+
// Dispatch onto the correct parse method
211+
switch (CurTok->Kind) {
212+
case TokenKind::kw_DescriptorTable:
213+
return ParseDescriptorTable();
214+
default:
215+
llvm_unreachable("Switch for an expected token was not provided");
216+
return true;
217+
}
218+
}
219+
220+
bool RootSignatureParser::ParseDescriptorTable() {
221+
DescriptorTable Table;
222+
223+
if (ConsumeExpectedToken(TokenKind::pu_l_paren))
224+
return true;
225+
226+
// Empty case:
227+
if (!ConsumeExpectedToken(TokenKind::pu_r_paren)) {
228+
Elements.push_back(Table);
229+
return false;
230+
}
231+
232+
return true;
233+
234+
}
235+
236+
bool RootSignatureParser::ConsumeNextToken() {
237+
CurTok++;
238+
if (LastTok == CurTok) {
239+
return true;
240+
}
241+
return false;
242+
}
243+
244+
// Is given token one of the expected kinds
245+
static bool IsExpectedToken(TokenKind Kind, ArrayRef<TokenKind> AnyExpected) {
246+
for (auto Expected : AnyExpected)
247+
if (Kind == Expected)
248+
return true;
249+
return false;
250+
}
251+
252+
bool RootSignatureParser::EnsureExpectedToken(TokenKind Expected) {
253+
return EnsureExpectedToken(ArrayRef{Expected});
254+
}
255+
256+
bool RootSignatureParser::EnsureExpectedToken(ArrayRef<TokenKind> AnyExpected) {
257+
if (IsExpectedToken(CurTok->Kind, AnyExpected))
258+
return false;
259+
189260
return true;
190261
}
262+
263+
bool RootSignatureParser::ConsumeExpectedToken(TokenKind Expected) {
264+
return ConsumeExpectedToken(ArrayRef{Expected});
265+
}
266+
267+
bool RootSignatureParser::ConsumeExpectedToken(
268+
ArrayRef<TokenKind> AnyExpected) {
269+
if (ConsumeNextToken())
270+
return true;
271+
272+
return EnsureExpectedToken(AnyExpected);
273+
}
274+
191275
} // namespace hlsl
192276
} // namespace clang

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,4 +305,34 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseEmptyTest) {
305305
ASSERT_TRUE(Consumer->IsSatisfied());
306306
}
307307

308+
TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
309+
const llvm::StringLiteral Source = R"cc(
310+
DescriptorTable()
311+
)cc";
312+
313+
TrivialModuleLoader ModLoader;
314+
auto PP = CreatePP(Source, ModLoader);
315+
auto TokLoc = SourceLocation();
316+
317+
hlsl::RootSignatureLexer Lexer(Source, TokLoc, *PP);
318+
319+
SmallVector<hlsl::RootSignatureToken> Tokens;
320+
321+
// Test no diagnostics produced
322+
Consumer->SetNoDiag();
323+
ASSERT_FALSE(Lexer.Lex(Tokens));
324+
325+
SmallVector<RootElement> Elements;
326+
hlsl::RootSignatureParser Parser(Elements, Tokens, Diags);
327+
328+
ASSERT_FALSE(Parser.Parse());
329+
RootElement Elem = Elements[0];
330+
331+
// Test generated DescriptorTable start has correct default values
332+
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
333+
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)0);
334+
335+
ASSERT_TRUE(Consumer->IsSatisfied());
336+
}
337+
308338
} // anonymous namespace

llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,15 @@ namespace llvm {
2020
namespace hlsl {
2121
namespace root_signature {
2222

23-
// Models RootElement
24-
using RootElement = std::variant<std::monostate>;
23+
// Definitions of the in-memory data layout structures
24+
25+
// Models the end of a descriptor table and stores its visibility
26+
struct DescriptorTable {
27+
uint32_t NumClauses = 0; // The number of clauses in the table
28+
};
29+
30+
// Models RootElement : DescriptorTable
31+
using RootElement = std::variant<DescriptorTable>;
2532

2633
} // namespace root_signature
2734
} // namespace hlsl

0 commit comments

Comments
 (0)