[llvm] [DirectX] Making sure we always parse, validate and verify Flags (PR #162171)

via llvm-commits llvm-commits at lists.llvm.org
Wed Oct 8 12:35:44 PDT 2025


https://github.com/joaosaffran updated https://github.com/llvm/llvm-project/pull/162171

>From e0612d71bab9829822d6cd969684cce630df40cf Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranllvm at gmail.com>
Date: Fri, 3 Oct 2025 14:11:54 -0700
Subject: [PATCH 01/10] remove error classes

---
 .../Frontend/HLSL/RootSignatureMetadata.h     | 269 ++++++++----------
 1 file changed, 122 insertions(+), 147 deletions(-)

diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
index bfcbf728d415c..65b637f2d80cc 100644
--- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
+++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
@@ -28,164 +28,139 @@ class Metadata;
 namespace hlsl {
 namespace rootsig {
 
-template <typename T>
-class RootSignatureValidationError
-    : public ErrorInfo<RootSignatureValidationError<T>> {
-public:
-  static char ID;
-  StringRef ParamName;
-  T Value;
-
-  RootSignatureValidationError(StringRef ParamName, T Value)
-      : ParamName(ParamName), Value(Value) {}
-
-  void log(raw_ostream &OS) const override {
-    OS << "Invalid value for " << ParamName << ": " << Value;
-  }
-
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
+enum class ErrorKind {
+  Validation,
+  AppendAfterUnboundedRange,
+  ShaderRegisterOverflow,
+  OffsetOverflow,
+  SamplerMixin,
+  GenericMetadata,
+  InvalidMetadataFormat,
+  InvalidMetadataValue
 };
 
-class OffsetAppendAfterOverflow : public ErrorInfo<OffsetAppendAfterOverflow> {
-public:
-  static char ID;
-  dxil::ResourceClass Type;
-  uint32_t Register;
-  uint32_t Space;
-
-  OffsetAppendAfterOverflow(dxil::ResourceClass Type, uint32_t Register,
-                            uint32_t Space)
-      : Type(Type), Register(Register), Space(Space) {}
-
-  void log(raw_ostream &OS) const override {
-    OS << "Range " << getResourceClassName(Type) << "(register=" << Register
+template <typename T>
+void formatImpl(raw_string_ostream &Buff,
+                std::integral_constant<ErrorKind, ErrorKind::Validation>,
+                StringRef ParamName, T Value) {
+  Buff << "Invalid value for: " << ParamName << ":" << Value;
+}
+
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<ErrorKind, ErrorKind::AppendAfterUnboundedRange>,
+    dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
+  Buff << "Range " << getResourceClassName(Type) << "(register=" << Register
        << ", space=" << Space << ") "
        << "cannot be appended after an unbounded range ";
-  }
-
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
-};
+}
 
-class ShaderRegisterOverflowError
-    : public ErrorInfo<ShaderRegisterOverflowError> {
-public:
-  static char ID;
-  dxil::ResourceClass Type;
-  uint32_t Register;
-  uint32_t Space;
-
-  ShaderRegisterOverflowError(dxil::ResourceClass Type, uint32_t Register,
-                              uint32_t Space)
-      : Type(Type), Register(Register), Space(Space) {}
-
-  void log(raw_ostream &OS) const override {
-    OS << "Overflow for shader register range: " << getResourceClassName(Type)
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<ErrorKind, ErrorKind::ShaderRegisterOverflow>,
+    dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
+  Buff << "Overflow for shader register range: " << getResourceClassName(Type)
        << "(register=" << Register << ", space=" << Space << ").";
-  }
+}
 
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
-};
-
-class OffsetOverflowError : public ErrorInfo<OffsetOverflowError> {
-public:
-  static char ID;
-  dxil::ResourceClass Type;
-  uint32_t Register;
-  uint32_t Space;
-
-  OffsetOverflowError(dxil::ResourceClass Type, uint32_t Register,
-                      uint32_t Space)
-      : Type(Type), Register(Register), Space(Space) {}
-
-  void log(raw_ostream &OS) const override {
-    OS << "Offset overflow for descriptor range: " << getResourceClassName(Type)
+void formatImpl(raw_string_ostream &Buff,
+                std::integral_constant<ErrorKind, ErrorKind::OffsetOverflow>,
+                dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
+  Buff << "Offset overflow for descriptor range: " << getResourceClassName(Type)
        << "(register=" << Register << ", space=" << Space << ").";
-  }
-
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
-};
-
-class TableSamplerMixinError : public ErrorInfo<TableSamplerMixinError> {
-public:
-  static char ID;
-  dxil::ResourceClass Type;
-  uint32_t Location;
-
-  TableSamplerMixinError(dxil::ResourceClass Type, uint32_t Location)
-      : Type(Type), Location(Location) {}
+}
 
-  void log(raw_ostream &OS) const override {
-    OS << "Samplers cannot be mixed with other "
+void formatImpl(raw_string_ostream &Buff,
+                std::integral_constant<ErrorKind, ErrorKind::SamplerMixin>,
+                dxil::ResourceClass Type, uint32_t Location) {
+  Buff << "Samplers cannot be mixed with other "
        << "resource types in a descriptor table, " << getResourceClassName(Type)
        << "(location=" << Location << ")";
-  }
-
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
-};
-
-class GenericRSMetadataError : public ErrorInfo<GenericRSMetadataError> {
-public:
-  LLVM_ABI static char ID;
-  StringRef Message;
-  MDNode *MD;
-
-  GenericRSMetadataError(StringRef Message, MDNode *MD)
-      : Message(Message), MD(MD) {}
-
-  void log(raw_ostream &OS) const override {
-    OS << Message;
-    if (MD) {
-      OS << "\n";
-      MD->printTree(OS);
-    }
-  }
-
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
-};
-
-class InvalidRSMetadataFormat : public ErrorInfo<InvalidRSMetadataFormat> {
-public:
-  LLVM_ABI static char ID;
-  StringRef ElementName;
-
-  InvalidRSMetadataFormat(StringRef ElementName) : ElementName(ElementName) {}
-
-  void log(raw_ostream &OS) const override {
-    OS << "Invalid format for  " << ElementName;
-  }
-
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
-};
-
-class InvalidRSMetadataValue : public ErrorInfo<InvalidRSMetadataValue> {
-public:
-  LLVM_ABI static char ID;
-  StringRef ParamName;
-
-  InvalidRSMetadataValue(StringRef ParamName) : ParamName(ParamName) {}
-
-  void log(raw_ostream &OS) const override {
-    OS << "Invalid value for " << ParamName;
-  }
-
-  std::error_code convertToErrorCode() const override {
-    return llvm::inconvertibleErrorCode();
-  }
-};
+}
+
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<ErrorKind, ErrorKind::InvalidMetadataFormat>,
+    StringRef ElementName) {
+  Buff << "Invalid format for  " << ElementName;
+}
+
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<ErrorKind, ErrorKind::InvalidMetadataValue>,
+    StringRef ParamName) {
+  Buff << "Invalid value for " << ParamName;
+}
+
+void formatImpl(raw_string_ostream &Buff,
+                std::integral_constant<ErrorKind, ErrorKind::GenericMetadata>,
+                StringRef Message, MDNode *MD) {
+  Buff << Message;
+  if (MD) {
+    Buff << "\n";
+    MD->printTree(Buff);
+  }
+}
+
+template <typename... ArgsTs>
+static void formatErrMsg(raw_string_ostream &Buff, ErrorKind Kind,
+                         ArgsTs... Args) {
+  switch (Kind) {
+  case ErrorKind::Validation:
+    formatImpl(Buff, std::integral_constant<ErrorKind, ErrorKind::Validation>{},
+               Args...);
+    break;
+  case ErrorKind::AppendAfterUnboundedRange:
+    formatImpl(Buff,
+               std::integral_constant<ErrorKind,
+                                      ErrorKind::AppendAfterUnboundedRange>{},
+               Args...);
+    break;
+  case ErrorKind::ShaderRegisterOverflow:
+    formatImpl(
+        Buff,
+        std::integral_constant<ErrorKind, ErrorKind::ShaderRegisterOverflow>{},
+        Args...);
+    break;
+  case ErrorKind::OffsetOverflow:
+    formatImpl(Buff,
+               std::integral_constant<ErrorKind, ErrorKind::OffsetOverflow>{},
+               Args...);
+    break;
+  case ErrorKind::SamplerMixin:
+    formatImpl(Buff,
+               std::integral_constant<ErrorKind, ErrorKind::SamplerMixin>{},
+               Args...);
+    break;
+  case ErrorKind::GenericMetadata:
+    formatImpl(Buff,
+               std::integral_constant<ErrorKind, ErrorKind::GenericMetadata>{},
+               Args...);
+    break;
+
+  case ErrorKind::InvalidMetadataFormat:
+    formatImpl(
+        Buff,
+        std::integral_constant<ErrorKind, ErrorKind::InvalidMetadataFormat>{},
+        Args...);
+    break;
+
+  case ErrorKind::InvalidMetadataValue:
+    formatImpl(
+        Buff,
+        std::integral_constant<ErrorKind, ErrorKind::InvalidMetadataValue>{},
+        Args...);
+    break;
+  }
+}
+
+template <typename... ArgsTs>
+static llvm::Error createRSError(ErrorKind Kind, ArgsTs... Args) {
+  std::string Msg;
+  raw_string_ostream Buff(Msg);
+  formatErrMsg(Buff, Kind, Args...);
+  return createStringError(std::move(Buff.str()), inconvertibleErrorCode());
+}
 
 class MetadataBuilder {
 public:

>From 7ae75fbd2988b327a530898622126f2e3c18f940 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranllvm at gmail.com>
Date: Fri, 3 Oct 2025 15:11:11 -0700
Subject: [PATCH 02/10] finish refactoring

---
 .../Frontend/HLSL/RootSignatureMetadata.h     | 149 ++++-----
 .../Frontend/HLSL/RootSignatureMetadata.cpp   | 314 +++++++++++-------
 2 files changed, 264 insertions(+), 199 deletions(-)

diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
index 65b637f2d80cc..76d9e93e2470a 100644
--- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
+++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
@@ -28,7 +28,7 @@ class Metadata;
 namespace hlsl {
 namespace rootsig {
 
-enum class ErrorKind {
+enum class RSErrorKind {
   Validation,
   AppendAfterUnboundedRange,
   ShaderRegisterOverflow,
@@ -41,124 +41,97 @@ enum class ErrorKind {
 
 template <typename T>
 void formatImpl(raw_string_ostream &Buff,
-                std::integral_constant<ErrorKind, ErrorKind::Validation>,
-                StringRef ParamName, T Value) {
-  Buff << "Invalid value for: " << ParamName << ":" << Value;
-}
+                std::integral_constant<RSErrorKind, RSErrorKind::Validation>,
+                StringRef ParamName, T Value);
 
 void formatImpl(
     raw_string_ostream &Buff,
-    std::integral_constant<ErrorKind, ErrorKind::AppendAfterUnboundedRange>,
-    dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
-  Buff << "Range " << getResourceClassName(Type) << "(register=" << Register
-       << ", space=" << Space << ") "
-       << "cannot be appended after an unbounded range ";
-}
+    std::integral_constant<RSErrorKind, RSErrorKind::AppendAfterUnboundedRange>,
+    dxil::ResourceClass Type, uint32_t Register, uint32_t Space);
 
 void formatImpl(
     raw_string_ostream &Buff,
-    std::integral_constant<ErrorKind, ErrorKind::ShaderRegisterOverflow>,
-    dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
-  Buff << "Overflow for shader register range: " << getResourceClassName(Type)
-       << "(register=" << Register << ", space=" << Space << ").";
-}
+    std::integral_constant<RSErrorKind, RSErrorKind::ShaderRegisterOverflow>,
+    dxil::ResourceClass Type, uint32_t Register, uint32_t Space);
 
-void formatImpl(raw_string_ostream &Buff,
-                std::integral_constant<ErrorKind, ErrorKind::OffsetOverflow>,
-                dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
-  Buff << "Offset overflow for descriptor range: " << getResourceClassName(Type)
-       << "(register=" << Register << ", space=" << Space << ").";
-}
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<RSErrorKind, RSErrorKind::OffsetOverflow>,
+    dxil::ResourceClass Type, uint32_t Register, uint32_t Space);
 
 void formatImpl(raw_string_ostream &Buff,
-                std::integral_constant<ErrorKind, ErrorKind::SamplerMixin>,
-                dxil::ResourceClass Type, uint32_t Location) {
-  Buff << "Samplers cannot be mixed with other "
-       << "resource types in a descriptor table, " << getResourceClassName(Type)
-       << "(location=" << Location << ")";
-}
+                std::integral_constant<RSErrorKind, RSErrorKind::SamplerMixin>,
+                dxil::ResourceClass Type, uint32_t Location);
 
 void formatImpl(
     raw_string_ostream &Buff,
-    std::integral_constant<ErrorKind, ErrorKind::InvalidMetadataFormat>,
-    StringRef ElementName) {
-  Buff << "Invalid format for  " << ElementName;
-}
+    std::integral_constant<RSErrorKind, RSErrorKind::InvalidMetadataFormat>,
+    StringRef ElementName);
 
 void formatImpl(
     raw_string_ostream &Buff,
-    std::integral_constant<ErrorKind, ErrorKind::InvalidMetadataValue>,
-    StringRef ParamName) {
-  Buff << "Invalid value for " << ParamName;
-}
+    std::integral_constant<RSErrorKind, RSErrorKind::InvalidMetadataValue>,
+    StringRef ParamName);
 
