Skip to content

Conversation

@inbelic
Copy link
Contributor

@inbelic inbelic commented Aug 5, 2025

Introduce the enumToStringRef enum into ScopedPrinter.h that replicates enumToString behaviour, expect that instead of returning a hex value string, it just returns an empty string. This allows us to return a StringRef and easily check if an invalid enum was provided based on the StringRef size

This then uses enumToStringRef to remove the redundant getResourceName and printEnum functions.

Resolves: #151200.

Introduce the `enumToStringRef` enum into `ScopedPrinter.h` that
replicates `enumToString` behaviour, expect that instead of returning a
hex value string, it just returns an empty string. This allows us to
return a StringRef and easily check if an invalid enum was provided
based on the StringRef size

This then uses `enumToStringRef` to remove the redundant
`getResourceName` and `printEnum` functions.

Resolves:
@inbelic inbelic marked this pull request as ready for review August 5, 2025 22:15
@llvmbot llvmbot added HLSL HLSL Language Support llvm:support labels Aug 5, 2025
@llvmbot
Copy link
Member

llvmbot commented Aug 5, 2025

@llvm/pr-subscribers-llvm-support

@llvm/pr-subscribers-hlsl

Author: Finn Plummer (inbelic)

Changes

Introduce the enumToStringRef enum into ScopedPrinter.h that replicates enumToString behaviour, expect that instead of returning a hex value string, it just returns an empty string. This allows us to return a StringRef and easily check if an invalid enum was provided based on the StringRef size

This then uses enumToStringRef to remove the redundant getResourceName and printEnum functions.

Resolves: #151200.


Full diff: https://github.com/llvm/llvm-project/pull/152211.diff

3 Files Affected:

  • (modified) llvm/include/llvm/Support/ScopedPrinter.h (+8)
  • (modified) llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp (+11-30)
  • (modified) llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp (+10-15)
diff --git a/llvm/include/llvm/Support/ScopedPrinter.h b/llvm/include/llvm/Support/ScopedPrinter.h
index e6c4cc4a4ea13..a25658c964c25 100644
--- a/llvm/include/llvm/Support/ScopedPrinter.h
+++ b/llvm/include/llvm/Support/ScopedPrinter.h
@@ -107,6 +107,14 @@ std::string enumToString(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues) {
   return utohexstr(Value, true);
 }
 
