xref: /freebsd/contrib/llvm-project/clang/lib/Parse/ParseHLSLRootSignature.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
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