//=== ParseHLSLRootSignature.cpp - Parse Root Signature -------------------===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//

#include "clang/Parse/ParseHLSLRootSignature.h"

#include "clang/Lex/LiteralSupport.h"

using namespace llvm::hlsl::rootsig;

namespace clang {
namespace hlsl {

using TokenKind = RootSignatureToken::Kind;

RootSignatureParser::RootSignatureParser(SmallVector<RootElement> &Elements,
                                         RootSignatureLexer &Lexer,
                                         Preprocessor &PP)
    : Elements(Elements), Lexer(Lexer), PP(PP), CurToken(SourceLocation()) {}

bool RootSignatureParser::parse() {
  // Iterate as many RootElements as possible
  do {
    if (tryConsumeExpectedToken(TokenKind::kw_RootFlags)) {
      auto Flags = parseRootFlags();
      if (!Flags.has_value())
        return true;
      Elements.push_back(*Flags);
    }

    if (tryConsumeExpectedToken(TokenKind::kw_RootConstants)) {
      auto Constants = parseRootConstants();
      if (!Constants.has_value())
        return true;
      Elements.push_back(*Constants);
    }

    if (tryConsumeExpectedToken(TokenKind::kw_DescriptorTable)) {
      auto Table = parseDescriptorTable();
      if (!Table.has_value())
        return true;
      Elements.push_back(*Table);
    }

    if (tryConsumeExpectedToken(
            {TokenKind::kw_CBV, TokenKind::kw_SRV, TokenKind::kw_UAV})) {
      auto Descriptor = parseRootDescriptor();
      if (!Descriptor.has_value())
        return true;
      Elements.push_back(*Descriptor);
    }

    if (tryConsumeExpectedToken(TokenKind::kw_StaticSampler)) {
      auto Sampler = parseStaticSampler();
      if (!Sampler.has_value())
        return true;
      Elements.push_back(*Sampler);
    }
  } while (tryConsumeExpectedToken(TokenKind::pu_comma));

  return consumeExpectedToken(TokenKind::end_of_stream,
                              diag::err_hlsl_unexpected_end_of_params,
                              /*param of=*/TokenKind::kw_RootSignature);
}

template <typename FlagType>
static FlagType maybeOrFlag(std::optional<FlagType> Flags, FlagType Flag) {
  if (!Flags.has_value())
    return Flag;

  return static_cast<FlagType>(llvm::to_underlying(Flags.value()) |
                               llvm::to_underlying(Flag));
}

std::optional<RootFlags> RootSignatureParser::parseRootFlags() {
  assert(CurToken.TokKind == TokenKind::kw_RootFlags &&
         "Expects to only be invoked starting at given keyword");

  if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
                           CurToken.TokKind))
    return std::nullopt;

  std::optional<RootFlags> Flags = RootFlags::None;

  // Handle the edge-case of '0' to specify no flags set
  if (tryConsumeExpectedToken(TokenKind::int_literal)) {
    if (!verifyZeroFlag()) {
      getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_non_zero_flag);
      return std::nullopt;
    }
  } else {
    // Otherwise, parse as many flags as possible
    TokenKind Expected[] = {
#define ROOT_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
    };

    do {
      if (tryConsumeExpectedToken(Expected)) {
        switch (CurToken.TokKind) {
#define ROOT_FLAG_ENUM(NAME, LIT)                                              \
  case TokenKind::en_##NAME:                                                   \
    Flags = maybeOrFlag<RootFlags>(Flags, RootFlags::NAME);                    \
    break;
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
        default:
          llvm_unreachable("Switch for consumed enum token was not provided");
        }
      }
    } while (tryConsumeExpectedToken(TokenKind::pu_or));
  }

  if (consumeExpectedToken(TokenKind::pu_r_paren,
                           diag::err_hlsl_unexpected_end_of_params,
                           /*param of=*/TokenKind::kw_RootFlags))
    return std::nullopt;

  return Flags;
}

std::optional<RootConstants> RootSignatureParser::parseRootConstants() {
  assert(CurToken.TokKind == TokenKind::kw_RootConstants &&
         "Expects to only be invoked starting at given keyword");

  if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
                           CurToken.TokKind))
    return std::nullopt;

  RootConstants Constants;

  auto Params = parseRootConstantParams();
  if (!Params.has_value())
    return std::nullopt;

  // Check mandatory parameters where provided
  if (!Params->Num32BitConstants.has_value()) {
    getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param)
        << TokenKind::kw_num32BitConstants;
    return std::nullopt;
  }

  Constants.Num32BitConstants = Params->Num32BitConstants.value();

  if (!Params->Reg.has_value()) {
    getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param)
        << TokenKind::bReg;
    return std::nullopt;
  }

  Constants.Reg = Params->Reg.value();

  // Fill in optional parameters
  if (Params->Visibility.has_value())
    Constants.Visibility = Params->Visibility.value();

  if (Params->Space.has_value())
    Constants.Space = Params->Space.value();

  if (consumeExpectedToken(TokenKind::pu_r_paren,
                           diag::err_hlsl_unexpected_end_of_params,
                           /*param of=*/TokenKind::kw_RootConstants))
    return std::nullopt;

  return Constants;
}

