Skip to content

Commit 5d1ec2f

Browse files
author
Finn Plummer
committed
review: remove abstraction of parsing arbitrary params
1 parent 1d2bd91 commit 5d1ec2f

File tree

3 files changed

+37
-124
lines changed

3 files changed

+37
-124
lines changed

Diff for: clang/include/clang/Parse/ParseHLSLRootSignature.h

+5-51
Original file line numberDiff line numberDiff line change
@@ -69,59 +69,13 @@ class RootSignatureParser {
6969
bool parseDescriptorTable();
7070
bool parseDescriptorTableClause();
7171

72-
/// Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any
73-
/// order and only exactly once. `ParsedParamState` provides a common
74-
/// stateful structure to facilitate a common abstraction over collecting
75-
/// parameters. By having a common return type we can follow clang's pattern
76-
/// of first parsing out the values and then validating when we construct
77-
/// the corresponding in-memory RootElements.
78-
struct ParsedParamState {
79-
// Parameter state to hold the parsed values. The value is only guarentted
80-
// to be correct if one of its keyword bits is set in `Seen`.
81-
// Eg) if any of the seen bits for `bReg, tReg, uReg, sReg` are set, then
82-
// Register will have an initialized value
83-
llvm::hlsl::rootsig::Register Register;
84-
uint32_t Space;
85-
86-
// Seen retains whether or not the corresponding keyword has been
87-
// seen
88-
uint32_t Seen = 0u;
89-
90-
// Valid keywords for the different parameter types and its corresponding
91-
// parsed value
92-
ArrayRef<RootSignatureToken::Kind> Keywords;
93-
94-
// Context of which RootElement is retained to dispatch on the correct
95-
// parse method.
96-
// Eg) If we encounter kw_flags, it will depend on Context
97-
// we are parsing to determine which `parse*Flags` method to call
98-
RootSignatureToken::Kind Context;
99-
100-
// Retain start of params for reporting diagnostics
101-
SourceLocation StartLoc;
102-
103-
// Must provide the starting context of the parameters
104-
ParsedParamState(ArrayRef<RootSignatureToken::Kind> Keywords,
105-
RootSignatureToken::Kind Context, SourceLocation StartLoc)
106-
: Keywords(Keywords), Context(Context), StartLoc(StartLoc) {}
107-
108-
// Helper functions to interact with Seen
109-
size_t getKeywordIdx(RootSignatureToken::Kind Keyword);
110-
bool checkAndSetSeen(RootSignatureToken::Kind Keyword);
111-
bool checkAndClearSeen(RootSignatureToken::Kind Keyword);
72+
struct ParsedParams {
73+
std::optional<llvm::hlsl::rootsig::Register> Register;
74+
std::optional<uint32_t> Space;
11275
};
113-
114-
/// Root signature parameters follow the form of `keyword` `=` `value`, or,
115-
/// are a register. Given a keyword and the context of which `RootElement`
116-
/// type we are parsing, we can dispatch onto the correct parseMethod to
117-
/// parse a value into the `ParsedParamState`.
118-
///
119-
/// This function implements the dispatch onto the correct parse method.
120-
bool parseParam(ParsedParamState &Params);
121-
122-
/// Parses out a `ParsedParamState` for the caller to use for construction
76+
/// Parses out a `ParsedParams` for the caller to use for construction
12377
/// of the in-memory representation of a Root Element.
124-
bool parseParams(ParsedParamState &Params);
78+
bool parseDescriptorTableClauseParams(ParsedParams &Params, RootSignatureToken::Kind RegType);
12579

12680
/// Parameter parse methods corresponding to a ParamType
12781
bool parseUIntParam(uint32_t &X);

Diff for: clang/lib/Parse/ParseHLSLRootSignature.cpp

+32-67
Original file line numberDiff line numberDiff line change
@@ -117,26 +117,21 @@ bool RootSignatureParser::parseDescriptorTableClause() {
117117
ParamKind))
118118
return true;
119119

120-
TokenKind Keywords[2] = {
121-
ExpectedRegister,
122-
TokenKind::kw_space,
123-
};
124-
ParsedParamState Params(Keywords, ParamKind, CurToken.TokLoc);
125-
if (parseParams(Params))
120+
ParsedParams Result;
121+
if (parseDescriptorTableClauseParams(Result, ExpectedRegister))
126122
return true;
127123

128-
// Mandatory parameters:
129-
if (!Params.checkAndClearSeen(ExpectedRegister)) {
124+
// Check mandatory parameters were provided
125+
if (!Result.Register.has_value()) {
130126
getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param)
131127
<< ExpectedRegister;
132128
return true;
133129
}
134130

135-
Clause.Register = Params.Register;
131+
Clause.Register = *Result.Register;
136132

137-
// Optional parameters:
138-
if (Params.checkAndClearSeen(TokenKind::kw_space))
139-
Clause.Space = Params.Space;
133+
if (Result.Space)
134+
Clause.Space = *Result.Space;
140135

141136
if (consumeExpectedToken(TokenKind::pu_r_paren,
142137
diag::err_hlsl_unexpected_end_of_params,
@@ -147,66 +142,36 @@ bool RootSignatureParser::parseDescriptorTableClause() {
147142
return false;
148143
}
149144

150-
size_t RootSignatureParser::ParsedParamState::getKeywordIdx(
151-
RootSignatureToken::Kind Keyword) {
152-
ArrayRef KeywordRef = Keywords;
153-
auto It = llvm::find(KeywordRef, Keyword);
154-
assert(It != KeywordRef.end() && "Did not provide a valid param keyword");
155-
return std::distance(KeywordRef.begin(), It);
156-
}
157-
158-
bool RootSignatureParser::ParsedParamState::checkAndSetSeen(
159-
RootSignatureToken::Kind Keyword) {
160-
size_t Idx = getKeywordIdx(Keyword);
161-
bool WasSeen = Seen & (1 << Idx);
162-
Seen |= 1u << Idx;
163-
return WasSeen;
164-
}
165-
166-
bool RootSignatureParser::ParsedParamState::checkAndClearSeen(
167-
RootSignatureToken::Kind Keyword) {
168-
size_t Idx = getKeywordIdx(Keyword);
169-
bool WasSeen = Seen & (1 << Idx);
170-
Seen &= ~(1u << Idx);
171-
return WasSeen;
172-
}
173-
174-
bool RootSignatureParser::parseParam(ParsedParamState &Params) {
175-
TokenKind Keyword = CurToken.TokKind;
176-
if (Keyword == TokenKind::bReg || Keyword == TokenKind::tReg ||
177-
Keyword == TokenKind::uReg || Keyword == TokenKind::sReg) {
178-
return parseRegister(Params.Register);
179-
}
180-
181-
if (consumeExpectedToken(TokenKind::pu_equal, diag::err_expected_after,
182-
Keyword))
183-
return true;
184-
185-
switch (Keyword) {
186-
case RootSignatureToken::Kind::kw_space:
187-
return parseUIntParam(Params.Space);
188-
default:
189-
llvm_unreachable("Switch for consumed keyword was not provided");
190-
}
191-
}
192-
193-
bool RootSignatureParser::parseParams(ParsedParamState &Params) {
145+
bool RootSignatureParser::parseDescriptorTableClauseParams(ParsedParams &Params, TokenKind RegType) {
194146
assert(CurToken.TokKind == TokenKind::pu_l_paren &&
195147
"Expects to only be invoked starting at given token");
196148

197-
while (tryConsumeExpectedToken(Params.Keywords)) {
198-
if (Params.checkAndSetSeen(CurToken.TokKind)) {
199-
getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
149+
do {
150+
if (tryConsumeExpectedToken(RegType)) {
151+
if (Params.Register.has_value()) {
152+
getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
200153
<< CurToken.TokKind;
201-
return true;
154+
return true;
155+
}
156+
Register Reg;
157+
if (parseRegister(Reg))
158+
return true;
159+
Params.Register = Reg;
202160
}
203-
204-
if (parseParam(Params))
205-
return true;
206-
207-
if (!tryConsumeExpectedToken(TokenKind::pu_comma))
208-
break;
209-
}
161+
if (tryConsumeExpectedToken(TokenKind::kw_space)) {
162+
if (Params.Space.has_value()) {
163+
getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
164+
<< CurToken.TokKind;
165+
return true;
166+
}
167+
if (consumeExpectedToken(TokenKind::pu_equal))
168+
return true;
169+
uint32_t Space;
170+
if (parseUIntParam(Space))
171+
return true;
172+
Params.Space = Space;
173+
}
174+
} while (tryConsumeExpectedToken(TokenKind::pu_comma));
210175

211176
return false;
212177
}

Diff for: llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h

-6
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,6 @@ struct DescriptorTableClause {
4646
// Models RootElement : DescriptorTable | DescriptorTableClause
4747
using RootElement = std::variant<DescriptorTable, DescriptorTableClause>;
4848

49-
// ParamType is used as an 'any' type that will reference to a parameter in
50-
// RootElement. Each variant of ParamType is expected to have a Parse method
51-
// defined that will be dispatched on when we are attempting to parse a
52-
// parameter
53-
using ParamType = std::variant<uint32_t *, Register *>;
54-
5549
} // namespace rootsig
5650
} // namespace hlsl
5751
} // namespace llvm

0 commit comments

Comments
 (0)