1*700637cbSDimitry Andric //=== ParseHLSLRootSignature.cpp - Parse Root Signature -------------------===//
2*700637cbSDimitry Andric //
3*700637cbSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*700637cbSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5*700637cbSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*700637cbSDimitry Andric //
7*700637cbSDimitry Andric //===----------------------------------------------------------------------===//
8*700637cbSDimitry Andric
9*700637cbSDimitry Andric #include "clang/Parse/ParseHLSLRootSignature.h"
10*700637cbSDimitry Andric
11*700637cbSDimitry Andric #include "clang/Lex/LiteralSupport.h"
12*700637cbSDimitry Andric
13*700637cbSDimitry Andric using namespace llvm::hlsl::rootsig;
14*700637cbSDimitry Andric
15*700637cbSDimitry Andric namespace clang {
16*700637cbSDimitry Andric namespace hlsl {
17*700637cbSDimitry Andric
18*700637cbSDimitry Andric using TokenKind = RootSignatureToken::Kind;
19*700637cbSDimitry Andric
20*700637cbSDimitry Andric static const TokenKind RootElementKeywords[] = {
21*700637cbSDimitry Andric TokenKind::kw_RootFlags,
22*700637cbSDimitry Andric TokenKind::kw_CBV,
23*700637cbSDimitry Andric TokenKind::kw_UAV,
24*700637cbSDimitry Andric TokenKind::kw_SRV,
25*700637cbSDimitry Andric TokenKind::kw_DescriptorTable,
26*700637cbSDimitry Andric TokenKind::kw_StaticSampler,
27*700637cbSDimitry Andric };
28*700637cbSDimitry Andric
RootSignatureParser(llvm::dxbc::RootSignatureVersion Version,SmallVector<RootSignatureElement> & Elements,StringLiteral * Signature,Preprocessor & PP)29*700637cbSDimitry Andric RootSignatureParser::RootSignatureParser(
30*700637cbSDimitry Andric llvm::dxbc::RootSignatureVersion Version,
31*700637cbSDimitry Andric SmallVector<RootSignatureElement> &Elements, StringLiteral *Signature,
32*700637cbSDimitry Andric Preprocessor &PP)
33*700637cbSDimitry Andric : Version(Version), Elements(Elements), Signature(Signature),
34*700637cbSDimitry Andric Lexer(Signature->getString()), PP(PP), CurToken(0) {}
35*700637cbSDimitry Andric
parse()36*700637cbSDimitry Andric bool RootSignatureParser::parse() {
37*700637cbSDimitry Andric // Iterate as many RootSignatureElements as possible, until we hit the
38*700637cbSDimitry Andric // end of the stream
39*700637cbSDimitry Andric bool HadError = false;
40*700637cbSDimitry Andric while (!peekExpectedToken(TokenKind::end_of_stream)) {
41*700637cbSDimitry Andric if (tryConsumeExpectedToken(TokenKind::kw_RootFlags)) {
42*700637cbSDimitry Andric SourceLocation ElementLoc = getTokenLocation(CurToken);
43*700637cbSDimitry Andric auto Flags = parseRootFlags();
44*700637cbSDimitry Andric if (!Flags.has_value()) {
45*700637cbSDimitry Andric HadError = true;
46*700637cbSDimitry Andric skipUntilExpectedToken(RootElementKeywords);
47*700637cbSDimitry Andric continue;
48*700637cbSDimitry Andric }
49*700637cbSDimitry Andric
50*700637cbSDimitry Andric Elements.emplace_back(ElementLoc, *Flags);
51*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_RootConstants)) {
52*700637cbSDimitry Andric SourceLocation ElementLoc = getTokenLocation(CurToken);
53*700637cbSDimitry Andric auto Constants = parseRootConstants();
54*700637cbSDimitry Andric if (!Constants.has_value()) {
55*700637cbSDimitry Andric HadError = true;
56*700637cbSDimitry Andric skipUntilExpectedToken(RootElementKeywords);
57*700637cbSDimitry Andric continue;
58*700637cbSDimitry Andric }
59*700637cbSDimitry Andric Elements.emplace_back(ElementLoc, *Constants);
60*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_DescriptorTable)) {
61*700637cbSDimitry Andric SourceLocation ElementLoc = getTokenLocation(CurToken);
62*700637cbSDimitry Andric auto Table = parseDescriptorTable();
63*700637cbSDimitry Andric if (!Table.has_value()) {
64*700637cbSDimitry Andric HadError = true;
65*700637cbSDimitry Andric // We are within a DescriptorTable, we will do our best to recover
66*700637cbSDimitry Andric // by skipping until we encounter the expected closing ')'.
67*700637cbSDimitry Andric skipUntilClosedParens();
68*700637cbSDimitry Andric consumeNextToken();
69*700637cbSDimitry Andric skipUntilExpectedToken(RootElementKeywords);
70*700637cbSDimitry Andric continue;
71*700637cbSDimitry Andric }
72*700637cbSDimitry Andric Elements.emplace_back(ElementLoc, *Table);
73*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(
74*700637cbSDimitry Andric {TokenKind::kw_CBV, TokenKind::kw_SRV, TokenKind::kw_UAV})) {
75*700637cbSDimitry Andric SourceLocation ElementLoc = getTokenLocation(CurToken);
76*700637cbSDimitry Andric auto Descriptor = parseRootDescriptor();
77*700637cbSDimitry Andric if (!Descriptor.has_value()) {
78*700637cbSDimitry Andric HadError = true;
79*700637cbSDimitry Andric skipUntilExpectedToken(RootElementKeywords);
80*700637cbSDimitry Andric continue;
81*700637cbSDimitry Andric }
82*700637cbSDimitry Andric Elements.emplace_back(ElementLoc, *Descriptor);
83*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_StaticSampler)) {
84*700637cbSDimitry Andric SourceLocation ElementLoc = getTokenLocation(CurToken);
85*700637cbSDimitry Andric auto Sampler = parseStaticSampler();
86*700637cbSDimitry Andric if (!Sampler.has_value()) {
87*700637cbSDimitry Andric HadError = true;
88*700637cbSDimitry Andric skipUntilExpectedToken(RootElementKeywords);
89*700637cbSDimitry Andric continue;
90*700637cbSDimitry Andric }
91*700637cbSDimitry Andric Elements.emplace_back(ElementLoc, *Sampler);
92*700637cbSDimitry Andric } else {
93*700637cbSDimitry Andric HadError = true;
94*700637cbSDimitry Andric consumeNextToken(); // let diagnostic be at the start of invalid token
95*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
96*700637cbSDimitry Andric << /*parameter=*/0 << /*param of*/ TokenKind::kw_RootSignature;
97*700637cbSDimitry Andric skipUntilExpectedToken(RootElementKeywords);
98*700637cbSDimitry Andric continue;
99*700637cbSDimitry Andric }
100*700637cbSDimitry Andric
101*700637cbSDimitry Andric if (!tryConsumeExpectedToken(TokenKind::pu_comma)) {
102*700637cbSDimitry Andric // ',' denotes another element, otherwise, expected to be at end of stream
103*700637cbSDimitry Andric break;
104*700637cbSDimitry Andric }
105*700637cbSDimitry Andric }
106*700637cbSDimitry Andric
107*700637cbSDimitry Andric return HadError ||
108*700637cbSDimitry Andric consumeExpectedToken(TokenKind::end_of_stream,
109*700637cbSDimitry Andric diag::err_expected_either, TokenKind::pu_comma);
110*700637cbSDimitry Andric }
111*700637cbSDimitry Andric
112*700637cbSDimitry Andric template <typename FlagType>
maybeOrFlag(std::optional<FlagType> Flags,FlagType Flag)113*700637cbSDimitry Andric static FlagType maybeOrFlag(std::optional<FlagType> Flags, FlagType Flag) {
114*700637cbSDimitry Andric if (!Flags.has_value())
115*700637cbSDimitry Andric return Flag;
116*700637cbSDimitry Andric
117*700637cbSDimitry Andric return static_cast<FlagType>(llvm::to_underlying(Flags.value()) |
118*700637cbSDimitry Andric llvm::to_underlying(Flag));
119*700637cbSDimitry Andric }
120*700637cbSDimitry Andric
parseRootFlags()121*700637cbSDimitry Andric std::optional<llvm::dxbc::RootFlags> RootSignatureParser::parseRootFlags() {
122*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::kw_RootFlags &&
123*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
124*700637cbSDimitry Andric
125*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
126*700637cbSDimitry Andric CurToken.TokKind))
127*700637cbSDimitry Andric return std::nullopt;
128*700637cbSDimitry Andric
129*700637cbSDimitry Andric std::optional<llvm::dxbc::RootFlags> Flags = llvm::dxbc::RootFlags::None;
130*700637cbSDimitry Andric
131*700637cbSDimitry Andric // Handle valid empty case
132*700637cbSDimitry Andric if (tryConsumeExpectedToken(TokenKind::pu_r_paren))
133*700637cbSDimitry Andric return Flags;
134*700637cbSDimitry Andric
135*700637cbSDimitry Andric // Handle the edge-case of '0' to specify no flags set
136*700637cbSDimitry Andric if (tryConsumeExpectedToken(TokenKind::int_literal)) {
137*700637cbSDimitry Andric if (!verifyZeroFlag()) {
138*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
139*700637cbSDimitry Andric return std::nullopt;
140*700637cbSDimitry Andric }
141*700637cbSDimitry Andric } else {
142*700637cbSDimitry Andric // Otherwise, parse as many flags as possible
143*700637cbSDimitry Andric TokenKind Expected[] = {
144*700637cbSDimitry Andric #define ROOT_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
145*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
146*700637cbSDimitry Andric };
147*700637cbSDimitry Andric
148*700637cbSDimitry Andric do {
149*700637cbSDimitry Andric if (tryConsumeExpectedToken(Expected)) {
150*700637cbSDimitry Andric switch (CurToken.TokKind) {
151*700637cbSDimitry Andric #define ROOT_FLAG_ENUM(NAME, LIT) \
152*700637cbSDimitry Andric case TokenKind::en_##NAME: \
153*700637cbSDimitry Andric Flags = maybeOrFlag<llvm::dxbc::RootFlags>(Flags, \
154*700637cbSDimitry Andric llvm::dxbc::RootFlags::NAME); \
155*700637cbSDimitry Andric break;
156*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
157*700637cbSDimitry Andric default:
158*700637cbSDimitry Andric llvm_unreachable("Switch for consumed enum token was not provided");
159*700637cbSDimitry Andric }
160*700637cbSDimitry Andric } else {
161*700637cbSDimitry Andric consumeNextToken(); // consume token to point at invalid token
162*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
163*700637cbSDimitry Andric << /*value=*/1 << /*value of*/ TokenKind::kw_RootFlags;
164*700637cbSDimitry Andric return std::nullopt;
165*700637cbSDimitry Andric }
166*700637cbSDimitry Andric } while (tryConsumeExpectedToken(TokenKind::pu_or));
167*700637cbSDimitry Andric }
168*700637cbSDimitry Andric
169*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
170*700637cbSDimitry Andric TokenKind::pu_comma))
171*700637cbSDimitry Andric return std::nullopt;
172*700637cbSDimitry Andric
173*700637cbSDimitry Andric return Flags;
174*700637cbSDimitry Andric }
175*700637cbSDimitry Andric
parseRootConstants()176*700637cbSDimitry Andric std::optional<RootConstants> RootSignatureParser::parseRootConstants() {
177*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::kw_RootConstants &&
178*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
179*700637cbSDimitry Andric
180*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
181*700637cbSDimitry Andric CurToken.TokKind))
182*700637cbSDimitry Andric return std::nullopt;
183*700637cbSDimitry Andric
184*700637cbSDimitry Andric RootConstants Constants;
185*700637cbSDimitry Andric
186*700637cbSDimitry Andric auto Params = parseRootConstantParams();
187*700637cbSDimitry Andric if (!Params.has_value())
188*700637cbSDimitry Andric return std::nullopt;
189*700637cbSDimitry Andric
190*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
191*700637cbSDimitry Andric TokenKind::pu_comma))
192*700637cbSDimitry Andric return std::nullopt;
193*700637cbSDimitry Andric
194*700637cbSDimitry Andric // Check mandatory parameters where provided
195*700637cbSDimitry Andric if (!Params->Num32BitConstants.has_value()) {
196*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_missing_param)
197*700637cbSDimitry Andric << TokenKind::kw_num32BitConstants;
198*700637cbSDimitry Andric return std::nullopt;
199*700637cbSDimitry Andric }
200*700637cbSDimitry Andric
201*700637cbSDimitry Andric Constants.Num32BitConstants = Params->Num32BitConstants.value();
202*700637cbSDimitry Andric
203*700637cbSDimitry Andric if (!Params->Reg.has_value()) {
204*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_missing_param) << TokenKind::bReg;
205*700637cbSDimitry Andric return std::nullopt;
206*700637cbSDimitry Andric }
207*700637cbSDimitry Andric
208*700637cbSDimitry Andric Constants.Reg = Params->Reg.value();
209*700637cbSDimitry Andric
210*700637cbSDimitry Andric // Fill in optional parameters
211*700637cbSDimitry Andric if (Params->Visibility.has_value())
212*700637cbSDimitry Andric Constants.Visibility = Params->Visibility.value();
213*700637cbSDimitry Andric
214*700637cbSDimitry Andric if (Params->Space.has_value())
215*700637cbSDimitry Andric Constants.Space = Params->Space.value();
216*700637cbSDimitry Andric
217*700637cbSDimitry Andric return Constants;
218*700637cbSDimitry Andric }
219*700637cbSDimitry Andric
parseRootDescriptor()220*700637cbSDimitry Andric std::optional<RootDescriptor> RootSignatureParser::parseRootDescriptor() {
221*700637cbSDimitry Andric assert((CurToken.TokKind == TokenKind::kw_CBV ||
222*700637cbSDimitry Andric CurToken.TokKind == TokenKind::kw_SRV ||
223*700637cbSDimitry Andric CurToken.TokKind == TokenKind::kw_UAV) &&
224*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
225*700637cbSDimitry Andric
226*700637cbSDimitry Andric TokenKind DescriptorKind = CurToken.TokKind;
227*700637cbSDimitry Andric
228*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
229*700637cbSDimitry Andric CurToken.TokKind))
230*700637cbSDimitry Andric return std::nullopt;
231*700637cbSDimitry Andric
232*700637cbSDimitry Andric RootDescriptor Descriptor;
233*700637cbSDimitry Andric TokenKind ExpectedReg;
234*700637cbSDimitry Andric switch (DescriptorKind) {
235*700637cbSDimitry Andric default:
236*700637cbSDimitry Andric llvm_unreachable("Switch for consumed token was not provided");
237*700637cbSDimitry Andric case TokenKind::kw_CBV:
238*700637cbSDimitry Andric Descriptor.Type = DescriptorType::CBuffer;
239*700637cbSDimitry Andric ExpectedReg = TokenKind::bReg;
240*700637cbSDimitry Andric break;
241*700637cbSDimitry Andric case TokenKind::kw_SRV:
242*700637cbSDimitry Andric Descriptor.Type = DescriptorType::SRV;
243*700637cbSDimitry Andric ExpectedReg = TokenKind::tReg;
244*700637cbSDimitry Andric break;
245*700637cbSDimitry Andric case TokenKind::kw_UAV:
246*700637cbSDimitry Andric Descriptor.Type = DescriptorType::UAV;
247*700637cbSDimitry Andric ExpectedReg = TokenKind::uReg;
248*700637cbSDimitry Andric break;
249*700637cbSDimitry Andric }
250*700637cbSDimitry Andric Descriptor.setDefaultFlags(Version);
251*700637cbSDimitry Andric
252*700637cbSDimitry Andric auto Params = parseRootDescriptorParams(DescriptorKind, ExpectedReg);
253*700637cbSDimitry Andric if (!Params.has_value())
254*700637cbSDimitry Andric return std::nullopt;
255*700637cbSDimitry Andric
256*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
257*700637cbSDimitry Andric TokenKind::pu_comma))
258*700637cbSDimitry Andric return std::nullopt;
259*700637cbSDimitry Andric
260*700637cbSDimitry Andric // Check mandatory parameters were provided
261*700637cbSDimitry Andric if (!Params->Reg.has_value()) {
262*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_missing_param) << ExpectedReg;
263*700637cbSDimitry Andric return std::nullopt;
264*700637cbSDimitry Andric }
265*700637cbSDimitry Andric
266*700637cbSDimitry Andric Descriptor.Reg = Params->Reg.value();
267*700637cbSDimitry Andric
268*700637cbSDimitry Andric // Fill in optional values
269*700637cbSDimitry Andric if (Params->Space.has_value())
270*700637cbSDimitry Andric Descriptor.Space = Params->Space.value();
271*700637cbSDimitry Andric
272*700637cbSDimitry Andric if (Params->Visibility.has_value())
273*700637cbSDimitry Andric Descriptor.Visibility = Params->Visibility.value();
274*700637cbSDimitry Andric
275*700637cbSDimitry Andric if (Params->Flags.has_value())
276*700637cbSDimitry Andric Descriptor.Flags = Params->Flags.value();
277*700637cbSDimitry Andric
278*700637cbSDimitry Andric return Descriptor;
279*700637cbSDimitry Andric }
280*700637cbSDimitry Andric
parseDescriptorTable()281*700637cbSDimitry Andric std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() {
282*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::kw_DescriptorTable &&
283*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
284*700637cbSDimitry Andric
285*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
286*700637cbSDimitry Andric CurToken.TokKind))
287*700637cbSDimitry Andric return std::nullopt;
288*700637cbSDimitry Andric
289*700637cbSDimitry Andric DescriptorTable Table;
290*700637cbSDimitry Andric std::optional<llvm::dxbc::ShaderVisibility> Visibility;
291*700637cbSDimitry Andric
292*700637cbSDimitry Andric // Iterate as many Clauses as possible, until we hit ')'
293*700637cbSDimitry Andric while (!peekExpectedToken(TokenKind::pu_r_paren)) {
294*700637cbSDimitry Andric if (tryConsumeExpectedToken({TokenKind::kw_CBV, TokenKind::kw_SRV,
295*700637cbSDimitry Andric TokenKind::kw_UAV, TokenKind::kw_Sampler})) {
296*700637cbSDimitry Andric // DescriptorTableClause - CBV, SRV, UAV, or Sampler
297*700637cbSDimitry Andric SourceLocation ElementLoc = getTokenLocation(CurToken);
298*700637cbSDimitry Andric auto Clause = parseDescriptorTableClause();
299*700637cbSDimitry Andric if (!Clause.has_value()) {
300*700637cbSDimitry Andric // We are within a DescriptorTableClause, we will do our best to recover
301*700637cbSDimitry Andric // by skipping until we encounter the expected closing ')'
302*700637cbSDimitry Andric skipUntilExpectedToken(TokenKind::pu_r_paren);
303*700637cbSDimitry Andric consumeNextToken();
304*700637cbSDimitry Andric return std::nullopt;
305*700637cbSDimitry Andric }
306*700637cbSDimitry Andric Elements.emplace_back(ElementLoc, *Clause);
307*700637cbSDimitry Andric Table.NumClauses++;
308*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
309*700637cbSDimitry Andric // visibility = SHADER_VISIBILITY
310*700637cbSDimitry Andric if (Visibility.has_value()) {
311*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
312*700637cbSDimitry Andric return std::nullopt;
313*700637cbSDimitry Andric }
314*700637cbSDimitry Andric
315*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
316*700637cbSDimitry Andric return std::nullopt;
317*700637cbSDimitry Andric
318*700637cbSDimitry Andric Visibility = parseShaderVisibility(TokenKind::kw_visibility);
319*700637cbSDimitry Andric if (!Visibility.has_value())
320*700637cbSDimitry Andric return std::nullopt;
321*700637cbSDimitry Andric } else {
322*700637cbSDimitry Andric consumeNextToken(); // let diagnostic be at the start of invalid token
323*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
324*700637cbSDimitry Andric << /*parameter=*/0 << /*param of*/ TokenKind::kw_DescriptorTable;
325*700637cbSDimitry Andric return std::nullopt;
326*700637cbSDimitry Andric }
327*700637cbSDimitry Andric
328*700637cbSDimitry Andric // ',' denotes another element, otherwise, expected to be at ')'
329*700637cbSDimitry Andric if (!tryConsumeExpectedToken(TokenKind::pu_comma))
330*700637cbSDimitry Andric break;
331*700637cbSDimitry Andric }
332*700637cbSDimitry Andric
333*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
334*700637cbSDimitry Andric TokenKind::pu_comma))
335*700637cbSDimitry Andric return std::nullopt;
336*700637cbSDimitry Andric
337*700637cbSDimitry Andric // Fill in optional visibility
338*700637cbSDimitry Andric if (Visibility.has_value())
339*700637cbSDimitry Andric Table.Visibility = Visibility.value();
340*700637cbSDimitry Andric
341*700637cbSDimitry Andric return Table;
342*700637cbSDimitry Andric }
343*700637cbSDimitry Andric
344*700637cbSDimitry Andric std::optional<DescriptorTableClause>
parseDescriptorTableClause()345*700637cbSDimitry Andric RootSignatureParser::parseDescriptorTableClause() {
346*700637cbSDimitry Andric assert((CurToken.TokKind == TokenKind::kw_CBV ||
347*700637cbSDimitry Andric CurToken.TokKind == TokenKind::kw_SRV ||
348*700637cbSDimitry Andric CurToken.TokKind == TokenKind::kw_UAV ||
349*700637cbSDimitry Andric CurToken.TokKind == TokenKind::kw_Sampler) &&
350*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
351*700637cbSDimitry Andric
352*700637cbSDimitry Andric TokenKind ParamKind = CurToken.TokKind;
353*700637cbSDimitry Andric
354*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
355*700637cbSDimitry Andric CurToken.TokKind))
356*700637cbSDimitry Andric return std::nullopt;
357*700637cbSDimitry Andric
358*700637cbSDimitry Andric DescriptorTableClause Clause;
359*700637cbSDimitry Andric TokenKind ExpectedReg;
360*700637cbSDimitry Andric switch (ParamKind) {
361*700637cbSDimitry Andric default:
362*700637cbSDimitry Andric llvm_unreachable("Switch for consumed token was not provided");
363*700637cbSDimitry Andric case TokenKind::kw_CBV:
364*700637cbSDimitry Andric Clause.Type = ClauseType::CBuffer;
365*700637cbSDimitry Andric ExpectedReg = TokenKind::bReg;
366*700637cbSDimitry Andric break;
367*700637cbSDimitry Andric case TokenKind::kw_SRV:
368*700637cbSDimitry Andric Clause.Type = ClauseType::SRV;
369*700637cbSDimitry Andric ExpectedReg = TokenKind::tReg;
370*700637cbSDimitry Andric break;
371*700637cbSDimitry Andric case TokenKind::kw_UAV:
372*700637cbSDimitry Andric Clause.Type = ClauseType::UAV;
373*700637cbSDimitry Andric ExpectedReg = TokenKind::uReg;
374*700637cbSDimitry Andric break;
375*700637cbSDimitry Andric case TokenKind::kw_Sampler:
376*700637cbSDimitry Andric Clause.Type = ClauseType::Sampler;
377*700637cbSDimitry Andric ExpectedReg = TokenKind::sReg;
378*700637cbSDimitry Andric break;
379*700637cbSDimitry Andric }
380*700637cbSDimitry Andric Clause.setDefaultFlags(Version);
381*700637cbSDimitry Andric
382*700637cbSDimitry Andric auto Params = parseDescriptorTableClauseParams(ParamKind, ExpectedReg);
383*700637cbSDimitry Andric if (!Params.has_value())
384*700637cbSDimitry Andric return std::nullopt;
385*700637cbSDimitry Andric
386*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
387*700637cbSDimitry Andric TokenKind::pu_comma))
388*700637cbSDimitry Andric return std::nullopt;
389*700637cbSDimitry Andric
390*700637cbSDimitry Andric // Check mandatory parameters were provided
391*700637cbSDimitry Andric if (!Params->Reg.has_value()) {
392*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_missing_param) << ExpectedReg;
393*700637cbSDimitry Andric return std::nullopt;
394*700637cbSDimitry Andric }
395*700637cbSDimitry Andric
396*700637cbSDimitry Andric Clause.Reg = Params->Reg.value();
397*700637cbSDimitry Andric
398*700637cbSDimitry Andric // Fill in optional values
399*700637cbSDimitry Andric if (Params->NumDescriptors.has_value())
400*700637cbSDimitry Andric Clause.NumDescriptors = Params->NumDescriptors.value();
401*700637cbSDimitry Andric
402*700637cbSDimitry Andric if (Params->Space.has_value())
403*700637cbSDimitry Andric Clause.Space = Params->Space.value();
404*700637cbSDimitry Andric
405*700637cbSDimitry Andric if (Params->Offset.has_value())
406*700637cbSDimitry Andric Clause.Offset = Params->Offset.value();
407*700637cbSDimitry Andric
408*700637cbSDimitry Andric if (Params->Flags.has_value())
409*700637cbSDimitry Andric Clause.Flags = Params->Flags.value();
410*700637cbSDimitry Andric
411*700637cbSDimitry Andric return Clause;
412*700637cbSDimitry Andric }
413*700637cbSDimitry Andric
parseStaticSampler()414*700637cbSDimitry Andric std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() {
415*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::kw_StaticSampler &&
416*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
417*700637cbSDimitry Andric
418*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
419*700637cbSDimitry Andric CurToken.TokKind))
420*700637cbSDimitry Andric return std::nullopt;
421*700637cbSDimitry Andric
422*700637cbSDimitry Andric StaticSampler Sampler;
423*700637cbSDimitry Andric
424*700637cbSDimitry Andric auto Params = parseStaticSamplerParams();
425*700637cbSDimitry Andric if (!Params.has_value())
426*700637cbSDimitry Andric return std::nullopt;
427*700637cbSDimitry Andric
428*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
429*700637cbSDimitry Andric TokenKind::pu_comma))
430*700637cbSDimitry Andric return std::nullopt;
431*700637cbSDimitry Andric
432*700637cbSDimitry Andric // Check mandatory parameters were provided
433*700637cbSDimitry Andric if (!Params->Reg.has_value()) {
434*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_missing_param) << TokenKind::sReg;
435*700637cbSDimitry Andric return std::nullopt;
436*700637cbSDimitry Andric }
437*700637cbSDimitry Andric
438*700637cbSDimitry Andric Sampler.Reg = Params->Reg.value();
439*700637cbSDimitry Andric
440*700637cbSDimitry Andric // Fill in optional values
441*700637cbSDimitry Andric if (Params->Filter.has_value())
442*700637cbSDimitry Andric Sampler.Filter = Params->Filter.value();
443*700637cbSDimitry Andric
444*700637cbSDimitry Andric if (Params->AddressU.has_value())
445*700637cbSDimitry Andric Sampler.AddressU = Params->AddressU.value();
446*700637cbSDimitry Andric
447*700637cbSDimitry Andric if (Params->AddressV.has_value())
448*700637cbSDimitry Andric Sampler.AddressV = Params->AddressV.value();
449*700637cbSDimitry Andric
450*700637cbSDimitry Andric if (Params->AddressW.has_value())
451*700637cbSDimitry Andric Sampler.AddressW = Params->AddressW.value();
452*700637cbSDimitry Andric
453*700637cbSDimitry Andric if (Params->MipLODBias.has_value())
454*700637cbSDimitry Andric Sampler.MipLODBias = Params->MipLODBias.value();
455*700637cbSDimitry Andric
456*700637cbSDimitry Andric if (Params->MaxAnisotropy.has_value())
457*700637cbSDimitry Andric Sampler.MaxAnisotropy = Params->MaxAnisotropy.value();
458*700637cbSDimitry Andric
459*700637cbSDimitry Andric if (Params->CompFunc.has_value())
460*700637cbSDimitry Andric Sampler.CompFunc = Params->CompFunc.value();
461*700637cbSDimitry Andric
462*700637cbSDimitry Andric if (Params->BorderColor.has_value())
463*700637cbSDimitry Andric Sampler.BorderColor = Params->BorderColor.value();
464*700637cbSDimitry Andric
465*700637cbSDimitry Andric if (Params->MinLOD.has_value())
466*700637cbSDimitry Andric Sampler.MinLOD = Params->MinLOD.value();
467*700637cbSDimitry Andric
468*700637cbSDimitry Andric if (Params->MaxLOD.has_value())
469*700637cbSDimitry Andric Sampler.MaxLOD = Params->MaxLOD.value();
470*700637cbSDimitry Andric
471*700637cbSDimitry Andric if (Params->Space.has_value())
472*700637cbSDimitry Andric Sampler.Space = Params->Space.value();
473*700637cbSDimitry Andric
474*700637cbSDimitry Andric if (Params->Visibility.has_value())
475*700637cbSDimitry Andric Sampler.Visibility = Params->Visibility.value();
476*700637cbSDimitry Andric
477*700637cbSDimitry Andric return Sampler;
478*700637cbSDimitry Andric }
479*700637cbSDimitry Andric
480*700637cbSDimitry Andric // Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any
481*700637cbSDimitry Andric // order and only exactly once. The following methods will parse through as
482*700637cbSDimitry Andric // many arguments as possible reporting an error if a duplicate is seen.
483*700637cbSDimitry Andric std::optional<RootSignatureParser::ParsedConstantParams>
parseRootConstantParams()484*700637cbSDimitry Andric RootSignatureParser::parseRootConstantParams() {
485*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_l_paren &&
486*700637cbSDimitry Andric "Expects to only be invoked starting at given token");
487*700637cbSDimitry Andric
488*700637cbSDimitry Andric ParsedConstantParams Params;
489*700637cbSDimitry Andric while (!peekExpectedToken(TokenKind::pu_r_paren)) {
490*700637cbSDimitry Andric if (tryConsumeExpectedToken(TokenKind::kw_num32BitConstants)) {
491*700637cbSDimitry Andric // `num32BitConstants` `=` POS_INT
492*700637cbSDimitry Andric if (Params.Num32BitConstants.has_value()) {
493*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
494*700637cbSDimitry Andric return std::nullopt;
495*700637cbSDimitry Andric }
496*700637cbSDimitry Andric
497*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
498*700637cbSDimitry Andric return std::nullopt;
499*700637cbSDimitry Andric
500*700637cbSDimitry Andric auto Num32BitConstants = parseUIntParam();
501*700637cbSDimitry Andric if (!Num32BitConstants.has_value())
502*700637cbSDimitry Andric return std::nullopt;
503*700637cbSDimitry Andric Params.Num32BitConstants = Num32BitConstants;
504*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::bReg)) {
505*700637cbSDimitry Andric // `b` POS_INT
506*700637cbSDimitry Andric if (Params.Reg.has_value()) {
507*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
508*700637cbSDimitry Andric return std::nullopt;
509*700637cbSDimitry Andric }
510*700637cbSDimitry Andric auto Reg = parseRegister();
511*700637cbSDimitry Andric if (!Reg.has_value())
512*700637cbSDimitry Andric return std::nullopt;
513*700637cbSDimitry Andric Params.Reg = Reg;
514*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
515*700637cbSDimitry Andric // `space` `=` POS_INT
516*700637cbSDimitry Andric if (Params.Space.has_value()) {
517*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
518*700637cbSDimitry Andric return std::nullopt;
519*700637cbSDimitry Andric }
520*700637cbSDimitry Andric
521*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
522*700637cbSDimitry Andric return std::nullopt;
523*700637cbSDimitry Andric
524*700637cbSDimitry Andric auto Space = parseUIntParam();
525*700637cbSDimitry Andric if (!Space.has_value())
526*700637cbSDimitry Andric return std::nullopt;
527*700637cbSDimitry Andric Params.Space = Space;
528*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
529*700637cbSDimitry Andric // `visibility` `=` SHADER_VISIBILITY
530*700637cbSDimitry Andric if (Params.Visibility.has_value()) {
531*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
532*700637cbSDimitry Andric return std::nullopt;
533*700637cbSDimitry Andric }
534*700637cbSDimitry Andric
535*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
536*700637cbSDimitry Andric return std::nullopt;
537*700637cbSDimitry Andric
538*700637cbSDimitry Andric auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
539*700637cbSDimitry Andric if (!Visibility.has_value())
540*700637cbSDimitry Andric return std::nullopt;
541*700637cbSDimitry Andric Params.Visibility = Visibility;
542*700637cbSDimitry Andric } else {
543*700637cbSDimitry Andric consumeNextToken(); // let diagnostic be at the start of invalid token
544*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
545*700637cbSDimitry Andric << /*parameter=*/0 << /*param of*/ TokenKind::kw_RootConstants;
546*700637cbSDimitry Andric return std::nullopt;
547*700637cbSDimitry Andric }
548*700637cbSDimitry Andric
549*700637cbSDimitry Andric // ',' denotes another element, otherwise, expected to be at ')'
550*700637cbSDimitry Andric if (!tryConsumeExpectedToken(TokenKind::pu_comma))
551*700637cbSDimitry Andric break;
552*700637cbSDimitry Andric }
553*700637cbSDimitry Andric
554*700637cbSDimitry Andric return Params;
555*700637cbSDimitry Andric }
556*700637cbSDimitry Andric
557*700637cbSDimitry Andric std::optional<RootSignatureParser::ParsedRootDescriptorParams>
parseRootDescriptorParams(TokenKind DescKind,TokenKind RegType)558*700637cbSDimitry Andric RootSignatureParser::parseRootDescriptorParams(TokenKind DescKind,
559*700637cbSDimitry Andric TokenKind RegType) {
560*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_l_paren &&
561*700637cbSDimitry Andric "Expects to only be invoked starting at given token");
562*700637cbSDimitry Andric
563*700637cbSDimitry Andric ParsedRootDescriptorParams Params;
564*700637cbSDimitry Andric while (!peekExpectedToken(TokenKind::pu_r_paren)) {
565*700637cbSDimitry Andric if (tryConsumeExpectedToken(RegType)) {
566*700637cbSDimitry Andric // ( `b` | `t` | `u`) POS_INT
567*700637cbSDimitry Andric if (Params.Reg.has_value()) {
568*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
569*700637cbSDimitry Andric return std::nullopt;
570*700637cbSDimitry Andric }
571*700637cbSDimitry Andric auto Reg = parseRegister();
572*700637cbSDimitry Andric if (!Reg.has_value())
573*700637cbSDimitry Andric return std::nullopt;
574*700637cbSDimitry Andric Params.Reg = Reg;
575*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
576*700637cbSDimitry Andric // `space` `=` POS_INT
577*700637cbSDimitry Andric if (Params.Space.has_value()) {
578*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
579*700637cbSDimitry Andric return std::nullopt;
580*700637cbSDimitry Andric }
581*700637cbSDimitry Andric
582*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
583*700637cbSDimitry Andric return std::nullopt;
584*700637cbSDimitry Andric
585*700637cbSDimitry Andric auto Space = parseUIntParam();
586*700637cbSDimitry Andric if (!Space.has_value())
587*700637cbSDimitry Andric return std::nullopt;
588*700637cbSDimitry Andric Params.Space = Space;
589*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
590*700637cbSDimitry Andric // `visibility` `=` SHADER_VISIBILITY
591*700637cbSDimitry Andric if (Params.Visibility.has_value()) {
592*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
593*700637cbSDimitry Andric return std::nullopt;
594*700637cbSDimitry Andric }
595*700637cbSDimitry Andric
596*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
597*700637cbSDimitry Andric return std::nullopt;
598*700637cbSDimitry Andric
599*700637cbSDimitry Andric auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
600*700637cbSDimitry Andric if (!Visibility.has_value())
601*700637cbSDimitry Andric return std::nullopt;
602*700637cbSDimitry Andric Params.Visibility = Visibility;
603*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
604*700637cbSDimitry Andric // `flags` `=` ROOT_DESCRIPTOR_FLAGS
605*700637cbSDimitry Andric if (Params.Flags.has_value()) {
606*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
607*700637cbSDimitry Andric return std::nullopt;
608*700637cbSDimitry Andric }
609*700637cbSDimitry Andric
610*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
611*700637cbSDimitry Andric return std::nullopt;
612*700637cbSDimitry Andric
613*700637cbSDimitry Andric auto Flags = parseRootDescriptorFlags(TokenKind::kw_flags);
614*700637cbSDimitry Andric if (!Flags.has_value())
615*700637cbSDimitry Andric return std::nullopt;
616*700637cbSDimitry Andric Params.Flags = Flags;
617*700637cbSDimitry Andric } else {
618*700637cbSDimitry Andric consumeNextToken(); // let diagnostic be at the start of invalid token
619*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
620*700637cbSDimitry Andric << /*parameter=*/0 << /*param of*/ DescKind;
621*700637cbSDimitry Andric return std::nullopt;
622*700637cbSDimitry Andric }
623*700637cbSDimitry Andric
624*700637cbSDimitry Andric // ',' denotes another element, otherwise, expected to be at ')'
625*700637cbSDimitry Andric if (!tryConsumeExpectedToken(TokenKind::pu_comma))
626*700637cbSDimitry Andric break;
627*700637cbSDimitry Andric }
628*700637cbSDimitry Andric
629*700637cbSDimitry Andric return Params;
630*700637cbSDimitry Andric }
631*700637cbSDimitry Andric
632*700637cbSDimitry Andric std::optional<RootSignatureParser::ParsedClauseParams>
parseDescriptorTableClauseParams(TokenKind ClauseKind,TokenKind RegType)633*700637cbSDimitry Andric RootSignatureParser::parseDescriptorTableClauseParams(TokenKind ClauseKind,
634*700637cbSDimitry Andric TokenKind RegType) {
635*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_l_paren &&
636*700637cbSDimitry Andric "Expects to only be invoked starting at given token");
637*700637cbSDimitry Andric
638*700637cbSDimitry Andric ParsedClauseParams Params;
639*700637cbSDimitry Andric while (!peekExpectedToken(TokenKind::pu_r_paren)) {
640*700637cbSDimitry Andric if (tryConsumeExpectedToken(RegType)) {
641*700637cbSDimitry Andric // ( `b` | `t` | `u` | `s`) POS_INT
642*700637cbSDimitry Andric if (Params.Reg.has_value()) {
643*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
644*700637cbSDimitry Andric return std::nullopt;
645*700637cbSDimitry Andric }
646*700637cbSDimitry Andric auto Reg = parseRegister();
647*700637cbSDimitry Andric if (!Reg.has_value())
648*700637cbSDimitry Andric return std::nullopt;
649*700637cbSDimitry Andric Params.Reg = Reg;
650*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_numDescriptors)) {
651*700637cbSDimitry Andric // `numDescriptors` `=` POS_INT | unbounded
652*700637cbSDimitry Andric if (Params.NumDescriptors.has_value()) {
653*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
654*700637cbSDimitry Andric return std::nullopt;
655*700637cbSDimitry Andric }
656*700637cbSDimitry Andric
657*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
658*700637cbSDimitry Andric return std::nullopt;
659*700637cbSDimitry Andric
660*700637cbSDimitry Andric std::optional<uint32_t> NumDescriptors;
661*700637cbSDimitry Andric if (tryConsumeExpectedToken(TokenKind::en_unbounded))
662*700637cbSDimitry Andric NumDescriptors = NumDescriptorsUnbounded;
663*700637cbSDimitry Andric else {
664*700637cbSDimitry Andric NumDescriptors = parseUIntParam();
665*700637cbSDimitry Andric if (!NumDescriptors.has_value())
666*700637cbSDimitry Andric return std::nullopt;
667*700637cbSDimitry Andric }
668*700637cbSDimitry Andric
669*700637cbSDimitry Andric Params.NumDescriptors = NumDescriptors;
670*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
671*700637cbSDimitry Andric // `space` `=` POS_INT
672*700637cbSDimitry Andric if (Params.Space.has_value()) {
673*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
674*700637cbSDimitry Andric return std::nullopt;
675*700637cbSDimitry Andric }
676*700637cbSDimitry Andric
677*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
678*700637cbSDimitry Andric return std::nullopt;
679*700637cbSDimitry Andric
680*700637cbSDimitry Andric auto Space = parseUIntParam();
681*700637cbSDimitry Andric if (!Space.has_value())
682*700637cbSDimitry Andric return std::nullopt;
683*700637cbSDimitry Andric Params.Space = Space;
684*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_offset)) {
685*700637cbSDimitry Andric // `offset` `=` POS_INT | DESCRIPTOR_RANGE_OFFSET_APPEND
686*700637cbSDimitry Andric if (Params.Offset.has_value()) {
687*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
688*700637cbSDimitry Andric return std::nullopt;
689*700637cbSDimitry Andric }
690*700637cbSDimitry Andric
691*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
692*700637cbSDimitry Andric return std::nullopt;
693*700637cbSDimitry Andric
694*700637cbSDimitry Andric std::optional<uint32_t> Offset;
695*700637cbSDimitry Andric if (tryConsumeExpectedToken(TokenKind::en_DescriptorRangeOffsetAppend))
696*700637cbSDimitry Andric Offset = DescriptorTableOffsetAppend;
697*700637cbSDimitry Andric else {
698*700637cbSDimitry Andric Offset = parseUIntParam();
699*700637cbSDimitry Andric if (!Offset.has_value())
700*700637cbSDimitry Andric return std::nullopt;
701*700637cbSDimitry Andric }
702*700637cbSDimitry Andric
703*700637cbSDimitry Andric Params.Offset = Offset;
704*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
705*700637cbSDimitry Andric // `flags` `=` DESCRIPTOR_RANGE_FLAGS
706*700637cbSDimitry Andric if (Params.Flags.has_value()) {
707*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
708*700637cbSDimitry Andric return std::nullopt;
709*700637cbSDimitry Andric }
710*700637cbSDimitry Andric
711*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
712*700637cbSDimitry Andric return std::nullopt;
713*700637cbSDimitry Andric
714*700637cbSDimitry Andric auto Flags = parseDescriptorRangeFlags(TokenKind::kw_flags);
715*700637cbSDimitry Andric if (!Flags.has_value())
716*700637cbSDimitry Andric return std::nullopt;
717*700637cbSDimitry Andric Params.Flags = Flags;
718*700637cbSDimitry Andric } else {
719*700637cbSDimitry Andric consumeNextToken(); // let diagnostic be at the start of invalid token
720*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
721*700637cbSDimitry Andric << /*parameter=*/0 << /*param of*/ ClauseKind;
722*700637cbSDimitry Andric return std::nullopt;
723*700637cbSDimitry Andric }
724*700637cbSDimitry Andric
725*700637cbSDimitry Andric // ',' denotes another element, otherwise, expected to be at ')'
726*700637cbSDimitry Andric if (!tryConsumeExpectedToken(TokenKind::pu_comma))
727*700637cbSDimitry Andric break;
728*700637cbSDimitry Andric }
729*700637cbSDimitry Andric
730*700637cbSDimitry Andric return Params;
731*700637cbSDimitry Andric }
732*700637cbSDimitry Andric
733*700637cbSDimitry Andric std::optional<RootSignatureParser::ParsedStaticSamplerParams>
parseStaticSamplerParams()734*700637cbSDimitry Andric RootSignatureParser::parseStaticSamplerParams() {
735*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_l_paren &&
736*700637cbSDimitry Andric "Expects to only be invoked starting at given token");
737*700637cbSDimitry Andric
738*700637cbSDimitry Andric ParsedStaticSamplerParams Params;
739*700637cbSDimitry Andric while (!peekExpectedToken(TokenKind::pu_r_paren)) {
740*700637cbSDimitry Andric if (tryConsumeExpectedToken(TokenKind::sReg)) {
741*700637cbSDimitry Andric // `s` POS_INT
742*700637cbSDimitry Andric if (Params.Reg.has_value()) {
743*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
744*700637cbSDimitry Andric return std::nullopt;
745*700637cbSDimitry Andric }
746*700637cbSDimitry Andric auto Reg = parseRegister();
747*700637cbSDimitry Andric if (!Reg.has_value())
748*700637cbSDimitry Andric return std::nullopt;
749*700637cbSDimitry Andric Params.Reg = Reg;
750*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_filter)) {
751*700637cbSDimitry Andric // `filter` `=` FILTER
752*700637cbSDimitry Andric if (Params.Filter.has_value()) {
753*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
754*700637cbSDimitry Andric return std::nullopt;
755*700637cbSDimitry Andric }
756*700637cbSDimitry Andric
757*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
758*700637cbSDimitry Andric return std::nullopt;
759*700637cbSDimitry Andric
760*700637cbSDimitry Andric auto Filter = parseSamplerFilter(TokenKind::kw_filter);
761*700637cbSDimitry Andric if (!Filter.has_value())
762*700637cbSDimitry Andric return std::nullopt;
763*700637cbSDimitry Andric Params.Filter = Filter;
764*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_addressU)) {
765*700637cbSDimitry Andric // `addressU` `=` TEXTURE_ADDRESS
766*700637cbSDimitry Andric if (Params.AddressU.has_value()) {
767*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
768*700637cbSDimitry Andric return std::nullopt;
769*700637cbSDimitry Andric }
770*700637cbSDimitry Andric
771*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
772*700637cbSDimitry Andric return std::nullopt;
773*700637cbSDimitry Andric
774*700637cbSDimitry Andric auto AddressU = parseTextureAddressMode(TokenKind::kw_addressU);
775*700637cbSDimitry Andric if (!AddressU.has_value())
776*700637cbSDimitry Andric return std::nullopt;
777*700637cbSDimitry Andric Params.AddressU = AddressU;
778*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_addressV)) {
779*700637cbSDimitry Andric // `addressV` `=` TEXTURE_ADDRESS
780*700637cbSDimitry Andric if (Params.AddressV.has_value()) {
781*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
782*700637cbSDimitry Andric return std::nullopt;
783*700637cbSDimitry Andric }
784*700637cbSDimitry Andric
785*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
786*700637cbSDimitry Andric return std::nullopt;
787*700637cbSDimitry Andric
788*700637cbSDimitry Andric auto AddressV = parseTextureAddressMode(TokenKind::kw_addressV);
789*700637cbSDimitry Andric if (!AddressV.has_value())
790*700637cbSDimitry Andric return std::nullopt;
791*700637cbSDimitry Andric Params.AddressV = AddressV;
792*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_addressW)) {
793*700637cbSDimitry Andric // `addressW` `=` TEXTURE_ADDRESS
794*700637cbSDimitry Andric if (Params.AddressW.has_value()) {
795*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
796*700637cbSDimitry Andric return std::nullopt;
797*700637cbSDimitry Andric }
798*700637cbSDimitry Andric
799*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
800*700637cbSDimitry Andric return std::nullopt;
801*700637cbSDimitry Andric
802*700637cbSDimitry Andric auto AddressW = parseTextureAddressMode(TokenKind::kw_addressW);
803*700637cbSDimitry Andric if (!AddressW.has_value())
804*700637cbSDimitry Andric return std::nullopt;
805*700637cbSDimitry Andric Params.AddressW = AddressW;
806*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_mipLODBias)) {
807*700637cbSDimitry Andric // `mipLODBias` `=` NUMBER
808*700637cbSDimitry Andric if (Params.MipLODBias.has_value()) {
809*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
810*700637cbSDimitry Andric return std::nullopt;
811*700637cbSDimitry Andric }
812*700637cbSDimitry Andric
813*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
814*700637cbSDimitry Andric return std::nullopt;
815*700637cbSDimitry Andric
816*700637cbSDimitry Andric auto MipLODBias = parseFloatParam();
817*700637cbSDimitry Andric if (!MipLODBias.has_value())
818*700637cbSDimitry Andric return std::nullopt;
819*700637cbSDimitry Andric Params.MipLODBias = MipLODBias;
820*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_maxAnisotropy)) {
821*700637cbSDimitry Andric // `maxAnisotropy` `=` POS_INT
822*700637cbSDimitry Andric if (Params.MaxAnisotropy.has_value()) {
823*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
824*700637cbSDimitry Andric return std::nullopt;
825*700637cbSDimitry Andric }
826*700637cbSDimitry Andric
827*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
828*700637cbSDimitry Andric return std::nullopt;
829*700637cbSDimitry Andric
830*700637cbSDimitry Andric auto MaxAnisotropy = parseUIntParam();
831*700637cbSDimitry Andric if (!MaxAnisotropy.has_value())
832*700637cbSDimitry Andric return std::nullopt;
833*700637cbSDimitry Andric Params.MaxAnisotropy = MaxAnisotropy;
834*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_comparisonFunc)) {
835*700637cbSDimitry Andric // `comparisonFunc` `=` COMPARISON_FUNC
836*700637cbSDimitry Andric if (Params.CompFunc.has_value()) {
837*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
838*700637cbSDimitry Andric return std::nullopt;
839*700637cbSDimitry Andric }
840*700637cbSDimitry Andric
841*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
842*700637cbSDimitry Andric return std::nullopt;
843*700637cbSDimitry Andric
844*700637cbSDimitry Andric auto CompFunc = parseComparisonFunc(TokenKind::kw_comparisonFunc);
845*700637cbSDimitry Andric if (!CompFunc.has_value())
846*700637cbSDimitry Andric return std::nullopt;
847*700637cbSDimitry Andric Params.CompFunc = CompFunc;
848*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_borderColor)) {
849*700637cbSDimitry Andric // `borderColor` `=` STATIC_BORDER_COLOR
850*700637cbSDimitry Andric if (Params.BorderColor.has_value()) {
851*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
852*700637cbSDimitry Andric return std::nullopt;
853*700637cbSDimitry Andric }
854*700637cbSDimitry Andric
855*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
856*700637cbSDimitry Andric return std::nullopt;
857*700637cbSDimitry Andric
858*700637cbSDimitry Andric auto BorderColor = parseStaticBorderColor(TokenKind::kw_borderColor);
859*700637cbSDimitry Andric if (!BorderColor.has_value())
860*700637cbSDimitry Andric return std::nullopt;
861*700637cbSDimitry Andric Params.BorderColor = BorderColor;
862*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_minLOD)) {
863*700637cbSDimitry Andric // `minLOD` `=` NUMBER
864*700637cbSDimitry Andric if (Params.MinLOD.has_value()) {
865*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
866*700637cbSDimitry Andric return std::nullopt;
867*700637cbSDimitry Andric }
868*700637cbSDimitry Andric
869*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
870*700637cbSDimitry Andric return std::nullopt;
871*700637cbSDimitry Andric
872*700637cbSDimitry Andric auto MinLOD = parseFloatParam();
873*700637cbSDimitry Andric if (!MinLOD.has_value())
874*700637cbSDimitry Andric return std::nullopt;
875*700637cbSDimitry Andric Params.MinLOD = MinLOD;
876*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_maxLOD)) {
877*700637cbSDimitry Andric // `maxLOD` `=` NUMBER
878*700637cbSDimitry Andric if (Params.MaxLOD.has_value()) {
879*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
880*700637cbSDimitry Andric return std::nullopt;
881*700637cbSDimitry Andric }
882*700637cbSDimitry Andric
883*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
884*700637cbSDimitry Andric return std::nullopt;
885*700637cbSDimitry Andric
886*700637cbSDimitry Andric auto MaxLOD = parseFloatParam();
887*700637cbSDimitry Andric if (!MaxLOD.has_value())
888*700637cbSDimitry Andric return std::nullopt;
889*700637cbSDimitry Andric Params.MaxLOD = MaxLOD;
890*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
891*700637cbSDimitry Andric // `space` `=` POS_INT
892*700637cbSDimitry Andric if (Params.Space.has_value()) {
893*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
894*700637cbSDimitry Andric return std::nullopt;
895*700637cbSDimitry Andric }
896*700637cbSDimitry Andric
897*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
898*700637cbSDimitry Andric return std::nullopt;
899*700637cbSDimitry Andric
900*700637cbSDimitry Andric auto Space = parseUIntParam();
901*700637cbSDimitry Andric if (!Space.has_value())
902*700637cbSDimitry Andric return std::nullopt;
903*700637cbSDimitry Andric Params.Space = Space;
904*700637cbSDimitry Andric } else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
905*700637cbSDimitry Andric // `visibility` `=` SHADER_VISIBILITY
906*700637cbSDimitry Andric if (Params.Visibility.has_value()) {
907*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
908*700637cbSDimitry Andric return std::nullopt;
909*700637cbSDimitry Andric }
910*700637cbSDimitry Andric
911*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::pu_equal))
912*700637cbSDimitry Andric return std::nullopt;
913*700637cbSDimitry Andric
914*700637cbSDimitry Andric auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
915*700637cbSDimitry Andric if (!Visibility.has_value())
916*700637cbSDimitry Andric return std::nullopt;
917*700637cbSDimitry Andric Params.Visibility = Visibility;
918*700637cbSDimitry Andric } else {
919*700637cbSDimitry Andric consumeNextToken(); // let diagnostic be at the start of invalid token
920*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
921*700637cbSDimitry Andric << /*parameter=*/0 << /*param of*/ TokenKind::kw_StaticSampler;
922*700637cbSDimitry Andric return std::nullopt;
923*700637cbSDimitry Andric }
924*700637cbSDimitry Andric
925*700637cbSDimitry Andric // ',' denotes another element, otherwise, expected to be at ')'
926*700637cbSDimitry Andric if (!tryConsumeExpectedToken(TokenKind::pu_comma))
927*700637cbSDimitry Andric break;
928*700637cbSDimitry Andric }
929*700637cbSDimitry Andric
930*700637cbSDimitry Andric return Params;
931*700637cbSDimitry Andric }
932*700637cbSDimitry Andric
parseUIntParam()933*700637cbSDimitry Andric std::optional<uint32_t> RootSignatureParser::parseUIntParam() {
934*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_equal &&
935*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
936*700637cbSDimitry Andric tryConsumeExpectedToken(TokenKind::pu_plus);
937*700637cbSDimitry Andric if (consumeExpectedToken(TokenKind::int_literal, diag::err_expected_after,
938*700637cbSDimitry Andric CurToken.TokKind))
939*700637cbSDimitry Andric return std::nullopt;
940*700637cbSDimitry Andric return handleUIntLiteral();
941*700637cbSDimitry Andric }
942*700637cbSDimitry Andric
parseRegister()943*700637cbSDimitry Andric std::optional<Register> RootSignatureParser::parseRegister() {
944*700637cbSDimitry Andric assert((CurToken.TokKind == TokenKind::bReg ||
945*700637cbSDimitry Andric CurToken.TokKind == TokenKind::tReg ||
946*700637cbSDimitry Andric CurToken.TokKind == TokenKind::uReg ||
947*700637cbSDimitry Andric CurToken.TokKind == TokenKind::sReg) &&
948*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
949*700637cbSDimitry Andric
950*700637cbSDimitry Andric Register Reg;
951*700637cbSDimitry Andric switch (CurToken.TokKind) {
952*700637cbSDimitry Andric default:
953*700637cbSDimitry Andric llvm_unreachable("Switch for consumed token was not provided");
954*700637cbSDimitry Andric case TokenKind::bReg:
955*700637cbSDimitry Andric Reg.ViewType = RegisterType::BReg;
956*700637cbSDimitry Andric break;
957*700637cbSDimitry Andric case TokenKind::tReg:
958*700637cbSDimitry Andric Reg.ViewType = RegisterType::TReg;
959*700637cbSDimitry Andric break;
960*700637cbSDimitry Andric case TokenKind::uReg:
961*700637cbSDimitry Andric Reg.ViewType = RegisterType::UReg;
962*700637cbSDimitry Andric break;
963*700637cbSDimitry Andric case TokenKind::sReg:
964*700637cbSDimitry Andric Reg.ViewType = RegisterType::SReg;
965*700637cbSDimitry Andric break;
966*700637cbSDimitry Andric }
967*700637cbSDimitry Andric
968*700637cbSDimitry Andric auto Number = handleUIntLiteral();
969*700637cbSDimitry Andric if (!Number.has_value())
970*700637cbSDimitry Andric return std::nullopt; // propogate NumericLiteralParser error
971*700637cbSDimitry Andric
972*700637cbSDimitry Andric Reg.Number = *Number;
973*700637cbSDimitry Andric return Reg;
974*700637cbSDimitry Andric }
975*700637cbSDimitry Andric
parseFloatParam()976*700637cbSDimitry Andric std::optional<float> RootSignatureParser::parseFloatParam() {
977*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_equal &&
978*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
979*700637cbSDimitry Andric // Consume sign modifier
980*700637cbSDimitry Andric bool Signed =
981*700637cbSDimitry Andric tryConsumeExpectedToken({TokenKind::pu_plus, TokenKind::pu_minus});
982*700637cbSDimitry Andric bool Negated = Signed && CurToken.TokKind == TokenKind::pu_minus;
983*700637cbSDimitry Andric
984*700637cbSDimitry Andric // DXC will treat a postive signed integer as unsigned
985*700637cbSDimitry Andric if (!Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {
986*700637cbSDimitry Andric std::optional<uint32_t> UInt = handleUIntLiteral();
987*700637cbSDimitry Andric if (!UInt.has_value())
988*700637cbSDimitry Andric return std::nullopt;
989*700637cbSDimitry Andric return float(UInt.value());
990*700637cbSDimitry Andric }
991*700637cbSDimitry Andric
992*700637cbSDimitry Andric if (Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {
993*700637cbSDimitry Andric std::optional<int32_t> Int = handleIntLiteral(Negated);
994*700637cbSDimitry Andric if (!Int.has_value())
995*700637cbSDimitry Andric return std::nullopt;
996*700637cbSDimitry Andric return float(Int.value());
997*700637cbSDimitry Andric }
998*700637cbSDimitry Andric
999*700637cbSDimitry Andric if (tryConsumeExpectedToken(TokenKind::float_literal)) {
1000*700637cbSDimitry Andric std::optional<float> Float = handleFloatLiteral(Negated);
1001*700637cbSDimitry Andric if (!Float.has_value())
1002*700637cbSDimitry Andric return std::nullopt;
1003*700637cbSDimitry Andric return Float.value();
1004*700637cbSDimitry Andric }
1005*700637cbSDimitry Andric
1006*700637cbSDimitry Andric return std::nullopt;
1007*700637cbSDimitry Andric }
1008*700637cbSDimitry Andric
1009*700637cbSDimitry Andric std::optional<llvm::dxbc::ShaderVisibility>
parseShaderVisibility(TokenKind Context)1010*700637cbSDimitry Andric RootSignatureParser::parseShaderVisibility(TokenKind Context) {
1011*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_equal &&
1012*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
1013*700637cbSDimitry Andric
1014*700637cbSDimitry Andric TokenKind Expected[] = {
1015*700637cbSDimitry Andric #define SHADER_VISIBILITY_ENUM(NAME, LIT) TokenKind::en_##NAME,
1016*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1017*700637cbSDimitry Andric };
1018*700637cbSDimitry Andric
1019*700637cbSDimitry Andric if (!tryConsumeExpectedToken(Expected)) {
1020*700637cbSDimitry Andric consumeNextToken(); // consume token to point at invalid token
1021*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
1022*700637cbSDimitry Andric << /*value=*/1 << /*value of*/ Context;
1023*700637cbSDimitry Andric return std::nullopt;
1024*700637cbSDimitry Andric }
1025*700637cbSDimitry Andric
1026*700637cbSDimitry Andric switch (CurToken.TokKind) {
1027*700637cbSDimitry Andric #define SHADER_VISIBILITY_ENUM(NAME, LIT) \
1028*700637cbSDimitry Andric case TokenKind::en_##NAME: \
1029*700637cbSDimitry Andric return llvm::dxbc::ShaderVisibility::NAME; \
1030*700637cbSDimitry Andric break;
1031*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1032*700637cbSDimitry Andric default:
1033*700637cbSDimitry Andric llvm_unreachable("Switch for consumed enum token was not provided");
1034*700637cbSDimitry Andric }
1035*700637cbSDimitry Andric
1036*700637cbSDimitry Andric return std::nullopt;
1037*700637cbSDimitry Andric }
1038*700637cbSDimitry Andric
1039*700637cbSDimitry Andric std::optional<llvm::dxbc::SamplerFilter>
parseSamplerFilter(TokenKind Context)1040*700637cbSDimitry Andric RootSignatureParser::parseSamplerFilter(TokenKind Context) {
1041*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_equal &&
1042*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
1043*700637cbSDimitry Andric
1044*700637cbSDimitry Andric TokenKind Expected[] = {
1045*700637cbSDimitry Andric #define FILTER_ENUM(NAME, LIT) TokenKind::en_##NAME,
1046*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1047*700637cbSDimitry Andric };
1048*700637cbSDimitry Andric
1049*700637cbSDimitry Andric if (!tryConsumeExpectedToken(Expected)) {
1050*700637cbSDimitry Andric consumeNextToken(); // consume token to point at invalid token
1051*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
1052*700637cbSDimitry Andric << /*value=*/1 << /*value of*/ Context;
1053*700637cbSDimitry Andric return std::nullopt;
1054*700637cbSDimitry Andric }
1055*700637cbSDimitry Andric
1056*700637cbSDimitry Andric switch (CurToken.TokKind) {
1057*700637cbSDimitry Andric #define FILTER_ENUM(NAME, LIT) \
1058*700637cbSDimitry Andric case TokenKind::en_##NAME: \
1059*700637cbSDimitry Andric return llvm::dxbc::SamplerFilter::NAME; \
1060*700637cbSDimitry Andric break;
1061*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1062*700637cbSDimitry Andric default:
1063*700637cbSDimitry Andric llvm_unreachable("Switch for consumed enum token was not provided");
1064*700637cbSDimitry Andric }
1065*700637cbSDimitry Andric
1066*700637cbSDimitry Andric return std::nullopt;
1067*700637cbSDimitry Andric }
1068*700637cbSDimitry Andric
1069*700637cbSDimitry Andric std::optional<llvm::dxbc::TextureAddressMode>
parseTextureAddressMode(TokenKind Context)1070*700637cbSDimitry Andric RootSignatureParser::parseTextureAddressMode(TokenKind Context) {
1071*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_equal &&
1072*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
1073*700637cbSDimitry Andric
1074*700637cbSDimitry Andric TokenKind Expected[] = {
1075*700637cbSDimitry Andric #define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) TokenKind::en_##NAME,
1076*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1077*700637cbSDimitry Andric };
1078*700637cbSDimitry Andric
1079*700637cbSDimitry Andric if (!tryConsumeExpectedToken(Expected)) {
1080*700637cbSDimitry Andric consumeNextToken(); // consume token to point at invalid token
1081*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
1082*700637cbSDimitry Andric << /*value=*/1 << /*value of*/ Context;
1083*700637cbSDimitry Andric return std::nullopt;
1084*700637cbSDimitry Andric }
1085*700637cbSDimitry Andric
1086*700637cbSDimitry Andric switch (CurToken.TokKind) {
1087*700637cbSDimitry Andric #define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) \
1088*700637cbSDimitry Andric case TokenKind::en_##NAME: \
1089*700637cbSDimitry Andric return llvm::dxbc::TextureAddressMode::NAME; \
1090*700637cbSDimitry Andric break;
1091*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1092*700637cbSDimitry Andric default:
1093*700637cbSDimitry Andric llvm_unreachable("Switch for consumed enum token was not provided");
1094*700637cbSDimitry Andric }
1095*700637cbSDimitry Andric
1096*700637cbSDimitry Andric return std::nullopt;
1097*700637cbSDimitry Andric }
1098*700637cbSDimitry Andric
1099*700637cbSDimitry Andric std::optional<llvm::dxbc::ComparisonFunc>
parseComparisonFunc(TokenKind Context)1100*700637cbSDimitry Andric RootSignatureParser::parseComparisonFunc(TokenKind Context) {
1101*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_equal &&
1102*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
1103*700637cbSDimitry Andric
1104*700637cbSDimitry Andric TokenKind Expected[] = {
1105*700637cbSDimitry Andric #define COMPARISON_FUNC_ENUM(NAME, LIT) TokenKind::en_##NAME,
1106*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1107*700637cbSDimitry Andric };
1108*700637cbSDimitry Andric
1109*700637cbSDimitry Andric if (!tryConsumeExpectedToken(Expected)) {
1110*700637cbSDimitry Andric consumeNextToken(); // consume token to point at invalid token
1111*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
1112*700637cbSDimitry Andric << /*value=*/1 << /*value of*/ Context;
1113*700637cbSDimitry Andric return std::nullopt;
1114*700637cbSDimitry Andric }
1115*700637cbSDimitry Andric
1116*700637cbSDimitry Andric switch (CurToken.TokKind) {
1117*700637cbSDimitry Andric #define COMPARISON_FUNC_ENUM(NAME, LIT) \
1118*700637cbSDimitry Andric case TokenKind::en_##NAME: \
1119*700637cbSDimitry Andric return llvm::dxbc::ComparisonFunc::NAME; \
1120*700637cbSDimitry Andric break;
1121*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1122*700637cbSDimitry Andric default:
1123*700637cbSDimitry Andric llvm_unreachable("Switch for consumed enum token was not provided");
1124*700637cbSDimitry Andric }
1125*700637cbSDimitry Andric
1126*700637cbSDimitry Andric return std::nullopt;
1127*700637cbSDimitry Andric }
1128*700637cbSDimitry Andric
1129*700637cbSDimitry Andric std::optional<llvm::dxbc::StaticBorderColor>
parseStaticBorderColor(TokenKind Context)1130*700637cbSDimitry Andric RootSignatureParser::parseStaticBorderColor(TokenKind Context) {
1131*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_equal &&
1132*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
1133*700637cbSDimitry Andric
1134*700637cbSDimitry Andric TokenKind Expected[] = {
1135*700637cbSDimitry Andric #define STATIC_BORDER_COLOR_ENUM(NAME, LIT) TokenKind::en_##NAME,
1136*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1137*700637cbSDimitry Andric };
1138*700637cbSDimitry Andric
1139*700637cbSDimitry Andric if (!tryConsumeExpectedToken(Expected)) {
1140*700637cbSDimitry Andric consumeNextToken(); // consume token to point at invalid token
1141*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
1142*700637cbSDimitry Andric << /*value=*/1 << /*value of*/ Context;
1143*700637cbSDimitry Andric return std::nullopt;
1144*700637cbSDimitry Andric }
1145*700637cbSDimitry Andric
1146*700637cbSDimitry Andric switch (CurToken.TokKind) {
1147*700637cbSDimitry Andric #define STATIC_BORDER_COLOR_ENUM(NAME, LIT) \
1148*700637cbSDimitry Andric case TokenKind::en_##NAME: \
1149*700637cbSDimitry Andric return llvm::dxbc::StaticBorderColor::NAME; \
1150*700637cbSDimitry Andric break;
1151*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1152*700637cbSDimitry Andric default:
1153*700637cbSDimitry Andric llvm_unreachable("Switch for consumed enum token was not provided");
1154*700637cbSDimitry Andric }
1155*700637cbSDimitry Andric
1156*700637cbSDimitry Andric return std::nullopt;
1157*700637cbSDimitry Andric }
1158*700637cbSDimitry Andric
1159*700637cbSDimitry Andric std::optional<llvm::dxbc::RootDescriptorFlags>
parseRootDescriptorFlags(TokenKind Context)1160*700637cbSDimitry Andric RootSignatureParser::parseRootDescriptorFlags(TokenKind Context) {
1161*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_equal &&
1162*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
1163*700637cbSDimitry Andric
1164*700637cbSDimitry Andric // Handle the edge-case of '0' to specify no flags set
1165*700637cbSDimitry Andric if (tryConsumeExpectedToken(TokenKind::int_literal)) {
1166*700637cbSDimitry Andric if (!verifyZeroFlag()) {
1167*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
1168*700637cbSDimitry Andric return std::nullopt;
1169*700637cbSDimitry Andric }
1170*700637cbSDimitry Andric return llvm::dxbc::RootDescriptorFlags::None;
1171*700637cbSDimitry Andric }
1172*700637cbSDimitry Andric
1173*700637cbSDimitry Andric TokenKind Expected[] = {
1174*700637cbSDimitry Andric #define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
1175*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1176*700637cbSDimitry Andric };
1177*700637cbSDimitry Andric
1178*700637cbSDimitry Andric std::optional<llvm::dxbc::RootDescriptorFlags> Flags;
1179*700637cbSDimitry Andric
1180*700637cbSDimitry Andric do {
1181*700637cbSDimitry Andric if (tryConsumeExpectedToken(Expected)) {
1182*700637cbSDimitry Andric switch (CurToken.TokKind) {
1183*700637cbSDimitry Andric #define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) \
1184*700637cbSDimitry Andric case TokenKind::en_##NAME: \
1185*700637cbSDimitry Andric Flags = maybeOrFlag<llvm::dxbc::RootDescriptorFlags>( \
1186*700637cbSDimitry Andric Flags, llvm::dxbc::RootDescriptorFlags::NAME); \
1187*700637cbSDimitry Andric break;
1188*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1189*700637cbSDimitry Andric default:
1190*700637cbSDimitry Andric llvm_unreachable("Switch for consumed enum token was not provided");
1191*700637cbSDimitry Andric }
1192*700637cbSDimitry Andric } else {
1193*700637cbSDimitry Andric consumeNextToken(); // consume token to point at invalid token
1194*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
1195*700637cbSDimitry Andric << /*value=*/1 << /*value of*/ Context;
1196*700637cbSDimitry Andric return std::nullopt;
1197*700637cbSDimitry Andric }
1198*700637cbSDimitry Andric } while (tryConsumeExpectedToken(TokenKind::pu_or));
1199*700637cbSDimitry Andric
1200*700637cbSDimitry Andric return Flags;
1201*700637cbSDimitry Andric }
1202*700637cbSDimitry Andric
1203*700637cbSDimitry Andric std::optional<llvm::dxbc::DescriptorRangeFlags>
parseDescriptorRangeFlags(TokenKind Context)1204*700637cbSDimitry Andric RootSignatureParser::parseDescriptorRangeFlags(TokenKind Context) {
1205*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::pu_equal &&
1206*700637cbSDimitry Andric "Expects to only be invoked starting at given keyword");
1207*700637cbSDimitry Andric
1208*700637cbSDimitry Andric // Handle the edge-case of '0' to specify no flags set
1209*700637cbSDimitry Andric if (tryConsumeExpectedToken(TokenKind::int_literal)) {
1210*700637cbSDimitry Andric if (!verifyZeroFlag()) {
1211*700637cbSDimitry Andric reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
1212*700637cbSDimitry Andric return std::nullopt;
1213*700637cbSDimitry Andric }
1214*700637cbSDimitry Andric return llvm::dxbc::DescriptorRangeFlags::None;
1215*700637cbSDimitry Andric }
1216*700637cbSDimitry Andric
1217*700637cbSDimitry Andric TokenKind Expected[] = {
1218*700637cbSDimitry Andric #define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) TokenKind::en_##NAME,
1219*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1220*700637cbSDimitry Andric };
1221*700637cbSDimitry Andric
1222*700637cbSDimitry Andric std::optional<llvm::dxbc::DescriptorRangeFlags> Flags;
1223*700637cbSDimitry Andric
1224*700637cbSDimitry Andric do {
1225*700637cbSDimitry Andric if (tryConsumeExpectedToken(Expected)) {
1226*700637cbSDimitry Andric switch (CurToken.TokKind) {
1227*700637cbSDimitry Andric #define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) \
1228*700637cbSDimitry Andric case TokenKind::en_##NAME: \
1229*700637cbSDimitry Andric Flags = maybeOrFlag<llvm::dxbc::DescriptorRangeFlags>( \
1230*700637cbSDimitry Andric Flags, llvm::dxbc::DescriptorRangeFlags::NAME); \
1231*700637cbSDimitry Andric break;
1232*700637cbSDimitry Andric #include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1233*700637cbSDimitry Andric default:
1234*700637cbSDimitry Andric llvm_unreachable("Switch for consumed enum token was not provided");
1235*700637cbSDimitry Andric }
1236*700637cbSDimitry Andric } else {
1237*700637cbSDimitry Andric consumeNextToken(); // consume token to point at invalid token
1238*700637cbSDimitry Andric reportDiag(diag::err_hlsl_invalid_token)
1239*700637cbSDimitry Andric << /*value=*/1 << /*value of*/ Context;
1240*700637cbSDimitry Andric return std::nullopt;
1241*700637cbSDimitry Andric }
1242*700637cbSDimitry Andric } while (tryConsumeExpectedToken(TokenKind::pu_or));
1243*700637cbSDimitry Andric
1244*700637cbSDimitry Andric return Flags;
1245*700637cbSDimitry Andric }
1246*700637cbSDimitry Andric
handleUIntLiteral()1247*700637cbSDimitry Andric std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() {
1248*700637cbSDimitry Andric // Parse the numeric value and do semantic checks on its specification
1249*700637cbSDimitry Andric clang::NumericLiteralParser Literal(
1250*700637cbSDimitry Andric CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),
1251*700637cbSDimitry Andric PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());
1252*700637cbSDimitry Andric if (Literal.hadError)
1253*700637cbSDimitry Andric return std::nullopt; // Error has already been reported so just return
1254*700637cbSDimitry Andric
1255*700637cbSDimitry Andric assert(Literal.isIntegerLiteral() &&
1256*700637cbSDimitry Andric "NumSpelling can only consist of digits");
1257*700637cbSDimitry Andric
1258*700637cbSDimitry Andric llvm::APSInt Val(32, /*IsUnsigned=*/true);
1259*700637cbSDimitry Andric if (Literal.GetIntegerValue(Val)) {
1260*700637cbSDimitry Andric // Report that the value has overflowed
1261*700637cbSDimitry Andric reportDiag(diag::err_hlsl_number_literal_overflow)
1262*700637cbSDimitry Andric << /*integer type*/ 0 << /*is signed*/ 0;
1263*700637cbSDimitry Andric return std::nullopt;
1264*700637cbSDimitry Andric }
1265*700637cbSDimitry Andric
1266*700637cbSDimitry Andric return Val.getExtValue();
1267*700637cbSDimitry Andric }
1268*700637cbSDimitry Andric
handleIntLiteral(bool Negated)1269*700637cbSDimitry Andric std::optional<int32_t> RootSignatureParser::handleIntLiteral(bool Negated) {
1270*700637cbSDimitry Andric // Parse the numeric value and do semantic checks on its specification
1271*700637cbSDimitry Andric clang::NumericLiteralParser Literal(
1272*700637cbSDimitry Andric CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),
1273*700637cbSDimitry Andric PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());
1274*700637cbSDimitry Andric if (Literal.hadError)
1275*700637cbSDimitry Andric return std::nullopt; // Error has already been reported so just return
1276*700637cbSDimitry Andric
1277*700637cbSDimitry Andric assert(Literal.isIntegerLiteral() &&
1278*700637cbSDimitry Andric "NumSpelling can only consist of digits");
1279*700637cbSDimitry Andric
1280*700637cbSDimitry Andric llvm::APSInt Val(32, /*IsUnsigned=*/true);
1281*700637cbSDimitry Andric // GetIntegerValue will overwrite Val from the parsed Literal and return
1282*700637cbSDimitry Andric // true if it overflows as a 32-bit unsigned int
1283*700637cbSDimitry Andric bool Overflowed = Literal.GetIntegerValue(Val);
1284*700637cbSDimitry Andric
1285*700637cbSDimitry Andric // So we then need to check that it doesn't overflow as a 32-bit signed int:
1286*700637cbSDimitry Andric int64_t MaxNegativeMagnitude = -int64_t(std::numeric_limits<int32_t>::min());
1287*700637cbSDimitry Andric Overflowed |= (Negated && MaxNegativeMagnitude < Val.getExtValue());
1288*700637cbSDimitry Andric
1289*700637cbSDimitry Andric int64_t MaxPositiveMagnitude = int64_t(std::numeric_limits<int32_t>::max());
1290*700637cbSDimitry Andric Overflowed |= (!Negated && MaxPositiveMagnitude < Val.getExtValue());
1291*700637cbSDimitry Andric
1292*700637cbSDimitry Andric if (Overflowed) {
1293*700637cbSDimitry Andric // Report that the value has overflowed
1294*700637cbSDimitry Andric reportDiag(diag::err_hlsl_number_literal_overflow)
1295*700637cbSDimitry Andric << /*integer type*/ 0 << /*is signed*/ 1;
1296*700637cbSDimitry Andric return std::nullopt;
1297*700637cbSDimitry Andric }
1298*700637cbSDimitry Andric
1299*700637cbSDimitry Andric if (Negated)
1300*700637cbSDimitry Andric Val = -Val;
1301*700637cbSDimitry Andric
1302*700637cbSDimitry Andric return int32_t(Val.getExtValue());
1303*700637cbSDimitry Andric }
1304*700637cbSDimitry Andric
handleFloatLiteral(bool Negated)1305*700637cbSDimitry Andric std::optional<float> RootSignatureParser::handleFloatLiteral(bool Negated) {
1306*700637cbSDimitry Andric // Parse the numeric value and do semantic checks on its specification
1307*700637cbSDimitry Andric clang::NumericLiteralParser Literal(
1308*700637cbSDimitry Andric CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),
1309*700637cbSDimitry Andric PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());
1310*700637cbSDimitry Andric if (Literal.hadError)
1311*700637cbSDimitry Andric return std::nullopt; // Error has already been reported so just return
1312*700637cbSDimitry Andric
1313*700637cbSDimitry Andric assert(Literal.isFloatingLiteral() &&
1314*700637cbSDimitry Andric "NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
1315*700637cbSDimitry Andric "will be caught and reported by NumericLiteralParser.");
1316*700637cbSDimitry Andric
1317*700637cbSDimitry Andric // DXC used `strtod` to convert the token string to a float which corresponds
1318*700637cbSDimitry Andric // to:
1319*700637cbSDimitry Andric auto DXCSemantics = llvm::APFloat::Semantics::S_IEEEdouble;
1320*700637cbSDimitry Andric auto DXCRoundingMode = llvm::RoundingMode::NearestTiesToEven;
1321*700637cbSDimitry Andric
1322*700637cbSDimitry Andric llvm::APFloat Val(llvm::APFloat::EnumToSemantics(DXCSemantics));
1323*700637cbSDimitry Andric llvm::APFloat::opStatus Status(Literal.GetFloatValue(Val, DXCRoundingMode));
1324*700637cbSDimitry Andric
1325*700637cbSDimitry Andric // Note: we do not error when opStatus::opInexact by itself as this just
1326*700637cbSDimitry Andric // denotes that rounding occured but not that it is invalid
1327*700637cbSDimitry Andric assert(!(Status & llvm::APFloat::opStatus::opInvalidOp) &&
1328*700637cbSDimitry Andric "NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
1329*700637cbSDimitry Andric "will be caught and reported by NumericLiteralParser.");
1330*700637cbSDimitry Andric
1331*700637cbSDimitry Andric assert(!(Status & llvm::APFloat::opStatus::opDivByZero) &&
1332*700637cbSDimitry Andric "It is not possible for a division to be performed when "
1333*700637cbSDimitry Andric "constructing an APFloat from a string");
1334*700637cbSDimitry Andric
1335*700637cbSDimitry Andric if (Status & llvm::APFloat::opStatus::opUnderflow) {
1336*700637cbSDimitry Andric // Report that the value has underflowed
1337*700637cbSDimitry Andric reportDiag(diag::err_hlsl_number_literal_underflow);
1338*700637cbSDimitry Andric return std::nullopt;
1339*700637cbSDimitry Andric }
1340*700637cbSDimitry Andric
1341*700637cbSDimitry Andric if (Status & llvm::APFloat::opStatus::opOverflow) {
1342*700637cbSDimitry Andric // Report that the value has overflowed
1343*700637cbSDimitry Andric reportDiag(diag::err_hlsl_number_literal_overflow) << /*float type*/ 1;
1344*700637cbSDimitry Andric return std::nullopt;
1345*700637cbSDimitry Andric }
1346*700637cbSDimitry Andric
1347*700637cbSDimitry Andric if (Negated)
1348*700637cbSDimitry Andric Val = -Val;
1349*700637cbSDimitry Andric
1350*700637cbSDimitry Andric double DoubleVal = Val.convertToDouble();
1351*700637cbSDimitry Andric double FloatMax = double(std::numeric_limits<float>::max());
1352*700637cbSDimitry Andric if (FloatMax < DoubleVal || DoubleVal < -FloatMax) {
1353*700637cbSDimitry Andric // Report that the value has overflowed
1354*700637cbSDimitry Andric reportDiag(diag::err_hlsl_number_literal_overflow) << /*float type*/ 1;
1355*700637cbSDimitry Andric return std::nullopt;
1356*700637cbSDimitry Andric }
1357*700637cbSDimitry Andric
1358*700637cbSDimitry Andric return static_cast<float>(DoubleVal);
1359*700637cbSDimitry Andric }
1360*700637cbSDimitry Andric
verifyZeroFlag()1361*700637cbSDimitry Andric bool RootSignatureParser::verifyZeroFlag() {
1362*700637cbSDimitry Andric assert(CurToken.TokKind == TokenKind::int_literal);
1363*700637cbSDimitry Andric auto X = handleUIntLiteral();
1364*700637cbSDimitry Andric return X.has_value() && X.value() == 0;
1365*700637cbSDimitry Andric }
1366*700637cbSDimitry Andric
peekExpectedToken(TokenKind Expected)1367*700637cbSDimitry Andric bool RootSignatureParser::peekExpectedToken(TokenKind Expected) {
1368*700637cbSDimitry Andric return peekExpectedToken(ArrayRef{Expected});
1369*700637cbSDimitry Andric }
1370*700637cbSDimitry Andric
peekExpectedToken(ArrayRef<TokenKind> AnyExpected)1371*700637cbSDimitry Andric bool RootSignatureParser::peekExpectedToken(ArrayRef<TokenKind> AnyExpected) {
1372*700637cbSDimitry Andric RootSignatureToken Result = Lexer.peekNextToken();
1373*700637cbSDimitry Andric return llvm::is_contained(AnyExpected, Result.TokKind);
1374*700637cbSDimitry Andric }
1375*700637cbSDimitry Andric
consumeExpectedToken(TokenKind Expected,unsigned DiagID,TokenKind Context)1376*700637cbSDimitry Andric bool RootSignatureParser::consumeExpectedToken(TokenKind Expected,
1377*700637cbSDimitry Andric unsigned DiagID,
1378*700637cbSDimitry Andric TokenKind Context) {
1379*700637cbSDimitry Andric if (tryConsumeExpectedToken(Expected))
1380*700637cbSDimitry Andric return false;
1381*700637cbSDimitry Andric
1382*700637cbSDimitry Andric // Report unexpected token kind error
1383*700637cbSDimitry Andric DiagnosticBuilder DB = reportDiag(DiagID);
1384*700637cbSDimitry Andric switch (DiagID) {
1385*700637cbSDimitry Andric case diag::err_expected:
1386*700637cbSDimitry Andric DB << Expected;
1387*700637cbSDimitry Andric break;
1388*700637cbSDimitry Andric case diag::err_expected_either:
1389*700637cbSDimitry Andric DB << Expected << Context;
1390*700637cbSDimitry Andric break;
1391*700637cbSDimitry Andric case diag::err_expected_after:
1392*700637cbSDimitry Andric DB << Context << Expected;
1393*700637cbSDimitry Andric break;
1394*700637cbSDimitry Andric default:
1395*700637cbSDimitry Andric break;
1396*700637cbSDimitry Andric }
1397*700637cbSDimitry Andric return true;
1398*700637cbSDimitry Andric }
1399*700637cbSDimitry Andric
tryConsumeExpectedToken(TokenKind Expected)1400*700637cbSDimitry Andric bool RootSignatureParser::tryConsumeExpectedToken(TokenKind Expected) {
1401*700637cbSDimitry Andric return tryConsumeExpectedToken(ArrayRef{Expected});
1402*700637cbSDimitry Andric }
1403*700637cbSDimitry Andric
tryConsumeExpectedToken(ArrayRef<TokenKind> AnyExpected)1404*700637cbSDimitry Andric bool RootSignatureParser::tryConsumeExpectedToken(
1405*700637cbSDimitry Andric ArrayRef<TokenKind> AnyExpected) {
1406*700637cbSDimitry Andric // If not the expected token just return
1407*700637cbSDimitry Andric if (!peekExpectedToken(AnyExpected))
1408*700637cbSDimitry Andric return false;
1409*700637cbSDimitry Andric consumeNextToken();
1410*700637cbSDimitry Andric return true;
1411*700637cbSDimitry Andric }
1412*700637cbSDimitry Andric
skipUntilExpectedToken(TokenKind Expected)1413*700637cbSDimitry Andric bool RootSignatureParser::skipUntilExpectedToken(TokenKind Expected) {
1414*700637cbSDimitry Andric return skipUntilExpectedToken(ArrayRef{Expected});
1415*700637cbSDimitry Andric }
1416*700637cbSDimitry Andric
skipUntilExpectedToken(ArrayRef<TokenKind> AnyExpected)1417*700637cbSDimitry Andric bool RootSignatureParser::skipUntilExpectedToken(
1418*700637cbSDimitry Andric ArrayRef<TokenKind> AnyExpected) {
1419*700637cbSDimitry Andric
1420*700637cbSDimitry Andric while (!peekExpectedToken(AnyExpected)) {
1421*700637cbSDimitry Andric if (peekExpectedToken(TokenKind::end_of_stream))
1422*700637cbSDimitry Andric return false;
1423*700637cbSDimitry Andric consumeNextToken();
1424*700637cbSDimitry Andric }
1425*700637cbSDimitry Andric
1426*700637cbSDimitry Andric return true;
1427*700637cbSDimitry Andric }
1428*700637cbSDimitry Andric
skipUntilClosedParens(uint32_t NumParens)1429*700637cbSDimitry Andric bool RootSignatureParser::skipUntilClosedParens(uint32_t NumParens) {
1430*700637cbSDimitry Andric TokenKind ParenKinds[] = {
1431*700637cbSDimitry Andric TokenKind::pu_l_paren,
1432*700637cbSDimitry Andric TokenKind::pu_r_paren,
1433*700637cbSDimitry Andric };
1434*700637cbSDimitry Andric while (skipUntilExpectedToken(ParenKinds)) {
1435*700637cbSDimitry Andric consumeNextToken();
1436*700637cbSDimitry Andric if (CurToken.TokKind == TokenKind::pu_r_paren)
1437*700637cbSDimitry Andric NumParens--;
1438*700637cbSDimitry Andric else
1439*700637cbSDimitry Andric NumParens++;
1440*700637cbSDimitry Andric if (NumParens == 0)
1441*700637cbSDimitry Andric return true;
1442*700637cbSDimitry Andric }
1443*700637cbSDimitry Andric
1444*700637cbSDimitry Andric return false;
1445*700637cbSDimitry Andric }
1446*700637cbSDimitry Andric
getTokenLocation(RootSignatureToken Tok)1447*700637cbSDimitry Andric SourceLocation RootSignatureParser::getTokenLocation(RootSignatureToken Tok) {
1448*700637cbSDimitry Andric return Signature->getLocationOfByte(Tok.LocOffset, PP.getSourceManager(),
1449*700637cbSDimitry Andric PP.getLangOpts(), PP.getTargetInfo());
1450*700637cbSDimitry Andric }
1451*700637cbSDimitry Andric
1452*700637cbSDimitry Andric } // namespace hlsl
1453*700637cbSDimitry Andric } // namespace clang
1454