std::optional<RootDescriptor> RootSignatureParser::parseRootDescriptor() {
  assert((CurToken.TokKind == TokenKind::kw_CBV ||
          CurToken.TokKind == TokenKind::kw_SRV ||
          CurToken.TokKind == TokenKind::kw_UAV) &&
         "Expects to only be invoked starting at given keyword");

  TokenKind DescriptorKind = CurToken.TokKind;

  if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
                           CurToken.TokKind))
    return std::nullopt;

  RootDescriptor Descriptor;
  TokenKind ExpectedReg;
  switch (DescriptorKind) {
  default:
    llvm_unreachable("Switch for consumed token was not provided");
  case TokenKind::kw_CBV:
    Descriptor.Type = DescriptorType::CBuffer;
    ExpectedReg = TokenKind::bReg;
    break;
  case TokenKind::kw_SRV:
    Descriptor.Type = DescriptorType::SRV;
    ExpectedReg = TokenKind::tReg;
    break;
  case TokenKind::kw_UAV:
    Descriptor.Type = DescriptorType::UAV;
    ExpectedReg = TokenKind::uReg;
    break;
  }
  Descriptor.setDefaultFlags();

  auto Params = parseRootDescriptorParams(ExpectedReg);
  if (!Params.has_value())
    return std::nullopt;

  // Check mandatory parameters were provided
  if (!Params->Reg.has_value()) {
    getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param)
        << ExpectedReg;
    return std::nullopt;
  }

  Descriptor.Reg = Params->Reg.value();

  // Fill in optional values
  if (Params->Space.has_value())
    Descriptor.Space = Params->Space.value();

  if (Params->Visibility.has_value())
    Descriptor.Visibility = Params->Visibility.value();

  if (Params->Flags.has_value())
    Descriptor.Flags = Params->Flags.value();

  if (consumeExpectedToken(TokenKind::pu_r_paren,
                           diag::err_hlsl_unexpected_end_of_params,
                           /*param of=*/TokenKind::kw_RootConstants))
    return std::nullopt;

  return Descriptor;
}

std::optional<DescriptorTable> RootSignatureParser::parseDescriptorTable() {
  assert(CurToken.TokKind == TokenKind::kw_DescriptorTable &&
         "Expects to only be invoked starting at given keyword");

  if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
                           CurToken.TokKind))
    return std::nullopt;

  DescriptorTable Table;
  std::optional<ShaderVisibility> Visibility;

  // Iterate as many Clauses as possible
  do {
    if (tryConsumeExpectedToken({TokenKind::kw_CBV, TokenKind::kw_SRV,
                                 TokenKind::kw_UAV, TokenKind::kw_Sampler})) {
      auto Clause = parseDescriptorTableClause();
      if (!Clause.has_value())
        return std::nullopt;
      Elements.push_back(*Clause);
      Table.NumClauses++;
    }

    if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
      if (Visibility.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      Visibility = parseShaderVisibility();
      if (!Visibility.has_value())
        return std::nullopt;
    }
  } while (tryConsumeExpectedToken(TokenKind::pu_comma));

  // Fill in optional visibility
  if (Visibility.has_value())
    Table.Visibility = Visibility.value();

  if (consumeExpectedToken(TokenKind::pu_r_paren,
                           diag::err_hlsl_unexpected_end_of_params,
                           /*param of=*/TokenKind::kw_DescriptorTable))
    return std::nullopt;

  return Table;
}