-void formatImpl(raw_string_ostream &Buff,
-                std::integral_constant<ErrorKind, ErrorKind::GenericMetadata>,
-                StringRef Message, MDNode *MD) {
-  Buff << Message;
-  if (MD) {
-    Buff << "\n";
-    MD->printTree(Buff);
-  }
-}
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<RSErrorKind, RSErrorKind::GenericMetadata>,
+    StringRef Message, MDNode *MD);
 
 template <typename... ArgsTs>
-static void formatErrMsg(raw_string_ostream &Buff, ErrorKind Kind,
-                         ArgsTs... Args) {
+inline void formatImpl(raw_string_ostream &Buff, RSErrorKind Kind,
+                       ArgsTs... Args) {
   switch (Kind) {
-  case ErrorKind::Validation:
-    formatImpl(Buff, std::integral_constant<ErrorKind, ErrorKind::Validation>{},
-               Args...);
-    break;
-  case ErrorKind::AppendAfterUnboundedRange:
-    formatImpl(Buff,
-               std::integral_constant<ErrorKind,
-                                      ErrorKind::AppendAfterUnboundedRange>{},
-               Args...);
-    break;
-  case ErrorKind::ShaderRegisterOverflow:
-    formatImpl(
+  case RSErrorKind::Validation:
+    return formatImpl(
+        Buff, std::integral_constant<RSErrorKind, RSErrorKind::Validation>(),
+        Args...);
+  case RSErrorKind::AppendAfterUnboundedRange:
+    return formatImpl(
         Buff,
-        std::integral_constant<ErrorKind, ErrorKind::ShaderRegisterOverflow>{},
+        std::integral_constant<RSErrorKind,
+                               RSErrorKind::AppendAfterUnboundedRange>(),
         Args...);
-    break;
-  case ErrorKind::OffsetOverflow:
-    formatImpl(Buff,
-               std::integral_constant<ErrorKind, ErrorKind::OffsetOverflow>{},
-               Args...);
-    break;
-  case ErrorKind::SamplerMixin:
-    formatImpl(Buff,
-               std::integral_constant<ErrorKind, ErrorKind::SamplerMixin>{},
-               Args...);
-    break;
-  case ErrorKind::GenericMetadata:
-    formatImpl(Buff,
-               std::integral_constant<ErrorKind, ErrorKind::GenericMetadata>{},
-               Args...);
-    break;
-
-  case ErrorKind::InvalidMetadataFormat:
-    formatImpl(
+  case RSErrorKind::ShaderRegisterOverflow:
+    return formatImpl(
         Buff,
-        std::integral_constant<ErrorKind, ErrorKind::InvalidMetadataFormat>{},
+        std::integral_constant<RSErrorKind,
+                               RSErrorKind::ShaderRegisterOverflow>(),
         Args...);
-    break;
-
-  case ErrorKind::InvalidMetadataValue:
-    formatImpl(
+  case RSErrorKind::OffsetOverflow:
+    return formatImpl(
+        Buff,
+        std::integral_constant<RSErrorKind, RSErrorKind::OffsetOverflow>(),
+        Args...);
+  case RSErrorKind::SamplerMixin:
+    return formatImpl(
+        Buff, std::integral_constant<RSErrorKind, RSErrorKind::SamplerMixin>(),
+        Args...);
+  case RSErrorKind::InvalidMetadataFormat:
+    return formatImpl(
+        Buff,
+        std::integral_constant<RSErrorKind,
+                               RSErrorKind::InvalidMetadataFormat>(),
+        Args...);
+  case RSErrorKind::InvalidMetadataValue:
+    return formatImpl(
+        Buff,
+        std::integral_constant<RSErrorKind,
+                               RSErrorKind::InvalidMetadataValue>(),
+        Args...);
+  case RSErrorKind::GenericMetadata:
+    return formatImpl(
         Buff,
-        std::integral_constant<ErrorKind, ErrorKind::InvalidMetadataValue>{},
+        std::integral_constant<RSErrorKind, RSErrorKind::GenericMetadata>(),
         Args...);
-    break;
   }
 }
 
 template <typename... ArgsTs>
-static llvm::Error createRSError(ErrorKind Kind, ArgsTs... Args) {
+static llvm::Error createRSError(RSErrorKind Kind, ArgsTs... Args) {
   std::string Msg;
   raw_string_ostream Buff(Msg);
-  formatErrMsg(Buff, Kind, Args...);
+  formatImpl(Buff, Kind, Args...);
   return createStringError(std::move(Buff.str()), inconvertibleErrorCode());
 }
 
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
index 7a0cf408968de..7ed4ec0dc3457 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
@@ -24,15 +24,75 @@ namespace llvm {
 namespace hlsl {
 namespace rootsig {
 
-char GenericRSMetadataError::ID;
-char InvalidRSMetadataFormat::ID;
-char InvalidRSMetadataValue::ID;
-char TableSamplerMixinError::ID;
-char ShaderRegisterOverflowError::ID;
-char OffsetOverflowError::ID;
-char OffsetAppendAfterOverflow::ID;
+template <typename T>
+void formatImpl(raw_string_ostream &Buff,
+                std::integral_constant<RSErrorKind, RSErrorKind::Validation>,
+                StringRef ParamName, T Value) {
+  Buff << "Invalid value for: " << ParamName << ":";
+  if constexpr (std::is_same_v<std::decay_t<T>, std::nullptr_t>) {
+    Buff << "nullptr";
+  } else {
+    Buff << Value;
+  }
+}
 
-template <typename T> char RootSignatureValidationError<T>::ID;
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<RSErrorKind, RSErrorKind::AppendAfterUnboundedRange>,
+    dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
+  Buff << "Range " << getResourceClassName(Type) << "(register=" << Register
+       << ", space=" << Space << ") "
+       << "cannot be appended after an unbounded range ";
+}
+
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<RSErrorKind, RSErrorKind::ShaderRegisterOverflow>,
+    dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
+  Buff << "Overflow for shader register range: " << getResourceClassName(Type)
+       << "(register=" << Register << ", space=" << Space << ").";
+}
+
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<RSErrorKind, RSErrorKind::OffsetOverflow>,
+    dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
+  Buff << "Offset overflow for descriptor range: " << getResourceClassName(Type)
+       << "(register=" << Register << ", space=" << Space << ").";
+}
+
+void formatImpl(raw_string_ostream &Buff,
+                std::integral_constant<RSErrorKind, RSErrorKind::SamplerMixin>,
+                dxil::ResourceClass Type, uint32_t Location) {
+  Buff << "Samplers cannot be mixed with other "
+       << "resource types in a descriptor table, " << getResourceClassName(Type)
+       << "(location=" << Location << ")";
+}
+
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<RSErrorKind, RSErrorKind::InvalidMetadataFormat>,
+    StringRef ElementName) {
+  Buff << "Invalid format for  " << ElementName;
+}
+
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<RSErrorKind, RSErrorKind::InvalidMetadataValue>,
+    StringRef ParamName) {
+  Buff << "Invalid value for " << ParamName;
+}
+
+void formatImpl(
+    raw_string_ostream &Buff,
+    std::integral_constant<RSErrorKind, RSErrorKind::GenericMetadata>,
+    StringRef Message, MDNode *MD) {
+  Buff << Message;
+  if (MD) {
+    Buff << "\n";
+    MD->printTree(Buff);
+  }
+}
 
 static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
                                                  unsigned int OpId) {
@@ -65,10 +125,11 @@ extractEnumValue(MDNode *Node, unsigned int OpId, StringRef ErrText,
                  llvm::function_ref<bool(uint32_t)> VerifyFn) {
   if (std::optional<uint32_t> Val = extractMdIntValue(Node, OpId)) {
     if (!VerifyFn(*Val))
-      return make_error<RootSignatureValidationError<uint32_t>>(ErrText, *Val);
+      return createRSError(RSErrorKind::Validation, ErrText, *Val);
     return static_cast<T>(*Val);
   }
-  return make_error<InvalidRSMetadataValue>("ShaderVisibility");
+  return createRSError(RSErrorKind::InvalidMetadataValue,
+                       StringRef("ShaderVisibility"));
 }
 
 namespace {
@@ -226,12 +287,14 @@ MDNode *MetadataBuilder::BuildStaticSampler(const StaticSampler &Sampler) {
 Error MetadataParser::parseRootFlags(mcdxbc::RootSignatureDesc &RSD,
                                      MDNode *RootFlagNode) {
   if (RootFlagNode->getNumOperands() != 2)
-    return make_error<InvalidRSMetadataFormat>("RootFlag Element");
+    return createRSError(RSErrorKind::InvalidMetadataFormat,
+                         StringRef("RootFlags Element"));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RootFlagNode, 1))
     RSD.Flags = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("RootFlag");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("RootFlag"));
 
   return Error::success();
 }
@@ -239,7 +302,8 @@ Error MetadataParser::parseRootFlags(mcdxbc::RootSignatureDesc &RSD,
 Error MetadataParser::parseRootConstants(mcdxbc::RootSignatureDesc &RSD,
                                          MDNode *RootConstantNode) {
   if (RootConstantNode->getNumOperands() != 5)
-    return make_error<InvalidRSMetadataFormat>("RootConstants Element");
+    return createRSError(RSErrorKind::InvalidMetadataFormat,
+                         StringRef("RootConstants Element"));
 
   Expected<dxbc::ShaderVisibility> Visibility =
       extractEnumValue<dxbc::ShaderVisibility>(RootConstantNode, 1,
@@ -252,17 +316,20 @@ Error MetadataParser::parseRootConstants(mcdxbc::RootSignatureDesc &RSD,
   if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 2))
     Constants.ShaderRegister = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("ShaderRegister");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("ShaderRegister"));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 3))
     Constants.RegisterSpace = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("RegisterSpace");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("RegisterSpace"));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 4))
     Constants.Num32BitValues = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("Num32BitValues");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("Num32BitValues"));
 
   RSD.ParametersContainer.addParameter(dxbc::RootParameterType::Constants32Bit,
                                        *Visibility, Constants);