+template <typename T, typename TEnum>
+StringRef enumToStringRef(T Value, ArrayRef<EnumEntry<TEnum>> EnumValues) {
+  for (const EnumEntry<TEnum> &EnumItem : EnumValues)
+    if (EnumItem.Value == Value)
+      return EnumItem.AltName;
+  return "";
+}
+
 class LLVM_ABI ScopedPrinter {
 public:
   enum class ScopedPrinterKind {
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
index 78c20a6c5c9ff..22d44e98feffe 100644
--- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -17,24 +17,6 @@ namespace llvm {
 namespace hlsl {
 namespace rootsig {
 
-template <typename T>
-static std::optional<StringRef> getEnumName(const T Value,
-                                            ArrayRef<EnumEntry<T>> Enums) {
-  for (const auto &EnumItem : Enums)
-    if (EnumItem.Value == Value)
-      return EnumItem.Name;
-  return std::nullopt;
-}
-
-template <typename T>
-static raw_ostream &printEnum(raw_ostream &OS, const T Value,
-                              ArrayRef<EnumEntry<T>> Enums) {
-  auto MaybeName = getEnumName(Value, Enums);
-  if (MaybeName)
-    OS << *MaybeName;
-  return OS;
-}
-
 template <typename T>
 static raw_ostream &printFlags(raw_ostream &OS, const T Value,
                                ArrayRef<EnumEntry<T>> Flags) {
@@ -46,9 +28,9 @@ static raw_ostream &printFlags(raw_ostream &OS, const T Value,
       if (FlagSet)
         OS << " | ";
 
-      auto MaybeFlag = getEnumName(T(Bit), Flags);
-      if (MaybeFlag)
-        OS << *MaybeFlag;
+      StringRef MaybeFlag = enumToStringRef(T(Bit), Flags);
+      if (0 < MaybeFlag.size())
+        OS << MaybeFlag;
       else
         OS << "invalid: " << Bit;
 
@@ -70,43 +52,42 @@ static const EnumEntry<RegisterType> RegisterNames[] = {
 };
 
 static raw_ostream &operator<<(raw_ostream &OS, const Register &Reg) {
-  printEnum(OS, Reg.ViewType, ArrayRef(RegisterNames));
-  OS << Reg.Number;
+  OS << enumToStringRef(Reg.ViewType, ArrayRef(RegisterNames)) << Reg.Number;
 
   return OS;
 }
 
 static raw_ostream &operator<<(raw_ostream &OS,
                                const llvm::dxbc::ShaderVisibility &Visibility) {
-  printEnum(OS, Visibility, dxbc::getShaderVisibility());
+  OS << enumToStringRef(Visibility, dxbc::getShaderVisibility());
 
   return OS;
 }
 
 static raw_ostream &operator<<(raw_ostream &OS,
                                const llvm::dxbc::SamplerFilter &Filter) {
-  printEnum(OS, Filter, dxbc::getSamplerFilters());
+  OS << enumToStringRef(Filter, dxbc::getSamplerFilters());
 
   return OS;
 }
 
 static raw_ostream &operator<<(raw_ostream &OS,
                                const dxbc::TextureAddressMode &Address) {
-  printEnum(OS, Address, dxbc::getTextureAddressModes());
+  OS << enumToStringRef(Address, dxbc::getTextureAddressModes());
 
   return OS;
 }
 
 static raw_ostream &operator<<(raw_ostream &OS,
                                const dxbc::ComparisonFunc &CompFunc) {
-  printEnum(OS, CompFunc, dxbc::getComparisonFuncs());
+  OS << enumToStringRef(CompFunc, dxbc::getComparisonFuncs());
 
   return OS;
 }
 
 static raw_ostream &operator<<(raw_ostream &OS,
                                const dxbc::StaticBorderColor &BorderColor) {
-  printEnum(OS, BorderColor, dxbc::getStaticBorderColors());
+  OS << enumToStringRef(BorderColor, dxbc::getStaticBorderColors());
 
   return OS;
 }
@@ -119,8 +100,8 @@ static const EnumEntry<dxil::ResourceClass> ResourceClassNames[] = {
 };
 
 static raw_ostream &operator<<(raw_ostream &OS, const ClauseType &Type) {
-  printEnum(OS, dxil::ResourceClass(llvm::to_underlying(Type)),
-            ArrayRef(ResourceClassNames));
+  OS << enumToStringRef(dxil::ResourceClass(llvm::to_underlying(Type)),
+                        ArrayRef(ResourceClassNames));
 
   return OS;
 }
diff --git a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
index 6d89fa7b1222c..4786efb9dea69 100644
--- a/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
+++ b/llvm/lib/Frontend/HLSL/RootSignatureMetadata.cpp
@@ -58,13 +58,6 @@ static const EnumEntry<dxil::ResourceClass> ResourceClassNames[] = {
     {"Sampler", dxil::ResourceClass::Sampler},
 };
 
-static std::optional<StringRef> getResourceName(dxil::ResourceClass Class) {
-  for (const auto &ClassEnum : ResourceClassNames)
-    if (ClassEnum.Value == Class)
-      return ClassEnum.Name;
-  return std::nullopt;
-}
-
 namespace {
 
 // We use the OverloadVisit with std::visit to ensure the compiler catches if a
@@ -133,10 +126,11 @@ MDNode *MetadataBuilder::BuildRootConstants(const RootConstants &Constants) {
 
 MDNode *MetadataBuilder::BuildRootDescriptor(const RootDescriptor &Descriptor) {
   IRBuilder<> Builder(Ctx);
-  std::optional<StringRef> ResName =
-      getResourceName(dxil::ResourceClass(to_underlying(Descriptor.Type)));
-  assert(ResName && "Provided an invalid Resource Class");
-  SmallString<7> Name({"Root", *ResName});
+  StringRef ResName =
+      enumToStringRef(dxil::ResourceClass(to_underlying(Descriptor.Type)),
+                      ArrayRef(ResourceClassNames));
+  assert(0 < ResName.size() && "Provided an invalid Resource Class");
+  SmallString<7> Name({"Root", ResName});
   Metadata *Operands[] = {
       MDString::get(Ctx, Name),
       ConstantAsMetadata::get(
@@ -174,11 +168,12 @@ MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) {
 MDNode *MetadataBuilder::BuildDescriptorTableClause(
     const DescriptorTableClause &Clause) {
   IRBuilder<> Builder(Ctx);
-  std::optional<StringRef> ResName =
-      getResourceName(dxil::ResourceClass(to_underlying(Clause.Type)));
-  assert(ResName && "Provided an invalid Resource Class");
+  StringRef ResName =
+      enumToStringRef(dxil::ResourceClass(to_underlying(Clause.Type)),
+                      ArrayRef(ResourceClassNames));
+  assert(0 < ResName.size() && "Provided an invalid Resource Class");
   Metadata *Operands[] = {
-      MDString::get(Ctx, *ResName),
+      MDString::get(Ctx, ResName),
       ConstantAsMetadata::get(Builder.getInt32(Clause.NumDescriptors)),
       ConstantAsMetadata::get(Builder.getInt32(Clause.Reg.Number)),
       ConstantAsMetadata::get(Builder.getInt32(Clause.Space)),

if (MaybeFlag)
OS << *MaybeFlag;
StringRef MaybeFlag = enumToStringRef(T(Bit), Flags);
if (0 < MaybeFlag.size())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this is a very strange way to write this check. Using an std::optional lets you keep the more typical if (MaybeFlag)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(this applies anywhere you have if (0 < MaybeFlag.size()))

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Alternatively the current code could be written as if( !MaybeFlag.empty())

I don't have strong feelings one way or another but empty strings for optional strings is pretty common.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah fair enough. Checking for empty() is also fine

return utohexstr(Value, true);
}

template <typename T, typename TEnum>
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is probably useful to add a doxygen comment block above this API explaining that it returns an empty string if the enum doesn't have a direct mapping.

@inbelic inbelic merged commit acb5d0c into llvm:main Aug 6, 2025
10 checks passed
@inbelic inbelic deleted the inbelic/enum-to-string-ref branch October 29, 2025 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

HLSL HLSL Language Support llvm:support

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[HLSL] Replace getResourceName usages with enumToString

4 participants