Path: blob/main/contrib/llvm-project/clang/lib/Parse/ParseHLSLRootSignature.cpp
213766 views
//=== ParseHLSLRootSignature.cpp - Parse Root Signature -------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "clang/Parse/ParseHLSLRootSignature.h"910#include "clang/Lex/LiteralSupport.h"1112using namespace llvm::hlsl::rootsig;1314namespace clang {15namespace hlsl {1617using TokenKind = RootSignatureToken::Kind;1819static const TokenKind RootElementKeywords[] = {20TokenKind::kw_RootFlags,21TokenKind::kw_CBV,22TokenKind::kw_UAV,23TokenKind::kw_SRV,24TokenKind::kw_DescriptorTable,25TokenKind::kw_StaticSampler,26};2728RootSignatureParser::RootSignatureParser(29llvm::dxbc::RootSignatureVersion Version,30SmallVector<RootSignatureElement> &Elements, StringLiteral *Signature,31Preprocessor &PP)32: Version(Version), Elements(Elements), Signature(Signature),33Lexer(Signature->getString()), PP(PP), CurToken(0) {}3435bool RootSignatureParser::parse() {36// Iterate as many RootSignatureElements as possible, until we hit the37// end of the stream38bool HadError = false;39while (!peekExpectedToken(TokenKind::end_of_stream)) {40if (tryConsumeExpectedToken(TokenKind::kw_RootFlags)) {41SourceLocation ElementLoc = getTokenLocation(CurToken);42auto Flags = parseRootFlags();43if (!Flags.has_value()) {44HadError = true;45skipUntilExpectedToken(RootElementKeywords);46continue;47}4849Elements.emplace_back(ElementLoc, *Flags);50} else if (tryConsumeExpectedToken(TokenKind::kw_RootConstants)) {51SourceLocation ElementLoc = getTokenLocation(CurToken);52auto Constants = parseRootConstants();53if (!Constants.has_value()) {54HadError = true;55skipUntilExpectedToken(RootElementKeywords);56continue;57}58Elements.emplace_back(ElementLoc, *Constants);59} else if (tryConsumeExpectedToken(TokenKind::kw_DescriptorTable)) {60SourceLocation ElementLoc = getTokenLocation(CurToken);61auto Table = parseDescriptorTable();62if (!Table.has_value()) {63HadError = true;64// We are within a DescriptorTable, we will do our best to recover65// by skipping until we encounter the expected closing ')'.66skipUntilClosedParens();67consumeNextToken();68skipUntilExpectedToken(RootElementKeywords);69continue;70}71Elements.emplace_back(ElementLoc, *Table);72} else if (tryConsumeExpectedToken(73{TokenKind::kw_CBV, TokenKind::kw_SRV, TokenKind::kw_UAV})) {74SourceLocation ElementLoc = getTokenLocation(CurToken);75auto Descriptor = parseRootDescriptor();76if (!Descriptor.has_value()) {77HadError = true;78skipUntilExpectedToken(RootElementKeywords);79continue;80}81Elements.emplace_back(ElementLoc, *Descriptor);82} else if (tryConsumeExpectedToken(TokenKind::kw_StaticSampler)) {83SourceLocation ElementLoc = getTokenLocation(CurToken);84auto Sampler = parseStaticSampler();85if (!Sampler.has_value()) {86HadError = true;87skipUntilExpectedToken(RootElementKeywords);88continue;89}90Elements.emplace_back(ElementLoc, *Sampler);91} else {92HadError = true;93consumeNextToken(); // let diagnostic be at the start of invalid token94reportDiag(diag::err_hlsl_invalid_token)95<< /*parameter=*/0 << /*param of*/ TokenKind::kw_RootSignature;96skipUntilExpectedToken(RootElementKeywords);97continue;98}99100if (!tryConsumeExpectedToken(TokenKind::pu_comma)) {101// ',' denotes another element, otherwise, expected to be at end of stream102break;103}104}105106return HadError ||107consumeExpectedToken(TokenKind::end_of_stream,108diag::err_expected_either, TokenKind::pu_comma);109}110111template <typename FlagType>112static FlagType maybeOrFlag(std::optional<FlagType> Flags, FlagType Flag) {113if (!Flags.has_value())114return Flag;115116return static_cast<FlagType>(llvm::to_underlying(Flags.value()) |117llvm::to_underlying(Flag));118}119120std::optional<llvm::dxbc::RootFlags> RootSignatureParser::parseRootFlags() {121assert(CurToken.TokKind == TokenKind::kw_RootFlags &&122"Expects to only be invoked starting at given keyword");123124if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,125CurToken.TokKind))126return std::nullopt;127128std::optional<llvm::dxbc::RootFlags> Flags = llvm::dxbc::RootFlags::None;129130// Handle valid empty case131if (tryConsumeExpectedToken(TokenKind::pu_r_paren))132return Flags;133134// Handle the edge-case of '0' to specify no flags set135if (tryConsumeExpectedToken(TokenKind::int_literal)) {136if (!verifyZeroFlag()) {137reportDiag(diag::err_hlsl_rootsig_non_zero_flag);138return std::nullopt;139}140} else {141// Otherwise, parse as many flags as possible142TokenKind Expected[] = {143#define ROOT_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,144#include "clang/Lex/HLSLRootSignatureTokenKinds.def"145};146147do {148if (tryConsumeExpectedToken(Expected)) {149switch (CurToken.TokKind) {150#define ROOT_FLAG_ENUM(NAME, LIT) \151case TokenKind::en_##NAME: \152Flags = maybeOrFlag<llvm::dxbc::RootFlags>(Flags, \153llvm::dxbc::RootFlags::NAME); \154break;155#include "clang/Lex/HLSLRootSignatureTokenKinds.def"156default:157llvm_unreachable("Switch for consumed enum token was not provided");158}159} else {160consumeNextToken(); // consume token to point at invalid token161reportDiag(diag::err_hlsl_invalid_token)162<< /*value=*/1 << /*value of*/ TokenKind::kw_RootFlags;163return std::nullopt;164}165} while (tryConsumeExpectedToken(TokenKind::pu_or));166}167168if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,169TokenKind::pu_comma))170return std::nullopt;171172return Flags;173}174175std::optional<RootConstants> RootSignatureParser::parseRootConstants() {176assert(CurToken.TokKind == TokenKind::kw_RootConstants &&177"Expects to only be invoked starting at given keyword");178179if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,180CurToken.TokKind))181return std::nullopt;182183RootConstants Constants;184185auto Params = parseRootConstantParams();186if (!Params.has_value())187return std::nullopt;188189if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,190TokenKind::pu_comma))191return std::nullopt;192193// Check mandatory parameters where provided194if (!Params->Num32BitConstants.has_value()) {195reportDiag(diag::err_hlsl_rootsig_missing_param)196<< TokenKind::kw_num32BitConstants;197return std::nullopt;198}199200Constants.Num32BitConstants = Params->Num32BitConstants.value();201202if (!Params->Reg.has_value()) {203reportDiag(diag::err_hlsl_rootsig_missing_param) << TokenKind::bReg;204return std::nullopt;205}206207Constants.Reg = Params->Reg.value();208209// Fill in optional parameters210if (Params->Visibility.has_value())211Constants.Visibility = Params->Visibility.value();212213if (Params->Space.has_value())214Constants.Space = Params->Space.value();215216return Constants;217}218219std::optional<RootDescriptor> RootSignatureParser::parseRootDescriptor() {220assert((CurToken.TokKind == TokenKind::kw_CBV ||221CurToken.TokKind == TokenKind::kw_SRV ||222CurToken.TokKind == TokenKind::kw_UAV) &&223"Expects to only be invoked starting at given keyword");224225TokenKind DescriptorKind = CurToken.TokKind;226227if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,228CurToken.TokKind))229return std::nullopt;230231RootDescriptor Descriptor;232TokenKind ExpectedReg;233switch (DescriptorKind) {234default:235llvm_unreachable("Switch for consumed token was not provided");236case TokenKind::kw_CBV:237Descriptor.Type = DescriptorType::CBuffer;238ExpectedReg = TokenKind::bReg;239break;240case TokenKind::kw_SRV:241Descriptor.Type = DescriptorType::SRV;242ExpectedReg = TokenKind::tReg;243break;244case TokenKind::kw_UAV:245Descriptor.Type = DescriptorType::UAV;246ExpectedReg = TokenKind::uReg;247break;248}249Descriptor.setDefaultFlags(Version);250251auto Params = parseRootDescriptorParams(DescriptorKind, ExpectedReg);252if (!Params.has_value())253return std::nullopt;254255if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,256TokenKind::pu_comma))257return std::nullopt;258259// Check mandatory parameters were provided260if (!Params->Reg.has_value()) {261reportDiag(diag::err_hlsl_rootsig_missing_param) << ExpectedReg;262return std::nullopt;263}264265Descriptor.Reg = Params->Reg.value();266267// Fill in optional values268if (Params->Space.has_value())269Descriptor.Space = Params->Space.value();270271if (Params->Visibility.has_value())272Descriptor.Visibility = Params->Visibility.value();273274if (Params->Flags.has_value())275Descriptor.Flags = Params->Flags.value();276277return Descriptor;278}279280std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() {281assert(CurToken.TokKind == TokenKind::kw_DescriptorTable &&282"Expects to only be invoked starting at given keyword");283284if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,285CurToken.TokKind))286return std::nullopt;287288DescriptorTable Table;289std::optional<llvm::dxbc::ShaderVisibility> Visibility;290291// Iterate as many Clauses as possible, until we hit ')'292while (!peekExpectedToken(TokenKind::pu_r_paren)) {293if (tryConsumeExpectedToken({TokenKind::kw_CBV, TokenKind::kw_SRV,294TokenKind::kw_UAV, TokenKind::kw_Sampler})) {295// DescriptorTableClause - CBV, SRV, UAV, or Sampler296SourceLocation ElementLoc = getTokenLocation(CurToken);297auto Clause = parseDescriptorTableClause();298if (!Clause.has_value()) {299// We are within a DescriptorTableClause, we will do our best to recover300// by skipping until we encounter the expected closing ')'301skipUntilExpectedToken(TokenKind::pu_r_paren);302consumeNextToken();303return std::nullopt;304}305Elements.emplace_back(ElementLoc, *Clause);306Table.NumClauses++;307} else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {308// visibility = SHADER_VISIBILITY309if (Visibility.has_value()) {310reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;311return std::nullopt;312}313314if (consumeExpectedToken(TokenKind::pu_equal))315return std::nullopt;316317Visibility = parseShaderVisibility(TokenKind::kw_visibility);318if (!Visibility.has_value())319return std::nullopt;320} else {321consumeNextToken(); // let diagnostic be at the start of invalid token322reportDiag(diag::err_hlsl_invalid_token)323<< /*parameter=*/0 << /*param of*/ TokenKind::kw_DescriptorTable;324return std::nullopt;325}326327// ',' denotes another element, otherwise, expected to be at ')'328if (!tryConsumeExpectedToken(TokenKind::pu_comma))329break;330}331332if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,333TokenKind::pu_comma))334return std::nullopt;335336// Fill in optional visibility337if (Visibility.has_value())338Table.Visibility = Visibility.value();339340return Table;341}342343std::optional<DescriptorTableClause>344RootSignatureParser::parseDescriptorTableClause() {345assert((CurToken.TokKind == TokenKind::kw_CBV ||346CurToken.TokKind == TokenKind::kw_SRV ||347CurToken.TokKind == TokenKind::kw_UAV ||348CurToken.TokKind == TokenKind::kw_Sampler) &&349"Expects to only be invoked starting at given keyword");350351TokenKind ParamKind = CurToken.TokKind;352353if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,354CurToken.TokKind))355return std::nullopt;356357DescriptorTableClause Clause;358TokenKind ExpectedReg;359switch (ParamKind) {360default:361llvm_unreachable("Switch for consumed token was not provided");362case TokenKind::kw_CBV:363Clause.Type = ClauseType::CBuffer;364ExpectedReg = TokenKind::bReg;365break;366case TokenKind::kw_SRV:367Clause.Type = ClauseType::SRV;368ExpectedReg = TokenKind::tReg;369break;370case TokenKind::kw_UAV:371Clause.Type = ClauseType::UAV;372ExpectedReg = TokenKind::uReg;373break;374case TokenKind::kw_Sampler:375Clause.Type = ClauseType::Sampler;376ExpectedReg = TokenKind::sReg;377break;378}379Clause.setDefaultFlags(Version);380381auto Params = parseDescriptorTableClauseParams(ParamKind, ExpectedReg);382if (!Params.has_value())383return std::nullopt;384385if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,386TokenKind::pu_comma))387return std::nullopt;388389// Check mandatory parameters were provided390if (!Params->Reg.has_value()) {391reportDiag(diag::err_hlsl_rootsig_missing_param) << ExpectedReg;392return std::nullopt;393}394395Clause.Reg = Params->Reg.value();396397// Fill in optional values398if (Params->NumDescriptors.has_value())399Clause.NumDescriptors = Params->NumDescriptors.value();400401if (Params->Space.has_value())402Clause.Space = Params->Space.value();403404if (Params->Offset.has_value())405Clause.Offset = Params->Offset.value();406407if (Params->Flags.has_value())408Clause.Flags = Params->Flags.value();409410return Clause;411}412413std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() {414assert(CurToken.TokKind == TokenKind::kw_StaticSampler &&415"Expects to only be invoked starting at given keyword");416417if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,418CurToken.TokKind))419return std::nullopt;420421StaticSampler Sampler;422423auto Params = parseStaticSamplerParams();424if (!Params.has_value())425return std::nullopt;426427if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_either,428TokenKind::pu_comma))429return std::nullopt;430431// Check mandatory parameters were provided432if (!Params->Reg.has_value()) {433reportDiag(diag::err_hlsl_rootsig_missing_param) << TokenKind::sReg;434return std::nullopt;435}436437Sampler.Reg = Params->Reg.value();438439// Fill in optional values440if (Params->Filter.has_value())441Sampler.Filter = Params->Filter.value();442443if (Params->AddressU.has_value())444Sampler.AddressU = Params->AddressU.value();445446if (Params->AddressV.has_value())447Sampler.AddressV = Params->AddressV.value();448449if (Params->AddressW.has_value())450Sampler.AddressW = Params->AddressW.value();451452if (Params->MipLODBias.has_value())453Sampler.MipLODBias = Params->MipLODBias.value();454455if (Params->MaxAnisotropy.has_value())456Sampler.MaxAnisotropy = Params->MaxAnisotropy.value();457458if (Params->CompFunc.has_value())459Sampler.CompFunc = Params->CompFunc.value();460461if (Params->BorderColor.has_value())462Sampler.BorderColor = Params->BorderColor.value();463464if (Params->MinLOD.has_value())465Sampler.MinLOD = Params->MinLOD.value();466467if (Params->MaxLOD.has_value())468Sampler.MaxLOD = Params->MaxLOD.value();469470if (Params->Space.has_value())471Sampler.Space = Params->Space.value();472473if (Params->Visibility.has_value())474Sampler.Visibility = Params->Visibility.value();475476return Sampler;477}478479// Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any480// order and only exactly once. The following methods will parse through as481// many arguments as possible reporting an error if a duplicate is seen.482std::optional<RootSignatureParser::ParsedConstantParams>483RootSignatureParser::parseRootConstantParams() {484assert(CurToken.TokKind == TokenKind::pu_l_paren &&485"Expects to only be invoked starting at given token");486487ParsedConstantParams Params;488while (!peekExpectedToken(TokenKind::pu_r_paren)) {489if (tryConsumeExpectedToken(TokenKind::kw_num32BitConstants)) {490// `num32BitConstants` `=` POS_INT491if (Params.Num32BitConstants.has_value()) {492reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;493return std::nullopt;494}495496if (consumeExpectedToken(TokenKind::pu_equal))497return std::nullopt;498499auto Num32BitConstants = parseUIntParam();500if (!Num32BitConstants.has_value())501return std::nullopt;502Params.Num32BitConstants = Num32BitConstants;503} else if (tryConsumeExpectedToken(TokenKind::bReg)) {504// `b` POS_INT505if (Params.Reg.has_value()) {506reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;507return std::nullopt;508}509auto Reg = parseRegister();510if (!Reg.has_value())511return std::nullopt;512Params.Reg = Reg;513} else if (tryConsumeExpectedToken(TokenKind::kw_space)) {514// `space` `=` POS_INT515if (Params.Space.has_value()) {516reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;517return std::nullopt;518}519520if (consumeExpectedToken(TokenKind::pu_equal))521return std::nullopt;522523auto Space = parseUIntParam();524if (!Space.has_value())525return std::nullopt;526Params.Space = Space;527} else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {528// `visibility` `=` SHADER_VISIBILITY529if (Params.Visibility.has_value()) {530reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;531return std::nullopt;532}533534if (consumeExpectedToken(TokenKind::pu_equal))535return std::nullopt;536537auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);538if (!Visibility.has_value())539return std::nullopt;540Params.Visibility = Visibility;541} else {542consumeNextToken(); // let diagnostic be at the start of invalid token543reportDiag(diag::err_hlsl_invalid_token)544<< /*parameter=*/0 << /*param of*/ TokenKind::kw_RootConstants;545return std::nullopt;546}547548// ',' denotes another element, otherwise, expected to be at ')'549if (!tryConsumeExpectedToken(TokenKind::pu_comma))550break;551}552553return Params;554}555556std::optional<RootSignatureParser::ParsedRootDescriptorParams>557RootSignatureParser::parseRootDescriptorParams(TokenKind DescKind,558TokenKind RegType) {559assert(CurToken.TokKind == TokenKind::pu_l_paren &&560"Expects to only be invoked starting at given token");561562ParsedRootDescriptorParams Params;563while (!peekExpectedToken(TokenKind::pu_r_paren)) {564if (tryConsumeExpectedToken(RegType)) {565// ( `b` | `t` | `u`) POS_INT566if (Params.Reg.has_value()) {567reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;568return std::nullopt;569}570auto Reg = parseRegister();571if (!Reg.has_value())572return std::nullopt;573Params.Reg = Reg;574} else if (tryConsumeExpectedToken(TokenKind::kw_space)) {575// `space` `=` POS_INT576if (Params.Space.has_value()) {577reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;578return std::nullopt;579}580581if (consumeExpectedToken(TokenKind::pu_equal))582return std::nullopt;583584auto Space = parseUIntParam();585if (!Space.has_value())586return std::nullopt;587Params.Space = Space;588} else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {589// `visibility` `=` SHADER_VISIBILITY590if (Params.Visibility.has_value()) {591reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;592return std::nullopt;593}594595if (consumeExpectedToken(TokenKind::pu_equal))596return std::nullopt;597598auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);599if (!Visibility.has_value())600return std::nullopt;601Params.Visibility = Visibility;602} else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {603// `flags` `=` ROOT_DESCRIPTOR_FLAGS604if (Params.Flags.has_value()) {605reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;606return std::nullopt;607}608609if (consumeExpectedToken(TokenKind::pu_equal))610return std::nullopt;611612auto Flags = parseRootDescriptorFlags(TokenKind::kw_flags);613if (!Flags.has_value())614return std::nullopt;615Params.Flags = Flags;616} else {617consumeNextToken(); // let diagnostic be at the start of invalid token618reportDiag(diag::err_hlsl_invalid_token)619<< /*parameter=*/0 << /*param of*/ DescKind;620return std::nullopt;621}622623// ',' denotes another element, otherwise, expected to be at ')'624if (!tryConsumeExpectedToken(TokenKind::pu_comma))625break;626}627628return Params;629}630631std::optional<RootSignatureParser::ParsedClauseParams>632RootSignatureParser::parseDescriptorTableClauseParams(TokenKind ClauseKind,633TokenKind RegType) {634assert(CurToken.TokKind == TokenKind::pu_l_paren &&635"Expects to only be invoked starting at given token");636637ParsedClauseParams Params;638while (!peekExpectedToken(TokenKind::pu_r_paren)) {639if (tryConsumeExpectedToken(RegType)) {640// ( `b` | `t` | `u` | `s`) POS_INT641if (Params.Reg.has_value()) {642reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;643return std::nullopt;644}645auto Reg = parseRegister();646if (!Reg.has_value())647return std::nullopt;648Params.Reg = Reg;649} else if (tryConsumeExpectedToken(TokenKind::kw_numDescriptors)) {650// `numDescriptors` `=` POS_INT | unbounded651if (Params.NumDescriptors.has_value()) {652reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;653return std::nullopt;654}655656if (consumeExpectedToken(TokenKind::pu_equal))657return std::nullopt;658659std::optional<uint32_t> NumDescriptors;660if (tryConsumeExpectedToken(TokenKind::en_unbounded))661NumDescriptors = NumDescriptorsUnbounded;662else {663NumDescriptors = parseUIntParam();664if (!NumDescriptors.has_value())665return std::nullopt;666}667668Params.NumDescriptors = NumDescriptors;669} else if (tryConsumeExpectedToken(TokenKind::kw_space)) {670// `space` `=` POS_INT671if (Params.Space.has_value()) {672reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;673return std::nullopt;674}675676if (consumeExpectedToken(TokenKind::pu_equal))677return std::nullopt;678679auto Space = parseUIntParam();680if (!Space.has_value())681return std::nullopt;682Params.Space = Space;683} else if (tryConsumeExpectedToken(TokenKind::kw_offset)) {684// `offset` `=` POS_INT | DESCRIPTOR_RANGE_OFFSET_APPEND685if (Params.Offset.has_value()) {686reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;687return std::nullopt;688}689690if (consumeExpectedToken(TokenKind::pu_equal))691return std::nullopt;692693std::optional<uint32_t> Offset;694if (tryConsumeExpectedToken(TokenKind::en_DescriptorRangeOffsetAppend))695Offset = DescriptorTableOffsetAppend;696else {697Offset = parseUIntParam();698if (!Offset.has_value())699return std::nullopt;700}701702Params.Offset = Offset;703} else if (tryConsumeExpectedToken(TokenKind::kw_flags)) {704// `flags` `=` DESCRIPTOR_RANGE_FLAGS705if (Params.Flags.has_value()) {706reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;707return std::nullopt;708}709710if (consumeExpectedToken(TokenKind::pu_equal))711return std::nullopt;712713auto Flags = parseDescriptorRangeFlags(TokenKind::kw_flags);714if (!Flags.has_value())715return std::nullopt;716Params.Flags = Flags;717} else {718consumeNextToken(); // let diagnostic be at the start of invalid token719reportDiag(diag::err_hlsl_invalid_token)720<< /*parameter=*/0 << /*param of*/ ClauseKind;721return std::nullopt;722}723724// ',' denotes another element, otherwise, expected to be at ')'725if (!tryConsumeExpectedToken(TokenKind::pu_comma))726break;727}728729return Params;730}731732std::optional<RootSignatureParser::ParsedStaticSamplerParams>733RootSignatureParser::parseStaticSamplerParams() {734assert(CurToken.TokKind == TokenKind::pu_l_paren &&735"Expects to only be invoked starting at given token");736737ParsedStaticSamplerParams Params;738while (!peekExpectedToken(TokenKind::pu_r_paren)) {739if (tryConsumeExpectedToken(TokenKind::sReg)) {740// `s` POS_INT741if (Params.Reg.has_value()) {742reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;743return std::nullopt;744}745auto Reg = parseRegister();746if (!Reg.has_value())747return std::nullopt;748Params.Reg = Reg;749} else if (tryConsumeExpectedToken(TokenKind::kw_filter)) {750// `filter` `=` FILTER751if (Params.Filter.has_value()) {752reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;753return std::nullopt;754}755756if (consumeExpectedToken(TokenKind::pu_equal))757return std::nullopt;758759auto Filter = parseSamplerFilter(TokenKind::kw_filter);760if (!Filter.has_value())761return std::nullopt;762Params.Filter = Filter;763} else if (tryConsumeExpectedToken(TokenKind::kw_addressU)) {764// `addressU` `=` TEXTURE_ADDRESS765if (Params.AddressU.has_value()) {766reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;767return std::nullopt;768}769770if (consumeExpectedToken(TokenKind::pu_equal))771return std::nullopt;772773auto AddressU = parseTextureAddressMode(TokenKind::kw_addressU);774if (!AddressU.has_value())775return std::nullopt;776Params.AddressU = AddressU;777} else if (tryConsumeExpectedToken(TokenKind::kw_addressV)) {778// `addressV` `=` TEXTURE_ADDRESS779if (Params.AddressV.has_value()) {780reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;781return std::nullopt;782}783784if (consumeExpectedToken(TokenKind::pu_equal))785return std::nullopt;786787auto AddressV = parseTextureAddressMode(TokenKind::kw_addressV);788if (!AddressV.has_value())789return std::nullopt;790Params.AddressV = AddressV;791} else if (tryConsumeExpectedToken(TokenKind::kw_addressW)) {792// `addressW` `=` TEXTURE_ADDRESS793if (Params.AddressW.has_value()) {794reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;795return std::nullopt;796}797798if (consumeExpectedToken(TokenKind::pu_equal))799return std::nullopt;800801auto AddressW = parseTextureAddressMode(TokenKind::kw_addressW);802if (!AddressW.has_value())803return std::nullopt;804Params.AddressW = AddressW;805} else if (tryConsumeExpectedToken(TokenKind::kw_mipLODBias)) {806// `mipLODBias` `=` NUMBER807if (Params.MipLODBias.has_value()) {808reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;809return std::nullopt;810}811812if (consumeExpectedToken(TokenKind::pu_equal))813return std::nullopt;814815auto MipLODBias = parseFloatParam();816if (!MipLODBias.has_value())817return std::nullopt;818Params.MipLODBias = MipLODBias;819} else if (tryConsumeExpectedToken(TokenKind::kw_maxAnisotropy)) {820// `maxAnisotropy` `=` POS_INT821if (Params.MaxAnisotropy.has_value()) {822reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;823return std::nullopt;824}825826if (consumeExpectedToken(TokenKind::pu_equal))827return std::nullopt;828829auto MaxAnisotropy = parseUIntParam();830if (!MaxAnisotropy.has_value())831return std::nullopt;832Params.MaxAnisotropy = MaxAnisotropy;833} else if (tryConsumeExpectedToken(TokenKind::kw_comparisonFunc)) {834// `comparisonFunc` `=` COMPARISON_FUNC835if (Params.CompFunc.has_value()) {836reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;837return std::nullopt;838}839840if (consumeExpectedToken(TokenKind::pu_equal))841return std::nullopt;842843auto CompFunc = parseComparisonFunc(TokenKind::kw_comparisonFunc);844if (!CompFunc.has_value())845return std::nullopt;846Params.CompFunc = CompFunc;847} else if (tryConsumeExpectedToken(TokenKind::kw_borderColor)) {848// `borderColor` `=` STATIC_BORDER_COLOR849if (Params.BorderColor.has_value()) {850reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;851return std::nullopt;852}853854if (consumeExpectedToken(TokenKind::pu_equal))855return std::nullopt;856857auto BorderColor = parseStaticBorderColor(TokenKind::kw_borderColor);858if (!BorderColor.has_value())859return std::nullopt;860Params.BorderColor = BorderColor;861} else if (tryConsumeExpectedToken(TokenKind::kw_minLOD)) {862// `minLOD` `=` NUMBER863if (Params.MinLOD.has_value()) {864reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;865return std::nullopt;866}867868if (consumeExpectedToken(TokenKind::pu_equal))869return std::nullopt;870871auto MinLOD = parseFloatParam();872if (!MinLOD.has_value())873return std::nullopt;874Params.MinLOD = MinLOD;875} else if (tryConsumeExpectedToken(TokenKind::kw_maxLOD)) {876// `maxLOD` `=` NUMBER877if (Params.MaxLOD.has_value()) {878reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;879return std::nullopt;880}881882if (consumeExpectedToken(TokenKind::pu_equal))883return std::nullopt;884885auto MaxLOD = parseFloatParam();886if (!MaxLOD.has_value())887return std::nullopt;888Params.MaxLOD = MaxLOD;889} else if (tryConsumeExpectedToken(TokenKind::kw_space)) {890// `space` `=` POS_INT891if (Params.Space.has_value()) {892reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;893return std::nullopt;894}895896if (consumeExpectedToken(TokenKind::pu_equal))897return std::nullopt;898899auto Space = parseUIntParam();900if (!Space.has_value())901return std::nullopt;902Params.Space = Space;903} else if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {904// `visibility` `=` SHADER_VISIBILITY905if (Params.Visibility.has_value()) {906reportDiag(diag::err_hlsl_rootsig_repeat_param) << CurToken.TokKind;907return std::nullopt;908}909910if (consumeExpectedToken(TokenKind::pu_equal))911return std::nullopt;912913auto Visibility = parseShaderVisibility(TokenKind::kw_visibility);914if (!Visibility.has_value())915return std::nullopt;916Params.Visibility = Visibility;917} else {918consumeNextToken(); // let diagnostic be at the start of invalid token919reportDiag(diag::err_hlsl_invalid_token)920<< /*parameter=*/0 << /*param of*/ TokenKind::kw_StaticSampler;921return std::nullopt;922}923924// ',' denotes another element, otherwise, expected to be at ')'925if (!tryConsumeExpectedToken(TokenKind::pu_comma))926break;927}928929return Params;930}931932std::optional<uint32_t> RootSignatureParser::parseUIntParam() {933assert(CurToken.TokKind == TokenKind::pu_equal &&934"Expects to only be invoked starting at given keyword");935tryConsumeExpectedToken(TokenKind::pu_plus);936if (consumeExpectedToken(TokenKind::int_literal, diag::err_expected_after,937CurToken.TokKind))938return std::nullopt;939return handleUIntLiteral();940}941942std::optional<Register> RootSignatureParser::parseRegister() {943assert((CurToken.TokKind == TokenKind::bReg ||944CurToken.TokKind == TokenKind::tReg ||945CurToken.TokKind == TokenKind::uReg ||946CurToken.TokKind == TokenKind::sReg) &&947"Expects to only be invoked starting at given keyword");948949Register Reg;950switch (CurToken.TokKind) {951default:952llvm_unreachable("Switch for consumed token was not provided");953case TokenKind::bReg:954Reg.ViewType = RegisterType::BReg;955break;956case TokenKind::tReg:957Reg.ViewType = RegisterType::TReg;958break;959case TokenKind::uReg:960Reg.ViewType = RegisterType::UReg;961break;962case TokenKind::sReg:963Reg.ViewType = RegisterType::SReg;964break;965}966967auto Number = handleUIntLiteral();968if (!Number.has_value())969return std::nullopt; // propogate NumericLiteralParser error970971Reg.Number = *Number;972return Reg;973}974975std::optional<float> RootSignatureParser::parseFloatParam() {976assert(CurToken.TokKind == TokenKind::pu_equal &&977"Expects to only be invoked starting at given keyword");978// Consume sign modifier979bool Signed =980tryConsumeExpectedToken({TokenKind::pu_plus, TokenKind::pu_minus});981bool Negated = Signed && CurToken.TokKind == TokenKind::pu_minus;982983// DXC will treat a postive signed integer as unsigned984if (!Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {985std::optional<uint32_t> UInt = handleUIntLiteral();986if (!UInt.has_value())987return std::nullopt;988return float(UInt.value());989}990991if (Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {992std::optional<int32_t> Int = handleIntLiteral(Negated);993if (!Int.has_value())994return std::nullopt;995return float(Int.value());996}997998if (tryConsumeExpectedToken(TokenKind::float_literal)) {999std::optional<float> Float = handleFloatLiteral(Negated);1000if (!Float.has_value())1001return std::nullopt;1002return Float.value();1003}10041005return std::nullopt;1006}10071008std::optional<llvm::dxbc::ShaderVisibility>1009RootSignatureParser::parseShaderVisibility(TokenKind Context) {1010assert(CurToken.TokKind == TokenKind::pu_equal &&1011"Expects to only be invoked starting at given keyword");10121013TokenKind Expected[] = {1014#define SHADER_VISIBILITY_ENUM(NAME, LIT) TokenKind::en_##NAME,1015#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1016};10171018if (!tryConsumeExpectedToken(Expected)) {1019consumeNextToken(); // consume token to point at invalid token1020reportDiag(diag::err_hlsl_invalid_token)1021<< /*value=*/1 << /*value of*/ Context;1022return std::nullopt;1023}10241025switch (CurToken.TokKind) {1026#define SHADER_VISIBILITY_ENUM(NAME, LIT) \1027case TokenKind::en_##NAME: \1028return llvm::dxbc::ShaderVisibility::NAME; \1029break;1030#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1031default:1032llvm_unreachable("Switch for consumed enum token was not provided");1033}10341035return std::nullopt;1036}10371038std::optional<llvm::dxbc::SamplerFilter>1039RootSignatureParser::parseSamplerFilter(TokenKind Context) {1040assert(CurToken.TokKind == TokenKind::pu_equal &&1041"Expects to only be invoked starting at given keyword");10421043TokenKind Expected[] = {1044#define FILTER_ENUM(NAME, LIT) TokenKind::en_##NAME,1045#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1046};10471048if (!tryConsumeExpectedToken(Expected)) {1049consumeNextToken(); // consume token to point at invalid token1050reportDiag(diag::err_hlsl_invalid_token)1051<< /*value=*/1 << /*value of*/ Context;1052return std::nullopt;1053}10541055switch (CurToken.TokKind) {1056#define FILTER_ENUM(NAME, LIT) \1057case TokenKind::en_##NAME: \1058return llvm::dxbc::SamplerFilter::NAME; \1059break;1060#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1061default:1062llvm_unreachable("Switch for consumed enum token was not provided");1063}10641065return std::nullopt;1066}10671068std::optional<llvm::dxbc::TextureAddressMode>1069RootSignatureParser::parseTextureAddressMode(TokenKind Context) {1070assert(CurToken.TokKind == TokenKind::pu_equal &&1071"Expects to only be invoked starting at given keyword");10721073TokenKind Expected[] = {1074#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) TokenKind::en_##NAME,1075#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1076};10771078if (!tryConsumeExpectedToken(Expected)) {1079consumeNextToken(); // consume token to point at invalid token1080reportDiag(diag::err_hlsl_invalid_token)1081<< /*value=*/1 << /*value of*/ Context;1082return std::nullopt;1083}10841085switch (CurToken.TokKind) {1086#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) \1087case TokenKind::en_##NAME: \1088return llvm::dxbc::TextureAddressMode::NAME; \1089break;1090#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1091default:1092llvm_unreachable("Switch for consumed enum token was not provided");1093}10941095return std::nullopt;1096}10971098std::optional<llvm::dxbc::ComparisonFunc>1099RootSignatureParser::parseComparisonFunc(TokenKind Context) {1100assert(CurToken.TokKind == TokenKind::pu_equal &&1101"Expects to only be invoked starting at given keyword");11021103TokenKind Expected[] = {1104#define COMPARISON_FUNC_ENUM(NAME, LIT) TokenKind::en_##NAME,1105#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1106};11071108if (!tryConsumeExpectedToken(Expected)) {1109consumeNextToken(); // consume token to point at invalid token1110reportDiag(diag::err_hlsl_invalid_token)1111<< /*value=*/1 << /*value of*/ Context;1112return std::nullopt;1113}11141115switch (CurToken.TokKind) {1116#define COMPARISON_FUNC_ENUM(NAME, LIT) \1117case TokenKind::en_##NAME: \1118return llvm::dxbc::ComparisonFunc::NAME; \1119break;1120#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1121default:1122llvm_unreachable("Switch for consumed enum token was not provided");1123}11241125return std::nullopt;1126}11271128std::optional<llvm::dxbc::StaticBorderColor>1129RootSignatureParser::parseStaticBorderColor(TokenKind Context) {1130assert(CurToken.TokKind == TokenKind::pu_equal &&1131"Expects to only be invoked starting at given keyword");11321133TokenKind Expected[] = {1134#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) TokenKind::en_##NAME,1135#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1136};11371138if (!tryConsumeExpectedToken(Expected)) {1139consumeNextToken(); // consume token to point at invalid token1140reportDiag(diag::err_hlsl_invalid_token)1141<< /*value=*/1 << /*value of*/ Context;1142return std::nullopt;1143}11441145switch (CurToken.TokKind) {1146#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) \1147case TokenKind::en_##NAME: \1148return llvm::dxbc::StaticBorderColor::NAME; \1149break;1150#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1151default:1152llvm_unreachable("Switch for consumed enum token was not provided");1153}11541155return std::nullopt;1156}11571158std::optional<llvm::dxbc::RootDescriptorFlags>1159RootSignatureParser::parseRootDescriptorFlags(TokenKind Context) {1160assert(CurToken.TokKind == TokenKind::pu_equal &&1161"Expects to only be invoked starting at given keyword");11621163// Handle the edge-case of '0' to specify no flags set1164if (tryConsumeExpectedToken(TokenKind::int_literal)) {1165if (!verifyZeroFlag()) {1166reportDiag(diag::err_hlsl_rootsig_non_zero_flag);1167return std::nullopt;1168}1169return llvm::dxbc::RootDescriptorFlags::None;1170}11711172TokenKind Expected[] = {1173#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,1174#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1175};11761177std::optional<llvm::dxbc::RootDescriptorFlags> Flags;11781179do {1180if (tryConsumeExpectedToken(Expected)) {1181switch (CurToken.TokKind) {1182#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) \1183case TokenKind::en_##NAME: \1184Flags = maybeOrFlag<llvm::dxbc::RootDescriptorFlags>( \1185Flags, llvm::dxbc::RootDescriptorFlags::NAME); \1186break;1187#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1188default:1189llvm_unreachable("Switch for consumed enum token was not provided");1190}1191} else {1192consumeNextToken(); // consume token to point at invalid token1193reportDiag(diag::err_hlsl_invalid_token)1194<< /*value=*/1 << /*value of*/ Context;1195return std::nullopt;1196}1197} while (tryConsumeExpectedToken(TokenKind::pu_or));11981199return Flags;1200}12011202std::optional<llvm::dxbc::DescriptorRangeFlags>1203RootSignatureParser::parseDescriptorRangeFlags(TokenKind Context) {1204assert(CurToken.TokKind == TokenKind::pu_equal &&1205"Expects to only be invoked starting at given keyword");12061207// Handle the edge-case of '0' to specify no flags set1208if (tryConsumeExpectedToken(TokenKind::int_literal)) {1209if (!verifyZeroFlag()) {1210reportDiag(diag::err_hlsl_rootsig_non_zero_flag);1211return std::nullopt;1212}1213return llvm::dxbc::DescriptorRangeFlags::None;1214}12151216TokenKind Expected[] = {1217#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) TokenKind::en_##NAME,1218#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1219};12201221std::optional<llvm::dxbc::DescriptorRangeFlags> Flags;12221223do {1224if (tryConsumeExpectedToken(Expected)) {1225switch (CurToken.TokKind) {1226#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) \1227case TokenKind::en_##NAME: \1228Flags = maybeOrFlag<llvm::dxbc::DescriptorRangeFlags>( \1229Flags, llvm::dxbc::DescriptorRangeFlags::NAME); \1230break;1231#include "clang/Lex/HLSLRootSignatureTokenKinds.def"1232default:1233llvm_unreachable("Switch for consumed enum token was not provided");1234}1235} else {1236consumeNextToken(); // consume token to point at invalid token1237reportDiag(diag::err_hlsl_invalid_token)1238<< /*value=*/1 << /*value of*/ Context;1239return std::nullopt;1240}1241} while (tryConsumeExpectedToken(TokenKind::pu_or));12421243return Flags;1244}12451246std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() {1247// Parse the numeric value and do semantic checks on its specification1248clang::NumericLiteralParser Literal(1249CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),1250PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());1251if (Literal.hadError)1252return std::nullopt; // Error has already been reported so just return12531254assert(Literal.isIntegerLiteral() &&1255"NumSpelling can only consist of digits");12561257llvm::APSInt Val(32, /*IsUnsigned=*/true);1258if (Literal.GetIntegerValue(Val)) {1259// Report that the value has overflowed1260reportDiag(diag::err_hlsl_number_literal_overflow)1261<< /*integer type*/ 0 << /*is signed*/ 0;1262return std::nullopt;1263}12641265return Val.getExtValue();1266}12671268std::optional<int32_t> RootSignatureParser::handleIntLiteral(bool Negated) {1269// Parse the numeric value and do semantic checks on its specification1270clang::NumericLiteralParser Literal(1271CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),1272PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());1273if (Literal.hadError)1274return std::nullopt; // Error has already been reported so just return12751276assert(Literal.isIntegerLiteral() &&1277"NumSpelling can only consist of digits");12781279llvm::APSInt Val(32, /*IsUnsigned=*/true);1280// GetIntegerValue will overwrite Val from the parsed Literal and return1281// true if it overflows as a 32-bit unsigned int1282bool Overflowed = Literal.GetIntegerValue(Val);12831284// So we then need to check that it doesn't overflow as a 32-bit signed int:1285int64_t MaxNegativeMagnitude = -int64_t(std::numeric_limits<int32_t>::min());1286Overflowed |= (Negated && MaxNegativeMagnitude < Val.getExtValue());12871288int64_t MaxPositiveMagnitude = int64_t(std::numeric_limits<int32_t>::max());1289Overflowed |= (!Negated && MaxPositiveMagnitude < Val.getExtValue());12901291if (Overflowed) {1292// Report that the value has overflowed1293reportDiag(diag::err_hlsl_number_literal_overflow)1294<< /*integer type*/ 0 << /*is signed*/ 1;1295return std::nullopt;1296}12971298if (Negated)1299Val = -Val;13001301return int32_t(Val.getExtValue());1302}13031304std::optional<float> RootSignatureParser::handleFloatLiteral(bool Negated) {1305// Parse the numeric value and do semantic checks on its specification1306clang::NumericLiteralParser Literal(1307CurToken.NumSpelling, getTokenLocation(CurToken), PP.getSourceManager(),1308PP.getLangOpts(), PP.getTargetInfo(), PP.getDiagnostics());1309if (Literal.hadError)1310return std::nullopt; // Error has already been reported so just return13111312assert(Literal.isFloatingLiteral() &&1313"NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "1314"will be caught and reported by NumericLiteralParser.");13151316// DXC used `strtod` to convert the token string to a float which corresponds1317// to:1318auto DXCSemantics = llvm::APFloat::Semantics::S_IEEEdouble;1319auto DXCRoundingMode = llvm::RoundingMode::NearestTiesToEven;13201321llvm::APFloat Val(llvm::APFloat::EnumToSemantics(DXCSemantics));1322llvm::APFloat::opStatus Status(Literal.GetFloatValue(Val, DXCRoundingMode));13231324// Note: we do not error when opStatus::opInexact by itself as this just1325// denotes that rounding occured but not that it is invalid1326assert(!(Status & llvm::APFloat::opStatus::opInvalidOp) &&1327"NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "1328"will be caught and reported by NumericLiteralParser.");13291330assert(!(Status & llvm::APFloat::opStatus::opDivByZero) &&1331"It is not possible for a division to be performed when "1332"constructing an APFloat from a string");13331334if (Status & llvm::APFloat::opStatus::opUnderflow) {1335// Report that the value has underflowed1336reportDiag(diag::err_hlsl_number_literal_underflow);1337return std::nullopt;1338}13391340if (Status & llvm::APFloat::opStatus::opOverflow) {1341// Report that the value has overflowed1342reportDiag(diag::err_hlsl_number_literal_overflow) << /*float type*/ 1;1343return std::nullopt;1344}13451346if (Negated)1347Val = -Val;13481349double DoubleVal = Val.convertToDouble();1350double FloatMax = double(std::numeric_limits<float>::max());1351if (FloatMax < DoubleVal || DoubleVal < -FloatMax) {1352// Report that the value has overflowed1353reportDiag(diag::err_hlsl_number_literal_overflow) << /*float type*/ 1;1354return std::nullopt;1355}13561357return static_cast<float>(DoubleVal);1358}13591360bool RootSignatureParser::verifyZeroFlag() {1361assert(CurToken.TokKind == TokenKind::int_literal);1362auto X = handleUIntLiteral();1363return X.has_value() && X.value() == 0;1364}13651366bool RootSignatureParser::peekExpectedToken(TokenKind Expected) {1367return peekExpectedToken(ArrayRef{Expected});1368}13691370bool RootSignatureParser::peekExpectedToken(ArrayRef<TokenKind> AnyExpected) {1371RootSignatureToken Result = Lexer.peekNextToken();1372return llvm::is_contained(AnyExpected, Result.TokKind);1373}13741375bool RootSignatureParser::consumeExpectedToken(TokenKind Expected,1376unsigned DiagID,1377TokenKind Context) {1378if (tryConsumeExpectedToken(Expected))1379return false;13801381// Report unexpected token kind error1382DiagnosticBuilder DB = reportDiag(DiagID);1383switch (DiagID) {1384case diag::err_expected:1385DB << Expected;1386break;1387case diag::err_expected_either:1388DB << Expected << Context;1389break;1390case diag::err_expected_after:1391DB << Context << Expected;1392break;1393default:1394break;1395}1396return true;1397}13981399bool RootSignatureParser::tryConsumeExpectedToken(TokenKind Expected) {1400return tryConsumeExpectedToken(ArrayRef{Expected});1401}14021403bool RootSignatureParser::tryConsumeExpectedToken(1404ArrayRef<TokenKind> AnyExpected) {1405// If not the expected token just return1406if (!peekExpectedToken(AnyExpected))1407return false;1408consumeNextToken();1409return true;1410}14111412bool RootSignatureParser::skipUntilExpectedToken(TokenKind Expected) {1413return skipUntilExpectedToken(ArrayRef{Expected});1414}14151416bool RootSignatureParser::skipUntilExpectedToken(1417ArrayRef<TokenKind> AnyExpected) {14181419while (!peekExpectedToken(AnyExpected)) {1420if (peekExpectedToken(TokenKind::end_of_stream))1421return false;1422consumeNextToken();1423}14241425return true;1426}14271428bool RootSignatureParser::skipUntilClosedParens(uint32_t NumParens) {1429TokenKind ParenKinds[] = {1430TokenKind::pu_l_paren,1431TokenKind::pu_r_paren,1432};1433while (skipUntilExpectedToken(ParenKinds)) {1434consumeNextToken();1435if (CurToken.TokKind == TokenKind::pu_r_paren)1436NumParens--;1437else1438NumParens++;1439if (NumParens == 0)1440return true;1441}14421443return false;1444}14451446SourceLocation RootSignatureParser::getTokenLocation(RootSignatureToken Tok) {1447return Signature->getLocationOfByte(Tok.LocOffset, PP.getSourceManager(),1448PP.getLangOpts(), PP.getTargetInfo());1449}14501451} // namespace hlsl1452} // namespace clang145314541455