@@ -279,7 +346,8 @@ Error MetadataParser::parseRootDescriptors(
          "parseRootDescriptors should only be called with RootDescriptor "
          "element kind.");
   if (RootDescriptorNode->getNumOperands() != 5)
-    return make_error<InvalidRSMetadataFormat>("Root Descriptor Element");
+    return createRSError(RSErrorKind::InvalidMetadataFormat,
+                         StringRef("Root Descriptor Element"));
 
   dxbc::RootParameterType Type;
   switch (ElementKind) {
@@ -308,12 +376,14 @@ Error MetadataParser::parseRootDescriptors(
   if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 2))
     Descriptor.ShaderRegister = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("ShaderRegister");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("ShaderRegister"));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 3))
     Descriptor.RegisterSpace = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("RegisterSpace");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("RegisterSpace"));
 
   if (RSD.Version == 1) {
     RSD.ParametersContainer.addParameter(Type, *Visibility, Descriptor);
@@ -324,7 +394,8 @@ Error MetadataParser::parseRootDescriptors(
   if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 4))
     Descriptor.Flags = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("Root Descriptor Flags");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("Root Descriptor Flags"));
 
   RSD.ParametersContainer.addParameter(Type, *Visibility, Descriptor);
   return Error::success();
@@ -333,7 +404,8 @@ Error MetadataParser::parseRootDescriptors(
 Error MetadataParser::parseDescriptorRange(mcdxbc::DescriptorTable &Table,
                                            MDNode *RangeDescriptorNode) {
   if (RangeDescriptorNode->getNumOperands() != 6)
-    return make_error<InvalidRSMetadataFormat>("Descriptor Range");
+    return createRSError(RSErrorKind::InvalidMetadataFormat,
+                         StringRef("Descriptor Range"));
 
   mcdxbc::DescriptorRange Range;
 
@@ -341,7 +413,8 @@ Error MetadataParser::parseDescriptorRange(mcdxbc::DescriptorTable &Table,
       extractMdStringValue(RangeDescriptorNode, 0);
 
   if (!ElementText.has_value())
-    return make_error<InvalidRSMetadataFormat>("Descriptor Range");
+    return createRSError(RSErrorKind::InvalidMetadataFormat,
+                         StringRef("Descriptor Range"));
 
   if (*ElementText == "CBV")
     Range.RangeType = dxil::ResourceClass::CBuffer;
@@ -352,35 +425,40 @@ Error MetadataParser::parseDescriptorRange(mcdxbc::DescriptorTable &Table,
   else if (*ElementText == "Sampler")
     Range.RangeType = dxil::ResourceClass::Sampler;
   else
-    return make_error<GenericRSMetadataError>("Invalid Descriptor Range type.",
-                                              RangeDescriptorNode);
+    return createRSError(RSErrorKind::GenericMetadata,
+                         StringRef("Invalid Descriptor Range type."),
+                         RangeDescriptorNode);
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 1))
     Range.NumDescriptors = *Val;
   else
-    return make_error<GenericRSMetadataError>("Number of Descriptor in Range",
-                                              RangeDescriptorNode);
+    return createRSError(RSErrorKind::GenericMetadata,
+                         StringRef("Number of Descriptor in Range"),
+                         RangeDescriptorNode);
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 2))
     Range.BaseShaderRegister = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("BaseShaderRegister");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("BaseShaderRegister"));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 3))
     Range.RegisterSpace = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("RegisterSpace");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("RegisterSpace"));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 4))
     Range.OffsetInDescriptorsFromTableStart = *Val;
   else
-    return make_error<InvalidRSMetadataValue>(
-        "OffsetInDescriptorsFromTableStart");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("OffsetInDescriptorsFromTableStart"));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 5))
     Range.Flags = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("Descriptor Range Flags");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("Descriptor Range Flags"));
 
   Table.Ranges.push_back(Range);
   return Error::success();
@@ -390,7 +468,8 @@ Error MetadataParser::parseDescriptorTable(mcdxbc::RootSignatureDesc &RSD,
                                            MDNode *DescriptorTableNode) {
   const unsigned int NumOperands = DescriptorTableNode->getNumOperands();
   if (NumOperands < 2)
-    return make_error<InvalidRSMetadataFormat>("Descriptor Table");
+    return createRSError(RSErrorKind::InvalidMetadataFormat,
+                         StringRef("Descriptor Table"));
 
   Expected<dxbc::ShaderVisibility> Visibility =
       extractEnumValue<dxbc::ShaderVisibility>(DescriptorTableNode, 1,
@@ -404,8 +483,9 @@ Error MetadataParser::parseDescriptorTable(mcdxbc::RootSignatureDesc &RSD,
   for (unsigned int I = 2; I < NumOperands; I++) {
     MDNode *Element = dyn_cast<MDNode>(DescriptorTableNode->getOperand(I));
     if (Element == nullptr)
-      return make_error<GenericRSMetadataError>(
-          "Missing Root Element Metadata Node.", DescriptorTableNode);
+      return createRSError(RSErrorKind::GenericMetadata,
+                           StringRef("Missing Root Element Metadata Node."),
+                           DescriptorTableNode);
 
     if (auto Err = parseDescriptorRange(Table, Element))
       return Err;
@@ -419,7 +499,8 @@ Error MetadataParser::parseDescriptorTable(mcdxbc::RootSignatureDesc &RSD,
 Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
                                          MDNode *StaticSamplerNode) {
   if (StaticSamplerNode->getNumOperands() != 15)
-    return make_error<InvalidRSMetadataFormat>("Static Sampler");
+    return createRSError(RSErrorKind::InvalidMetadataFormat,
+                         StringRef("Static Sampler"));
 
   mcdxbc::StaticSampler Sampler;
 
@@ -453,12 +534,14 @@ Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
   if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 5))
     Sampler.MipLODBias = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("MipLODBias");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("MipLODBias"));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 6))
     Sampler.MaxAnisotropy = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("MaxAnisotropy");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("MaxAnisotropy"));
 
   Expected<dxbc::ComparisonFunc> ComparisonFunc =
       extractEnumValue<dxbc::ComparisonFunc>(
@@ -477,22 +560,26 @@ Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
   if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 9))
     Sampler.MinLOD = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("MinLOD");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("MinLOD"));
 
   if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 10))
     Sampler.MaxLOD = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("MaxLOD");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("MaxLOD"));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 11))
     Sampler.ShaderRegister = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("ShaderRegister");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("ShaderRegister"));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 12))
     Sampler.RegisterSpace = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("RegisterSpace");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("RegisterSpace"));
 
   Expected<dxbc::ShaderVisibility> Visibility =
       extractEnumValue<dxbc::ShaderVisibility>(StaticSamplerNode, 13,
@@ -511,7 +598,8 @@ Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
   if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 14))
     Sampler.Flags = *Val;
   else
-    return make_error<InvalidRSMetadataValue>("Static Sampler Flags");
+    return createRSError(RSErrorKind::InvalidMetadataValue,
+                         StringRef("Static Sampler Flags"));
 
   RSD.StaticSamplers.push_back(Sampler);
   return Error::success();
@@ -521,7 +609,8 @@ Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD,
                                                 MDNode *Element) {
   std::optional<StringRef> ElementText = extractMdStringValue(Element, 0);
   if (!ElementText.has_value())
-    return make_error<InvalidRSMetadataFormat>("Root Element");
+    return createRSError(RSErrorKind::InvalidMetadataFormat,
+                         StringRef("Root Element"));
 
   RootSignatureElementKind ElementKind =
       StringSwitch<RootSignatureElementKind>(*ElementText)
@@ -549,8 +638,8 @@ Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD,
   case RootSignatureElementKind::StaticSamplers:
     return parseStaticSampler(RSD, Element);
   case RootSignatureElementKind::Error:
-    return make_error<GenericRSMetadataError>("Invalid Root Signature Element",
-                                              Element);
+    return createRSError(RSErrorKind::GenericMetadata,
+                         StringRef("Invalid Root Signature Element"), Element);
   }
 
   llvm_unreachable("Unhandled RootSignatureElementKind enum.");
