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();
494std::optional<RootSignatureParser::ParsedConstantParams>
495RootSignatureParser::parseRootConstantParams() {
496 assert(CurToken.TokKind == TokenKind::pu_l_paren &&
497 "Expects to only be invoked starting at given token");
499 ParsedConstantParams Params;
500 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
501 if (tryConsumeExpectedToken(TokenKind::kw_num32BitConstants)) {
503 if (Params.Num32BitConstants.has_value()) {
504 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
508 if (consumeExpectedToken(TokenKind::pu_equal))
511 auto Num32BitConstants = parseUIntParam();
512 if (!Num32BitConstants.has_value())
514 Params.Num32BitConstants = Num32BitConstants;
515 }
else if (tryConsumeExpectedToken(TokenKind::bReg)) {
517 if (Params.Reg.has_value()) {
518 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
521 auto Reg = parseRegister();
522 if (!Reg.has_value())
525 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
527 if (Params.Space.has_value()) {
528 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
532 if (consumeExpectedToken(TokenKind::pu_equal))
535 auto Space = parseUIntParam();
536 if (!Space.has_value())
538 Params.Space = Space;
539 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
541 if (Params.Visibility.has_value()) {
542 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
546 if (consumeExpectedToken(TokenKind::pu_equal))
549 auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
555 reportDiag(diag::err_hlsl_invalid_token)
556 << 0 << TokenKind::kw_RootConstants;
561 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
568std::optional<RootSignatureParser::ParsedRootDescriptorParams>
569RootSignatureParser::parseRootDescriptorParams(
TokenKind DescKind,
571 assert(CurToken.TokKind == TokenKind::pu_l_paren &&
572 "Expects to only be invoked starting at given token");
574 ParsedRootDescriptorParams Params;
575 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
576 if (tryConsumeExpectedToken(RegType)) {
578 if (Params.Reg.has_value()) {
579 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
582 auto Reg = parseRegister();
583 if (!Reg.has_value())
586 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
588 if (Params.Space.has_value()) {
589 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
593 if (consumeExpectedToken(TokenKind::pu_equal))
596 auto Space = parseUIntParam();
597 if (!Space.has_value())
599 Params.Space = Space;
600 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
602 if (Params.Visibility.has_value()) {
603 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
607 if (consumeExpectedToken(TokenKind::pu_equal))
610 auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
614 }
else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
616 if (Params.Flags.has_value()) {
617 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
621 if (consumeExpectedToken(TokenKind::pu_equal))
624 auto Flags = parseRootDescriptorFlags(TokenKind::kw_flags);
625 if (!Flags.has_value())
627 Params.Flags = Flags;
630 reportDiag(diag::err_hlsl_invalid_token)
636 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
643std::optional<RootSignatureParser::ParsedClauseParams>
644RootSignatureParser::parseDescriptorTableClauseParams(
TokenKind ClauseKind,
646 assert(CurToken.TokKind == TokenKind::pu_l_paren &&
647 "Expects to only be invoked starting at given token");
649 ParsedClauseParams Params;
650 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
651 if (tryConsumeExpectedToken(RegType)) {
653 if (Params.Reg.has_value()) {
654 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
657 auto Reg = parseRegister();
658 if (!Reg.has_value())
661 }
else if (tryConsumeExpectedToken(TokenKind::kw_numDescriptors)) {
663 if (Params.NumDescriptors.has_value()) {
664 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
668 if (consumeExpectedToken(TokenKind::pu_equal))
671 std::optional<uint32_t> NumDescriptors;
672 if (tryConsumeExpectedToken(TokenKind::en_unbounded))
673 NumDescriptors = NumDescriptorsUnbounded;
675 NumDescriptors = parseUIntParam();
676 if (!NumDescriptors.has_value())
680 Params.NumDescriptors = NumDescriptors;
681 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
683 if (Params.Space.has_value()) {
684 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
688 if (consumeExpectedToken(TokenKind::pu_equal))
691 auto Space = parseUIntParam();
692 if (!Space.has_value())
694 Params.Space = Space;
695 }
else if (tryConsumeExpectedToken(TokenKind::kw_offset)) {
697 if (Params.Offset.has_value()) {
698 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
702 if (consumeExpectedToken(TokenKind::pu_equal))
705 std::optional<uint32_t> Offset;
706 if (tryConsumeExpectedToken(TokenKind::en_DescriptorRangeOffsetAppend))
707 Offset = DescriptorTableOffsetAppend;
709 Offset = parseUIntParam();
710 if (!Offset.has_value())
714 Params.Offset = Offset;
715 }
else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
717 if (Params.Flags.has_value()) {
718 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
722 if (consumeExpectedToken(TokenKind::pu_equal))
725 auto Flags = parseDescriptorRangeFlags(TokenKind::kw_flags);
726 if (!Flags.has_value())
728 Params.Flags = Flags;
731 reportDiag(diag::err_hlsl_invalid_token)
737 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
744std::optional<RootSignatureParser::ParsedStaticSamplerParams>
745RootSignatureParser::parseStaticSamplerParams() {
746 assert(CurToken.TokKind == TokenKind::pu_l_paren &&
747 "Expects to only be invoked starting at given token");
749 ParsedStaticSamplerParams Params;
750 while (!peekExpectedToken(TokenKind::pu_r_paren)) {
751 if (tryConsumeExpectedToken(TokenKind::sReg)) {
753 if (Params.Reg.has_value()) {
754 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
757 auto Reg = parseRegister();
758 if (!Reg.has_value())
761 }
else if (tryConsumeExpectedToken(TokenKind::kw_filter)) {
763 if (Params.Filter.has_value()) {
764 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
768 if (consumeExpectedToken(TokenKind::pu_equal))
771 auto Filter = parseSamplerFilter(TokenKind::kw_filter);
775 }
else if (tryConsumeExpectedToken(TokenKind::kw_addressU)) {
777 if (Params.AddressU.has_value()) {
778 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
782 if (consumeExpectedToken(TokenKind::pu_equal))
785 auto AddressU = parseTextureAddressMode(TokenKind::kw_addressU);
786 if (!AddressU.has_value())
788 Params.AddressU = AddressU;
789 }
else if (tryConsumeExpectedToken(TokenKind::kw_addressV)) {
791 if (Params.AddressV.has_value()) {
792 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
796 if (consumeExpectedToken(TokenKind::pu_equal))
799 auto AddressV = parseTextureAddressMode(TokenKind::kw_addressV);
800 if (!AddressV.has_value())
802 Params.AddressV = AddressV;
803 }
else if (tryConsumeExpectedToken(TokenKind::kw_addressW)) {
805 if (Params.AddressW.has_value()) {
806 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
810 if (consumeExpectedToken(TokenKind::pu_equal))
813 auto AddressW = parseTextureAddressMode(TokenKind::kw_addressW);
814 if (!AddressW.has_value())
816 Params.AddressW = AddressW;
817 }
else if (tryConsumeExpectedToken(TokenKind::kw_mipLODBias)) {
819 if (Params.MipLODBias.has_value()) {
820 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
824 if (consumeExpectedToken(TokenKind::pu_equal))
827 auto MipLODBias = parseFloatParam();
828 if (!MipLODBias.has_value())
830 Params.MipLODBias = MipLODBias;
831 }
else if (tryConsumeExpectedToken(TokenKind::kw_maxAnisotropy)) {
833 if (Params.MaxAnisotropy.has_value()) {
834 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
838 if (consumeExpectedToken(TokenKind::pu_equal))
841 auto MaxAnisotropy = parseUIntParam();
842 if (!MaxAnisotropy.has_value())
844 Params.MaxAnisotropy = MaxAnisotropy;
845 }
else if (tryConsumeExpectedToken(TokenKind::kw_comparisonFunc)) {
847 if (Params.CompFunc.has_value()) {
848 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
852 if (consumeExpectedToken(TokenKind::pu_equal))
855 auto CompFunc = parseComparisonFunc(TokenKind::kw_comparisonFunc);
856 if (!CompFunc.has_value())
858 Params.CompFunc = CompFunc;
859 }
else if (tryConsumeExpectedToken(TokenKind::kw_borderColor)) {
861 if (Params.BorderColor.has_value()) {
862 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
866 if (consumeExpectedToken(TokenKind::pu_equal))
869 auto BorderColor = parseStaticBorderColor(TokenKind::kw_borderColor);
870 if (!BorderColor.has_value())
872 Params.BorderColor = BorderColor;
873 }
else if (tryConsumeExpectedToken(TokenKind::kw_minLOD)) {
875 if (Params.MinLOD.has_value()) {
876 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
880 if (consumeExpectedToken(TokenKind::pu_equal))
883 auto MinLOD = parseFloatParam();
884 if (!MinLOD.has_value())
886 Params.MinLOD = MinLOD;
887 }
else if (tryConsumeExpectedToken(TokenKind::kw_maxLOD)) {
889 if (Params.MaxLOD.has_value()) {
890 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
894 if (consumeExpectedToken(TokenKind::pu_equal))
897 auto MaxLOD = parseFloatParam();
898 if (!MaxLOD.has_value())
900 Params.MaxLOD = MaxLOD;
901 }
else if (tryConsumeExpectedToken(TokenKind::kw_space)) {
903 if (Params.Space.has_value()) {
904 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
908 if (consumeExpectedToken(TokenKind::pu_equal))
911 auto Space = parseUIntParam();
912 if (!Space.has_value())
914 Params.Space = Space;
915 }
else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
917 if (Params.Visibility.has_value()) {
918 reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;
922 if (consumeExpectedToken(TokenKind::pu_equal))
925 auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);
931 reportDiag(diag::err_hlsl_invalid_token)
932 << 0 << TokenKind::kw_StaticSampler;
937 if (!tryConsumeExpectedToken(TokenKind::pu_comma))
944std::optional<uint32_t> RootSignatureParser::parseUIntParam() {
945 assert(CurToken.TokKind == TokenKind::pu_equal &&
946 "Expects to only be invoked starting at given keyword");
947 tryConsumeExpectedToken(TokenKind::pu_plus);
948 if (consumeExpectedToken(TokenKind::int_literal, diag::err_expected_after,
951 return handleUIntLiteral();
954std::optional<Register> RootSignatureParser::parseRegister() {
955 assert((CurToken.TokKind == TokenKind::bReg ||
956 CurToken.TokKind == TokenKind::tReg ||
957 CurToken.TokKind == TokenKind::uReg ||
958 CurToken.TokKind == TokenKind::sReg) &&
959 "Expects to only be invoked starting at given keyword");
962 switch (CurToken.TokKind) {
964 llvm_unreachable(
"Switch for consumed token was not provided");
965 case TokenKind::bReg:
966 Reg.ViewType = RegisterType::BReg;
968 case TokenKind::tReg:
969 Reg.ViewType = RegisterType::TReg;
971 case TokenKind::uReg:
972 Reg.ViewType = RegisterType::UReg;
974 case TokenKind::sReg:
975 Reg.ViewType = RegisterType::SReg;
979 auto Number = handleUIntLiteral();
980 if (!Number.has_value())
983 Reg.Number = *Number;
987std::optional<float> RootSignatureParser::parseFloatParam() {
988 assert(CurToken.TokKind == TokenKind::pu_equal &&
989 "Expects to only be invoked starting at given keyword");
992 tryConsumeExpectedToken({TokenKind::pu_plus, TokenKind::pu_minus});
993 bool Negated =
Signed && CurToken.TokKind == TokenKind::pu_minus;
996 if (!Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {
997 std::optional<uint32_t> UInt = handleUIntLiteral();
998 if (!UInt.has_value())
1000 return float(UInt.value());
1003 if (Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {
1004 std::optional<int32_t>
Int = handleIntLiteral(Negated);
1005 if (!
Int.has_value())
1006 return std::nullopt;
1010 if (tryConsumeExpectedToken(TokenKind::float_literal)) {
1011 std::optional<float>
Float = handleFloatLiteral(Negated);
1012 if (!
Float.has_value())
1013 return std::nullopt;
1014 return Float.value();
1017 return std::nullopt;
1020std::optional<llvm::dxbc::ShaderVisibility>
1021RootSignatureParser::parseShaderVisibility(
TokenKind Context) {
1022 assert(CurToken.TokKind == TokenKind::pu_equal &&
1023 "Expects to only be invoked starting at given keyword");
1026#define SHADER_VISIBILITY_ENUM(NAME, LIT) TokenKind::en_##NAME,
1027#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1030 if (!tryConsumeExpectedToken(Expected)) {
1032 reportDiag(diag::err_hlsl_invalid_token)
1034 return std::nullopt;
1037 switch (CurToken.TokKind) {
1038#define SHADER_VISIBILITY_ENUM(NAME, LIT) \
1039 case TokenKind::en_##NAME: \
1040 return llvm::dxbc::ShaderVisibility::NAME; \
1042#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1044 llvm_unreachable(
"Switch for consumed enum token was not provided");
1047 return std::nullopt;
1050std::optional<llvm::dxbc::SamplerFilter>
1051RootSignatureParser::parseSamplerFilter(
TokenKind Context) {
1052 assert(CurToken.TokKind == TokenKind::pu_equal &&
1053 "Expects to only be invoked starting at given keyword");
1056#define FILTER_ENUM(NAME, LIT) TokenKind::en_##NAME,
1057#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1060 if (!tryConsumeExpectedToken(Expected)) {
1062 reportDiag(diag::err_hlsl_invalid_token)
1064 return std::nullopt;
1067 switch (CurToken.TokKind) {
1068#define FILTER_ENUM(NAME, LIT) \
1069 case TokenKind::en_##NAME: \
1070 return llvm::dxbc::SamplerFilter::NAME; \
1072#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1074 llvm_unreachable(
"Switch for consumed enum token was not provided");
1077 return std::nullopt;
1080std::optional<llvm::dxbc::TextureAddressMode>
1081RootSignatureParser::parseTextureAddressMode(
TokenKind Context) {
1082 assert(CurToken.TokKind == TokenKind::pu_equal &&
1083 "Expects to only be invoked starting at given keyword");
1086#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) TokenKind::en_##NAME,
1087#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1090 if (!tryConsumeExpectedToken(Expected)) {
1092 reportDiag(diag::err_hlsl_invalid_token)
1094 return std::nullopt;
1097 switch (CurToken.TokKind) {
1098#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) \
1099 case TokenKind::en_##NAME: \
1100 return llvm::dxbc::TextureAddressMode::NAME; \
1102#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1104 llvm_unreachable(
"Switch for consumed enum token was not provided");
1107 return std::nullopt;
1110std::optional<llvm::dxbc::ComparisonFunc>
1111RootSignatureParser::parseComparisonFunc(
TokenKind Context) {
1112 assert(CurToken.TokKind == TokenKind::pu_equal &&
1113 "Expects to only be invoked starting at given keyword");
1116#define COMPARISON_FUNC_ENUM(NAME, LIT) TokenKind::en_##NAME,
1117#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1120 if (!tryConsumeExpectedToken(Expected)) {
1122 reportDiag(diag::err_hlsl_invalid_token)
1124 return std::nullopt;
1127 switch (CurToken.TokKind) {
1128#define COMPARISON_FUNC_ENUM(NAME, LIT) \
1129 case TokenKind::en_##NAME: \
1130 return llvm::dxbc::ComparisonFunc::NAME; \
1132#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1134 llvm_unreachable(
"Switch for consumed enum token was not provided");
1137 return std::nullopt;
1140std::optional<llvm::dxbc::StaticBorderColor>
1141RootSignatureParser::parseStaticBorderColor(
TokenKind Context) {
1142 assert(CurToken.TokKind == TokenKind::pu_equal &&
1143 "Expects to only be invoked starting at given keyword");
1146#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) TokenKind::en_##NAME,
1147#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1150 if (!tryConsumeExpectedToken(Expected)) {
1152 reportDiag(diag::err_hlsl_invalid_token)
1154 return std::nullopt;
1157 switch (CurToken.TokKind) {
1158#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) \
1159 case TokenKind::en_##NAME: \
1160 return llvm::dxbc::StaticBorderColor::NAME; \
1162#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1164 llvm_unreachable(
"Switch for consumed enum token was not provided");
1167 return std::nullopt;
1170std::optional<llvm::dxbc::RootDescriptorFlags>
1171RootSignatureParser::parseRootDescriptorFlags(
TokenKind Context) {
1172 assert(CurToken.TokKind == TokenKind::pu_equal &&
1173 "Expects to only be invoked starting at given keyword");
1176 if (tryConsumeExpectedToken(TokenKind::int_literal)) {
1177 if (!verifyZeroFlag()) {
1178 reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
1179 return std::nullopt;
1181 return llvm::dxbc::RootDescriptorFlags::None;
1185#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
1186#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1189 std::optional<llvm::dxbc::RootDescriptorFlags> Flags;
1192 if (tryConsumeExpectedToken(Expected)) {
1193 switch (CurToken.TokKind) {
1194#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) \
1195 case TokenKind::en_##NAME: \
1196 Flags = maybeOrFlag<llvm::dxbc::RootDescriptorFlags>( \
1197 Flags, llvm::dxbc::RootDescriptorFlags::NAME); \
1199#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1201 llvm_unreachable(
"Switch for consumed enum token was not provided");
1205 reportDiag(diag::err_hlsl_invalid_token)
1207 return std::nullopt;
1209 }
while (tryConsumeExpectedToken(TokenKind::pu_or));
1214std::optional<llvm::dxbc::DescriptorRangeFlags>
1215RootSignatureParser::parseDescriptorRangeFlags(
TokenKind Context) {
1216 assert(CurToken.TokKind == TokenKind::pu_equal &&
1217 "Expects to only be invoked starting at given keyword");
1220 if (tryConsumeExpectedToken(TokenKind::int_literal)) {
1221 if (!verifyZeroFlag()) {
1222 reportDiag(diag::err_hlsl_rootsig_non_zero_flag);
1223 return std::nullopt;
1225 return llvm::dxbc::DescriptorRangeFlags::None;
1229#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) TokenKind::en_##NAME,
1230#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1233 std::optional<llvm::dxbc::DescriptorRangeFlags> Flags;
1236 if (tryConsumeExpectedToken(Expected)) {
1237 switch (CurToken.TokKind) {
1238#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) \
1239 case TokenKind::en_##NAME: \
1240 Flags = maybeOrFlag<llvm::dxbc::DescriptorRangeFlags>( \
1241 Flags, llvm::dxbc::DescriptorRangeFlags::NAME); \
1243#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
1245 llvm_unreachable(
"Switch for consumed enum token was not provided");
1249 reportDiag(diag::err_hlsl_invalid_token)
1251 return std::nullopt;
1253 }
while (tryConsumeExpectedToken(TokenKind::pu_or));
1258std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() {
1260 clang::NumericLiteralParser
Literal(
1261 CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),
1262 PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());
1264 return std::nullopt;
1266 assert(
Literal.isIntegerLiteral() &&
1267 "NumSpelling can only consist of digits");
1269 llvm::APSInt Val(32,
true);
1270 if (
Literal.GetIntegerValue(Val)) {
1272 reportDiag(diag::err_hlsl_number_literal_overflow)
1274 return std::nullopt;
1277 return Val.getExtValue();
1280std::optional<int32_t> RootSignatureParser::handleIntLiteral(
bool Negated) {
1282 clang::NumericLiteralParser
Literal(
1283 CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),
1284 PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());
1286 return std::nullopt;
1288 assert(
Literal.isIntegerLiteral() &&
1289 "NumSpelling can only consist of digits");
1291 llvm::APSInt Val(32,
true);
1294 bool Overflowed =
Literal.GetIntegerValue(Val);
1297 int64_t MaxNegativeMagnitude = -
int64_t(std::numeric_limits<int32_t>::min());
1298 Overflowed |= (Negated && MaxNegativeMagnitude < Val.getExtValue());
1300 int64_t MaxPositiveMagnitude =
int64_t(std::numeric_limits<int32_t>::max());
1301 Overflowed |= (!Negated && MaxPositiveMagnitude < Val.getExtValue());
1305 reportDiag(diag::err_hlsl_number_literal_overflow)
1307 return std::nullopt;
1313 return int32_t(Val.getExtValue());
1316std::optional<float> RootSignatureParser::handleFloatLiteral(
bool Negated) {
1318 clang::NumericLiteralParser
Literal(
1319 CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),
1320 PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());
1322 return std::nullopt;
1324 assert(
Literal.isFloatingLiteral() &&
1325 "NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
1326 "will be caught and reported by NumericLiteralParser.");
1330 auto DXCSemantics = llvm::APFloat::Semantics::S_IEEEdouble;
1331 auto DXCRoundingMode = llvm::RoundingMode::NearestTiesToEven;
1333 llvm::APFloat Val(llvm::APFloat::EnumToSemantics(DXCSemantics));
1334 llvm::APFloat::opStatus Status(
Literal.GetFloatValue(Val, DXCRoundingMode));
1338 assert(!(Status & llvm::APFloat::opStatus::opInvalidOp) &&
1339 "NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
1340 "will be caught and reported by NumericLiteralParser.");
1342 assert(!(Status & llvm::APFloat::opStatus::opDivByZero) &&
1343 "It is not possible for a division to be performed when "
1344 "constructing an APFloat from a string");
1346 if (Status & llvm::APFloat::opStatus::opUnderflow) {
1348 reportDiag(diag::err_hlsl_number_literal_underflow);
1349 return std::nullopt;
1352 if (Status & llvm::APFloat::opStatus::opOverflow) {
1354 reportDiag(diag::err_hlsl_number_literal_overflow) << 1;
1355 return std::nullopt;
1361 double DoubleVal = Val.convertToDouble();
1362 double FloatMax =
double(std::numeric_limits<float>::max());
1363 if (FloatMax < DoubleVal || DoubleVal < -FloatMax) {
1365 reportDiag(diag::err_hlsl_number_literal_overflow) << 1;
1366 return std::nullopt;
1369 return static_cast<float>(DoubleVal);
1372bool RootSignatureParser::verifyZeroFlag() {
1373 assert(CurToken.TokKind == TokenKind::int_literal);
1374 auto X = handleUIntLiteral();
1375 return X.has_value() &&
X.value() == 0;
1378bool RootSignatureParser::peekExpectedToken(
TokenKind Expected) {
1379 return peekExpectedToken(ArrayRef{Expected});
1382bool RootSignatureParser::peekExpectedToken(ArrayRef<TokenKind> AnyExpected) {
1383 RootSignatureToken
Result = Lexer.peekNextToken();
1384 return llvm::is_contained(AnyExpected,
Result.TokKind);
1387bool RootSignatureParser::consumeExpectedToken(
TokenKind Expected,
1390 if (tryConsumeExpectedToken(Expected))
1394 DiagnosticBuilder DB = reportDiag(DiagID);
1396 case diag::err_expected:
1399 case diag::err_expected_either:
1400 DB << Expected << Context;
1402 case diag::err_expected_after:
1403 DB << Context << Expected;
1411bool RootSignatureParser::tryConsumeExpectedToken(
TokenKind Expected) {
1412 return tryConsumeExpectedToken(ArrayRef{Expected});
1415bool RootSignatureParser::tryConsumeExpectedToken(
1416 ArrayRef<TokenKind> AnyExpected) {
1418 if (!peekExpectedToken(AnyExpected))
1424bool RootSignatureParser::skipUntilExpectedToken(
TokenKind Expected) {
1425 return skipUntilExpectedToken(ArrayRef{Expected});
1428bool RootSignatureParser::skipUntilExpectedToken(
1429 ArrayRef<TokenKind> AnyExpected) {
1431 while (!peekExpectedToken(AnyExpected)) {
1432 if (peekExpectedToken(TokenKind::end_of_stream))
1440bool RootSignatureParser::skipUntilClosedParens(uint32_t NumParens) {
1442 TokenKind::pu_l_paren,
1443 TokenKind::pu_r_paren,
1445 while (skipUntilExpectedToken(ParenKinds)) {
1447 if (CurToken.TokKind == TokenKind::pu_r_paren)
1459 return Signature->getLocationOfByte(
Tok.LocOffset, PP.getSourceManager(),
1460 PP.getLangOpts(), PP.getTargetInfo());
1464 llvm::dxbc::RootSignatureVersion Version,
1467 auto [DeclIdent,
Found] =
1502 while (P->getCurToken().getKind() != tok::eof)
1503 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.