Skip to content

Commit 6f57e87

Browse files
committed
add support for empty descriptor table clause
1 parent 123b4ac commit 6f57e87

File tree

4 files changed

+134
-4
lines changed

4 files changed

+134
-4
lines changed

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,15 +103,28 @@ class RootSignatureParser {
103103
// Root Element helpers
104104
bool ParseRootElement(bool First);
105105
bool ParseDescriptorTable();
106+
bool ParseDescriptorTableClause();
106107

108+
// Helper dispatch method
107109
// Increment the token iterator if we have not reached the end.
108110
// Return value denotes if we were already at the last token.
109111
bool ConsumeNextToken();
110112

113+
// Attempt to retrieve the next token, if TokenKind is invalid then there was
114+
// no next token.
115+
RootSignatureToken PeekNextToken();
116+
111117
// Is the current token one of the expected kinds
112118
bool EnsureExpectedToken(TokenKind AnyExpected);
113119
bool EnsureExpectedToken(ArrayRef<TokenKind> AnyExpected);
114120

121+
// Peek if the next token is of the expected kind.
122+
//
123+
// Return value denotes if it failed to match the expected kind, either it is
124+
// the end of the stream or it didn't match any of the expected kinds.
125+
bool PeekExpectedToken(TokenKind Expected);
126+
bool PeekExpectedToken(ArrayRef<TokenKind> AnyExpected);
127+
115128
// Consume the next token and report an error if it is not of the expected
116129
// kind.
117130
//
@@ -120,6 +133,15 @@ class RootSignatureParser {
120133
bool ConsumeExpectedToken(TokenKind Expected);
121134
bool ConsumeExpectedToken(ArrayRef<TokenKind> AnyExpected);
122135

136+
// Peek if the next token is of the expected kind and if it is then consume
137+
// it.
138+
//
139+
// Return value denotes if it failed to match the expected kind, either it is
140+
// the end of the stream or it didn't match any of the expected kinds. It will
141+
// not report an error if there isn't a match.
142+
bool TryConsumeExpectedToken(TokenKind Expected);
143+
bool TryConsumeExpectedToken(ArrayRef<TokenKind> Expected);
144+
123145
private:
124146
SmallVector<rs::RootElement> &Elements;
125147
SmallVector<RootSignatureToken>::const_iterator CurTok;

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 78 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -273,12 +273,64 @@ bool RootSignatureParser::ParseDescriptorTable() {
273273
return true;
274274

275275
// Empty case:
276-
if (!ConsumeExpectedToken(TokenKind::pu_r_paren)) {
276+
if (!TryConsumeExpectedToken(TokenKind::pu_r_paren)) {
277277
Elements.push_back(Table);
278278
return false;
279279
}
280280

281-
return true;
281+
// Iterate through all the defined clauses
282+
do {
283+
if (ParseDescriptorTableClause())
284+
return true;
285+
Table.NumClauses++;
286+
} while (!TryConsumeExpectedToken(TokenKind::pu_comma));
287+
288+
if (ConsumeExpectedToken(TokenKind::pu_r_paren))
289+
return true;
290+
291+
Elements.push_back(Table);
292+
return false;
293+
}
294+
295+
bool RootSignatureParser::ParseDescriptorTableClause() {
296+
if (ConsumeExpectedToken({TokenKind::kw_CBV, TokenKind::kw_SRV,
297+
TokenKind::kw_UAV, TokenKind::kw_Sampler}))
298+
return true;
299+
300+
DescriptorTableClause Clause;
301+
switch (CurTok->Kind) {
302+
case TokenKind::kw_CBV:
303+
Clause.Type = ClauseType::CBuffer;
304+
break;
305+
case TokenKind::kw_SRV:
306+
Clause.Type = ClauseType::SRV;
307+
break;
308+
case TokenKind::kw_UAV:
309+
Clause.Type = ClauseType::UAV;
310+
break;
311+
case TokenKind::kw_Sampler:
312+
Clause.Type = ClauseType::Sampler;
313+
break;
314+
default:
315+
llvm_unreachable("Switch for an expected token was not provided");
316+
return true;
317+
}
318+
if (ConsumeExpectedToken(TokenKind::pu_l_paren))
319+
return true;
320+
321+
if (ConsumeExpectedToken(TokenKind::pu_r_paren))
322+
return true;
323+
324+
Elements.push_back(Clause);
325+
return false;
326+
}
327+
328+
RootSignatureToken RootSignatureParser::PeekNextToken() {
329+
// Create an invalid token
330+
RootSignatureToken Token = RootSignatureToken(SourceLocation());
331+
if (CurTok != LastTok)
332+
Token = *(CurTok + 1);
333+
return Token;
282334
}
283335

284336
bool RootSignatureParser::ConsumeNextToken() {
@@ -313,6 +365,19 @@ bool RootSignatureParser::EnsureExpectedToken(ArrayRef<TokenKind> AnyExpected) {
313365
return true;
314366
}
315367

368+
bool RootSignatureParser::PeekExpectedToken(TokenKind Expected) {
369+
return PeekExpectedToken(ArrayRef{Expected});
370+
}
371+
372+
bool RootSignatureParser::PeekExpectedToken(ArrayRef<TokenKind> AnyExpected) {
373+
RootSignatureToken Token = PeekNextToken();
374+
if (Token.Kind == TokenKind::invalid)
375+
return true;
376+
if (IsExpectedToken(Token.Kind, AnyExpected))
377+
return false;
378+
return true;
379+
}
380+
316381
bool RootSignatureParser::ConsumeExpectedToken(TokenKind Expected) {
317382
return ConsumeExpectedToken(ArrayRef{Expected});
318383
}
@@ -325,5 +390,16 @@ bool RootSignatureParser::ConsumeExpectedToken(
325390
return EnsureExpectedToken(AnyExpected);
326391
}
327392

393+
bool RootSignatureParser::TryConsumeExpectedToken(TokenKind Expected) {
394+
return TryConsumeExpectedToken(ArrayRef{Expected});
395+
}
396+
397+
bool RootSignatureParser::TryConsumeExpectedToken(
398+
ArrayRef<TokenKind> AnyExpected) {
399+
if (PeekExpectedToken(AnyExpected))
400+
return true;
401+
return ConsumeNextToken();
402+
}
403+
328404
} // namespace hlsl
329405
} // namespace clang

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -307,6 +307,12 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseEmptyTest) {
307307

308308
TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
309309
const llvm::StringLiteral Source = R"cc(
310+
DescriptorTable(
311+
CBV(),
312+
SRV(),
313+
Sampler(),
314+
UAV()
315+
),
310316
DescriptorTable()
311317
)cc";
312318

@@ -327,7 +333,26 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseDTClausesTest) {
327333

328334
ASSERT_FALSE(Parser.Parse());
329335
RootElement Elem = Elements[0];
336+
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
337+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Type, ClauseType::CBuffer);
330338