@@ -563,7 +652,7 @@ validateDescriptorTableSamplerMixin(const mcdxbc::DescriptorTable &Table,
   for (const mcdxbc::DescriptorRange &Range : Table.Ranges) {
     if (Range.RangeType == dxil::ResourceClass::Sampler &&
         CurrRC != dxil::ResourceClass::Sampler)
-      return make_error<TableSamplerMixinError>(CurrRC, Location);
+      return createRSError(RSErrorKind::SamplerMixin, CurrRC, Location);
     CurrRC = Range.RangeType;
   }
   return Error::success();
@@ -583,8 +672,8 @@ validateDescriptorTableRegisterOverflow(const mcdxbc::DescriptorTable &Table,
         Range.BaseShaderRegister, Range.NumDescriptors);
 
     if (!verifyNoOverflowedOffset(RangeBound))
-      return make_error<ShaderRegisterOverflowError>(
-          Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace);
+      return createRSError(RSErrorKind::ShaderRegisterOverflow, Range.RangeType,
+                           Range.BaseShaderRegister, Range.RegisterSpace);
 
     bool IsAppending =
         Range.OffsetInDescriptorsFromTableStart == DescriptorTableOffsetAppend;
@@ -592,15 +681,16 @@ validateDescriptorTableRegisterOverflow(const mcdxbc::DescriptorTable &Table,
       Offset = Range.OffsetInDescriptorsFromTableStart;
 
     if (IsPrevUnbound && IsAppending)
-      return make_error<OffsetAppendAfterOverflow>(
-          Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace);
+      return createRSError(RSErrorKind::AppendAfterUnboundedRange,
+                           Range.RangeType, Range.BaseShaderRegister,
+                           Range.RegisterSpace);
 
     const uint64_t OffsetBound =
         llvm::hlsl::rootsig::computeRangeBound(Offset, Range.NumDescriptors);
 
     if (!verifyNoOverflowedOffset(OffsetBound))
-      return make_error<OffsetOverflowError>(
-          Range.RangeType, Range.BaseShaderRegister, Range.RegisterSpace);
+      return createRSError(RSErrorKind::OffsetOverflow, Range.RangeType,
+                           Range.BaseShaderRegister, Range.RegisterSpace);
 
     Offset = OffsetBound + 1;
     IsPrevUnbound =
@@ -614,17 +704,15 @@ Error MetadataParser::validateRootSignature(
     const mcdxbc::RootSignatureDesc &RSD) {
   Error DeferredErrs = Error::success();
   if (!hlsl::rootsig::verifyVersion(RSD.Version)) {
-    DeferredErrs =
-        joinErrors(std::move(DeferredErrs),
-                   make_error<RootSignatureValidationError<uint32_t>>(
-                       "Version", RSD.Version));
+    DeferredErrs = joinErrors(std::move(DeferredErrs),
+                              createRSError(RSErrorKind::Validation,
+                                            StringRef("Version"), RSD.Version));
   }
 
   if (!hlsl::rootsig::verifyRootFlag(RSD.Flags)) {
-    DeferredErrs =
-        joinErrors(std::move(DeferredErrs),
-                   make_error<RootSignatureValidationError<uint32_t>>(
-                       "RootFlags", RSD.Flags));
+    DeferredErrs = joinErrors(std::move(DeferredErrs),
+                              createRSError(RSErrorKind::Validation,
+                                            StringRef("RootFlags"), RSD.Flags));
   }
 
   for (const mcdxbc::RootParameterInfo &Info : RSD.ParametersContainer) {
@@ -639,24 +727,24 @@ Error MetadataParser::validateRootSignature(
       const mcdxbc::RootDescriptor &Descriptor =
           RSD.ParametersContainer.getRootDescriptor(Info.Location);
       if (!hlsl::rootsig::verifyRegisterValue(Descriptor.ShaderRegister))
-        DeferredErrs =
-            joinErrors(std::move(DeferredErrs),
-                       make_error<RootSignatureValidationError<uint32_t>>(
-                           "ShaderRegister", Descriptor.ShaderRegister));
+        DeferredErrs = joinErrors(std::move(DeferredErrs),
+                                  createRSError(RSErrorKind::Validation,
+                                                StringRef("ShaderRegister"),
+                                                Descriptor.ShaderRegister));
 
       if (!hlsl::rootsig::verifyRegisterSpace(Descriptor.RegisterSpace))
-        DeferredErrs =
-            joinErrors(std::move(DeferredErrs),
-                       make_error<RootSignatureValidationError<uint32_t>>(
-                           "RegisterSpace", Descriptor.RegisterSpace));
+        DeferredErrs = joinErrors(std::move(DeferredErrs),
+                                  createRSError(RSErrorKind::Validation,
+                                                StringRef("RegisterSpace"),
+                                                Descriptor.RegisterSpace));
 
       if (RSD.Version > 1) {
         if (!hlsl::rootsig::verifyRootDescriptorFlag(RSD.Version,
                                                      Descriptor.Flags))
-          DeferredErrs =
-              joinErrors(std::move(DeferredErrs),
-                         make_error<RootSignatureValidationError<uint32_t>>(
-                             "RootDescriptorFlag", Descriptor.Flags));
+          DeferredErrs = joinErrors(
+              std::move(DeferredErrs),
+              createRSError(RSErrorKind::Validation,
+                            StringRef("RootDescriptorFlag"), Descriptor.Flags));
       }
       break;
     }
@@ -665,24 +753,24 @@ Error MetadataParser::validateRootSignature(
           RSD.ParametersContainer.getDescriptorTable(Info.Location);
       for (const mcdxbc::DescriptorRange &Range : Table) {
         if (!hlsl::rootsig::verifyRegisterSpace(Range.RegisterSpace))
-          DeferredErrs =
-              joinErrors(std::move(DeferredErrs),
-                         make_error<RootSignatureValidationError<uint32_t>>(
-                             "RegisterSpace", Range.RegisterSpace));
+          DeferredErrs = joinErrors(std::move(DeferredErrs),
+                                    createRSError(RSErrorKind::Validation,
+                                                  StringRef("RegisterSpace"),
+                                                  Range.RegisterSpace));
 
         if (!hlsl::rootsig::verifyNumDescriptors(Range.NumDescriptors))
-          DeferredErrs =
-              joinErrors(std::move(DeferredErrs),
-                         make_error<RootSignatureValidationError<uint32_t>>(
-                             "NumDescriptors", Range.NumDescriptors));
+          DeferredErrs = joinErrors(std::move(DeferredErrs),
+                                    createRSError(RSErrorKind::Validation,
+                                                  StringRef("NumDescriptors"),
+                                                  Range.NumDescriptors));
 
         if (!hlsl::rootsig::verifyDescriptorRangeFlag(
                 RSD.Version, Range.RangeType,
                 dxbc::DescriptorRangeFlags(Range.Flags)))
-          DeferredErrs =
-              joinErrors(std::move(DeferredErrs),
-                         make_error<RootSignatureValidationError<uint32_t>>(
-                             "DescriptorFlag", Range.Flags));
+          DeferredErrs = joinErrors(std::move(DeferredErrs),
+                                    createRSError(RSErrorKind::Validation,
+                                                  StringRef("DescriptorFlag"),
+                                                  Range.Flags));
 
         if (Error Err =
                 validateDescriptorTableSamplerMixin(Table, Info.Location))
@@ -701,42 +789,45 @@ Error MetadataParser::validateRootSignature(
 
     if (!hlsl::rootsig::verifyMipLODBias(Sampler.MipLODBias))
       DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                make_error<RootSignatureValidationError<float>>(
-                                    "MipLODBias", Sampler.MipLODBias));
+                                createRSError(RSErrorKind::Validation,
+                                              StringRef("MipLODBias"),
+                                              Sampler.MipLODBias));
 
     if (!hlsl::rootsig::verifyMaxAnisotropy(Sampler.MaxAnisotropy))
-      DeferredErrs =
-          joinErrors(std::move(DeferredErrs),
-                     make_error<RootSignatureValidationError<uint32_t>>(
-                         "MaxAnisotropy", Sampler.MaxAnisotropy));
+      DeferredErrs = joinErrors(std::move(DeferredErrs),
+                                createRSError(RSErrorKind::Validation,
+                                              StringRef("MaxAnisotropy"),
+                                              Sampler.MaxAnisotropy));
 
     if (!hlsl::rootsig::verifyLOD(Sampler.MinLOD))
-      DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                make_error<RootSignatureValidationError<float>>(
-                                    "MinLOD", Sampler.MinLOD));
+      DeferredErrs =
+          joinErrors(std::move(DeferredErrs),
+                     createRSError(RSErrorKind::Validation, StringRef("MinLOD"),
+                                   Sampler.MinLOD));
 
     if (!hlsl::rootsig::verifyLOD(Sampler.MaxLOD))
-      DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                make_error<RootSignatureValidationError<float>>(
-                                    "MaxLOD", Sampler.MaxLOD));
-
-    if (!hlsl::rootsig::verifyRegisterValue(Sampler.ShaderRegister))
       DeferredErrs =
           joinErrors(std::move(DeferredErrs),
-                     make_error<RootSignatureValidationError<uint32_t>>(
-                         "ShaderRegister", Sampler.ShaderRegister));
+                     createRSError(RSErrorKind::Validation, StringRef("MaxLOD"),
+                                   Sampler.MaxLOD));
+
+    if (!hlsl::rootsig::verifyRegisterValue(Sampler.ShaderRegister))
+      DeferredErrs = joinErrors(std::move(DeferredErrs),
+                                createRSError(RSErrorKind::Validation,
+                                              StringRef("ShaderRegister"),
+                                              Sampler.ShaderRegister));
 
     if (!hlsl::rootsig::verifyRegisterSpace(Sampler.RegisterSpace))
-      DeferredErrs =
-          joinErrors(std::move(DeferredErrs),
-                     make_error<RootSignatureValidationError<uint32_t>>(
-                         "RegisterSpace", Sampler.RegisterSpace));
+      DeferredErrs = joinErrors(std::move(DeferredErrs),
+                                createRSError(RSErrorKind::Validation,
+                                              StringRef("RegisterSpace"),
+                                              Sampler.RegisterSpace));
 
     if (!hlsl::rootsig::verifyStaticSamplerFlags(RSD.Version, Sampler.Flags))
-      DeferredErrs =
-          joinErrors(std::move(DeferredErrs),
-                     make_error<RootSignatureValidationError<uint32_t>>(
-                         "Static Sampler Flag", Sampler.Flags));
+      DeferredErrs = joinErrors(std::move(DeferredErrs),
+                                createRSError(RSErrorKind::Validation,
+                                              StringRef("Static Sampler Flag"),
+                                              Sampler.Flags));
   }
 
   return DeferredErrs;
@@ -750,9 +841,10 @@ MetadataParser::ParseRootSignature(uint32_t Version) {
   for (const auto &Operand : Root->operands()) {
     MDNode *Element = dyn_cast<MDNode>(Operand);
     if (Element == nullptr)
-      return joinErrors(std::move(DeferredErrs),
-                        make_error<GenericRSMetadataError>(
-                            "Missing Root Element Metadata Node.", nullptr));
+      return joinErrors(
+          std::move(DeferredErrs),
+          createRSError(RSErrorKind::GenericMetadata,
+                        StringRef("Missing Root Element Metadata Node.")));
 
     if (auto Err = parseRootSignatureElement(RSD, Element))
       DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));

>From 02c956d5589e887922da23d058678c2d688a6b2a Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranllvm at gmail.com>
Date: Mon, 6 Oct 2025 10:05:46 -0700
Subject: [PATCH 03/10] start changes

---
 .../Frontend/HLSL/RootSignatureMetadata.cpp   | 22 ++++++-------------
 .../HLSL/RootSignatureValidations.cpp         | 10 ++++++---
 ...gnature-RootDescriptor-Invalid-Flags_V1.ll | 18 +++++++++++++++
 3 files changed, 32 insertions(+), 18 deletions(-)
 create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootDescriptor-Invalid-Flags_V1.ll

diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
index 7ed4ec0dc3457..5f93a48e796ba 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
@@ -28,7 +28,7 @@ template <typename T>
 void formatImpl(raw_string_ostream &Buff,
                 std::integral_constant<RSErrorKind, RSErrorKind::Validation>,
                 StringRef ParamName, T Value) {
-  Buff << "Invalid value for: " << ParamName << ":";
+  Buff << "Invalid value for " << ParamName << ": ";
   if constexpr (std::is_same_v<std::decay_t<T>, std::nullptr_t>) {
     Buff << "nullptr";
   } else {
@@ -385,12 +385,6 @@ Error MetadataParser::parseRootDescriptors(
     return createRSError(RSErrorKind::InvalidMetadataValue,
                          StringRef("RegisterSpace"));
 
-  if (RSD.Version == 1) {
-    RSD.ParametersContainer.addParameter(Type, *Visibility, Descriptor);
-    return Error::success();
-  }
-  assert(RSD.Version > 1);
-
   if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 4))
     Descriptor.Flags = *Val;
   else
@@ -738,14 +732,12 @@ Error MetadataParser::validateRootSignature(
                                                 StringRef("RegisterSpace"),
                                                 Descriptor.RegisterSpace));
 
-      if (RSD.Version > 1) {
-        if (!hlsl::rootsig::verifyRootDescriptorFlag(RSD.Version,
-                                                     Descriptor.Flags))
-          DeferredErrs = joinErrors(
-              std::move(DeferredErrs),
-              createRSError(RSErrorKind::Validation,
-                            StringRef("RootDescriptorFlag"), Descriptor.Flags));
-      }
+      if (!hlsl::rootsig::verifyRootDescriptorFlag(RSD.Version,
+                                                    Descriptor.Flags))
+        DeferredErrs = joinErrors(
+            std::move(DeferredErrs),
+            createRSError(RSErrorKind::Validation,
+                          StringRef("RootDescriptorFlag"), Descriptor.Flags));
       break;
     }
     case dxbc::RootParameterType::DescriptorTable: {
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
index 8a2b03d9ede8b..bed35c0015604 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
@@ -35,13 +35,17 @@ bool verifyRegisterSpace(uint32_t RegisterSpace) {
 }
 
 bool verifyRootDescriptorFlag(uint32_t Version, uint32_t FlagsVal) {
+  assert((Version <= 3) && "Provided invalid root signature version");
+  uint32_t LargestValue = llvm::to_underlying(
+      dxbc::RootDescriptorFlags::LLVM_BITMASK_LARGEST_ENUMERATOR);
+  if (FlagsVal >= NextPowerOf2(LargestValue))
+    return false;
+  
   using FlagT = dxbc::RootDescriptorFlags;
   FlagT Flags = FlagT(FlagsVal);
   if (Version == 1)
     return Flags == FlagT::DataVolatile;
 
-  assert((Version <= 3) && "Provided invalid root signature version");
-
   // The data-specific flags are mutually exclusive.
   FlagT DataFlags = FlagT::DataVolatile | FlagT::DataStatic |
                     FlagT::DataStaticWhileSetAtExecute;
@@ -114,6 +118,7 @@ bool verifyDescriptorRangeFlag(uint32_t Version, dxil::ResourceClass Type,
 }
 
 bool verifyStaticSamplerFlags(uint32_t Version, uint32_t FlagsNumber) {
+  assert(Version == 3 && "Provided invalid root signature version");
   uint32_t LargestValue = llvm::to_underlying(
       dxbc::StaticSamplerFlags::LLVM_BITMASK_LARGEST_ENUMERATOR);
   if (FlagsNumber >= NextPowerOf2(LargestValue))
@@ -123,7 +128,6 @@ bool verifyStaticSamplerFlags(uint32_t Version, uint32_t FlagsNumber) {
   if (Version <= 2)
     return Flags == dxbc::StaticSamplerFlags::None;
 
-  assert(Version == 3 && "Provided invalid root signature version");
 
   dxbc::StaticSamplerFlags Mask =
       dxbc::StaticSamplerFlags::NonNormalizedCoordinates |
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootDescriptor-Invalid-Flags_V1.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootDescriptor-Invalid-Flags_V1.ll
new file mode 100644
index 0000000000000..610ce4f4617d0
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-RootDescriptor-Invalid-Flags_V1.ll
@@ -0,0 +1,18 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+; On Version 1, the only valid flag is DataVolatile (2).
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+
+; CHECK: error: Invalid value for RootDescriptorFlag: 4
+; CHECK-NOT: Root Signature Definitions
+define void @main() #0 {
+entry:
+  ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3, i32 1 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"RootCBV", i32 0, i32 1, i32 2, i32 4  }

>From 4db9f54e7c59cb5305c18ed95e6c6f30fd1bf09d Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranllvm at gmail.com>
Date: Mon, 6 Oct 2025 10:40:54 -0700
Subject: [PATCH 04/10] fix test

---
 llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
index 7ed4ec0dc3457..cf4568d49c0f8 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
@@ -28,7 +28,7 @@ template <typename T>
 void formatImpl(raw_string_ostream &Buff,
                 std::integral_constant<RSErrorKind, RSErrorKind::Validation>,
                 StringRef ParamName, T Value) {
-  Buff << "Invalid value for: " << ParamName << ":";
+  Buff << "Invalid value for " << ParamName << ": ";
   if constexpr (std::is_same_v<std::decay_t<T>, std::nullptr_t>) {
     Buff << "nullptr";
   } else {
@@ -844,7 +844,8 @@ MetadataParser::ParseRootSignature(uint32_t Version) {
       return joinErrors(
           std::move(DeferredErrs),
           createRSError(RSErrorKind::GenericMetadata,
-                        StringRef("Missing Root Element Metadata Node.")));
+                        StringRef("Missing Root Element Metadata Node."),
+                        Element));
 
     if (auto Err = parseRootSignatureElement(RSD, Element))
       DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));

>From b5fdd5e85c56bd149c03f1fa60b18f83d8e674bc Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranllvm at gmail.com>
Date: Mon, 6 Oct 2025 11:27:53 -0700
Subject: [PATCH 05/10] removing the enforcing while parsing

---
 .../Frontend/HLSL/RootSignatureMetadata.cpp   |  6 ------
 .../HLSL/RootSignatureValidations.cpp         |  2 +-
 ...ignature-StaticSamplers-Invalid-Flag_V1.ll | 19 +++++++++++++++++++
 3 files changed, 20 insertions(+), 7 deletions(-)
 create mode 100644 llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-Flag_V1.ll

diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
index a14a3ba8d1191..f0f3bce88ba3a 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
@@ -583,12 +583,6 @@ Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
     return Error(std::move(E));
   Sampler.ShaderVisibility = *Visibility;
 
-  if (RSD.Version < 3) {
-    RSD.StaticSamplers.push_back(Sampler);
-    return Error::success();
-  }
-  assert(RSD.Version >= 3);
-
   if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 14))
     Sampler.Flags = *Val;
   else
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
index bed35c0015604..65b431aa66944 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureValidations.cpp
@@ -118,7 +118,7 @@ bool verifyDescriptorRangeFlag(uint32_t Version, dxil::ResourceClass Type,
 }
 
 bool verifyStaticSamplerFlags(uint32_t Version, uint32_t FlagsNumber) {
-  assert(Version == 3 && "Provided invalid root signature version");
+  assert(Version <= 3 && "Provided invalid root signature version");
   uint32_t LargestValue = llvm::to_underlying(
       dxbc::StaticSamplerFlags::LLVM_BITMASK_LARGEST_ENUMERATOR);
   if (FlagsNumber >= NextPowerOf2(LargestValue))
diff --git a/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-Flag_V1.ll b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-Flag_V1.ll
new file mode 100644
index 0000000000000..76b60b82db852
--- /dev/null
+++ b/llvm/test/CodeGen/DirectX/ContainerData/RootSignature-StaticSamplers-Invalid-Flag_V1.ll
@@ -0,0 +1,19 @@
+; RUN: not opt -passes='print<dxil-root-signature>' %s -S -o - 2>&1 | FileCheck %s
+
+
+target triple = "dxil-unknown-shadermodel6.0-compute"
+
+; CHECK: error: Invalid value for Static Sampler Flag: 1 
+; CHECK-NOT: Root Signature Definitions
+
+define void @main() #0 {
+entry:
+  ret void
+}
+attributes #0 = { "hlsl.numthreads"="1,1,1" "hlsl.shader"="compute" }
+
+
+!dx.rootsignatures = !{!2} ; list of function/root signature pairs
+!2 = !{ ptr @main, !3, i32 1 } ; function, root signature
+!3 = !{ !5 } ; list of root signature elements
+!5 = !{ !"StaticSampler", i32 4, i32 2, i32 3, i32 5, float 0x3FF6CCCCC0000000, i32 9, i32 3, i32 2, float -1.280000e+02, float 1.280000e+02, i32 42, i32 0, i32 0, i32 1 }

