================ @@ -89,37 +88,178 @@ bool RootSignatureParser::parseDescriptorTableClause() { CurToken.TokKind == TokenKind::kw_UAV || CurToken.TokKind == TokenKind::kw_Sampler) && "Expects to only be invoked starting at given keyword"); + TokenKind ParamKind = CurToken.TokKind; // retain for diagnostics DescriptorTableClause Clause; - switch (CurToken.TokKind) { + TokenKind ExpectedRegister; + switch (ParamKind) { default: llvm_unreachable("Switch for consumed token was not provided"); case TokenKind::kw_CBV: Clause.Type = ClauseType::CBuffer; + ExpectedRegister = TokenKind::bReg; break; case TokenKind::kw_SRV: Clause.Type = ClauseType::SRV; + ExpectedRegister = TokenKind::tReg; break; case TokenKind::kw_UAV: Clause.Type = ClauseType::UAV; + ExpectedRegister = TokenKind::uReg; break; case TokenKind::kw_Sampler: Clause.Type = ClauseType::Sampler; + ExpectedRegister = TokenKind::sReg; break; } if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after, - CurToken.TokKind)) + ParamKind)) return true; - if (consumeExpectedToken(TokenKind::pu_r_paren, diag::err_expected_after, - CurToken.TokKind)) + llvm::SmallDenseMap<TokenKind, ParamType> Params = { + {ExpectedRegister, &Clause.Register}, + {TokenKind::kw_space, &Clause.Space}, + }; + llvm::SmallDenseSet<TokenKind> Mandatory = { + ExpectedRegister, + }; + + if (parseParams(Params, Mandatory)) + return true; + + if (consumeExpectedToken(TokenKind::pu_r_paren, + diag::err_hlsl_unexpected_end_of_params, + /*param of=*/ParamKind)) return true; Elements.push_back(Clause); return false; } +// Helper struct defined to use the overloaded notation of std::visit. +template <class... Ts> struct ParseParamTypeMethods : Ts... { + using Ts::operator()...; +}; +template <class... Ts> +ParseParamTypeMethods(Ts...) -> ParseParamTypeMethods<Ts...>; + +bool RootSignatureParser::parseParam(ParamType Ref) { + return std::visit( + ParseParamTypeMethods{ + [this](Register *X) -> bool { return parseRegister(X); }, + [this](uint32_t *X) -> bool { + return consumeExpectedToken(TokenKind::pu_equal, + diag::err_expected_after, + CurToken.TokKind) || + parseUIntParam(X); + }, + }, + Ref); +} + +bool RootSignatureParser::parseParams( + llvm::SmallDenseMap<TokenKind, ParamType> &Params, + llvm::SmallDenseSet<TokenKind> &Mandatory) { + + // Initialize a vector of possible keywords + SmallVector<TokenKind> Keywords; + for (auto Pair : Params) + Keywords.push_back(Pair.first); + + // Keep track of which keywords have been seen to report duplicates + llvm::SmallDenseSet<TokenKind> Seen; + + while (tryConsumeExpectedToken(Keywords)) { + if (Seen.contains(CurToken.TokKind)) { + getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param) + << CurToken.TokKind; + return true; + } + Seen.insert(CurToken.TokKind); + + if (parseParam(Params[CurToken.TokKind])) + return true; + + if (!tryConsumeExpectedToken(TokenKind::pu_comma)) + break; + } + + bool AllMandatoryDefined = true; + for (auto Kind : Mandatory) { + bool SeenParam = Seen.contains(Kind); + if (!SeenParam) { + getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param) + << Kind; + } + AllMandatoryDefined &= SeenParam; + } + + return !AllMandatoryDefined; +} + +bool RootSignatureParser::parseUIntParam(uint32_t *X) { + assert(CurToken.TokKind == TokenKind::pu_equal && ---------------- joaosaffran wrote:
This made me confused. The only place this is called is parsing `TokenKind::pu_equal` before calling it, so it seems confusing, IMHO, that this assert is here. https://github.com/llvm/llvm-project/pull/133800 _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits