Skip to content

Commit d230139

Browse files
committed
add support for an empty descriptor table
1 parent d60ce48 commit d230139

File tree

4 files changed

+133
-2
lines changed

4 files changed

+133
-2
lines changed

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,35 @@ class RootSignatureParser {
108108
/// can sucessfully reach the end of the tokens.
109109
bool Parse();
110110

111+
private:
112+
// Root Element helpers
113+
bool ParseRootElement();
114+
bool ParseDescriptorTable();
115+
116+
/// Invoke the lexer to consume a token and update CurToken with the result
117+
///
118+
/// Return value denotes if we were already at the last token.
119+
///
120+
/// This is used to avoid having to constantly access the Lexer's CurToken
121+
bool ConsumeNextToken() {
122+
if (Lexer.ConsumeToken())
123+
return true; // Report lexer err
124+
CurToken = Lexer.GetCurToken();
125+
return false;
126+
}
127+
128+
// Is the current token one of the expected kinds
129+
bool EnsureExpectedToken(TokenKind AnyExpected);
130+
bool EnsureExpectedToken(ArrayRef<TokenKind> AnyExpected);
131+
132+
/// Consume the next token and report an error if it is not of the expected
133+
/// kind.
134+
///
135+
/// Return value denotes if it failed to match the expected kind, either it is
136+
/// the end of the stream or it didn't match any of the expected kinds.
137+
bool ConsumeExpectedToken(TokenKind Expected);
138+
bool ConsumeExpectedToken(ArrayRef<TokenKind> AnyExpected);
139+
111140
private:
112141
SmallVector<llvm::hlsl::rootsig::RootElement> &Elements;
113142
RootSignatureLexer &Lexer;

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,76 @@ bool RootSignatureParser::Parse() {
182182
if (Lexer.EndOfBuffer())
183183
return false;
184184

185+
// Iterate as many RootElements as possible
186+
while (!ParseRootElement()) {
187+
if (Lexer.EndOfBuffer())
188+
return false;
189+
if (ConsumeExpectedToken(TokenKind::pu_comma))
190+
return true;
191+
}
192+
193+
return true;
194+
}
195+
196+
bool RootSignatureParser::ParseRootElement() {
197+
if (ConsumeExpectedToken(TokenKind::kw_DescriptorTable))
198+
return true;
199+
200+
// Dispatch onto the correct parse method
201+
switch (CurToken.Kind) {
202+
case TokenKind::kw_DescriptorTable:
203+
return ParseDescriptorTable();
204+
default:
205+
llvm_unreachable("Switch for an expected token was not provided");
206+
}
207+
return true;
208+
}
209+
210+
bool RootSignatureParser::ParseDescriptorTable() {
211+
DescriptorTable Table;
212+
213+
if (ConsumeExpectedToken(TokenKind::pu_l_paren))
214+
return true;
215+
216+
// Empty case:
217+
if (!ConsumeExpectedToken(TokenKind::pu_r_paren)) {
218+
Elements.push_back(Table);
219+
return false;
220+
}
221+
185222
return true;
223+
224+
}
225+
226+
// Is given token one of the expected kinds
227+
static bool IsExpectedToken(TokenKind Kind, ArrayRef<TokenKind> AnyExpected) {
228+
for (auto Expected : AnyExpected)
229+
if (Kind == Expected)
230+
return true;
231+
return false;
232+
}
233+
234+
bool RootSignatureParser::EnsureExpectedToken(TokenKind Expected) {
235+
return EnsureExpectedToken(ArrayRef{Expected});
236+
}
237+
238+
bool RootSignatureParser::EnsureExpectedToken(ArrayRef<TokenKind> AnyExpected) {
239+
if (IsExpectedToken(CurToken.Kind, AnyExpected))
240+
return false;
241+
242+
return true;
243+
}
244+
245+
bool RootSignatureParser::ConsumeExpectedToken(TokenKind Expected) {
246+
return ConsumeExpectedToken(ArrayRef{Expected});
247+
}
248+
249+
bool RootSignatureParser::ConsumeExpectedToken(
250+
ArrayRef<TokenKind> AnyExpected) {
251+
if (ConsumeNextToken())
252+
return true;
253+
254+
return EnsureExpectedToken(AnyExpected);
186255
}
187256

188257
} // namespace hlsl

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -335,4 +335,30 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseEmptyTest) {
335335
ASSERT_TRUE(Consumer->IsSatisfied());
336336
}
337337

338+
TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
339+
const llvm::StringLiteral Source = R"cc(
340+
DescriptorTable()
341+
)cc";
342+
343+
TrivialModuleLoader ModLoader;
344+
auto PP = CreatePP(Source, ModLoader);
345+
auto TokLoc = SourceLocation();
346+
347+
hlsl::RootSignatureLexer Lexer(Source, TokLoc, *PP);
348+
SmallVector<RootElement> Elements;
349+
hlsl::RootSignatureParser Parser(Elements, Lexer, Diags);
350+
351+
// Test no diagnostics produced
352+
Consumer->SetNoDiag();
353+
354+
ASSERT_FALSE(Parser.Parse());
355+
RootElement Elem = Elements[0];
356+
357+
// Test generated DescriptorTable start has correct default values
358+
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
359+
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)0);
360+
361+
ASSERT_TRUE(Consumer->IsSatisfied());
362+
}
363+
338364
} // 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 rootsig {
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 rootsig
2734
} // namespace hlsl

0 commit comments

Comments
 (0)