>From 92e0913032c6ca89fc9699f001d53538ed859a31 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranllvm at gmail.com>
Date: Mon, 6 Oct 2025 15:02:19 -0700
Subject: [PATCH 06/10] formating

---
 llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
index 73d91a47cab25..d58a17cd58ede 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
@@ -811,10 +811,10 @@ Error MetadataParser::validateRootSignature(
                                    Sampler.MinLOD));
 
     if (!hlsl::rootsig::verifyLOD(Sampler.MaxLOD))
-      DeferredErrs =
-          joinErrors(std::move(DeferredErrs),
-                     createRSError(RSErrorKind::Validation, StringRef("MaxLOD"),
-                                   Sampler.MaxLOD));
+      DeferredErrs = joinErrors(std::move(DeferredErrs),
+                                createRSError(RSErrorKind::Validation,
+                                              StringRef("RegisterSpace"),
+                                              Sampler.RegisterSpace));
 
     if (!hlsl::rootsig::verifyRegisterValue(Sampler.ShaderRegister))
       DeferredErrs = joinErrors(std::move(DeferredErrs),

>From 3984b78a4b4ae910e767ebff5e030d73c113ddda Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 7 Oct 2025 18:52:33 +0000
Subject: [PATCH 07/10] make messages inline

---
 .../Frontend/HLSL/RootSignatureMetadata.h     | 116 +-----
 .../Frontend/HLSL/RootSignatureMetadata.cpp   | 354 +++++++-----------
 2 files changed, 156 insertions(+), 314 deletions(-)

diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
index 76d9e93e2470a..bac0e35cde9f9 100644
--- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
+++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
@@ -19,6 +19,7 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/MC/DXContainerRootSignature.h"
 #include "llvm/Support/Compiler.h"
+#include "llvm/Support/FormatVariadic.h"
 
 namespace llvm {
 class LLVMContext;
@@ -27,113 +28,20 @@ class Metadata;
 
 namespace hlsl {
 namespace rootsig {
+class RootSignatureValidationError
+    : public ErrorInfo<RootSignatureValidationError> {
+public:
+  static char ID;
+  std::string Msg;
 
-enum class RSErrorKind {
-  Validation,
-  AppendAfterUnboundedRange,
-  ShaderRegisterOverflow,
-  OffsetOverflow,
-  SamplerMixin,
-  GenericMetadata,
-  InvalidMetadataFormat,
-  InvalidMetadataValue
-};
+  RootSignatureValidationError(const Twine &Msg) : Msg(Msg.str()) {}
 
-template <typename T>
-void formatImpl(raw_string_ostream &Buff,
-                std::integral_constant<RSErrorKind, RSErrorKind::Validation>,
-                StringRef ParamName, T Value);
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::AppendAfterUnboundedRange>,
-    dxil::ResourceClass Type, uint32_t Register, uint32_t Space);
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::ShaderRegisterOverflow>,
-    dxil::ResourceClass Type, uint32_t Register, uint32_t Space);
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::OffsetOverflow>,
-    dxil::ResourceClass Type, uint32_t Register, uint32_t Space);
-
-void formatImpl(raw_string_ostream &Buff,
-                std::integral_constant<RSErrorKind, RSErrorKind::SamplerMixin>,
-                dxil::ResourceClass Type, uint32_t Location);
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::InvalidMetadataFormat>,
-    StringRef ElementName);
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::InvalidMetadataValue>,
-    StringRef ParamName);
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::GenericMetadata>,
-    StringRef Message, MDNode *MD);
-
-template <typename... ArgsTs>
-inline void formatImpl(raw_string_ostream &Buff, RSErrorKind Kind,
-                       ArgsTs... Args) {
-  switch (Kind) {
-  case RSErrorKind::Validation:
-    return formatImpl(
-        Buff, std::integral_constant<RSErrorKind, RSErrorKind::Validation>(),
-        Args...);
-  case RSErrorKind::AppendAfterUnboundedRange:
-    return formatImpl(
-        Buff,
-        std::integral_constant<RSErrorKind,
-                               RSErrorKind::AppendAfterUnboundedRange>(),
-        Args...);
-  case RSErrorKind::ShaderRegisterOverflow:
-    return formatImpl(
-        Buff,
-        std::integral_constant<RSErrorKind,
-                               RSErrorKind::ShaderRegisterOverflow>(),
-        Args...);
-  case RSErrorKind::OffsetOverflow:
-    return formatImpl(
-        Buff,
-        std::integral_constant<RSErrorKind, RSErrorKind::OffsetOverflow>(),
-        Args...);
-  case RSErrorKind::SamplerMixin:
-    return formatImpl(
-        Buff, std::integral_constant<RSErrorKind, RSErrorKind::SamplerMixin>(),
-        Args...);
-  case RSErrorKind::InvalidMetadataFormat:
-    return formatImpl(
-        Buff,
-        std::integral_constant<RSErrorKind,
-                               RSErrorKind::InvalidMetadataFormat>(),
-        Args...);
-  case RSErrorKind::InvalidMetadataValue:
-    return formatImpl(
-        Buff,
-        std::integral_constant<RSErrorKind,
-                               RSErrorKind::InvalidMetadataValue>(),
-        Args...);
-  case RSErrorKind::GenericMetadata:
-    return formatImpl(
-        Buff,
-        std::integral_constant<RSErrorKind, RSErrorKind::GenericMetadata>(),
-        Args...);
-  }
-}
+  void log(raw_ostream &OS) const override { OS << Msg; }
 
