Skip to content

Commit 0c42aef

Browse files
authored
[HLSL][RootSignature] Add parsing of Register in params for RootDescriptors (#140148)
- defines the `parseRootDescriptorParams` infrastructure for parsing the params of a `RootDescriptor` - defines the register type to illustrate use - add tests to demonstrate functionality Part 2 of #126577
1 parent 9d3ce55 commit 0c42aef

File tree

4 files changed

+80
-3
lines changed

4 files changed

+80
-3
lines changed

clang/include/clang/Parse/ParseHLSLRootSignature.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,12 @@ class RootSignatureParser {
8989
};
9090
std::optional<ParsedConstantParams> parseRootConstantParams();
9191

92+
struct ParsedRootDescriptorParams {
93+
std::optional<llvm::hlsl::rootsig::Register> Reg;
94+
};
95+
std::optional<ParsedRootDescriptorParams>
96+
parseRootDescriptorParams(RootSignatureToken::Kind RegType);
97+
9298
struct ParsedClauseParams {
9399
std::optional<llvm::hlsl::rootsig::Register> Reg;
94100
std::optional<uint32_t> NumDescriptors;

clang/lib/Parse/ParseHLSLRootSignature.cpp

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,20 +176,37 @@ std::optional<RootDescriptor> RootSignatureParser::parseRootDescriptor() {
176176
return std::nullopt;
177177

178178
RootDescriptor Descriptor;
179+
TokenKind ExpectedReg;
179180
switch (DescriptorKind) {
180181
default:
181182
llvm_unreachable("Switch for consumed token was not provided");
182183
case TokenKind::kw_CBV:
183184
Descriptor.Type = DescriptorType::CBuffer;
185+
ExpectedReg = TokenKind::bReg;
184186
break;
185187
case TokenKind::kw_SRV:
186188
Descriptor.Type = DescriptorType::SRV;
189+
ExpectedReg = TokenKind::tReg;
187190
break;
188191
case TokenKind::kw_UAV:
189192
Descriptor.Type = DescriptorType::UAV;
193+
ExpectedReg = TokenKind::uReg;
190194
break;
191195
}
192196

197+
auto Params = parseRootDescriptorParams(ExpectedReg);
198+
if (!Params.has_value())
199+
return std::nullopt;
200+
201+
// Check mandatory parameters were provided
202+
if (!Params->Reg.has_value()) {
203+
getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param)
204+
<< ExpectedReg;
205+
return std::nullopt;
206+
}
207+
208+
Descriptor.Reg = Params->Reg.value();
209+
193210
if (consumeExpectedToken(TokenKind::pu_r_paren,
194211
diag::err_hlsl_unexpected_end_of_params,
195212
/*param of=*/TokenKind::kw_RootConstants))
@@ -398,6 +415,31 @@ RootSignatureParser::parseRootConstantParams() {
398415
return Params;
399416
}
400417

418+
std::optional<RootSignatureParser::ParsedRootDescriptorParams>
419+
RootSignatureParser::parseRootDescriptorParams(TokenKind RegType) {
420+
assert(CurToken.TokKind == TokenKind::pu_l_paren &&
421+
"Expects to only be invoked starting at given token");
422+
423+
ParsedRootDescriptorParams Params;
424+
do {
425+
// ( `b` | `t` | `u`) POS_INT
426+
if (tryConsumeExpectedToken(RegType)) {
427+
if (Params.Reg.has_value()) {
428+
getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
429+
<< CurToken.TokKind;
430+
return std::nullopt;
431+
}
432+
auto Reg = parseRegister();
433+
if (!Reg.has_value())
434+
return std::nullopt;
435+
Params.Reg = Reg;
436+
}
437+
438+
} while (tryConsumeExpectedToken(TokenKind::pu_comma));
439+
440+
return Params;
441+
}
442+
401443
std::optional<RootSignatureParser::ParsedClauseParams>
402444
RootSignatureParser::parseDescriptorTableClauseParams(TokenKind RegType) {
403445
assert(CurToken.TokKind == TokenKind::pu_l_paren &&

clang/unittests/Parse/ParseHLSLRootSignatureTest.cpp

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -346,9 +346,9 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseRootFlagsTest) {
346346

347347
TEST_F(ParseHLSLRootSignatureTest, ValidParseRootDescriptorsTest) {
348348
const llvm::StringLiteral Source = R"cc(
349-
CBV(),
350-
SRV(),
351-
UAV()
349+
CBV(b0),
350+
SRV(t42),
351+
UAV(u34893247)
352352
)cc";
353353

354354
TrivialModuleLoader ModLoader;
@@ -369,14 +369,20 @@ TEST_F(ParseHLSLRootSignatureTest, ValidParseRootDescriptorsTest) {
369369
RootElement Elem = Elements[0];
370370
ASSERT_TRUE(std::holds_alternative<RootDescriptor>(Elem));
371371
ASSERT_EQ(std::get<RootDescriptor>(Elem).Type, DescriptorType::CBuffer);
372+
ASSERT_EQ(std::get<RootDescriptor>(Elem).Reg.ViewType, RegisterType::BReg);
373+
ASSERT_EQ(std::get<RootDescriptor>(Elem).Reg.Number, 0u);
372374

373375
Elem = Elements[1];
374376
ASSERT_TRUE(std::holds_alternative<RootDescriptor>(Elem));
375377
ASSERT_EQ(std::get<RootDescriptor>(Elem).Type, DescriptorType::SRV);
378+
ASSERT_EQ(std::get<RootDescriptor>(Elem).Reg.ViewType, RegisterType::TReg);
379+
ASSERT_EQ(std::get<RootDescriptor>(Elem).Reg.Number, 42u);
376380

377381
Elem = Elements[2];
378382
ASSERT_TRUE(std::holds_alternative<RootDescriptor>(Elem));
379383
ASSERT_EQ(std::get<RootDescriptor>(Elem).Type, DescriptorType::UAV);
384+
ASSERT_EQ(std::get<RootDescriptor>(Elem).Reg.ViewType, RegisterType::UReg);
385+
ASSERT_EQ(std::get<RootDescriptor>(Elem).Reg.Number, 34893247u);
380386

381387
ASSERT_TRUE(Consumer->isSatisfied());
382388
}
@@ -494,6 +500,28 @@ TEST_F(ParseHLSLRootSignatureTest, InvalidMissingDTParameterTest) {
494500
ASSERT_TRUE(Consumer->isSatisfied());
495501
}
496502

503+
TEST_F(ParseHLSLRootSignatureTest, InvalidMissingRDParameterTest) {
504+
// This test will check that the parsing fails due a mandatory
505+
// parameter (register) not being specified
506+
const llvm::StringLiteral Source = R"cc(
507+
SRV()
508+
)cc";
509+
510+
TrivialModuleLoader ModLoader;
511+
auto PP = createPP(Source, ModLoader);
512+
auto TokLoc = SourceLocation();
513+
514+
hlsl::RootSignatureLexer Lexer(Source, TokLoc);
515+
SmallVector<RootElement> Elements;
516+
hlsl::RootSignatureParser Parser(Elements, Lexer, *PP);
517+
518+
// Test correct diagnostic produced
519+
Consumer->setExpected(diag::err_hlsl_rootsig_missing_param);
520+
ASSERT_TRUE(Parser.parse());
521+
522+
ASSERT_TRUE(Consumer->isSatisfied());
523+
}
524+
497525
TEST_F(ParseHLSLRootSignatureTest, InvalidMissingRCParameterTest) {
498526
// This test will check that the parsing fails due a mandatory
499527
// parameter (num32BitConstants) not being specified

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

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ using DescriptorType = llvm::dxil::ResourceClass;
8989
// Models RootDescriptor : CBV | SRV | UAV, by collecting like parameters
9090
struct RootDescriptor {
9191
DescriptorType Type;
92+
Register Reg;
9293
};
9394

9495
// Models the end of a descriptor table and stores its visibility

0 commit comments

Comments
 (0)