15using namespace llvm::hlsl::rootsig;
23 TokenKind::kw_RootFlags,
27 TokenKind::kw_DescriptorTable,
28 TokenKind::kw_StaticSampler,
32 llvm::dxbc::RootSignatureVersion Version,
StringLiteral *Signature,
34 : Version(Version), Signature(Signature), Lexer(Signature->getString()),
35 PP(PP), CurToken(0) {}
40 bool HadError =
false;
41 bool HasRootFlags =
false;
42 while (!peekExpectedToken(TokenKind::end_of_stream)) {
43 if (tryConsumeExpectedToken(TokenKind::kw_RootFlags)) {
45 reportDiag(diag::err_hlsl_rootsig_repeat_param)
46 << TokenKind::kw_RootFlags;
54 auto Flags = parseRootFlags();
55 if (!Flags.has_value()) {
61 Elements.emplace_back(ElementLoc, *Flags);
62 }
else if (tryConsumeExpectedToken(TokenKind::kw_RootConstants)) {
64 auto Constants = parseRootConstants();
65 if (!Constants.has_value()) {
70 Elements.emplace_back(ElementLoc, *Constants);
71 }
else if (tryConsumeExpectedToken(TokenKind::kw_DescriptorTable)) {
73 auto Table = parseDescriptorTable();
74 if (!Table.has_value()) {
78 skipUntilClosedParens();
83 Elements.emplace_back(ElementLoc, *Table);
84 }
else if (tryConsumeExpectedToken(
85 {TokenKind::kw_CBV, TokenKind::kw_SRV, TokenKind::kw_UAV})) {
87 auto Descriptor = parseRootDescriptor();
88 if (!Descriptor.has_value()) {
93 Elements.emplace_back(ElementLoc, *Descriptor);
94 }
else if (tryConsumeExpectedToken(TokenKind::kw_StaticSampler)) {
96 auto Sampler = parseStaticSampler();
97 if (!Sampler.has_value()) {
102 Elements.emplace_back(ElementLoc, *Sampler);
106 reportDiag(diag::err_hlsl_invalid_token)
107 << 0 << TokenKind::kw_RootSignature;
112 if (!tryConsumeExpectedToken(TokenKind::pu_comma)) {
119 consumeExpectedToken(TokenKind::end_of_stream,
120 diag::err_expected_either, TokenKind::pu_comma);
123template <
typename FlagType>
124static FlagType
maybeOrFlag(std::optional<FlagType> Flags, FlagType Flag) {
125 if (!Flags.has_value())
128 return static_cast<FlagType
>(llvm::to_underlying(Flags.value()) |
129 llvm::to_underlying(Flag));
132std::optional<llvm::dxbc::RootFlags> RootSignatureParser::parseRootFlags() {
133 assert(CurToken.
TokKind == TokenKind::kw_RootFlags &&
134 "Expects to only be invoked starting at given keyword");
136 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
140 std::optional<llvm::dxbc::RootFlags> Flags = llvm::dxbc::RootFlags::None;
143 if (tryConsumeExpectedToken(TokenKind::pu_r_paren))
147 if (tryConsumeExpectedToken(TokenKind::int_literal)) {
148 if (!verifyZeroFlag()) {
149 reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
155#define ROOT_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
156#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
160 if (tryConsumeExpectedToken(Expected)) {
161 switch (CurToken.TokKind) {
162#define ROOT_FLAG_ENUM(NAME, LIT) \
163 case TokenKind::en_##NAME: \
164 Flags = maybeOrFlag<llvm::dxbc::RootFlags>(Flags, \
165 llvm::dxbc::RootFlags::NAME); \
167#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
169 llvm_unreachable(
"Switch for consumed enum token was not provided");
173 reportDiag(diag::err_hlsl_invalid_token)
174 << 1 << TokenKind::kw_RootFlags;
177 }
while (tryConsumeExpectedToken(TokenKind::pu_or));
180 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
181 TokenKind::pu_comma))
187std::optional<RootConstants> RootSignatureParser::parseRootConstants() {
188 assert(CurToken.TokKind == TokenKind::kw_RootConstants &&
189 "Expects to only be invoked starting at given keyword");
191 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
195 RootConstants Constants;
197 auto Params = parseRootConstantParams();
198 if (!Params.has_value())
201 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
202 TokenKind::pu_comma))
206 if (!Params->Num32BitConstants.has_value()) {
207 reportDiag(diag::err_hlsl_rootsig_missing_param)
208 << TokenKind::kw_num32BitConstants;
212 Constants.Num32BitConstants = Params->Num32BitConstants.value();
214 if (!Params->Reg.has_value()) {
215 reportDiag(diag::err_hlsl_rootsig_missing_param) << TokenKind::bReg;
219 Constants.Reg = Params->Reg.value();
222 if (Params->Visibility.has_value())
223 Constants.Visibility = Params->Visibility.value();
225 if (Params->Space.has_value())
226 Constants.Space = Params->Space.value();
231std::optional<RootDescriptor> RootSignatureParser::parseRootDescriptor() {
232 assert((CurToken.TokKind == TokenKind::kw_CBV ||
233 CurToken.TokKind == TokenKind::kw_SRV ||
234 CurToken.TokKind == TokenKind::kw_UAV) &&
235 "Expects to only be invoked starting at given keyword");
237 TokenKind DescriptorKind = CurToken.TokKind;
239 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
243 RootDescriptor Descriptor;
245 switch (DescriptorKind) {
247 llvm_unreachable(
"Switch for consumed token was not provided");
248 case TokenKind::kw_CBV:
249 Descriptor.Type = ResourceClass::CBuffer;
250 ExpectedReg = TokenKind::bReg;
252 case TokenKind::kw_SRV:
253 Descriptor.Type = ResourceClass::SRV;
254 ExpectedReg = TokenKind::tReg;
256 case TokenKind::kw_UAV:
257 Descriptor.Type = ResourceClass::UAV;
258 ExpectedReg = TokenKind::uReg;
261 Descriptor.setDefaultFlags(Version);
263 auto Params = parseRootDescriptorParams(DescriptorKind, ExpectedReg);
264 if (!Params.has_value())
267 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
268 TokenKind::pu_comma))
272 if (!Params->Reg.has_value()) {
273 reportDiag(diag::err_hlsl_rootsig_missing_param) << ExpectedReg;
277 Descriptor.Reg = Params->Reg.value();
280 if (Params->Space.has_value())
281 Descriptor.Space = Params->Space.value();
283 if (Params->Visibility.has_value())
284 Descriptor.Visibility = Params->Visibility.value();
286 if (Params->Flags.has_value())
287 Descriptor.Flags = Params->Flags.value();
292std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() {
293 assert(CurToken.TokKind == TokenKind::kw_DescriptorTable &&
294 "Expects to only be invoked starting at given keyword");
296 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
300 DescriptorTable Table;
301 std::optional<llvm::dxbc::ShaderVisibility>
Visibility;
304 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
305 if (tryConsumeExpectedToken({TokenKind::kw_CBV, TokenKind::kw_SRV,
306 TokenKind::kw_UAV, TokenKind::kw_Sampler})) {
308 SourceLocation ElementLoc = getTokenLocation(CurToken);
309 auto Clause = parseDescriptorTableClause();
310 if (!Clause.has_value()) {
313 skipUntilExpectedToken(TokenKind::pu_r_paren);
317 Elements.emplace_back(ElementLoc, *Clause);
319 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
322 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
326 if (consumeExpectedToken(TokenKind::pu_equal))
329 Visibility = parseShaderVisibility(TokenKind::kw_visibility);
334 reportDiag(diag::err_hlsl_invalid_token)
335 << 0 << TokenKind::kw_DescriptorTable;
340 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
344 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
345 TokenKind::pu_comma))
355std::optional<DescriptorTableClause>
356RootSignatureParser::parseDescriptorTableClause() {
357 assert((CurToken.TokKind == TokenKind::kw_CBV ||
358 CurToken.TokKind == TokenKind::kw_SRV ||
359 CurToken.TokKind == TokenKind::kw_UAV ||
360 CurToken.TokKind == TokenKind::kw_Sampler) &&
361 "Expects to only be invoked starting at given keyword");
365 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
369 DescriptorTableClause Clause;
373 llvm_unreachable(
"Switch for consumed token was not provided");
374 case TokenKind::kw_CBV:
375 Clause.Type = ResourceClass::CBuffer;
376 ExpectedReg = TokenKind::bReg;
378 case TokenKind::kw_SRV:
379 Clause.Type = ResourceClass::SRV;
380 ExpectedReg = TokenKind::tReg;
382 case TokenKind::kw_UAV:
383 Clause.Type = ResourceClass::UAV;
384 ExpectedReg = TokenKind::uReg;
386 case TokenKind::kw_Sampler:
387 Clause.Type = ResourceClass::Sampler;
388 ExpectedReg = TokenKind::sReg;
391 Clause.setDefaultFlags(Version);
393 auto Params = parseDescriptorTableClauseParams(ParamKind, ExpectedReg);
394 if (!Params.has_value())
397 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
398 TokenKind::pu_comma))
402 if (!Params->Reg.has_value()) {
403 reportDiag(diag::err_hlsl_rootsig_missing_param) << ExpectedReg;
407 Clause.Reg = Params->Reg.value();
410 if (Params->NumDescriptors.has_value())
411 Clause.NumDescriptors = Params->NumDescriptors.value();
413 if (Params->Space.has_value())
414 Clause.Space = Params->Space.value();
416 if (Params->Offset.has_value())
417 Clause.Offset = Params->Offset.value();
419 if (Params->Flags.has_value())
420 Clause.Flags = Params->Flags.value();
425std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() {
426 assert(CurToken.TokKind == TokenKind::kw_StaticSampler &&
427 "Expects to only be invoked starting at given keyword");
429 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
433 StaticSampler Sampler;
435 auto Params = parseStaticSamplerParams();
436 if (!Params.has_value())
439 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
440 TokenKind::pu_comma))
444 if (!Params->Reg.has_value()) {
445 reportDiag(diag::err_hlsl_rootsig_missing_param) << TokenKind::sReg;
449 Sampler.Reg = Params->Reg.value();
452 if (Params->Filter.has_value())
453 Sampler.Filter = Params->Filter.value();
455 if (Params->AddressU.has_value())
456 Sampler.AddressU = Params->AddressU.value();
458 if (Params->AddressV.has_value())
459 Sampler.AddressV = Params->AddressV.value();
461 if (Params->AddressW.has_value())
462 Sampler.AddressW = Params->AddressW.value();
464 if (Params->MipLODBias.has_value())
465 Sampler.MipLODBias = Params->MipLODBias.value();
467 if (Params->MaxAnisotropy.has_value())
468 Sampler.MaxAnisotropy = Params->MaxAnisotropy.value();
470 if (Params->CompFunc.has_value())
471 Sampler.CompFunc = Params->CompFunc.value();
473 if (Params->BorderColor.has_value())
474 Sampler.BorderColor = Params->BorderColor.value();
476 if (Params->MinLOD.has_value())
477 Sampler.MinLOD = Params->MinLOD.value();
479 if (Params->MaxLOD.has_value())
480 Sampler.MaxLOD = Params->MaxLOD.value();
482 if (Params->Space.has_value())
483 Sampler.Space = Params->Space.value();
485 if (Params->Visibility.has_value())
486 Sampler.Visibility = Params->Visibility.value();
488 if (Params->Flags.has_value())
489 Sampler.Flags = Params->Flags.value();
497std::optional<RootSignatureParser::ParsedConstantParams>
498RootSignatureParser::parseRootConstantParams() {
499 assert(CurToken.TokKind == TokenKind::pu_l_paren &&
500 "Expects to only be invoked starting at given token");
502 ParsedConstantParams Params;
503 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
504 if (tryConsumeExpectedToken(TokenKind::kw_num32BitConstants)) {
506 if (Params.Num32BitConstants.has_value()) {
507 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
511 if (consumeExpectedToken(TokenKind::pu_equal))
514 auto Num32BitConstants = parseUIntParam();
515 if (!Num32BitConstants.has_value())
517 Params.Num32BitConstants = Num32BitConstants;
518 }
else if (tryConsumeExpectedToken(TokenKind::bReg)) {
520 if (Params.Reg.has_value()) {
521 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
524 auto Reg = parseRegister();
525 if (!Reg.has_value())
528 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
530 if (Params.Space.has_value()) {
531 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
535 if (consumeExpectedToken(TokenKind::pu_equal))
538 auto Space = parseUIntParam();
539 if (!Space.has_value())
541 Params.Space = Space;
542 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
544 if (Params.Visibility.has_value()) {
545 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
549 if (consumeExpectedToken(TokenKind::pu_equal))
552 auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
558 reportDiag(diag::err_hlsl_invalid_token)
559 << 0 << TokenKind::kw_RootConstants;
564 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
571std::optional<RootSignatureParser::ParsedRootDescriptorParams>
572RootSignatureParser::parseRootDescriptorParams(
TokenKind DescKind,
574 assert(CurToken.TokKind == TokenKind::pu_l_paren &&
575 "Expects to only be invoked starting at given token");
577 ParsedRootDescriptorParams Params;
578 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
579 if (tryConsumeExpectedToken(RegType)) {
581 if (Params.Reg.has_value()) {
582 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
585 auto Reg = parseRegister();
586 if (!Reg.has_value())
589 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
591 if (Params.Space.has_value()) {
592 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
596 if (consumeExpectedToken(TokenKind::pu_equal))
599 auto Space = parseUIntParam();
600 if (!Space.has_value())
602 Params.Space = Space;
603 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
605 if (Params.Visibility.has_value()) {
606 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
610 if (consumeExpectedToken(TokenKind::pu_equal))
613 auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
617 }
else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
619 if (Params.Flags.has_value()) {
620 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
624 if (consumeExpectedToken(TokenKind::pu_equal))
627 auto Flags = parseRootDescriptorFlags(TokenKind::kw_flags);
628 if (!Flags.has_value())
630 Params.Flags = Flags;
633 reportDiag(diag::err_hlsl_invalid_token)
639 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
646std::optional<RootSignatureParser::ParsedClauseParams>
647RootSignatureParser::parseDescriptorTableClauseParams(
TokenKind ClauseKind,
649 assert(CurToken.TokKind == TokenKind::pu_l_paren &&
650 "Expects to only be invoked starting at given token");
652 ParsedClauseParams Params;
653 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
654 if (tryConsumeExpectedToken(RegType)) {
656 if (Params.Reg.has_value()) {
657 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
660 auto Reg = parseRegister();
661 if (!Reg.has_value())
664 }
else if (tryConsumeExpectedToken(TokenKind::kw_numDescriptors)) {
666 if (Params.NumDescriptors.has_value()) {
667 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
671 if (consumeExpectedToken(TokenKind::pu_equal))
674 std::optional<uint32_t> NumDescriptors;
675 if (tryConsumeExpectedToken(TokenKind::en_unbounded))
676 NumDescriptors = NumDescriptorsUnbounded;
678 NumDescriptors = parseUIntParam();
679 if (!NumDescriptors.has_value())
683 Params.NumDescriptors = NumDescriptors;
684 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
686 if (Params.Space.has_value()) {
687 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
691 if (consumeExpectedToken(TokenKind::pu_equal))
694 auto Space = parseUIntParam();
695 if (!Space.has_value())
697 Params.Space = Space;
698 }
else if (tryConsumeExpectedToken(TokenKind::kw_offset)) {
700 if (Params.Offset.has_value()) {
701 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
705 if (consumeExpectedToken(TokenKind::pu_equal))
708 std::optional<uint32_t> Offset;
709 if (tryConsumeExpectedToken(TokenKind::en_DescriptorRangeOffsetAppend))
710 Offset = DescriptorTableOffsetAppend;
712 Offset = parseUIntParam();
713 if (!Offset.has_value())
717 Params.Offset = Offset;
718 }
else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
720 if (Params.Flags.has_value()) {
721 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
725 if (consumeExpectedToken(TokenKind::pu_equal))
728 auto Flags = parseDescriptorRangeFlags(TokenKind::kw_flags);
729 if (!Flags.has_value())
731 Params.Flags = Flags;
734 reportDiag(diag::err_hlsl_invalid_token)
740 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
747std::optional<RootSignatureParser::ParsedStaticSamplerParams>
748RootSignatureParser::parseStaticSamplerParams() {
749 assert(CurToken.TokKind == TokenKind::pu_l_paren &&
750 "Expects to only be invoked starting at given token");
752 ParsedStaticSamplerParams Params;
753 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
754 if (tryConsumeExpectedToken(TokenKind::sReg)) {
756 if (Params.Reg.has_value()) {
757 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
760 auto Reg = parseRegister();
761 if (!Reg.has_value())
764 }
else if (tryConsumeExpectedToken(TokenKind::kw_filter)) {
766 if (Params.Filter.has_value()) {
767 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
771 if (consumeExpectedToken(TokenKind::pu_equal))
774 auto Filter = parseSamplerFilter(TokenKind::kw_filter);
778 }
else if (tryConsumeExpectedToken(TokenKind::kw_addressU)) {
780 if (Params.AddressU.has_value()) {
781 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
785 if (consumeExpectedToken(TokenKind::pu_equal))
788 auto AddressU = parseTextureAddressMode(TokenKind::kw_addressU);
789 if (!AddressU.has_value())
791 Params.AddressU = AddressU;
792 }
else if (tryConsumeExpectedToken(TokenKind::kw_addressV)) {
794 if (Params.AddressV.has_value()) {
795 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
799 if (consumeExpectedToken(TokenKind::pu_equal))
802 auto AddressV = parseTextureAddressMode(TokenKind::kw_addressV);
803 if (!AddressV.has_value())
805 Params.AddressV = AddressV;
806 }
else if (tryConsumeExpectedToken(TokenKind::kw_addressW)) {
808 if (Params.AddressW.has_value()) {
809 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
813 if (consumeExpectedToken(TokenKind::pu_equal))
816 auto AddressW = parseTextureAddressMode(TokenKind::kw_addressW);
817 if (!AddressW.has_value())
819 Params.AddressW = AddressW;
820 }
else if (tryConsumeExpectedToken(TokenKind::kw_mipLODBias)) {
822 if (Params.MipLODBias.has_value()) {
823 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
827 if (consumeExpectedToken(TokenKind::pu_equal))
830 auto MipLODBias = parseFloatParam();
831 if (!MipLODBias.has_value())
833 Params.MipLODBias = MipLODBias;
834 }
else if (tryConsumeExpectedToken(TokenKind::kw_maxAnisotropy)) {
836 if (Params.MaxAnisotropy.has_value()) {
837 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
841 if (consumeExpectedToken(TokenKind::pu_equal))
844 auto MaxAnisotropy = parseUIntParam();
845 if (!MaxAnisotropy.has_value())
847 Params.MaxAnisotropy = MaxAnisotropy;
848 }
else if (tryConsumeExpectedToken(TokenKind::kw_comparisonFunc)) {
850 if (Params.CompFunc.has_value()) {
851 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
855 if (consumeExpectedToken(TokenKind::pu_equal))
858 auto CompFunc = parseComparisonFunc(TokenKind::kw_comparisonFunc);
859 if (!CompFunc.has_value())
861 Params.CompFunc = CompFunc;
862 }
else if (tryConsumeExpectedToken(TokenKind::kw_borderColor)) {
864 if (Params.BorderColor.has_value()) {
865 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
869 if (consumeExpectedToken(TokenKind::pu_equal))
872 auto BorderColor = parseStaticBorderColor(TokenKind::kw_borderColor);
873 if (!BorderColor.has_value())
875 Params.BorderColor = BorderColor;
876 }
else if (tryConsumeExpectedToken(TokenKind::kw_minLOD)) {
878 if (Params.MinLOD.has_value()) {
879 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
883 if (consumeExpectedToken(TokenKind::pu_equal))
886 auto MinLOD = parseFloatParam();
887 if (!MinLOD.has_value())
889 Params.MinLOD = MinLOD;
890 }
else if (tryConsumeExpectedToken(TokenKind::kw_maxLOD)) {
892 if (Params.MaxLOD.has_value()) {
893 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
897 if (consumeExpectedToken(TokenKind::pu_equal))
900 auto MaxLOD = parseFloatParam();
901 if (!MaxLOD.has_value())
903 Params.MaxLOD = MaxLOD;
904 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
906 if (Params.Space.has_value()) {
907 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
911 if (consumeExpectedToken(TokenKind::pu_equal))
914 auto Space = parseUIntParam();
915 if (!Space.has_value())
917 Params.Space = Space;
918 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
920 if (Params.Visibility.has_value()) {
921 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
925 if (consumeExpectedToken(TokenKind::pu_equal))
928 auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
932 }
else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
934 if (Params.Flags.has_value()) {
935 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
939 if (consumeExpectedToken(TokenKind::pu_equal))
942 auto Flags = parseStaticSamplerFlags(TokenKind::kw_flags);
943 if (!Flags.has_value())
945 Params.Flags = Flags;
948 reportDiag(diag::err_hlsl_invalid_token)
949 << 0 << TokenKind::kw_StaticSampler;
954 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
961std::optional<uint32_t> RootSignatureParser::parseUIntParam() {
962 assert(CurToken.TokKind == TokenKind::pu_equal &&
963 "Expects to only be invoked starting at given keyword");
964 tryConsumeExpectedToken(TokenKind::pu_plus);
965 if (consumeExpectedToken(TokenKind::int_literal, diag::err_expected_after,
968 return handleUIntLiteral();
971std::optional<Register> RootSignatureParser::parseRegister() {
972 assert((CurToken.TokKind == TokenKind::bReg ||
973 CurToken.TokKind == TokenKind::tReg ||
974 CurToken.TokKind == TokenKind::uReg ||
975 CurToken.TokKind == TokenKind::sReg) &&
976 "Expects to only be invoked starting at given keyword");
979 switch (CurToken.TokKind) {
981 llvm_unreachable(
"Switch for consumed token was not provided");
982 case TokenKind::bReg:
983 Reg.ViewType = RegisterType::BReg;
985 case TokenKind::tReg:
986 Reg.ViewType = RegisterType::TReg;
988 case TokenKind::uReg:
989 Reg.ViewType = RegisterType::UReg;
991 case TokenKind::sReg:
992 Reg.ViewType = RegisterType::SReg;
996 auto Number = handleUIntLiteral();
997 if (!Number.has_value())
1000 Reg.Number = *Number;
1004std::optional<float> RootSignatureParser::parseFloatParam() {
1005 assert(CurToken.TokKind == TokenKind::pu_equal &&
1006 "Expects to only be invoked starting at given keyword");
1009 tryConsumeExpectedToken({TokenKind::pu_plus, TokenKind::pu_minus});
1010 bool Negated =
Signed && CurToken.TokKind == TokenKind::pu_minus;
1013 if (!Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {
1014 std::optional<uint32_t> UInt = handleUIntLiteral();
1015 if (!UInt.has_value())
1016 return std::nullopt;
1017 return float(UInt.value());
1020 if (Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {
1021 std::optional<int32_t>
Int = handleIntLiteral(Negated);
1022 if (!
Int.has_value())
1023 return std::nullopt;
1027 if (tryConsumeExpectedToken(TokenKind::float_literal)) {
1028 std::optional<float>
Float = handleFloatLiteral(Negated);
1029 if (!
Float.has_value())
1030 return std::nullopt;
1031 return Float.value();
1034 return std::nullopt;
1037std::optional<llvm::dxbc::ShaderVisibility>
1038RootSignatureParser::parseShaderVisibility(
TokenKind Context) {
1039 assert(CurToken.TokKind == TokenKind::pu_equal &&
1040 "Expects to only be invoked starting at given keyword");
1043#define SHADER_VISIBILITY_ENUM(NAME, LIT) TokenKind::en_##NAME,
1044#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1047 if (!tryConsumeExpectedToken(Expected)) {
1049 reportDiag(diag::err_hlsl_invalid_token)
1051 return std::nullopt;
1054 switch (CurToken.TokKind) {
1055#define SHADER_VISIBILITY_ENUM(NAME, LIT) \
1056 case TokenKind::en_##NAME: \
1057 return llvm::dxbc::ShaderVisibility::NAME; \
1059#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1061 llvm_unreachable(
"Switch for consumed enum token was not provided");
1064 return std::nullopt;
1067std::optional<llvm::dxbc::SamplerFilter>
1068RootSignatureParser::parseSamplerFilter(
TokenKind Context) {
1069 assert(CurToken.TokKind == TokenKind::pu_equal &&
1070 "Expects to only be invoked starting at given keyword");
1073#define FILTER_ENUM(NAME, LIT) TokenKind::en_##NAME,
1074#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1077 if (!tryConsumeExpectedToken(Expected)) {
1079 reportDiag(diag::err_hlsl_invalid_token)
1081 return std::nullopt;
1084 switch (CurToken.TokKind) {
1085#define FILTER_ENUM(NAME, LIT) \
1086 case TokenKind::en_##NAME: \
1087 return llvm::dxbc::SamplerFilter::NAME; \
1089#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1091 llvm_unreachable(
"Switch for consumed enum token was not provided");
1094 return std::nullopt;
1097std::optional<llvm::dxbc::TextureAddressMode>
1098RootSignatureParser::parseTextureAddressMode(
TokenKind Context) {
1099 assert(CurToken.TokKind == TokenKind::pu_equal &&
1100 "Expects to only be invoked starting at given keyword");
1103#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) TokenKind::en_##NAME,
1104#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1107 if (!tryConsumeExpectedToken(Expected)) {
1109 reportDiag(diag::err_hlsl_invalid_token)
1111 return std::nullopt;
1114 switch (CurToken.TokKind) {
1115#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) \
1116 case TokenKind::en_##NAME: \
1117 return llvm::dxbc::TextureAddressMode::NAME; \
1119#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1121 llvm_unreachable(
"Switch for consumed enum token was not provided");
1124 return std::nullopt;
1127std::optional<llvm::dxbc::ComparisonFunc>
1128RootSignatureParser::parseComparisonFunc(
TokenKind Context) {
1129 assert(CurToken.TokKind == TokenKind::pu_equal &&
1130 "Expects to only be invoked starting at given keyword");
1133#define COMPARISON_FUNC_ENUM(NAME, LIT) TokenKind::en_##NAME,
1134#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1137 if (!tryConsumeExpectedToken(Expected)) {
1139 reportDiag(diag::err_hlsl_invalid_token)
1141 return std::nullopt;
1144 switch (CurToken.TokKind) {
1145#define COMPARISON_FUNC_ENUM(NAME, LIT) \
1146 case TokenKind::en_##NAME: \
1147 return llvm::dxbc::ComparisonFunc::NAME; \
1149#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1151 llvm_unreachable(
"Switch for consumed enum token was not provided");
1154 return std::nullopt;
1157std::optional<llvm::dxbc::StaticBorderColor>
1158RootSignatureParser::parseStaticBorderColor(
TokenKind Context) {
1159 assert(CurToken.TokKind == TokenKind::pu_equal &&
1160 "Expects to only be invoked starting at given keyword");
1163#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) TokenKind::en_##NAME,
1164#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1167 if (!tryConsumeExpectedToken(Expected)) {
1169 reportDiag(diag::err_hlsl_invalid_token)
1171 return std::nullopt;
1174 switch (CurToken.TokKind) {
1175#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) \
1176 case TokenKind::en_##NAME: \
1177 return llvm::dxbc::StaticBorderColor::NAME; \
1179#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1181 llvm_unreachable(
"Switch for consumed enum token was not provided");
1184 return std::nullopt;
1187std::optional<llvm::dxbc::RootDescriptorFlags>
1188RootSignatureParser::parseRootDescriptorFlags(
TokenKind Context) {
1189 assert(CurToken.TokKind == TokenKind::pu_equal &&
1190 "Expects to only be invoked starting at given keyword");
1193 if (tryConsumeExpectedToken(TokenKind::int_literal)) {
1194 if (!verifyZeroFlag()) {
1195 reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
1196 return std::nullopt;
1198 return llvm::dxbc::RootDescriptorFlags::None;
1202#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
1203#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1206 std::optional<llvm::dxbc::RootDescriptorFlags> Flags;
1209 if (tryConsumeExpectedToken(Expected)) {
1210 switch (CurToken.TokKind) {
1211#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) \
1212 case TokenKind::en_##NAME: \
1213 Flags = maybeOrFlag<llvm::dxbc::RootDescriptorFlags>( \
1214 Flags, llvm::dxbc::RootDescriptorFlags::NAME); \
1216#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1218 llvm_unreachable(
"Switch for consumed enum token was not provided");
1222 reportDiag(diag::err_hlsl_invalid_token)
1224 return std::nullopt;
1226 }
while (tryConsumeExpectedToken(TokenKind::pu_or));
1231std::optional<llvm::dxbc::DescriptorRangeFlags>
1232RootSignatureParser::parseDescriptorRangeFlags(
TokenKind Context) {
1233 assert(CurToken.TokKind == TokenKind::pu_equal &&
1234 "Expects to only be invoked starting at given keyword");
1237 if (tryConsumeExpectedToken(TokenKind::int_literal)) {
1238 if (!verifyZeroFlag()) {
1239 reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
1240 return std::nullopt;
1242 return llvm::dxbc::DescriptorRangeFlags::None;
1246#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) TokenKind::en_##NAME,
1247#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1250 std::optional<llvm::dxbc::DescriptorRangeFlags> Flags;
1253 if (tryConsumeExpectedToken(Expected)) {
1254 switch (CurToken.TokKind) {
1255#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) \
1256 case TokenKind::en_##NAME: \
1257 Flags = maybeOrFlag<llvm::dxbc::DescriptorRangeFlags>( \
1258 Flags, llvm::dxbc::DescriptorRangeFlags::NAME); \
1260#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1262 llvm_unreachable(
"Switch for consumed enum token was not provided");
1266 reportDiag(diag::err_hlsl_invalid_token)
1268 return std::nullopt;
1270 }
while (tryConsumeExpectedToken(TokenKind::pu_or));
1275std::optional<llvm::dxbc::StaticSamplerFlags>
1276RootSignatureParser::parseStaticSamplerFlags(
TokenKind Context) {
1277 assert(CurToken.TokKind == TokenKind::pu_equal &&
1278 "Expects to only be invoked starting at given keyword");
1281 if (tryConsumeExpectedToken(TokenKind::int_literal)) {
1282 if (!verifyZeroFlag()) {
1283 reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
1284 return std::nullopt;
1286 return llvm::dxbc::StaticSamplerFlags::None;
1290#define STATIC_SAMPLER_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
1291#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1294 std::optional<llvm::dxbc::StaticSamplerFlags> Flags;
1297 if (tryConsumeExpectedToken(Expected)) {
1298 switch (CurToken.TokKind) {
1299#define STATIC_SAMPLER_FLAG_ENUM(NAME, LIT) \
1300 case TokenKind::en_##NAME: \
1301 Flags = maybeOrFlag<llvm::dxbc::StaticSamplerFlags>( \
1302 Flags, llvm::dxbc::StaticSamplerFlags::NAME); \
1304#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1306 llvm_unreachable(
"Switch for consumed enum token was not provided");
1310 reportDiag(diag::err_hlsl_invalid_token)
1312 return std::nullopt;
1314 }
while (tryConsumeExpectedToken(TokenKind::pu_or));
1319std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() {
1321 clang::NumericLiteralParser
Literal(
1322 CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),
1323 PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());
1325 return std::nullopt;
1327 assert(
Literal.isIntegerLiteral() &&
1328 "NumSpelling can only consist of digits");
1330 llvm::APSInt Val(32,
true);
1331 if (
Literal.GetIntegerValue(Val)) {
1333 reportDiag(diag::err_hlsl_number_literal_overflow)
1335 return std::nullopt;
1338 return Val.getExtValue();
1341std::optional<int32_t> RootSignatureParser::handleIntLiteral(
bool Negated) {
1343 clang::NumericLiteralParser
Literal(
1344 CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),
1345 PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());
1347 return std::nullopt;
1349 assert(
Literal.isIntegerLiteral() &&
1350 "NumSpelling can only consist of digits");
1352 llvm::APSInt Val(32,
true);
1355 bool Overflowed =
Literal.GetIntegerValue(Val);
1358 int64_t MaxNegativeMagnitude = -
int64_t(std::numeric_limits<int32_t>::min());
1359 Overflowed |= (Negated && MaxNegativeMagnitude < Val.getExtValue());
1361 int64_t MaxPositiveMagnitude =
int64_t(std::numeric_limits<int32_t>::max());
1362 Overflowed |= (!Negated && MaxPositiveMagnitude < Val.getExtValue());
1366 reportDiag(diag::err_hlsl_number_literal_overflow)
1368 return std::nullopt;
1374 return int32_t(Val.getExtValue());
1377std::optional<float> RootSignatureParser::handleFloatLiteral(
bool Negated) {
1379 clang::NumericLiteralParser
Literal(
1380 CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),
1381 PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());
1383 return std::nullopt;
1385 assert(
Literal.isFloatingLiteral() &&
1386 "NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
1387 "will be caught and reported by NumericLiteralParser.");
1391 auto DXCSemantics = llvm::APFloat::Semantics::S_IEEEdouble;
1392 auto DXCRoundingMode = llvm::RoundingMode::NearestTiesToEven;
1394 llvm::APFloat Val(llvm::APFloat::EnumToSemantics(DXCSemantics));
1395 llvm::APFloat::opStatus Status(
Literal.GetFloatValue(Val, DXCRoundingMode));
1399 assert(!(Status & llvm::APFloat::opStatus::opInvalidOp) &&
1400 "NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
1401 "will be caught and reported by NumericLiteralParser.");
1403 assert(!(Status & llvm::APFloat::opStatus::opDivByZero) &&
1404 "It is not possible for a division to be performed when "
1405 "constructing an APFloat from a string");
1407 if (Status & llvm::APFloat::opStatus::opUnderflow) {
1409 reportDiag(diag::err_hlsl_number_literal_underflow);
1410 return std::nullopt;
1413 if (Status & llvm::APFloat::opStatus::opOverflow) {
1415 reportDiag(diag::err_hlsl_number_literal_overflow) << 1;
1416 return std::nullopt;
1422 double DoubleVal = Val.convertToDouble();
1423 double FloatMax =
double(std::numeric_limits<float>::max());
1424 if (FloatMax < DoubleVal || DoubleVal < -FloatMax) {
1426 reportDiag(diag::err_hlsl_number_literal_overflow) << 1;
1427 return std::nullopt;
1430 return static_cast<float>(DoubleVal);
1433bool RootSignatureParser::verifyZeroFlag() {
1434 assert(CurToken.TokKind == TokenKind::int_literal);
1435 auto X = handleUIntLiteral();
1436 return X.has_value() &&
X.value() == 0;
1439bool RootSignatureParser::peekExpectedToken(
TokenKind Expected) {
1440 return peekExpectedToken(ArrayRef{Expected});
1443bool RootSignatureParser::peekExpectedToken(ArrayRef<TokenKind> AnyExpected) {
1444 RootSignatureToken
Result = Lexer.peekNextToken();
1445 return llvm::is_contained(AnyExpected,
Result.TokKind);
1448bool RootSignatureParser::consumeExpectedToken(
TokenKind Expected,
1451 if (tryConsumeExpectedToken(Expected))
1455 DiagnosticBuilder DB = reportDiag(DiagID);
1457 case diag::err_expected:
1460 case diag::err_expected_either:
1461 DB << Expected << Context;
1463 case diag::err_expected_after:
1464 DB << Context << Expected;
1472bool RootSignatureParser::tryConsumeExpectedToken(
TokenKind Expected) {
1473 return tryConsumeExpectedToken(ArrayRef{Expected});
1476bool RootSignatureParser::tryConsumeExpectedToken(
1477 ArrayRef<TokenKind> AnyExpected) {
1479 if (!peekExpectedToken(AnyExpected))
1485bool RootSignatureParser::skipUntilExpectedToken(
TokenKind Expected) {
1486 return skipUntilExpectedToken(ArrayRef{Expected});
1489bool RootSignatureParser::skipUntilExpectedToken(
1490 ArrayRef<TokenKind> AnyExpected) {
1492 while (!peekExpectedToken(AnyExpected)) {
1493 if (peekExpectedToken(TokenKind::end_of_stream))
1501bool RootSignatureParser::skipUntilClosedParens(uint32_t NumParens) {
1503 TokenKind::pu_l_paren,
1504 TokenKind::pu_r_paren,
1506 while (skipUntilExpectedToken(ParenKinds)) {
1508 if (CurToken.TokKind == TokenKind::pu_r_paren)
1520 return Signature->getLocationOfByte(
Tok.LocOffset, PP.getSourceManager(),
1521 PP.getLangOpts(), PP.getTargetInfo());
1525 llvm::dxbc::RootSignatureVersion Version,
1528 auto [DeclIdent,
Found] =
1563 while (P->getCurToken().getKind() != tok::eof)
1564 P->ConsumeAnyToken();
ASTConsumer - This is an abstract interface that should be implemented by clients that read ASTs.
virtual void HandleTranslationUnit(ASTContext &Ctx)
HandleTranslationUnit - This method is called when the ASTs for entire translation unit have been par...
virtual bool HandleTopLevelDecl(DeclGroupRef D)
HandleTopLevelDecl - Handle the specified top-level declaration.
TranslationUnitDecl * getTranslationUnitDecl() const
DiagnosticBuilder Report(SourceLocation Loc, unsigned DiagID)
Issue the message to the client.
One of these records is kept for each identifier that is lexed.
Parser - This implements a parser for the C family of languages.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
PreprocessorLexer * getCurrentLexer() const
Return the current lexer being lexed from.
void EnterMainSourceFile()
Enter the specified FileID as the main source file, which implicitly adds the builtin defines etc.
HLSLRootSignatureDecl * lookupRootSignatureOverrideDecl(DeclContext *DC) const
std::pair< IdentifierInfo *, bool > ActOnStartRootSignatureDecl(StringRef Signature)
Computes the unique Root Signature identifier from the given signature, then lookup if there is a pre...
void ActOnFinishRootSignatureDecl(SourceLocation Loc, IdentifierInfo *DeclIdent, ArrayRef< hlsl::RootSignatureElement > Elements)
Creates the Root Signature decl of the parsed Root Signature elements onto the AST and push it onto c...
Sema - This implements semantic analysis and AST building for C.
Preprocessor & getPreprocessor() const
DiagnosticsEngine & getDiagnostics() const
ASTContext & getASTContext() const
ASTConsumer & getASTConsumer() const
void ActOnStartOfTranslationUnit()
This is called before the very first declaration in the translation unit is parsed.
Encodes a location in the source.
StringLiteral - This represents a string literal expression, e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
StringRef getString() const
bool parse()
Consumes tokens from the Lexer and constructs the in-memory representations of the RootElements.
RootSignatureParser(llvm::dxbc::RootSignatureVersion Version, StringLiteral *Signature, Preprocessor &PP)
uint32_t Literal
Literals are represented as positive integers.
void HandleRootSignatureTarget(Sema &S, StringRef EntryRootSig)
IdentifierInfo * ParseHLSLRootSignature(Sema &Actions, llvm::dxbc::RootSignatureVersion Version, StringLiteral *Signature)
static FlagType maybeOrFlag(std::optional< FlagType > Flags, FlagType Flag)
static const TokenKind RootElementKeywords[]
RootSignatureToken::Kind TokenKind
The JSON file list parser is used to communicate input to InstallAPI.
@ Result
The result type of a method or function.
Visibility
Describes the different kinds of visibility that a declaration may have.