-template <typename... ArgsTs>
-static llvm::Error createRSError(RSErrorKind Kind, ArgsTs... Args) {
-  std::string Msg;
-  raw_string_ostream Buff(Msg);
-  formatImpl(Buff, Kind, Args...);
-  return createStringError(std::move(Buff.str()), inconvertibleErrorCode());
-}
+  std::error_code convertToErrorCode() const override {
+    return llvm::inconvertibleErrorCode();
+  }
+};
 
 class MetadataBuilder {
 public:
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
index d58a17cd58ede..e1fd1c39f96e4 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
@@ -16,6 +16,7 @@
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/Support/DXILABI.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/ScopedPrinter.h"
 
 using namespace llvm;
@@ -24,75 +25,7 @@ namespace llvm {
 namespace hlsl {
 namespace rootsig {
 
-template <typename T>
-void formatImpl(raw_string_ostream &Buff,
-                std::integral_constant<RSErrorKind, RSErrorKind::Validation>,
-                StringRef ParamName, T Value) {
-  Buff << "Invalid value for " << ParamName << ": ";
-  if constexpr (std::is_same_v<std::decay_t<T>, std::nullptr_t>) {
-    Buff << "nullptr";
-  } else {
-    Buff << Value;
-  }
-}
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::AppendAfterUnboundedRange>,
-    dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
-  Buff << "Range " << getResourceClassName(Type) << "(register=" << Register
-       << ", space=" << Space << ") "
-       << "cannot be appended after an unbounded range ";
-}
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::ShaderRegisterOverflow>,
-    dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
-  Buff << "Overflow for shader register range: " << getResourceClassName(Type)
-       << "(register=" << Register << ", space=" << Space << ").";
-}
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::OffsetOverflow>,
-    dxil::ResourceClass Type, uint32_t Register, uint32_t Space) {
-  Buff << "Offset overflow for descriptor range: " << getResourceClassName(Type)
-       << "(register=" << Register << ", space=" << Space << ").";
-}
-
-void formatImpl(raw_string_ostream &Buff,
-                std::integral_constant<RSErrorKind, RSErrorKind::SamplerMixin>,
-                dxil::ResourceClass Type, uint32_t Location) {
-  Buff << "Samplers cannot be mixed with other "
-       << "resource types in a descriptor table, " << getResourceClassName(Type)
-       << "(location=" << Location << ")";
-}
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::InvalidMetadataFormat>,
-    StringRef ElementName) {
-  Buff << "Invalid format for  " << ElementName;
-}
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::InvalidMetadataValue>,
-    StringRef ParamName) {
-  Buff << "Invalid value for " << ParamName;
-}
-
-void formatImpl(
-    raw_string_ostream &Buff,
-    std::integral_constant<RSErrorKind, RSErrorKind::GenericMetadata>,
-    StringRef Message, MDNode *MD) {
-  Buff << Message;
-  if (MD) {
-    Buff << "\n";
-    MD->printTree(Buff);
-  }
-}
+char RootSignatureValidationError::ID;
 
 static std::optional<uint32_t> extractMdIntValue(MDNode *Node,
                                                  unsigned int OpId) {
@@ -117,21 +50,6 @@ static std::optional<StringRef> extractMdStringValue(MDNode *Node,
   return NodeText->getString();
 }
 
-template <typename T, typename = std::enable_if_t<
-                          std::is_enum_v<T> &&
-                          std::is_same_v<std::underlying_type_t<T>, uint32_t>>>
-static Expected<T>
-extractEnumValue(MDNode *Node, unsigned int OpId, StringRef ErrText,
-                 llvm::function_ref<bool(uint32_t)> VerifyFn) {
-  if (std::optional<uint32_t> Val = extractMdIntValue(Node, OpId)) {
-    if (!VerifyFn(*Val))
-      return createRSError(RSErrorKind::Validation, ErrText, *Val);
-    return static_cast<T>(*Val);
-  }
-  return createRSError(RSErrorKind::InvalidMetadataValue,
-                       StringRef("ShaderVisibility"));
-}
-
 namespace {
 
 // We use the OverloadVisit with std::visit to ensure the compiler catches if a
@@ -142,8 +60,52 @@ template <class... Ts> struct OverloadedVisit : Ts... {
 };
 template <class... Ts> OverloadedVisit(Ts...) -> OverloadedVisit<Ts...>;
 
+struct FmtRange {
+  dxil::ResourceClass Type;
+  uint32_t Register;
+  uint32_t Space;
+
+  FmtRange(const mcdxbc::DescriptorRange &Range)
+      : Type(Range.RangeType), Register(Range.BaseShaderRegister),
+        Space(Range.RegisterSpace) {}
+};
+
+raw_ostream &operator<<(llvm::raw_ostream &OS, const FmtRange &Range) {
+  OS << getResourceClassName(Range.Type) << "(register=" << Range.Register
+     << ", space=" << Range.Space << ")";
+  return OS;
+}
+
+struct FmtMDNode {
+  const MDNode *Node;
+
+  FmtMDNode(const MDNode *Node) : Node(Node) {}
+};
+
+raw_ostream &operator<<(llvm::raw_ostream &OS, FmtMDNode Fmt) {
+  Fmt.Node->printTree(OS);
+  return OS;
+}
+
+static Error makeRSError(const Twine &Msg) {
+  return make_error<RootSignatureValidationError>(Msg);
+}
 } // namespace
 
+template <typename T, typename = std::enable_if_t<
+                          std::is_enum_v<T> &&
+                          std::is_same_v<std::underlying_type_t<T>, uint32_t>>>
+static Expected<T>
+extractEnumValue(MDNode *Node, unsigned int OpId, StringRef ErrText,
+                 llvm::function_ref<bool(uint32_t)> VerifyFn) {
+  if (std::optional<uint32_t> Val = extractMdIntValue(Node, OpId)) {
+    if (!VerifyFn(*Val))
+      return makeRSError(formatv("Invalid value for {0}: {1}", ErrText, Val));
+    return static_cast<T>(*Val);
+  }
+  return makeRSError(formatv("Invalid value for ShaderVisibility"));
+}
+
 MDNode *MetadataBuilder::BuildRootSignature() {
   const auto Visitor = OverloadedVisit{
       [this](const dxbc::RootFlags &Flags) -> MDNode * {
@@ -287,14 +249,12 @@ MDNode *MetadataBuilder::BuildStaticSampler(const StaticSampler &Sampler) {
 Error MetadataParser::parseRootFlags(mcdxbc::RootSignatureDesc &RSD,
                                      MDNode *RootFlagNode) {
   if (RootFlagNode->getNumOperands() != 2)
-    return createRSError(RSErrorKind::InvalidMetadataFormat,
-                         StringRef("RootFlags Element"));
+    return makeRSError("Invalid format for RootFlags Element");
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RootFlagNode, 1))
     RSD.Flags = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("RootFlag"));
+    return makeRSError("Invalid value for RootFlag");
 
   return Error::success();
 }
@@ -302,8 +262,7 @@ Error MetadataParser::parseRootFlags(mcdxbc::RootSignatureDesc &RSD,
 Error MetadataParser::parseRootConstants(mcdxbc::RootSignatureDesc &RSD,
                                          MDNode *RootConstantNode) {
   if (RootConstantNode->getNumOperands() != 5)
-    return createRSError(RSErrorKind::InvalidMetadataFormat,
-                         StringRef("RootConstants Element"));
+    return makeRSError("Invalid format for RootConstants Element");
 
   Expected<dxbc::ShaderVisibility> Visibility =
       extractEnumValue<dxbc::ShaderVisibility>(RootConstantNode, 1,
@@ -316,20 +275,17 @@ Error MetadataParser::parseRootConstants(mcdxbc::RootSignatureDesc &RSD,
   if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 2))
     Constants.ShaderRegister = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("ShaderRegister"));
+    return makeRSError("Invalid value for ShaderRegister");
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 3))
     Constants.RegisterSpace = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("RegisterSpace"));
+    return makeRSError("Invalid value for RegisterSpace");
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RootConstantNode, 4))
     Constants.Num32BitValues = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("Num32BitValues"));
+    return makeRSError("Invalid value for Num32BitValues");
 
   RSD.ParametersContainer.addParameter(dxbc::RootParameterType::Constants32Bit,
                                        *Visibility, Constants);
@@ -346,8 +302,7 @@ Error MetadataParser::parseRootDescriptors(
          "parseRootDescriptors should only be called with RootDescriptor "
          "element kind.");
   if (RootDescriptorNode->getNumOperands() != 5)
-    return createRSError(RSErrorKind::InvalidMetadataFormat,
-                         StringRef("Root Descriptor Element"));
+    return makeRSError("Invalid format for Root Descriptor Element");
 
   dxbc::RootParameterType Type;
   switch (ElementKind) {
@@ -376,14 +331,12 @@ Error MetadataParser::parseRootDescriptors(
   if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 2))
     Descriptor.ShaderRegister = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("ShaderRegister"));
+    return makeRSError("Invalid value for ShaderRegister");
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 3))
     Descriptor.RegisterSpace = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("RegisterSpace"));
+    return makeRSError("Invalid value for RegisterSpace");
 
   if (RSD.Version == 1) {
     RSD.ParametersContainer.addParameter(Type, *Visibility, Descriptor);
@@ -394,8 +347,7 @@ Error MetadataParser::parseRootDescriptors(
   if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 4))
     Descriptor.Flags = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("Root Descriptor Flags"));
+    return makeRSError("Invalid value for Root Descriptor Flags");
 
   RSD.ParametersContainer.addParameter(Type, *Visibility, Descriptor);
   return Error::success();
@@ -404,8 +356,7 @@ Error MetadataParser::parseRootDescriptors(
 Error MetadataParser::parseDescriptorRange(mcdxbc::DescriptorTable &Table,
                                            MDNode *RangeDescriptorNode) {
   if (RangeDescriptorNode->getNumOperands() != 6)
-    return createRSError(RSErrorKind::InvalidMetadataFormat,
-                         StringRef("Descriptor Range"));
+    return makeRSError("Invalid format for Descriptor Range");
 
   mcdxbc::DescriptorRange Range;
 
@@ -413,8 +364,7 @@ Error MetadataParser::parseDescriptorRange(mcdxbc::DescriptorTable &Table,
       extractMdStringValue(RangeDescriptorNode, 0);
 
   if (!ElementText.has_value())
-    return createRSError(RSErrorKind::InvalidMetadataFormat,
-                         StringRef("Descriptor Range"));
+    return makeRSError("Invalid format for Descriptor Range");
 
   if (*ElementText == "CBV")
     Range.RangeType = dxil::ResourceClass::CBuffer;
@@ -425,40 +375,34 @@ Error MetadataParser::parseDescriptorRange(mcdxbc::DescriptorTable &Table,
   else if (*ElementText == "Sampler")
     Range.RangeType = dxil::ResourceClass::Sampler;
   else
-    return createRSError(RSErrorKind::GenericMetadata,
-                         StringRef("Invalid Descriptor Range type."),
-                         RangeDescriptorNode);
+    return makeRSError(formatv("Invalid Descriptor Range type. \n {0}",
+                               FmtMDNode{RangeDescriptorNode}));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 1))
     Range.NumDescriptors = *Val;
   else
-    return createRSError(RSErrorKind::GenericMetadata,
-                         StringRef("Number of Descriptor in Range"),
-                         RangeDescriptorNode);
+    return makeRSError(formatv("Invalid number of Descriptor in Range. \n {0}",
+                               FmtMDNode{RangeDescriptorNode}));
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 2))
     Range.BaseShaderRegister = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("BaseShaderRegister"));