std::optional<DescriptorTableClause>
RootSignatureParser::parseDescriptorTableClause() {
  assert((CurToken.TokKind == TokenKind::kw_CBV ||
          CurToken.TokKind == TokenKind::kw_SRV ||
          CurToken.TokKind == TokenKind::kw_UAV ||
          CurToken.TokKind == TokenKind::kw_Sampler) &&
         "Expects to only be invoked starting at given keyword");

  TokenKind ParamKind = CurToken.TokKind;

  if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
                           CurToken.TokKind))
    return std::nullopt;

  DescriptorTableClause Clause;
  TokenKind ExpectedReg;
  switch (ParamKind) {
  default:
    llvm_unreachable("Switch for consumed token was not provided");
  case TokenKind::kw_CBV:
    Clause.Type = ClauseType::CBuffer;
    ExpectedReg = TokenKind::bReg;
    break;
  case TokenKind::kw_SRV:
    Clause.Type = ClauseType::SRV;
    ExpectedReg = TokenKind::tReg;
    break;
  case TokenKind::kw_UAV:
    Clause.Type = ClauseType::UAV;
    ExpectedReg = TokenKind::uReg;
    break;
  case TokenKind::kw_Sampler:
    Clause.Type = ClauseType::Sampler;
    ExpectedReg = TokenKind::sReg;
    break;
  }
  Clause.setDefaultFlags();

  auto Params = parseDescriptorTableClauseParams(ExpectedReg);
  if (!Params.has_value())
    return std::nullopt;

  // Check mandatory parameters were provided
  if (!Params->Reg.has_value()) {
    getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param)
        << ExpectedReg;
    return std::nullopt;
  }

  Clause.Reg = Params->Reg.value();

  // Fill in optional values
  if (Params->NumDescriptors.has_value())
    Clause.NumDescriptors = Params->NumDescriptors.value();

  if (Params->Space.has_value())
    Clause.Space = Params->Space.value();

  if (Params->Offset.has_value())
    Clause.Offset = Params->Offset.value();

  if (Params->Flags.has_value())
    Clause.Flags = Params->Flags.value();

  if (consumeExpectedToken(TokenKind::pu_r_paren,
                           diag::err_hlsl_unexpected_end_of_params,
                           /*param of=*/ParamKind))
    return std::nullopt;

  return Clause;
}

std::optional<StaticSampler> RootSignatureParser::parseStaticSampler() {
  assert(CurToken.TokKind == TokenKind::kw_StaticSampler &&
         "Expects to only be invoked starting at given keyword");

  if (consumeExpectedToken(TokenKind::pu_l_paren, diag::err_expected_after,
                           CurToken.TokKind))
    return std::nullopt;

  StaticSampler Sampler;

  auto Params = parseStaticSamplerParams();
  if (!Params.has_value())
    return std::nullopt;

  // Check mandatory parameters were provided
  if (!Params->Reg.has_value()) {
    getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_missing_param)
        << TokenKind::sReg;
    return std::nullopt;
  }

  Sampler.Reg = Params->Reg.value();

  // Fill in optional values
  if (Params->AddressU.has_value())
    Sampler.AddressU = Params->AddressU.value();

  if (Params->AddressV.has_value())
    Sampler.AddressV = Params->AddressV.value();

  if (Params->AddressW.has_value())
    Sampler.AddressW = Params->AddressW.value();

  if (Params->MipLODBias.has_value())
    Sampler.MipLODBias = Params->MipLODBias.value();

  if (Params->MaxAnisotropy.has_value())
    Sampler.MaxAnisotropy = Params->MaxAnisotropy.value();

  if (Params->CompFunc.has_value())
    Sampler.CompFunc = Params->CompFunc.value();

  if (Params->BorderColor.has_value())
    Sampler.BorderColor = Params->BorderColor.value();

  if (Params->MinLOD.has_value())
    Sampler.MinLOD = Params->MinLOD.value();

  if (Params->MaxLOD.has_value())
    Sampler.MaxLOD = Params->MaxLOD.value();

  if (Params->Space.has_value())
    Sampler.Space = Params->Space.value();

  if (Params->Visibility.has_value())
    Sampler.Visibility = Params->Visibility.value();

  if (consumeExpectedToken(TokenKind::pu_r_paren,
                           diag::err_hlsl_unexpected_end_of_params,
                           /*param of=*/TokenKind::kw_StaticSampler))
    return std::nullopt;

  return Sampler;
}

