14using namespace llvm::hlsl::rootsig;
22 TokenKind::kw_RootFlags,
26 TokenKind::kw_DescriptorTable,
27 TokenKind::kw_StaticSampler,
31 llvm::dxbc::RootSignatureVersion Version,
StringLiteral *Signature,
33 : Version(Version), Signature(Signature),
Lexer(Signature->getString()),
34 PP(PP), CurToken(0) {}
39 bool HadError =
false;
40 while (!peekExpectedToken(TokenKind::end_of_stream)) {
41 if (tryConsumeExpectedToken(TokenKind::kw_RootFlags)) {
43 auto Flags = parseRootFlags();
44 if (!Flags.has_value()) {
50 Elements.emplace_back(ElementLoc, *Flags);
51 }
else if (tryConsumeExpectedToken(TokenKind::kw_RootConstants)) {
53 auto Constants = parseRootConstants();
54 if (!Constants.has_value()) {
59 Elements.emplace_back(ElementLoc, *Constants);
60 }
else if (tryConsumeExpectedToken(TokenKind::kw_DescriptorTable)) {
62 auto Table = parseDescriptorTable();
63 if (!Table.has_value()) {
67 skipUntilClosedParens();
72 Elements.emplace_back(ElementLoc, *Table);
73 }
else if (tryConsumeExpectedToken(
74 {TokenKind::kw_CBV, TokenKind::kw_SRV, TokenKind::kw_UAV})) {
76 auto Descriptor = parseRootDescriptor();
77 if (!Descriptor.has_value()) {
82 Elements.emplace_back(ElementLoc, *Descriptor);
83 }
else if (tryConsumeExpectedToken(TokenKind::kw_StaticSampler)) {
85 auto Sampler = parseStaticSampler();
86 if (!Sampler.has_value()) {
91 Elements.emplace_back(ElementLoc, *Sampler);
95 reportDiag(diag::err_hlsl_invalid_token)
96 << 0 << TokenKind::kw_RootSignature;
101 if (!tryConsumeExpectedToken(TokenKind::pu_comma)) {
108 consumeExpectedToken(TokenKind::end_of_stream,
109 diag::err_expected_either, TokenKind::pu_comma);
112template <
typename FlagType>
113static FlagType
maybeOrFlag(std::optional<FlagType> Flags, FlagType Flag) {
114 if (!Flags.has_value())
117 return static_cast<FlagType
>(llvm::to_underlying(Flags.value()) |
118 llvm::to_underlying(Flag));
121std::optional<llvm::dxbc::RootFlags> RootSignatureParser::parseRootFlags() {
122 assert(CurToken.
TokKind == TokenKind::kw_RootFlags &&
123 "Expects to only be invoked starting at given keyword");
125 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
129 std::optional<llvm::dxbc::RootFlags> Flags = llvm::dxbc::RootFlags::None;
132 if (tryConsumeExpectedToken(TokenKind::pu_r_paren))
136 if (tryConsumeExpectedToken(TokenKind::int_literal)) {
137 if (!verifyZeroFlag()) {
138 reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
144#define ROOT_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
145#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
149 if (tryConsumeExpectedToken(Expected)) {
151#define ROOT_FLAG_ENUM(NAME, LIT) \
152 case TokenKind::en_##NAME: \
153 Flags = maybeOrFlag<llvm::dxbc::RootFlags>(Flags, \
154 llvm::dxbc::RootFlags::NAME); \
156#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
158 llvm_unreachable(
"Switch for consumed enum token was not provided");
162 reportDiag(diag::err_hlsl_invalid_token)
163 << 1 << TokenKind::kw_RootFlags;
166 }
while (tryConsumeExpectedToken(TokenKind::pu_or));
169 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
170 TokenKind::pu_comma))
176std::optional<RootConstants> RootSignatureParser::parseRootConstants() {
177 assert(CurToken.
TokKind == TokenKind::kw_RootConstants &&
178 "Expects to only be invoked starting at given keyword");
180 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
184 RootConstants Constants;
186 auto Params = parseRootConstantParams();
187 if (!Params.has_value())
190 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
191 TokenKind::pu_comma))
195 if (!Params->Num32BitConstants.has_value()) {
196 reportDiag(diag::err_hlsl_rootsig_missing_param)
197 << TokenKind::kw_num32BitConstants;
201 Constants.Num32BitConstants = Params->Num32BitConstants.value();
203 if (!Params->Reg.has_value()) {
204 reportDiag(diag::err_hlsl_rootsig_missing_param) << TokenKind::bReg;
208 Constants.Reg = Params->Reg.value();
211 if (Params->Visibility.has_value())
212 Constants.Visibility = Params->Visibility.value();
214 if (Params->Space.has_value())
215 Constants.Space = Params->Space.value();
220std::optional<RootDescriptor> RootSignatureParser::parseRootDescriptor() {
221 assert((CurToken.
TokKind == TokenKind::kw_CBV ||
222 CurToken.
TokKind == TokenKind::kw_SRV ||
223 CurToken.
TokKind == TokenKind::kw_UAV) &&
224 "Expects to only be invoked starting at given keyword");
228 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
232 RootDescriptor Descriptor;
234 switch (DescriptorKind) {
236 llvm_unreachable(
"Switch for consumed token was not provided");
237 case TokenKind::kw_CBV:
238 Descriptor.Type = ResourceClass::CBuffer;
239 ExpectedReg = TokenKind::bReg;
241 case TokenKind::kw_SRV:
242 Descriptor.Type = ResourceClass::SRV;
243 ExpectedReg = TokenKind::tReg;
245 case TokenKind::kw_UAV:
246 Descriptor.Type = ResourceClass::UAV;
247 ExpectedReg = TokenKind::uReg;
250 Descriptor.setDefaultFlags(Version);
252 auto Params = parseRootDescriptorParams(DescriptorKind, ExpectedReg);
253 if (!Params.has_value())
256 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
257 TokenKind::pu_comma))
261 if (!Params->Reg.has_value()) {
262 reportDiag(diag::err_hlsl_rootsig_missing_param) << ExpectedReg;
266 Descriptor.Reg = Params->Reg.value();
269 if (Params->Space.has_value())
270 Descriptor.Space = Params->Space.value();
272 if (Params->Visibility.has_value())
273 Descriptor.Visibility = Params->Visibility.value();
275 if (Params->Flags.has_value())
276 Descriptor.Flags = Params->Flags.value();
281std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() {
282 assert(CurToken.
TokKind == TokenKind::kw_DescriptorTable &&
283 "Expects to only be invoked starting at given keyword");
285 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
289 DescriptorTable Table;
290 std::optional<llvm::dxbc::ShaderVisibility>
Visibility;
293 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
294 if (tryConsumeExpectedToken({TokenKind::kw_CBV, TokenKind::kw_SRV,
295 TokenKind::kw_UAV, TokenKind::kw_Sampler})) {
297 SourceLocation ElementLoc = getTokenLocation(CurToken);
298 auto Clause = parseDescriptorTableClause();
299 if (!Clause.has_value()) {
302 skipUntilExpectedToken(TokenKind::pu_r_paren);
306 Elements.emplace_back(ElementLoc, *Clause);
308 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
311 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
315 if (consumeExpectedToken(TokenKind::pu_equal))
318 Visibility = parseShaderVisibility(TokenKind::kw_visibility);
323 reportDiag(diag::err_hlsl_invalid_token)
324 << 0 << TokenKind::kw_DescriptorTable;
329 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
333 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
334 TokenKind::pu_comma))
344std::optional<DescriptorTableClause>
345RootSignatureParser::parseDescriptorTableClause() {
346 assert((CurToken.
TokKind == TokenKind::kw_CBV ||
347 CurToken.
TokKind == TokenKind::kw_SRV ||
348 CurToken.
TokKind == TokenKind::kw_UAV ||
349 CurToken.
TokKind == TokenKind::kw_Sampler) &&
350 "Expects to only be invoked starting at given keyword");
354 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
358 DescriptorTableClause Clause;
362 llvm_unreachable(
"Switch for consumed token was not provided");
363 case TokenKind::kw_CBV:
364 Clause.Type = ResourceClass::CBuffer;
365 ExpectedReg = TokenKind::bReg;
367 case TokenKind::kw_SRV:
368 Clause.Type = ResourceClass::SRV;
369 ExpectedReg = TokenKind::tReg;
371 case TokenKind::kw_UAV:
372 Clause.Type = ResourceClass::UAV;
373 ExpectedReg = TokenKind::uReg;
375 case TokenKind::kw_Sampler:
376 Clause.Type = ResourceClass::Sampler;
377 ExpectedReg = TokenKind::sReg;
380 Clause.setDefaultFlags(Version);
382 auto Params = parseDescriptorTableClauseParams(ParamKind, ExpectedReg);
383 if (!Params.has_value())
386 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
387 TokenKind::pu_comma))
391 if (!Params->Reg.has_value()) {
392 reportDiag(diag::err_hlsl_rootsig_missing_param) << ExpectedReg;
396 Clause.Reg = Params->Reg.value();
399 if (Params->NumDescriptors.has_value())
400 Clause.NumDescriptors = Params->NumDescriptors.value();
402 if (Params->Space.has_value())
403 Clause.Space = Params->Space.value();
405 if (Params->Offset.has_value())
406 Clause.Offset = Params->Offset.value();
408 if (Params->Flags.has_value())
409 Clause.Flags = Params->Flags.value();
414std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() {
415 assert(CurToken.
TokKind == TokenKind::kw_StaticSampler &&
416 "Expects to only be invoked starting at given keyword");
418 if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
422 StaticSampler Sampler;
424 auto Params = parseStaticSamplerParams();
425 if (!Params.has_value())
428 if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,
429 TokenKind::pu_comma))
433 if (!Params->Reg.has_value()) {
434 reportDiag(diag::err_hlsl_rootsig_missing_param) << TokenKind::sReg;
438 Sampler.Reg = Params->Reg.value();
441 if (Params->Filter.has_value())
442 Sampler.Filter = Params->Filter.value();
444 if (Params->AddressU.has_value())
445 Sampler.AddressU = Params->AddressU.value();
447 if (Params->AddressV.has_value())
448 Sampler.AddressV = Params->AddressV.value();
450 if (Params->AddressW.has_value())
451 Sampler.AddressW = Params->AddressW.value();
453 if (Params->MipLODBias.has_value())
454 Sampler.MipLODBias = Params->MipLODBias.value();
456 if (Params->MaxAnisotropy.has_value())
457 Sampler.MaxAnisotropy = Params->MaxAnisotropy.value();
459 if (Params->CompFunc.has_value())
460 Sampler.CompFunc = Params->CompFunc.value();
462 if (Params->BorderColor.has_value())
463 Sampler.BorderColor = Params->BorderColor.value();
465 if (Params->MinLOD.has_value())
466 Sampler.MinLOD = Params->MinLOD.value();
468 if (Params->MaxLOD.has_value())
469 Sampler.MaxLOD = Params->MaxLOD.value();
471 if (Params->Space.has_value())
472 Sampler.Space = Params->Space.value();
474 if (Params->Visibility.has_value())
475 Sampler.Visibility = Params->Visibility.value();
483std::optional<RootSignatureParser::ParsedConstantParams>
484RootSignatureParser::parseRootConstantParams() {
485 assert(CurToken.
TokKind == TokenKind::pu_l_paren &&
486 "Expects to only be invoked starting at given token");
488 ParsedConstantParams Params;
489 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
490 if (tryConsumeExpectedToken(TokenKind::kw_num32BitConstants)) {
492 if (Params.Num32BitConstants.has_value()) {
493 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
497 if (consumeExpectedToken(TokenKind::pu_equal))
500 auto Num32BitConstants = parseUIntParam();
501 if (!Num32BitConstants.has_value())
503 Params.Num32BitConstants = Num32BitConstants;
504 }
else if (tryConsumeExpectedToken(TokenKind::bReg)) {
506 if (Params.Reg.has_value()) {
507 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
510 auto Reg = parseRegister();
511 if (!Reg.has_value())
514 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
516 if (Params.Space.has_value()) {
517 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
521 if (consumeExpectedToken(TokenKind::pu_equal))
524 auto Space = parseUIntParam();
525 if (!Space.has_value())
527 Params.Space = Space;
528 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
530 if (Params.Visibility.has_value()) {
531 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
535 if (consumeExpectedToken(TokenKind::pu_equal))
538 auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
544 reportDiag(diag::err_hlsl_invalid_token)
545 << 0 << TokenKind::kw_RootConstants;
550 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
557std::optional<RootSignatureParser::ParsedRootDescriptorParams>
558RootSignatureParser::parseRootDescriptorParams(
TokenKind DescKind,
560 assert(CurToken.
TokKind == TokenKind::pu_l_paren &&
561 "Expects to only be invoked starting at given token");
563 ParsedRootDescriptorParams Params;
564 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
565 if (tryConsumeExpectedToken(RegType)) {
567 if (Params.Reg.has_value()) {
568 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
571 auto Reg = parseRegister();
572 if (!Reg.has_value())
575 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
577 if (Params.Space.has_value()) {
578 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
582 if (consumeExpectedToken(TokenKind::pu_equal))
585 auto Space = parseUIntParam();
586 if (!Space.has_value())
588 Params.Space = Space;
589 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
591 if (Params.Visibility.has_value()) {
592 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
596 if (consumeExpectedToken(TokenKind::pu_equal))
599 auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
603 }
else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
605 if (Params.Flags.has_value()) {
606 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
610 if (consumeExpectedToken(TokenKind::pu_equal))
613 auto Flags = parseRootDescriptorFlags(TokenKind::kw_flags);
614 if (!Flags.has_value())
616 Params.Flags = Flags;
619 reportDiag(diag::err_hlsl_invalid_token)
625 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
632std::optional<RootSignatureParser::ParsedClauseParams>
633RootSignatureParser::parseDescriptorTableClauseParams(
TokenKind ClauseKind,
635 assert(CurToken.
TokKind == TokenKind::pu_l_paren &&
636 "Expects to only be invoked starting at given token");
638 ParsedClauseParams Params;
639 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
640 if (tryConsumeExpectedToken(RegType)) {
642 if (Params.Reg.has_value()) {
643 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
646 auto Reg = parseRegister();
647 if (!Reg.has_value())
650 }
else if (tryConsumeExpectedToken(TokenKind::kw_numDescriptors)) {
652 if (Params.NumDescriptors.has_value()) {
653 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
657 if (consumeExpectedToken(TokenKind::pu_equal))
660 std::optional<uint32_t> NumDescriptors;
661 if (tryConsumeExpectedToken(TokenKind::en_unbounded))
662 NumDescriptors = NumDescriptorsUnbounded;
664 NumDescriptors = parseUIntParam();
665 if (!NumDescriptors.has_value())
669 Params.NumDescriptors = NumDescriptors;
670 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
672 if (Params.Space.has_value()) {
673 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
677 if (consumeExpectedToken(TokenKind::pu_equal))
680 auto Space = parseUIntParam();
681 if (!Space.has_value())
683 Params.Space = Space;
684 }
else if (tryConsumeExpectedToken(TokenKind::kw_offset)) {
686 if (Params.Offset.has_value()) {
687 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
691 if (consumeExpectedToken(TokenKind::pu_equal))
694 std::optional<uint32_t> Offset;
695 if (tryConsumeExpectedToken(TokenKind::en_DescriptorRangeOffsetAppend))
696 Offset = DescriptorTableOffsetAppend;
698 Offset = parseUIntParam();
699 if (!Offset.has_value())
703 Params.Offset = Offset;
704 }
else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
706 if (Params.Flags.has_value()) {
707 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
711 if (consumeExpectedToken(TokenKind::pu_equal))
714 auto Flags = parseDescriptorRangeFlags(TokenKind::kw_flags);
715 if (!Flags.has_value())
717 Params.Flags = Flags;
720 reportDiag(diag::err_hlsl_invalid_token)
726 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
733std::optional<RootSignatureParser::ParsedStaticSamplerParams>
734RootSignatureParser::parseStaticSamplerParams() {
735 assert(CurToken.
TokKind == TokenKind::pu_l_paren &&
736 "Expects to only be invoked starting at given token");
738 ParsedStaticSamplerParams Params;
739 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
740 if (tryConsumeExpectedToken(TokenKind::sReg)) {
742 if (Params.Reg.has_value()) {
743 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
746 auto Reg = parseRegister();
747 if (!Reg.has_value())
750 }
else if (tryConsumeExpectedToken(TokenKind::kw_filter)) {
752 if (Params.Filter.has_value()) {
753 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
757 if (consumeExpectedToken(TokenKind::pu_equal))
760 auto Filter = parseSamplerFilter(TokenKind::kw_filter);
764 }
else if (tryConsumeExpectedToken(TokenKind::kw_addressU)) {
766 if (Params.AddressU.has_value()) {
767 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
771 if (consumeExpectedToken(TokenKind::pu_equal))
774 auto AddressU = parseTextureAddressMode(TokenKind::kw_addressU);
775 if (!AddressU.has_value())
777 Params.AddressU = AddressU;
778 }
else if (tryConsumeExpectedToken(TokenKind::kw_addressV)) {
780 if (Params.AddressV.has_value()) {
781 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
785 if (consumeExpectedToken(TokenKind::pu_equal))
788 auto AddressV = parseTextureAddressMode(TokenKind::kw_addressV);
789 if (!AddressV.has_value())
791 Params.AddressV = AddressV;
792 }
else if (tryConsumeExpectedToken(TokenKind::kw_addressW)) {
794 if (Params.AddressW.has_value()) {
795 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
799 if (consumeExpectedToken(TokenKind::pu_equal))
802 auto AddressW = parseTextureAddressMode(TokenKind::kw_addressW);
803 if (!AddressW.has_value())
805 Params.AddressW = AddressW;
806 }
else if (tryConsumeExpectedToken(TokenKind::kw_mipLODBias)) {
808 if (Params.MipLODBias.has_value()) {
809 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
813 if (consumeExpectedToken(TokenKind::pu_equal))
816 auto MipLODBias = parseFloatParam();
817 if (!MipLODBias.has_value())
819 Params.MipLODBias = MipLODBias;
820 }
else if (tryConsumeExpectedToken(TokenKind::kw_maxAnisotropy)) {
822 if (Params.MaxAnisotropy.has_value()) {
823 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
827 if (consumeExpectedToken(TokenKind::pu_equal))
830 auto MaxAnisotropy = parseUIntParam();
831 if (!MaxAnisotropy.has_value())
833 Params.MaxAnisotropy = MaxAnisotropy;
834 }
else if (tryConsumeExpectedToken(TokenKind::kw_comparisonFunc)) {
836 if (Params.CompFunc.has_value()) {
837 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
841 if (consumeExpectedToken(TokenKind::pu_equal))
844 auto CompFunc = parseComparisonFunc(TokenKind::kw_comparisonFunc);
845 if (!CompFunc.has_value())
847 Params.CompFunc = CompFunc;
848 }
else if (tryConsumeExpectedToken(TokenKind::kw_borderColor)) {
850 if (Params.BorderColor.has_value()) {
851 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
855 if (consumeExpectedToken(TokenKind::pu_equal))
858 auto BorderColor = parseStaticBorderColor(TokenKind::kw_borderColor);
859 if (!BorderColor.has_value())
861 Params.BorderColor = BorderColor;
862 }
else if (tryConsumeExpectedToken(TokenKind::kw_minLOD)) {
864 if (Params.MinLOD.has_value()) {
865 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
869 if (consumeExpectedToken(TokenKind::pu_equal))
872 auto MinLOD = parseFloatParam();
873 if (!MinLOD.has_value())
875 Params.MinLOD = MinLOD;
876 }
else if (tryConsumeExpectedToken(TokenKind::kw_maxLOD)) {
878 if (Params.MaxLOD.has_value()) {
879 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
883 if (consumeExpectedToken(TokenKind::pu_equal))
886 auto MaxLOD = parseFloatParam();
887 if (!MaxLOD.has_value())
889 Params.MaxLOD = MaxLOD;
890 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
892 if (Params.Space.has_value()) {
893 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
897 if (consumeExpectedToken(TokenKind::pu_equal))
900 auto Space = parseUIntParam();
901 if (!Space.has_value())
903 Params.Space = Space;
904 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
906 if (Params.Visibility.has_value()) {
907 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.
TokKind;
911 if (consumeExpectedToken(TokenKind::pu_equal))
914 auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
920 reportDiag(diag::err_hlsl_invalid_token)
921 << 0 << TokenKind::kw_StaticSampler;
926 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
933std::optional<uint32_t> RootSignatureParser::parseUIntParam() {
934 assert(CurToken.
TokKind == TokenKind::pu_equal &&
935 "Expects to only be invoked starting at given keyword");
936 tryConsumeExpectedToken(TokenKind::pu_plus);
937 if (consumeExpectedToken(TokenKind::int_literal, diag::err_expected_after,
940 return handleUIntLiteral();
943std::optional<Register> RootSignatureParser::parseRegister() {
944 assert((CurToken.
TokKind == TokenKind::bReg ||
945 CurToken.
TokKind == TokenKind::tReg ||
946 CurToken.
TokKind == TokenKind::uReg ||
947 CurToken.
TokKind == TokenKind::sReg) &&
948 "Expects to only be invoked starting at given keyword");
953 llvm_unreachable(
"Switch for consumed token was not provided");
954 case TokenKind::bReg:
955 Reg.ViewType = RegisterType::BReg;
957 case TokenKind::tReg:
958 Reg.ViewType = RegisterType::TReg;
960 case TokenKind::uReg:
961 Reg.ViewType = RegisterType::UReg;
963 case TokenKind::sReg:
964 Reg.ViewType = RegisterType::SReg;
968 auto Number = handleUIntLiteral();
969 if (!Number.has_value())
972 Reg.Number = *Number;
976std::optional<float> RootSignatureParser::parseFloatParam() {
977 assert(CurToken.
TokKind == TokenKind::pu_equal &&
978 "Expects to only be invoked starting at given keyword");
981 tryConsumeExpectedToken({TokenKind::pu_plus, TokenKind::pu_minus});
982 bool Negated =
Signed && CurToken.
TokKind == TokenKind::pu_minus;
985 if (!Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {
986 std::optional<uint32_t> UInt = handleUIntLiteral();
987 if (!UInt.has_value())
989 return float(UInt.value());
992 if (Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {
993 std::optional<int32_t>
Int = handleIntLiteral(Negated);
994 if (!
Int.has_value())
999 if (tryConsumeExpectedToken(TokenKind::float_literal)) {
1000 std::optional<float>
Float = handleFloatLiteral(Negated);
1001 if (!
Float.has_value())
1002 return std::nullopt;
1003 return Float.value();
1006 return std::nullopt;
1009std::optional<llvm::dxbc::ShaderVisibility>
1010RootSignatureParser::parseShaderVisibility(
TokenKind Context) {
1011 assert(CurToken.
TokKind == TokenKind::pu_equal &&
1012 "Expects to only be invoked starting at given keyword");
1015#define SHADER_VISIBILITY_ENUM(NAME, LIT) TokenKind::en_##NAME,
1016#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1019 if (!tryConsumeExpectedToken(Expected)) {
1021 reportDiag(diag::err_hlsl_invalid_token)
1023 return std::nullopt;
1027#define SHADER_VISIBILITY_ENUM(NAME, LIT) \
1028 case TokenKind::en_##NAME: \
1029 return llvm::dxbc::ShaderVisibility::NAME; \
1031#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1033 llvm_unreachable(
"Switch for consumed enum token was not provided");
1036 return std::nullopt;
1039std::optional<llvm::dxbc::SamplerFilter>
1040RootSignatureParser::parseSamplerFilter(
TokenKind Context) {
1041 assert(CurToken.
TokKind == TokenKind::pu_equal &&
1042 "Expects to only be invoked starting at given keyword");
1045#define FILTER_ENUM(NAME, LIT) TokenKind::en_##NAME,
1046#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1049 if (!tryConsumeExpectedToken(Expected)) {
1051 reportDiag(diag::err_hlsl_invalid_token)
1053 return std::nullopt;
1057#define FILTER_ENUM(NAME, LIT) \
1058 case TokenKind::en_##NAME: \
1059 return llvm::dxbc::SamplerFilter::NAME; \
1061#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1063 llvm_unreachable(
"Switch for consumed enum token was not provided");
1066 return std::nullopt;
1069std::optional<llvm::dxbc::TextureAddressMode>
1070RootSignatureParser::parseTextureAddressMode(
TokenKind Context) {
1071 assert(CurToken.
TokKind == TokenKind::pu_equal &&
1072 "Expects to only be invoked starting at given keyword");
1075#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) TokenKind::en_##NAME,
1076#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1079 if (!tryConsumeExpectedToken(Expected)) {
1081 reportDiag(diag::err_hlsl_invalid_token)
1083 return std::nullopt;
1087#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) \
1088 case TokenKind::en_##NAME: \
1089 return llvm::dxbc::TextureAddressMode::NAME; \
1091#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1093 llvm_unreachable(
"Switch for consumed enum token was not provided");
1096 return std::nullopt;
1099std::optional<llvm::dxbc::ComparisonFunc>
1100RootSignatureParser::parseComparisonFunc(
TokenKind Context) {
1101 assert(CurToken.
TokKind == TokenKind::pu_equal &&
1102 "Expects to only be invoked starting at given keyword");
1105#define COMPARISON_FUNC_ENUM(NAME, LIT) TokenKind::en_##NAME,
1106#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1109 if (!tryConsumeExpectedToken(Expected)) {
1111 reportDiag(diag::err_hlsl_invalid_token)
1113 return std::nullopt;
1117#define COMPARISON_FUNC_ENUM(NAME, LIT) \
1118 case TokenKind::en_##NAME: \
1119 return llvm::dxbc::ComparisonFunc::NAME; \
1121#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1123 llvm_unreachable(
"Switch for consumed enum token was not provided");
1126 return std::nullopt;
1129std::optional<llvm::dxbc::StaticBorderColor>
1130RootSignatureParser::parseStaticBorderColor(
TokenKind Context) {
1131 assert(CurToken.
TokKind == TokenKind::pu_equal &&
1132 "Expects to only be invoked starting at given keyword");
1135#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) TokenKind::en_##NAME,
1136#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1139 if (!tryConsumeExpectedToken(Expected)) {
1141 reportDiag(diag::err_hlsl_invalid_token)
1143 return std::nullopt;
1147#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) \
1148 case TokenKind::en_##NAME: \
1149 return llvm::dxbc::StaticBorderColor::NAME; \
1151#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1153 llvm_unreachable(
"Switch for consumed enum token was not provided");
1156 return std::nullopt;
1159std::optional<llvm::dxbc::RootDescriptorFlags>
1160RootSignatureParser::parseRootDescriptorFlags(
TokenKind Context) {
1161 assert(CurToken.
TokKind == TokenKind::pu_equal &&
1162 "Expects to only be invoked starting at given keyword");
1165 if (tryConsumeExpectedToken(TokenKind::int_literal)) {
1166 if (!verifyZeroFlag()) {
1167 reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
1168 return std::nullopt;
1170 return llvm::dxbc::RootDescriptorFlags::None;
1174#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
1175#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1178 std::optional<llvm::dxbc::RootDescriptorFlags> Flags;
1181 if (tryConsumeExpectedToken(Expected)) {
1183#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) \
1184 case TokenKind::en_##NAME: \
1185 Flags = maybeOrFlag<llvm::dxbc::RootDescriptorFlags>( \
1186 Flags, llvm::dxbc::RootDescriptorFlags::NAME); \
1188#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1190 llvm_unreachable(
"Switch for consumed enum token was not provided");
1194 reportDiag(diag::err_hlsl_invalid_token)
1196 return std::nullopt;
1198 }
while (tryConsumeExpectedToken(TokenKind::pu_or));
1203std::optional<llvm::dxbc::DescriptorRangeFlags>
1204RootSignatureParser::parseDescriptorRangeFlags(
TokenKind Context) {
1205 assert(CurToken.
TokKind == TokenKind::pu_equal &&
1206 "Expects to only be invoked starting at given keyword");
1209 if (tryConsumeExpectedToken(TokenKind::int_literal)) {
1210 if (!verifyZeroFlag()) {
1211 reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
1212 return std::nullopt;
1214 return llvm::dxbc::DescriptorRangeFlags::None;
1218#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) TokenKind::en_##NAME,
1219#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1222 std::optional<llvm::dxbc::DescriptorRangeFlags> Flags;
1225 if (tryConsumeExpectedToken(Expected)) {
1227#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) \
1228 case TokenKind::en_##NAME: \
1229 Flags = maybeOrFlag<llvm::dxbc::DescriptorRangeFlags>( \
1230 Flags, llvm::dxbc::DescriptorRangeFlags::NAME); \
1232#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1234 llvm_unreachable(
"Switch for consumed enum token was not provided");
1238 reportDiag(diag::err_hlsl_invalid_token)
1240 return std::nullopt;
1242 }
while (tryConsumeExpectedToken(TokenKind::pu_or));
1247std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() {
1253 return std::nullopt;
1255 assert(
Literal.isIntegerLiteral() &&
1256 "NumSpelling can only consist of digits");
1258 llvm::APSInt Val(32,
true);
1259 if (
Literal.GetIntegerValue(Val)) {
1261 reportDiag(diag::err_hlsl_number_literal_overflow)
1263 return std::nullopt;
1266 return Val.getExtValue();
1269std::optional<int32_t> RootSignatureParser::handleIntLiteral(
bool Negated) {
1275 return std::nullopt;
1277 assert(
Literal.isIntegerLiteral() &&
1278 "NumSpelling can only consist of digits");
1280 llvm::APSInt Val(32,
true);
1283 bool Overflowed =
Literal.GetIntegerValue(Val);
1286 int64_t MaxNegativeMagnitude = -
int64_t(std::numeric_limits<int32_t>::min());
1287 Overflowed |= (Negated && MaxNegativeMagnitude < Val.getExtValue());
1289 int64_t MaxPositiveMagnitude =
int64_t(std::numeric_limits<int32_t>::max());
1290 Overflowed |= (!Negated && MaxPositiveMagnitude < Val.getExtValue());
1294 reportDiag(diag::err_hlsl_number_literal_overflow)
1296 return std::nullopt;
1302 return int32_t(Val.getExtValue());
1305std::optional<float> RootSignatureParser::handleFloatLiteral(
bool Negated) {
1311 return std::nullopt;
1313 assert(
Literal.isFloatingLiteral() &&
1314 "NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
1315 "will be caught and reported by NumericLiteralParser.");
1319 auto DXCSemantics = llvm::APFloat::Semantics::S_IEEEdouble;
1320 auto DXCRoundingMode = llvm::RoundingMode::NearestTiesToEven;
1322 llvm::APFloat Val(llvm::APFloat::EnumToSemantics(DXCSemantics));
1323 llvm::APFloat::opStatus Status(
Literal.GetFloatValue(Val, DXCRoundingMode));
1327 assert(!(Status & llvm::APFloat::opStatus::opInvalidOp) &&
1328 "NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
1329 "will be caught and reported by NumericLiteralParser.");
1331 assert(!(Status & llvm::APFloat::opStatus::opDivByZero) &&
1332 "It is not possible for a division to be performed when "
1333 "constructing an APFloat from a string");
1335 if (Status & llvm::APFloat::opStatus::opUnderflow) {
1337 reportDiag(diag::err_hlsl_number_literal_underflow);
1338 return std::nullopt;
1341 if (Status & llvm::APFloat::opStatus::opOverflow) {
1343 reportDiag(diag::err_hlsl_number_literal_overflow) << 1;
1344 return std::nullopt;
1350 double DoubleVal = Val.convertToDouble();
1351 double FloatMax =
double(std::numeric_limits<float>::max());
1352 if (FloatMax < DoubleVal || DoubleVal < -FloatMax) {
1354 reportDiag(diag::err_hlsl_number_literal_overflow) << 1;
1355 return std::nullopt;
1358 return static_cast<float>(DoubleVal);
1361bool RootSignatureParser::verifyZeroFlag() {
1362 assert(CurToken.
TokKind == TokenKind::int_literal);
1363 auto X = handleUIntLiteral();
1364 return X.has_value() &&
X.value() == 0;
1367bool RootSignatureParser::peekExpectedToken(
TokenKind Expected) {
1368 return peekExpectedToken(ArrayRef{Expected});
1371bool RootSignatureParser::peekExpectedToken(ArrayRef<TokenKind> AnyExpected) {
1373 return llvm::is_contained(AnyExpected,
Result.TokKind);
1376bool RootSignatureParser::consumeExpectedToken(
TokenKind Expected,
1379 if (tryConsumeExpectedToken(Expected))
1385 case diag::err_expected:
1388 case diag::err_expected_either:
1389 DB << Expected << Context;
1391 case diag::err_expected_after:
1392 DB << Context << Expected;
1400bool RootSignatureParser::tryConsumeExpectedToken(
TokenKind Expected) {
1401 return tryConsumeExpectedToken(ArrayRef{Expected});
1404bool RootSignatureParser::tryConsumeExpectedToken(
1405 ArrayRef<TokenKind> AnyExpected) {
1407 if (!peekExpectedToken(AnyExpected))
1413bool RootSignatureParser::skipUntilExpectedToken(
TokenKind Expected) {
1414 return skipUntilExpectedToken(ArrayRef{Expected});
1417bool RootSignatureParser::skipUntilExpectedToken(
1418 ArrayRef<TokenKind> AnyExpected) {
1420 while (!peekExpectedToken(AnyExpected)) {
1421 if (peekExpectedToken(TokenKind::end_of_stream))
1429bool RootSignatureParser::skipUntilClosedParens(uint32_t NumParens) {
1431 TokenKind::pu_l_paren,
1432 TokenKind::pu_r_paren,
1434 while (skipUntilExpectedToken(ParenKinds)) {
1436 if (CurToken.
TokKind == TokenKind::pu_r_paren)
1447SourceLocation RootSignatureParser::getTokenLocation(RootSignatureToken Tok) {
1453 llvm::dxbc::RootSignatureVersion Version,
1456 auto [DeclIdent,
Found] =
Class to make it convenient to initialize TrapReason objects which can be used to attach the "trap re...
One of these records is kept for each identifier that is lexed.
Lexer - This provides a simple interface that turns a text buffer into a stream of tokens.
NumericLiteralParser - This performs strict semantic analysis of the content of a ppnumber,...
Parser - This implements a parser for the C family of languages.
Engages in a tight little dance with the lexer to efficiently preprocess tokens.
SourceManager & getSourceManager() const
const TargetInfo & getTargetInfo() const
const LangOptions & getLangOpts() const
DiagnosticsEngine & getDiagnostics() 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
Encodes a location in the source.
StringLiteral - This represents a string literal expression, e.g.
SourceLocation getBeginLoc() const LLVM_READONLY
SourceLocation getLocationOfByte(unsigned ByteNo, const SourceManager &SM, const LangOptions &Features, const TargetInfo &Target, unsigned *StartToken=nullptr, unsigned *StartTokenByteOffset=nullptr) const
getLocationOfByte - Return a source location that points to the specified byte of this string literal...
StringRef getString() const
RootSignatureToken peekNextToken()
Returns the token that proceeds CurToken.
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.
RootSignatureToken::Kind TokenKind
IdentifierInfo * ParseHLSLRootSignature(Sema &Actions, llvm::dxbc::RootSignatureVersion Version, StringLiteral *Signature)
static FlagType maybeOrFlag(std::optional< FlagType > Flags, FlagType Flag)
static const TokenKind RootElementKeywords[]
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.