+    return makeRSError("Invalid value for BaseShaderRegister");
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 3))
     Range.RegisterSpace = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("RegisterSpace"));
+    return makeRSError("Invalid value for RegisterSpace");
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 4))
     Range.OffsetInDescriptorsFromTableStart = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("OffsetInDescriptorsFromTableStart"));
+    return makeRSError("Invalid value for OffsetInDescriptorsFromTableStart");
 
   if (std::optional<uint32_t> Val = extractMdIntValue(RangeDescriptorNode, 5))
     Range.Flags = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("Descriptor Range Flags"));
+    return makeRSError("Invalid value for Descriptor Range Flags");
 
   Table.Ranges.push_back(Range);
   return Error::success();
@@ -468,8 +412,7 @@ Error MetadataParser::parseDescriptorTable(mcdxbc::RootSignatureDesc &RSD,
                                            MDNode *DescriptorTableNode) {
   const unsigned int NumOperands = DescriptorTableNode->getNumOperands();
   if (NumOperands < 2)
-    return createRSError(RSErrorKind::InvalidMetadataFormat,
-                         StringRef("Descriptor Table"));
+    return makeRSError("Invalid format for Descriptor Table");
 
   Expected<dxbc::ShaderVisibility> Visibility =
       extractEnumValue<dxbc::ShaderVisibility>(DescriptorTableNode, 1,
@@ -483,9 +426,8 @@ Error MetadataParser::parseDescriptorTable(mcdxbc::RootSignatureDesc &RSD,
   for (unsigned int I = 2; I < NumOperands; I++) {
     MDNode *Element = dyn_cast<MDNode>(DescriptorTableNode->getOperand(I));
     if (Element == nullptr)
-      return createRSError(RSErrorKind::GenericMetadata,
-                           StringRef("Missing Root Element Metadata Node."),
-                           DescriptorTableNode);
+      return makeRSError(formatv("Missing Root Element Metadata Node.\n {0}",
+                                 FmtMDNode{DescriptorTableNode}));
 
     if (auto Err = parseDescriptorRange(Table, Element))
       return Err;
@@ -499,8 +441,7 @@ Error MetadataParser::parseDescriptorTable(mcdxbc::RootSignatureDesc &RSD,
 Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
                                          MDNode *StaticSamplerNode) {
   if (StaticSamplerNode->getNumOperands() != 15)
-    return createRSError(RSErrorKind::InvalidMetadataFormat,
-                         StringRef("Static Sampler"));
+    return makeRSError("Invalid format for Static Sampler");
 
   mcdxbc::StaticSampler Sampler;
 
@@ -534,14 +475,12 @@ Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
   if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 5))
     Sampler.MipLODBias = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("MipLODBias"));
+    return makeRSError("Invalid value for MipLODBias");
 
   if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 6))
     Sampler.MaxAnisotropy = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("MaxAnisotropy"));
+    return makeRSError("Invalid value for MaxAnisotropy");
 
   Expected<dxbc::ComparisonFunc> ComparisonFunc =
       extractEnumValue<dxbc::ComparisonFunc>(
@@ -560,26 +499,22 @@ Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
   if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 9))
     Sampler.MinLOD = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("MinLOD"));
+    return makeRSError("Invalid value for MinLOD");
 
   if (std::optional<float> Val = extractMdFloatValue(StaticSamplerNode, 10))
     Sampler.MaxLOD = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("MaxLOD"));
+    return makeRSError("Invalid value for MaxLOD");
 
   if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 11))
     Sampler.ShaderRegister = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("ShaderRegister"));
+    return makeRSError("Invalid value for ShaderRegister");
 
   if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 12))
     Sampler.RegisterSpace = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("RegisterSpace"));
+    return makeRSError("Invalid value for RegisterSpace");
 
   Expected<dxbc::ShaderVisibility> Visibility =
       extractEnumValue<dxbc::ShaderVisibility>(StaticSamplerNode, 13,
@@ -598,8 +533,7 @@ Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
   if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 14))
     Sampler.Flags = *Val;
   else
-    return createRSError(RSErrorKind::InvalidMetadataValue,
-                         StringRef("Static Sampler Flags"));
+    return makeRSError("Invalid value for Static Sampler Flags");
 
   RSD.StaticSamplers.push_back(Sampler);
   return Error::success();
@@ -609,8 +543,7 @@ Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD,
                                                 MDNode *Element) {
   std::optional<StringRef> ElementText = extractMdStringValue(Element, 0);
   if (!ElementText.has_value())
-    return createRSError(RSErrorKind::InvalidMetadataFormat,
-                         StringRef("Root Element"));
+    return makeRSError("Invalid format for Root Element");
 
   RootSignatureElementKind ElementKind =
       StringSwitch<RootSignatureElementKind>(*ElementText)
@@ -638,8 +571,8 @@ Error MetadataParser::parseRootSignatureElement(mcdxbc::RootSignatureDesc &RSD,
   case RootSignatureElementKind::StaticSamplers:
     return parseStaticSampler(RSD, Element);
   case RootSignatureElementKind::Error:
-    return createRSError(RSErrorKind::GenericMetadata,
-                         StringRef("Invalid Root Signature Element"), Element);
+    return makeRSError(
+        formatv("Invalid Root Signature Element\n {0}", FmtMDNode{Element}));
   }
 
   llvm_unreachable("Unhandled RootSignatureElementKind enum.");
@@ -652,7 +585,10 @@ validateDescriptorTableSamplerMixin(const mcdxbc::DescriptorTable &Table,
   for (const mcdxbc::DescriptorRange &Range : Table.Ranges) {
     if (Range.RangeType == dxil::ResourceClass::Sampler &&
         CurrRC != dxil::ResourceClass::Sampler)
-      return createRSError(RSErrorKind::SamplerMixin, CurrRC, Location);
+      return makeRSError(
+          formatv("Samplers cannot be mixed with other resource types in a "
+                  "descriptor table, {0}(location={1})",
+                  getResourceClassName(CurrRC), Location));
     CurrRC = Range.RangeType;
   }
   return Error::success();
@@ -672,8 +608,8 @@ validateDescriptorTableRegisterOverflow(const mcdxbc::DescriptorTable &Table,
         Range.BaseShaderRegister, Range.NumDescriptors);
 
     if (!verifyNoOverflowedOffset(RangeBound))
-      return createRSError(RSErrorKind::ShaderRegisterOverflow, Range.RangeType,
-                           Range.BaseShaderRegister, Range.RegisterSpace);
+      return makeRSError(
+          formatv("Overflow for shader register range: {0}", FmtRange{Range}));
 
     bool IsAppending =
         Range.OffsetInDescriptorsFromTableStart == DescriptorTableOffsetAppend;
@@ -681,16 +617,16 @@ validateDescriptorTableRegisterOverflow(const mcdxbc::DescriptorTable &Table,
       Offset = Range.OffsetInDescriptorsFromTableStart;
 
     if (IsPrevUnbound && IsAppending)
-      return createRSError(RSErrorKind::AppendAfterUnboundedRange,
-                           Range.RangeType, Range.BaseShaderRegister,
-                           Range.RegisterSpace);
+      return makeRSError(
+          formatv("Range {0} cannot be appended after an unbounded range",
+                  FmtRange{Range}));
 
     const uint64_t OffsetBound =
         llvm::hlsl::rootsig::computeRangeBound(Offset, Range.NumDescriptors);
 
     if (!verifyNoOverflowedOffset(OffsetBound))
-      return createRSError(RSErrorKind::OffsetOverflow, Range.RangeType,
-                           Range.BaseShaderRegister, Range.RegisterSpace);
+      return makeRSError(formatv("Offset overflow for descriptor range: {0}.",
+                                 FmtRange{Range}));
 
     Offset = OffsetBound + 1;
     IsPrevUnbound =
@@ -704,15 +640,15 @@ Error MetadataParser::validateRootSignature(
     const mcdxbc::RootSignatureDesc &RSD) {
   Error DeferredErrs = Error::success();
   if (!hlsl::rootsig::verifyVersion(RSD.Version)) {
-    DeferredErrs = joinErrors(std::move(DeferredErrs),
-                              createRSError(RSErrorKind::Validation,
-                                            StringRef("Version"), RSD.Version));
+    DeferredErrs = joinErrors(
+        std::move(DeferredErrs),
+        makeRSError(formatv("Invalid value for Version: {0}", RSD.Version)));
   }
 
   if (!hlsl::rootsig::verifyRootFlag(RSD.Flags)) {
-    DeferredErrs = joinErrors(std::move(DeferredErrs),
-                              createRSError(RSErrorKind::Validation,
-                                            StringRef("RootFlags"), RSD.Flags));
+    DeferredErrs = joinErrors(
+        std::move(DeferredErrs),
+        makeRSError(formatv("Invalid value for RootFlags: {0}", RSD.Flags)));
   }
 
   for (const mcdxbc::RootParameterInfo &Info : RSD.ParametersContainer) {
@@ -727,16 +663,16 @@ Error MetadataParser::validateRootSignature(
       const mcdxbc::RootDescriptor &Descriptor =
           RSD.ParametersContainer.getRootDescriptor(Info.Location);
       if (!hlsl::rootsig::verifyRegisterValue(Descriptor.ShaderRegister))
-        DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                  createRSError(RSErrorKind::Validation,
-                                                StringRef("ShaderRegister"),
-                                                Descriptor.ShaderRegister));
+        DeferredErrs = joinErrors(
+            std::move(DeferredErrs),
+            makeRSError(formatv("Invalid value for ShaderRegister: {0}",
+                                Descriptor.ShaderRegister)));
 
       if (!hlsl::rootsig::verifyRegisterSpace(Descriptor.RegisterSpace))
-        DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                  createRSError(RSErrorKind::Validation,
-                                                StringRef("RegisterSpace"),
-                                                Descriptor.RegisterSpace));
+        DeferredErrs = joinErrors(
+            std::move(DeferredErrs),
+            makeRSError(formatv("Invalid value for RegisterSpace: {0}",
+                                Descriptor.RegisterSpace)));
 
       if (RSD.Version > 1) {
         bool IsValidFlag =
@@ -746,8 +682,8 @@ Error MetadataParser::validateRootSignature(
         if (!IsValidFlag)
           DeferredErrs = joinErrors(
               std::move(DeferredErrs),
-              createRSError(RSErrorKind::Validation,
-                            StringRef("RootDescriptorFlag"), Descriptor.Flags));
+              makeRSError(formatv("Invalid value for RootDescriptorFlag: {0}",
+                                  Descriptor.Flags)));
       }
       break;
     }
@@ -756,26 +692,26 @@ Error MetadataParser::validateRootSignature(
           RSD.ParametersContainer.getDescriptorTable(Info.Location);
       for (const mcdxbc::DescriptorRange &Range : Table) {
         if (!hlsl::rootsig::verifyRegisterSpace(Range.RegisterSpace))
-          DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                    createRSError(RSErrorKind::Validation,
-                                                  StringRef("RegisterSpace"),
-                                                  Range.RegisterSpace));
+          DeferredErrs = joinErrors(
+              std::move(DeferredErrs),
+              makeRSError(formatv("Invalid value for RegisterSpace: {0}",
+                                  Range.RegisterSpace)));
 
         if (!hlsl::rootsig::verifyNumDescriptors(Range.NumDescriptors))
-          DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                    createRSError(RSErrorKind::Validation,
-                                                  StringRef("NumDescriptors"),
-                                                  Range.NumDescriptors));
+          DeferredErrs = joinErrors(
+              std::move(DeferredErrs),
+              makeRSError(formatv("Invalid value for NumDescriptors: {0}",
+                                  Range.NumDescriptors)));
 
         bool IsValidFlag = dxbc::isValidDescriptorRangeFlags(Range.Flags) &&
                            hlsl::rootsig::verifyDescriptorRangeFlag(
                                RSD.Version, Range.RangeType,
                                dxbc::DescriptorRangeFlags(Range.Flags));
         if (!IsValidFlag)
-          DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                    createRSError(RSErrorKind::Validation,
-                                                  StringRef("DescriptorFlag"),
-                                                  Range.Flags));
+          DeferredErrs = joinErrors(
+              std::move(DeferredErrs),
+              makeRSError(formatv("Invalid value for DescriptorFlag: {0}",
+                                  Range.Flags)));
 
         if (Error Err =
                 validateDescriptorTableSamplerMixin(Table, Info.Location))
@@ -793,49 +729,49 @@ Error MetadataParser::validateRootSignature(
   for (const mcdxbc::StaticSampler &Sampler : RSD.StaticSamplers) {
 
     if (!hlsl::rootsig::verifyMipLODBias(Sampler.MipLODBias))
-      DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                createRSError(RSErrorKind::Validation,
-                                              StringRef("MipLODBias"),
-                                              Sampler.MipLODBias));
+      DeferredErrs =
+          joinErrors(std::move(DeferredErrs),
+                     makeRSError(formatv("Invalid value for MipLODBias: {0:e}",
+                                         Sampler.MipLODBias)));
 
     if (!hlsl::rootsig::verifyMaxAnisotropy(Sampler.MaxAnisotropy))
-      DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                createRSError(RSErrorKind::Validation,
-                                              StringRef("MaxAnisotropy"),
-                                              Sampler.MaxAnisotropy));
+      DeferredErrs =
+          joinErrors(std::move(DeferredErrs),
+                     makeRSError(formatv("Invalid value for MaxAnisotropy: {0}",
+                                         Sampler.MaxAnisotropy)));
 
     if (!hlsl::rootsig::verifyLOD(Sampler.MinLOD))
       DeferredErrs =
           joinErrors(std::move(DeferredErrs),
-                     createRSError(RSErrorKind::Validation, StringRef("MinLOD"),
-                                   Sampler.MinLOD));
+                     makeRSError(formatv("Invalid value for MinLOD: {0}",
+                                         Sampler.MinLOD)));
 
     if (!hlsl::rootsig::verifyLOD(Sampler.MaxLOD))
-      DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                createRSError(RSErrorKind::Validation,
-                                              StringRef("RegisterSpace"),
-                                              Sampler.RegisterSpace));
+      DeferredErrs =
+          joinErrors(std::move(DeferredErrs),
+                     makeRSError(formatv("Invalid value for MaxLOD: {0}",
+                                         Sampler.MaxLOD)));
 
     if (!hlsl::rootsig::verifyRegisterValue(Sampler.ShaderRegister))