// Parameter arguments (eg. `bReg`, `space`, ...) can be specified in any
// order and only exactly once. The following methods will parse through as
// many arguments as possible reporting an error if a duplicate is seen.
std::optional<RootSignatureParser::ParsedConstantParams>
RootSignatureParser::parseRootConstantParams() {
  assert(CurToken.TokKind == TokenKind::pu_l_paren &&
         "Expects to only be invoked starting at given token");

  ParsedConstantParams Params;
  do {
    // `num32BitConstants` `=` POS_INT
    if (tryConsumeExpectedToken(TokenKind::kw_num32BitConstants)) {
      if (Params.Num32BitConstants.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto Num32BitConstants = parseUIntParam();
      if (!Num32BitConstants.has_value())
        return std::nullopt;
      Params.Num32BitConstants = Num32BitConstants;
    }

    // `b` POS_INT
    if (tryConsumeExpectedToken(TokenKind::bReg)) {
      if (Params.Reg.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }
      auto Reg = parseRegister();
      if (!Reg.has_value())
        return std::nullopt;
      Params.Reg = Reg;
    }

    // `space` `=` POS_INT
    if (tryConsumeExpectedToken(TokenKind::kw_space)) {
      if (Params.Space.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto Space = parseUIntParam();
      if (!Space.has_value())
        return std::nullopt;
      Params.Space = Space;
    }

    // `visibility` `=` SHADER_VISIBILITY
    if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
      if (Params.Visibility.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto Visibility = parseShaderVisibility();
      if (!Visibility.has_value())
        return std::nullopt;
      Params.Visibility = Visibility;
    }
  } while (tryConsumeExpectedToken(TokenKind::pu_comma));

  return Params;
}

std::optional<RootSignatureParser::ParsedRootDescriptorParams>
RootSignatureParser::parseRootDescriptorParams(TokenKind RegType) {
  assert(CurToken.TokKind == TokenKind::pu_l_paren &&
         "Expects to only be invoked starting at given token");

  ParsedRootDescriptorParams Params;
  do {
    // ( `b` | `t` | `u`) POS_INT
    if (tryConsumeExpectedToken(RegType)) {
      if (Params.Reg.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }
      auto Reg = parseRegister();
      if (!Reg.has_value())
        return std::nullopt;
      Params.Reg = Reg;
    }

    // `space` `=` POS_INT
    if (tryConsumeExpectedToken(TokenKind::kw_space)) {
      if (Params.Space.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto Space = parseUIntParam();
      if (!Space.has_value())
        return std::nullopt;
      Params.Space = Space;
    }

    // `visibility` `=` SHADER_VISIBILITY
    if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
      if (Params.Visibility.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto Visibility = parseShaderVisibility();
      if (!Visibility.has_value())
        return std::nullopt;
      Params.Visibility = Visibility;
    }

    // `flags` `=` ROOT_DESCRIPTOR_FLAGS
    if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
      if (Params.Flags.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto Flags = parseRootDescriptorFlags();
      if (!Flags.has_value())
        return std::nullopt;
      Params.Flags = Flags;
    }
  } while (tryConsumeExpectedToken(TokenKind::pu_comma));

  return Params;
}

std::optional<RootSignatureParser::ParsedClauseParams>
RootSignatureParser::parseDescriptorTableClauseParams(TokenKind RegType) {
  assert(CurToken.TokKind == TokenKind::pu_l_paren &&
         "Expects to only be invoked starting at given token");

  ParsedClauseParams Params;
  do {
    // ( `b` | `t` | `u` | `s`) POS_INT
    if (tryConsumeExpectedToken(RegType)) {
      if (Params.Reg.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }
      auto Reg = parseRegister();
      if (!Reg.has_value())
        return std::nullopt;
      Params.Reg = Reg;
    }

    // `numDescriptors` `=` POS_INT | unbounded
    if (tryConsumeExpectedToken(TokenKind::kw_numDescriptors)) {
      if (Params.NumDescriptors.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      std::optional<uint32_t> NumDescriptors;
      if (tryConsumeExpectedToken(TokenKind::en_unbounded))
        NumDescriptors = NumDescriptorsUnbounded;
      else {
        NumDescriptors = parseUIntParam();
        if (!NumDescriptors.has_value())
          return std::nullopt;
      }

      Params.NumDescriptors = NumDescriptors;
    }

    // `space` `=` POS_INT
    if (tryConsumeExpectedToken(TokenKind::kw_space)) {
      if (Params.Space.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto Space = parseUIntParam();
      if (!Space.has_value())
        return std::nullopt;
      Params.Space = Space;
    }

    // `offset` `=` POS_INT | DESCRIPTOR_RANGE_OFFSET_APPEND
    if (tryConsumeExpectedToken(TokenKind::kw_offset)) {
      if (Params.Offset.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      std::optional<uint32_t> Offset;
      if (tryConsumeExpectedToken(TokenKind::en_DescriptorRangeOffsetAppend))
        Offset = DescriptorTableOffsetAppend;
      else {
        Offset = parseUIntParam();
        if (!Offset.has_value())
          return std::nullopt;
      }

      Params.Offset = Offset;
    }

    // `flags` `=` DESCRIPTOR_RANGE_FLAGS
    if (tryConsumeExpectedToken(TokenKind::kw_flags)) {
      if (Params.Flags.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto Flags = parseDescriptorRangeFlags();
      if (!Flags.has_value())
        return std::nullopt;
      Params.Flags = Flags;
    }

  } while (tryConsumeExpectedToken(TokenKind::pu_comma));

  return Params;
}

std::optional<RootSignatureParser::ParsedStaticSamplerParams>
RootSignatureParser::parseStaticSamplerParams() {
  assert(CurToken.TokKind == TokenKind::pu_l_paren &&
         "Expects to only be invoked starting at given token");

  ParsedStaticSamplerParams Params;
  do {
    // `s` POS_INT
    if (tryConsumeExpectedToken(TokenKind::sReg)) {
      if (Params.Reg.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }
      auto Reg = parseRegister();
      if (!Reg.has_value())
        return std::nullopt;
      Params.Reg = Reg;
    }

    // `addressU` `=` TEXTURE_ADDRESS
    if (tryConsumeExpectedToken(TokenKind::kw_addressU)) {
      if (Params.AddressU.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto AddressU = parseTextureAddressMode();
      if (!AddressU.has_value())
        return std::nullopt;
      Params.AddressU = AddressU;
    }

    // `addressV` `=` TEXTURE_ADDRESS
    if (tryConsumeExpectedToken(TokenKind::kw_addressV)) {
      if (Params.AddressV.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto AddressV = parseTextureAddressMode();
      if (!AddressV.has_value())
        return std::nullopt;
      Params.AddressV = AddressV;
    }

    // `addressW` `=` TEXTURE_ADDRESS
    if (tryConsumeExpectedToken(TokenKind::kw_addressW)) {
      if (Params.AddressW.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto AddressW = parseTextureAddressMode();
      if (!AddressW.has_value())
        return std::nullopt;
      Params.AddressW = AddressW;
    }

    // `mipLODBias` `=` NUMBER
    if (tryConsumeExpectedToken(TokenKind::kw_mipLODBias)) {
      if (Params.MipLODBias.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto MipLODBias = parseFloatParam();
      if (!MipLODBias.has_value())
        return std::nullopt;
      Params.MipLODBias = MipLODBias;
    }

    // `maxAnisotropy` `=` POS_INT
    if (tryConsumeExpectedToken(TokenKind::kw_maxAnisotropy)) {
      if (Params.MaxAnisotropy.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto MaxAnisotropy = parseUIntParam();
      if (!MaxAnisotropy.has_value())
        return std::nullopt;
      Params.MaxAnisotropy = MaxAnisotropy;
    }

    // `comparisonFunc` `=` COMPARISON_FUNC
    if (tryConsumeExpectedToken(TokenKind::kw_comparisonFunc)) {
      if (Params.CompFunc.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto CompFunc = parseComparisonFunc();
      if (!CompFunc.has_value())
        return std::nullopt;
      Params.CompFunc = CompFunc;
    }

    // `borderColor` `=` STATIC_BORDER_COLOR
    if (tryConsumeExpectedToken(TokenKind::kw_borderColor)) {
      if (Params.BorderColor.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto BorderColor = parseStaticBorderColor();
      if (!BorderColor.has_value())
        return std::nullopt;
      Params.BorderColor = BorderColor;
    }

    // `minLOD` `=` NUMBER
    if (tryConsumeExpectedToken(TokenKind::kw_minLOD)) {
      if (Params.MinLOD.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto MinLOD = parseFloatParam();
      if (!MinLOD.has_value())
        return std::nullopt;
      Params.MinLOD = MinLOD;
    }

    // `maxLOD` `=` NUMBER
    if (tryConsumeExpectedToken(TokenKind::kw_maxLOD)) {
      if (Params.MaxLOD.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto MaxLOD = parseFloatParam();
      if (!MaxLOD.has_value())
        return std::nullopt;
      Params.MaxLOD = MaxLOD;
    }

    // `space` `=` POS_INT
    if (tryConsumeExpectedToken(TokenKind::kw_space)) {
      if (Params.Space.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto Space = parseUIntParam();
      if (!Space.has_value())
        return std::nullopt;
      Params.Space = Space;
    }

    // `visibility` `=` SHADER_VISIBILITY
    if (tryConsumeExpectedToken(TokenKind::kw_visibility)) {
      if (Params.Visibility.has_value()) {
        getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_repeat_param)
            << CurToken.TokKind;
        return std::nullopt;
      }

      if (consumeExpectedToken(TokenKind::pu_equal))
        return std::nullopt;

      auto Visibility = parseShaderVisibility();
      if (!Visibility.has_value())
        return std::nullopt;
      Params.Visibility = Visibility;
    }
  } while (tryConsumeExpectedToken(TokenKind::pu_comma));

  return Params;
}

std::optional<uint32_t> RootSignatureParser::parseUIntParam() {
  assert(CurToken.TokKind == TokenKind::pu_equal &&
         "Expects to only be invoked starting at given keyword");
  tryConsumeExpectedToken(TokenKind::pu_plus);
  if (consumeExpectedToken(TokenKind::int_literal, diag::err_expected_after,
                           CurToken.TokKind))
    return std::nullopt;
  return handleUIntLiteral();
}

std::optional<Register> RootSignatureParser::parseRegister() {
  assert((CurToken.TokKind == TokenKind::bReg ||
          CurToken.TokKind == TokenKind::tReg ||
          CurToken.TokKind == TokenKind::uReg ||
          CurToken.TokKind == TokenKind::sReg) &&
         "Expects to only be invoked starting at given keyword");

  Register Reg;
  switch (CurToken.TokKind) {
  default:
    llvm_unreachable("Switch for consumed token was not provided");
  case TokenKind::bReg:
    Reg.ViewType = RegisterType::BReg;
    break;
  case TokenKind::tReg:
    Reg.ViewType = RegisterType::TReg;
    break;
  case TokenKind::uReg:
    Reg.ViewType = RegisterType::UReg;
    break;
  case TokenKind::sReg:
    Reg.ViewType = RegisterType::SReg;
    break;
  }

  auto Number = handleUIntLiteral();
  if (!Number.has_value())
    return std::nullopt; // propogate NumericLiteralParser error

  Reg.Number = *Number;
  return Reg;
}

std::optional<float> RootSignatureParser::parseFloatParam() {
  assert(CurToken.TokKind == TokenKind::pu_equal &&
         "Expects to only be invoked starting at given keyword");
  // Consume sign modifier
  bool Signed =
      tryConsumeExpectedToken({TokenKind::pu_plus, TokenKind::pu_minus});
  bool Negated = Signed && CurToken.TokKind == TokenKind::pu_minus;

  // DXC will treat a postive signed integer as unsigned
  if (!Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {
    std::optional<uint32_t> UInt = handleUIntLiteral();
    if (!UInt.has_value())
      return std::nullopt;
    return float(UInt.value());
  }

  if (Negated && tryConsumeExpectedToken(TokenKind::int_literal)) {
    std::optional<int32_t> Int = handleIntLiteral(Negated);
    if (!Int.has_value())
      return std::nullopt;
    return float(Int.value());
  }

  if (tryConsumeExpectedToken(TokenKind::float_literal)) {
    std::optional<float> Float = handleFloatLiteral(Negated);
    if (!Float.has_value())
      return std::nullopt;
    return Float.value();
  }

  return std::nullopt;
}

std::optional<llvm::hlsl::rootsig::ShaderVisibility>
RootSignatureParser::parseShaderVisibility() {
  assert(CurToken.TokKind == TokenKind::pu_equal &&
         "Expects to only be invoked starting at given keyword");

  TokenKind Expected[] = {
#define SHADER_VISIBILITY_ENUM(NAME, LIT) TokenKind::en_##NAME,
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
  };

  if (!tryConsumeExpectedToken(Expected))
    return std::nullopt;

  switch (CurToken.TokKind) {
#define SHADER_VISIBILITY_ENUM(NAME, LIT)                                      \
  case TokenKind::en_##NAME:                                                   \
    return ShaderVisibility::NAME;                                             \
    break;
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
  default:
    llvm_unreachable("Switch for consumed enum token was not provided");
  }

  return std::nullopt;
}

std::optional<llvm::hlsl::rootsig::TextureAddressMode>
RootSignatureParser::parseTextureAddressMode() {
  assert(CurToken.TokKind == TokenKind::pu_equal &&
         "Expects to only be invoked starting at given keyword");

  TokenKind Expected[] = {
#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT) TokenKind::en_##NAME,
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
  };

  if (!tryConsumeExpectedToken(Expected))
    return std::nullopt;

  switch (CurToken.TokKind) {
#define TEXTURE_ADDRESS_MODE_ENUM(NAME, LIT)                                   \
  case TokenKind::en_##NAME:                                                   \
    return TextureAddressMode::NAME;                                           \
    break;
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
  default:
    llvm_unreachable("Switch for consumed enum token was not provided");
  }

  return std::nullopt;
}

std::optional<llvm::hlsl::rootsig::ComparisonFunc>
RootSignatureParser::parseComparisonFunc() {
  assert(CurToken.TokKind == TokenKind::pu_equal &&
         "Expects to only be invoked starting at given keyword");

  TokenKind Expected[] = {
#define COMPARISON_FUNC_ENUM(NAME, LIT) TokenKind::en_##NAME,
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
  };

  if (!tryConsumeExpectedToken(Expected))
    return std::nullopt;

  switch (CurToken.TokKind) {
#define COMPARISON_FUNC_ENUM(NAME, LIT)                                        \
  case TokenKind::en_##NAME:                                                   \
    return ComparisonFunc::NAME;                                               \
    break;
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
  default:
    llvm_unreachable("Switch for consumed enum token was not provided");
  }

  return std::nullopt;
}

std::optional<llvm::hlsl::rootsig::StaticBorderColor>
RootSignatureParser::parseStaticBorderColor() {
  assert(CurToken.TokKind == TokenKind::pu_equal &&
         "Expects to only be invoked starting at given keyword");

  TokenKind Expected[] = {
#define STATIC_BORDER_COLOR_ENUM(NAME, LIT) TokenKind::en_##NAME,
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
  };

  if (!tryConsumeExpectedToken(Expected))
    return std::nullopt;

  switch (CurToken.TokKind) {
#define STATIC_BORDER_COLOR_ENUM(NAME, LIT)                                    \
  case TokenKind::en_##NAME:                                                   \
    return StaticBorderColor::NAME;                                            \
    break;
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
  default:
    llvm_unreachable("Switch for consumed enum token was not provided");
  }

  return std::nullopt;
}

std::optional<llvm::hlsl::rootsig::RootDescriptorFlags>
RootSignatureParser::parseRootDescriptorFlags() {
  assert(CurToken.TokKind == TokenKind::pu_equal &&
         "Expects to only be invoked starting at given keyword");

  // Handle the edge-case of '0' to specify no flags set
  if (tryConsumeExpectedToken(TokenKind::int_literal)) {
    if (!verifyZeroFlag()) {
      getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_non_zero_flag);
      return std::nullopt;
    }
    return RootDescriptorFlags::None;
  }

  TokenKind Expected[] = {
#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT) TokenKind::en_##NAME,
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
  };

  std::optional<RootDescriptorFlags> Flags;

  do {
    if (tryConsumeExpectedToken(Expected)) {
      switch (CurToken.TokKind) {
#define ROOT_DESCRIPTOR_FLAG_ENUM(NAME, LIT)                                   \
  case TokenKind::en_##NAME:                                                   \
    Flags =                                                                    \
        maybeOrFlag<RootDescriptorFlags>(Flags, RootDescriptorFlags::NAME);    \
    break;
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
      default:
        llvm_unreachable("Switch for consumed enum token was not provided");
      }
    }
  } while (tryConsumeExpectedToken(TokenKind::pu_or));

  return Flags;
}

std::optional<llvm::hlsl::rootsig::DescriptorRangeFlags>
RootSignatureParser::parseDescriptorRangeFlags() {
  assert(CurToken.TokKind == TokenKind::pu_equal &&
         "Expects to only be invoked starting at given keyword");

  // Handle the edge-case of '0' to specify no flags set
  if (tryConsumeExpectedToken(TokenKind::int_literal)) {
    if (!verifyZeroFlag()) {
      getDiags().Report(CurToken.TokLoc, diag::err_hlsl_rootsig_non_zero_flag);
      return std::nullopt;
    }
    return DescriptorRangeFlags::None;
  }

  TokenKind Expected[] = {
#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON) TokenKind::en_##NAME,
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
  };

  std::optional<DescriptorRangeFlags> Flags;

  do {
    if (tryConsumeExpectedToken(Expected)) {
      switch (CurToken.TokKind) {
#define DESCRIPTOR_RANGE_FLAG_ENUM(NAME, LIT, ON)                              \
  case TokenKind::en_##NAME:                                                   \
    Flags =                                                                    \
        maybeOrFlag<DescriptorRangeFlags>(Flags, DescriptorRangeFlags::NAME);  \
    break;
#include "clang/Lex/HLSLRootSignatureTokenKinds.def"
      default:
        llvm_unreachable("Switch for consumed enum token was not provided");
      }
    }
  } while (tryConsumeExpectedToken(TokenKind::pu_or));

  return Flags;
}

std::optional<uint32_t> RootSignatureParser::handleUIntLiteral() {
  // Parse the numeric value and do semantic checks on its specification
  clang::NumericLiteralParser Literal(CurToken.NumSpelling, CurToken.TokLoc,
                                      PP.getSourceManager(), PP.getLangOpts(),
                                      PP.getTargetInfo(), PP.getDiagnostics());
  if (Literal.hadError)
    return std::nullopt; // Error has already been reported so just return

  assert(Literal.isIntegerLiteral() &&
         "NumSpelling can only consist of digits");

  llvm::APSInt Val(32, /*IsUnsigned=*/true);
  if (Literal.GetIntegerValue(Val)) {
    // Report that the value has overflowed
    PP.getDiagnostics().Report(CurToken.TokLoc,
                               diag::err_hlsl_number_literal_overflow)
        << /*integer type*/ 0 << /*is signed*/ 0;
    return std::nullopt;
  }

  return Val.getExtValue();
}

std::optional<int32_t> RootSignatureParser::handleIntLiteral(bool Negated) {
  // Parse the numeric value and do semantic checks on its specification
  clang::NumericLiteralParser Literal(CurToken.NumSpelling, CurToken.TokLoc,
                                      PP.getSourceManager(), PP.getLangOpts(),
                                      PP.getTargetInfo(), PP.getDiagnostics());
  if (Literal.hadError)
    return std::nullopt; // Error has already been reported so just return

  assert(Literal.isIntegerLiteral() &&
         "NumSpelling can only consist of digits");

  llvm::APSInt Val(32, /*IsUnsigned=*/true);
  // GetIntegerValue will overwrite Val from the parsed Literal and return
  // true if it overflows as a 32-bit unsigned int
  bool Overflowed = Literal.GetIntegerValue(Val);

  // So we then need to check that it doesn't overflow as a 32-bit signed int:
  int64_t MaxNegativeMagnitude = -int64_t(std::numeric_limits<int32_t>::min());
  Overflowed |= (Negated && MaxNegativeMagnitude < Val.getExtValue());

  int64_t MaxPositiveMagnitude = int64_t(std::numeric_limits<int32_t>::max());
  Overflowed |= (!Negated && MaxPositiveMagnitude < Val.getExtValue());

  if (Overflowed) {
    // Report that the value has overflowed
    PP.getDiagnostics().Report(CurToken.TokLoc,
                               diag::err_hlsl_number_literal_overflow)
        << /*integer type*/ 0 << /*is signed*/ 1;
    return std::nullopt;
  }

  if (Negated)
    Val = -Val;

  return int32_t(Val.getExtValue());
}

std::optional<float> RootSignatureParser::handleFloatLiteral(bool Negated) {
  // Parse the numeric value and do semantic checks on its specification
  clang::NumericLiteralParser Literal(CurToken.NumSpelling, CurToken.TokLoc,
                                      PP.getSourceManager(), PP.getLangOpts(),
                                      PP.getTargetInfo(), PP.getDiagnostics());
  if (Literal.hadError)
    return std::nullopt; // Error has already been reported so just return

  assert(Literal.isFloatingLiteral() &&
         "NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
         "will be caught and reported by NumericLiteralParser.");

  // DXC used `strtod` to convert the token string to a float which corresponds
  // to:
  auto DXCSemantics = llvm::APFloat::Semantics::S_IEEEdouble;
  auto DXCRoundingMode = llvm::RoundingMode::NearestTiesToEven;

  llvm::APFloat Val(llvm::APFloat::EnumToSemantics(DXCSemantics));
  llvm::APFloat::opStatus Status(Literal.GetFloatValue(Val, DXCRoundingMode));

  // Note: we do not error when opStatus::opInexact by itself as this just
  // denotes that rounding occured but not that it is invalid
  assert(!(Status & llvm::APFloat::opStatus::opInvalidOp) &&
         "NumSpelling consists only of [0-9.ef+-]. Any malformed NumSpelling "
         "will be caught and reported by NumericLiteralParser.");

  assert(!(Status & llvm::APFloat::opStatus::opDivByZero) &&
         "It is not possible for a division to be performed when "
         "constructing an APFloat from a string");

  if (Status & llvm::APFloat::opStatus::opUnderflow) {
    // Report that the value has underflowed
    PP.getDiagnostics().Report(CurToken.TokLoc,
                               diag::err_hlsl_number_literal_underflow);
    return std::nullopt;
  }

  if (Status & llvm::APFloat::opStatus::opOverflow) {
    // Report that the value has overflowed
    PP.getDiagnostics().Report(CurToken.TokLoc,
                               diag::err_hlsl_number_literal_overflow)
        << /*float type*/ 1;
    return std::nullopt;
  }

  if (Negated)
    Val = -Val;

  double DoubleVal = Val.convertToDouble();
  double FloatMax = double(std::numeric_limits<float>::max());
  if (FloatMax < DoubleVal || DoubleVal < -FloatMax) {
    // Report that the value has overflowed
    PP.getDiagnostics().Report(CurToken.TokLoc,
                               diag::err_hlsl_number_literal_overflow)
        << /*float type*/ 1;
    return std::nullopt;
  }

  return static_cast<float>(DoubleVal);
}

bool RootSignatureParser::verifyZeroFlag() {
  assert(CurToken.TokKind == TokenKind::int_literal);
  auto X = handleUIntLiteral();
  return X.has_value() && X.value() == 0;
}

bool RootSignatureParser::peekExpectedToken(TokenKind Expected) {
  return peekExpectedToken(ArrayRef{Expected});
}

bool RootSignatureParser::peekExpectedToken(ArrayRef<TokenKind> AnyExpected) {
  RootSignatureToken Result = Lexer.peekNextToken();
  return llvm::is_contained(AnyExpected, Result.TokKind);
}

bool RootSignatureParser::consumeExpectedToken(TokenKind Expected,
                                               unsigned DiagID,
                                               TokenKind Context) {
  if (tryConsumeExpectedToken(Expected))
    return false;

  // Report unexpected token kind error
  DiagnosticBuilder DB = getDiags().Report(CurToken.TokLoc, DiagID);
  switch (DiagID) {
  case diag::err_expected:
    DB << Expected;
    break;
  case diag::err_hlsl_unexpected_end_of_params:
  case diag::err_expected_either:
  case diag::err_expected_after:
    DB << Expected << Context;
    break;
  default:
    break;
  }
  return true;
}

bool RootSignatureParser::tryConsumeExpectedToken(TokenKind Expected) {
  return tryConsumeExpectedToken(ArrayRef{Expected});
}

bool RootSignatureParser::tryConsumeExpectedToken(
    ArrayRef<TokenKind> AnyExpected) {
  // If not the expected token just return
  if (!peekExpectedToken(AnyExpected))
    return false;
  consumeNextToken();
  return true;
}

} // namespace hlsl
} // namespace clang