339+
Elem = Elements[1];
340+
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
341+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Type, ClauseType::SRV);
342+
343+
Elem = Elements[2];
344+
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
345+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Type, ClauseType::Sampler);
346+
347+
Elem = Elements[3];
348+
ASSERT_TRUE(std::holds_alternative<DescriptorTableClause>(Elem));
349+
ASSERT_EQ(std::get<DescriptorTableClause>(Elem).Type, ClauseType::UAV);
350+
351+
Elem = Elements[4];
352+
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
353+
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)4);
354+
355+
Elem = Elements[5];
331356
// Test generated DescriptorTable start has correct default values
332357
ASSERT_TRUE(std::holds_alternative<DescriptorTable>(Elem));
333358
ASSERT_EQ(std::get<DescriptorTable>(Elem).NumClauses, (uint32_t)0);

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

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
#ifndef LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
1515
#define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
1616

17+
#include "llvm/Support/DXILABI.h"
1718
#include <variant>
1819

1920
namespace llvm {
@@ -27,8 +28,14 @@ struct DescriptorTable {
2728
uint32_t NumClauses = 0; // The number of clauses in the table
2829
};
2930

30-
// Models RootElement : DescriptorTable
31-
using RootElement = std::variant<DescriptorTable>;
31+
// Models DTClause : CBV | SRV | UAV | Sampler, by collecting like parameters
32+
using ClauseType = llvm::dxil::ResourceClass;
33+
struct DescriptorTableClause {
34+
ClauseType Type;
35+
};
36+
37+
// Models RootElement : DescriptorTable | DescriptorTableClause
38+
using RootElement = std::variant<DescriptorTable, DescriptorTableClause>;
3239

3340
} // namespace root_signature
3441
} // namespace hlsl

0 commit comments

Comments
 (0)