-      DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                createRSError(RSErrorKind::Validation,
-                                              StringRef("ShaderRegister"),
-                                              Sampler.ShaderRegister));
+      DeferredErrs = joinErrors(
+          std::move(DeferredErrs),
+          makeRSError(formatv("Invalid value for ShaderRegister: {0}",
+                              Sampler.ShaderRegister)));
 
     if (!hlsl::rootsig::verifyRegisterSpace(Sampler.RegisterSpace))
       DeferredErrs =
           joinErrors(std::move(DeferredErrs),
-                     createRSError(RSErrorKind::Validation, StringRef(
-                         "RegisterSpace"), Sampler.RegisterSpace));
+                     makeRSError(formatv("Invalid value for RegisterSpace: {0}",
+                                         Sampler.RegisterSpace)));
     bool IsValidFlag =
         dxbc::isValidStaticSamplerFlags(Sampler.Flags) &&
         hlsl::rootsig::verifyStaticSamplerFlags(
             RSD.Version, dxbc::StaticSamplerFlags(Sampler.Flags));
     if (!IsValidFlag)
-      DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                createRSError(RSErrorKind::Validation,
-                                              StringRef("Static Sampler Flag"),
-                                              Sampler.Flags));
+      DeferredErrs = joinErrors(
+          std::move(DeferredErrs),
+          makeRSError(formatv("Invalid value for Static Sampler Flag: {0}",
+                              Sampler.Flags)));
   }
 
   return DeferredErrs;
@@ -851,9 +787,7 @@ MetadataParser::ParseRootSignature(uint32_t Version) {
     if (Element == nullptr)
       return joinErrors(
           std::move(DeferredErrs),
-          createRSError(RSErrorKind::GenericMetadata,
-                        StringRef("Missing Root Element Metadata Node."),
-                        Element));
+          makeRSError(formatv("Missing Root Element Metadata Node.")));
 
     if (auto Err = parseRootSignatureElement(RSD, Element))
       DeferredErrs = joinErrors(std::move(DeferredErrs), std::move(Err));

>From d1d40af740b84a05c107d081fc4df357120b28e8 Mon Sep 17 00:00:00 2001
From: joaosaffran <joao.saffran at microsoft.com>
Date: Tue, 7 Oct 2025 18:59:29 +0000
Subject: [PATCH 08/10] clean up

---
 llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h | 1 -
 llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp        | 1 -
 2 files changed, 2 deletions(-)

diff --git a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
index bac0e35cde9f9..7ef6667a5437d 100644
--- a/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
+++ b/llvm/include/llvm/Frontend/HLSL/RootSignatureMetadata.h
@@ -19,7 +19,6 @@
 #include "llvm/IR/Constants.h"
 #include "llvm/MC/DXContainerRootSignature.h"
 #include "llvm/Support/Compiler.h"
-#include "llvm/Support/FormatVariadic.h"
 
 namespace llvm {
 class LLVMContext;
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
index e1fd1c39f96e4..37128a63ce330 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
@@ -16,7 +16,6 @@
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/Support/DXILABI.h"
-#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/ScopedPrinter.h"
 
 using namespace llvm;

>From 30596fd0928de10038898aa06b031ba448690465 Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranllvm at gmail.com>
Date: Wed, 8 Oct 2025 12:33:17 -0700
Subject: [PATCH 09/10] fix test

---
 .../Frontend/HLSL/RootSignatureMetadata.cpp   | 36 +++++--------------
 .../DirectX/DXILWriter/DXILBitcodeWriter.cpp  |  2 +-
 2 files changed, 10 insertions(+), 28 deletions(-)

diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
index b4c85931e78cc..132a280c659a1 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
@@ -337,12 +337,6 @@ Error MetadataParser::parseRootDescriptors(
   else
     return makeRSError("Invalid value for RegisterSpace");
 
-  if (RSD.Version == 1) {
-    RSD.ParametersContainer.addParameter(Type, *Visibility, Descriptor);
-    return Error::success();
-  }
-  assert(RSD.Version > 1);
-
   if (std::optional<uint32_t> Val = extractMdIntValue(RootDescriptorNode, 4))
     Descriptor.Flags = *Val;
   else
@@ -523,12 +517,6 @@ Error MetadataParser::parseStaticSampler(mcdxbc::RootSignatureDesc &RSD,
     return Error(std::move(E));
   Sampler.ShaderVisibility = *Visibility;
 
-  if (RSD.Version < 3) {
-    RSD.StaticSamplers.push_back(Sampler);
-    return Error::success();
-  }
-  assert(RSD.Version >= 3);
-
   if (std::optional<uint32_t> Val = extractMdIntValue(StaticSamplerNode, 14))
     Sampler.Flags = *Val;
   else
@@ -673,15 +661,15 @@ Error MetadataParser::validateRootSignature(
             makeRSError(formatv("Invalid value for RegisterSpace: {0}",
                                 Descriptor.RegisterSpace)));
 
-        bool IsValidFlag =
-            dxbc::isValidRootDesciptorFlags(Descriptor.Flags) &&
-            hlsl::rootsig::verifyRootDescriptorFlag(
-                RSD.Version, dxbc::RootDescriptorFlags(Descriptor.Flags));
-        if (!IsValidFlag)
-          DeferredErrs = joinErrors(
-              std::move(DeferredErrs),
-              makeRSError(formatv("Invalid value for RootDescriptorFlag: {0}",
-                                  Descriptor.Flags)));
+      bool IsValidFlag =
+          dxbc::isValidRootDesciptorFlags(Descriptor.Flags) &&
+          hlsl::rootsig::verifyRootDescriptorFlag(
+              RSD.Version, dxbc::RootDescriptorFlags(Descriptor.Flags));
+      if (!IsValidFlag)
+        DeferredErrs = joinErrors(
+            std::move(DeferredErrs),
+            makeRSError(formatv("Invalid value for RootDescriptorFlag: {0}",
+                                Descriptor.Flags)));
       break;
     }
     case dxbc::RootParameterType::DescriptorTable: {
@@ -732,12 +720,6 @@ Error MetadataParser::validateRootSignature(
                                          Sampler.MipLODBias)));
 
     if (!hlsl::rootsig::verifyMaxAnisotropy(Sampler.MaxAnisotropy))
-      DeferredErrs = joinErrors(std::move(DeferredErrs),
-                                createRSError(RSErrorKind::Validation,
-                                              StringRef("MaxAnisotropy"),
-                                              Sampler.MaxAnisotropy));
-
-    if (!hlsl::rootsig::verifyLOD(Sampler.MinLOD))
       DeferredErrs =
           joinErrors(std::move(DeferredErrs),
                      makeRSError(formatv("Invalid value for MaxAnisotropy: {0}",
diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index bc1a3a7995bda..82c43ff8dc352 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -1507,7 +1507,7 @@ void DXILBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
                                            SmallVectorImpl<uint64_t> &Record,
                                            unsigned Abbrev) {
   Record.push_back(N->isDistinct());
-  Record.push_back(N->getSourceLanguage());
+  Record.push_back(N->getSourceLanguage().getUnversionedName());
   Record.push_back(VE.getMetadataOrNullID(N->getFile()));
   Record.push_back(VE.getMetadataOrNullID(N->getRawProducer()));
   Record.push_back(N->isOptimized());

>From 6bb6ae16baad14cbf78ea750b62db601d64b099b Mon Sep 17 00:00:00 2001
From: Joao Saffran <joaosaffranllvm at gmail.com>
Date: Wed, 8 Oct 2025 12:35:26 -0700
Subject: [PATCH 10/10] remove unrelated change

---
 llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
index 82c43ff8dc352..bc1a3a7995bda 100644
--- a/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
+++ b/llvm/lib/Target/DirectX/DXILWriter/DXILBitcodeWriter.cpp
@@ -1507,7 +1507,7 @@ void DXILBitcodeWriter::writeDICompileUnit(const DICompileUnit *N,
                                            SmallVectorImpl<uint64_t> &Record,
                                            unsigned Abbrev) {
   Record.push_back(N->isDistinct());
-  Record.push_back(N->getSourceLanguage().getUnversionedName());
+  Record.push_back(N->getSourceLanguage());
   Record.push_back(VE.getMetadataOrNullID(N->getFile()));
   Record.push_back(VE.getMetadataOrNullID(N->getRawProducer()));
   Record.push_back(N->isOptimized());



More information about the llvm-commits mailing list