Skip to content

[HLSL][RootSignature] Add Metadata generation of Root Signatures for Attr #125131

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed

Conversation

inbelic
Copy link
Contributor

@inbelic inbelic commented Jan 30, 2025

  • Define and implement MetadataBuilder in HLSLRootSignature
  • Integrate and invoke the builder in CGHLSLRuntime.cpp to generate the Root Signature for any associated entry functions
  • Add tests to demonstrate functionality in RootSignature.hlsl

Resolves #126584

Copy link

github-actions bot commented Jan 30, 2025

✅ With the latest revision this PR passed the C/C++ code formatter.

@inbelic inbelic linked an issue Feb 10, 2025 that may be closed by this pull request
5 tasks
@inbelic inbelic force-pushed the users/inbelic/pr-123985 branch from 14e7253 to 4180ab7 Compare February 12, 2025 23:31
@inbelic inbelic marked this pull request as ready for review February 13, 2025 00:22
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. HLSL HLSL Language Support labels Feb 13, 2025
@llvmbot
Copy link
Member

llvmbot commented Feb 13, 2025

@llvm/pr-subscribers-hlsl

@llvm/pr-subscribers-clang

Author: Finn Plummer (inbelic)

Changes
  • Define and implement MetadataBuilder in HLSLRootSignature
  • Integrate and invoke the builder in CGHLSLRuntime.cpp to generate the Root Signature for any associated entry functions
  • Add tests to demonstrate functionality in RootSignature.hlsl

Resolves #126584


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

5 Files Affected:

  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+20)
  • (added) clang/test/CodeGenHLSL/RootSignature.hlsl (+29)
  • (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+27)
  • (modified) llvm/lib/Frontend/HLSL/CMakeLists.txt (+1)
  • (added) llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp (+108)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index c354e58e15f4b..62d062be91046 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -119,6 +119,20 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {
   return CBGV;
 }
 
+void addRootSignature(ArrayRef<llvm::hlsl::rootsig::RootElement> Elements,
+                      llvm::Function *Fn, llvm::Module &M) {
+  auto &Ctx = M.getContext();
+
+  llvm::hlsl::rootsig::MetadataBuilder Builder(Ctx, Elements);
+  MDNode *RootSignature = Builder.BuildRootSignature();
+  MDNode *FnPairing =
+      MDNode::get(Ctx, {ValueAsMetadata::get(Fn), RootSignature});
+
+  StringRef RootSignatureValKey = "dx.rootsignatures";
+  auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
+  RootSignatureValMD->addOperand(FnPairing);
+}
+
 } // namespace
 
 llvm::Type *CGHLSLRuntime::convertHLSLSpecificType(const Type *T) {
@@ -453,6 +467,12 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
   // FIXME: Handle codegen for return type semantics.
   // See: https://github.com/llvm/llvm-project/issues/57875
   B.CreateRetVoid();
+
+  // Add and identify root signature to function, if applicable
+  const AttrVec &Attrs = FD->getAttrs();
+  for (const Attr *Attr : Attrs)
+    if (const auto *RSAttr = dyn_cast<HLSLRootSignatureAttr>(Attr))
+      addRootSignature(RSAttr->getElements(), EntryFn, M);
 }
 
 void CGHLSLRuntime::setHLSLFunctionAttributes(const FunctionDecl *FD,
diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl
new file mode 100644
index 0000000000000..76aa2690b96a7
--- /dev/null
+++ b/clang/test/CodeGenHLSL/RootSignature.hlsl
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-DAG: ![[#EMPTY:]] = !{}
+[shader("compute"), RootSignature("")]
+[numthreads(1,1,1)]
+void FirstEntry() {}
+
+// CHECK-DAG: ![[#CBV:]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4}
+// CHECK-DAG: ![[#SRV:]] = !{!"SRV", i32 4, i32 42, i32 3, i32 32, i32 0}
+// CHECK-DAG: ![[#TABLE:]] = !{!"DescriptorTable", i32 0, ![[#CBV]], ![[#SRV]]}
+// CHECK-DAG: ![[#SECOND_RS:]] = !{![[#TABLE]]}
+
+#define SampleDescriptorTable \
+  "DescriptorTable( " \
+  "  CBV(b0), " \
+  "  SRV(t42, space = 3, offset = 32, numDescriptors = 4, flags = 0) " \
+  ")"
+[shader("compute"), RootSignature(SampleDescriptorTable)]
+[numthreads(1,1,1)]
+void SecondEntry() {}
+
+// Sanity test to ensure no root is added for this function
+[shader("compute")]
+[numthreads(1,1,1)]
+void ThirdEntry() {}
+
+// CHECK-DAG: ![[#FIRST_ENTRY:]] = !{ptr @FirstEntry, ![[#EMPTY]]}
+// CHECK-DAG: ![[#SECOND_ENTRY:]] = !{ptr @SecondEntry, ![[#SECOND_RS]]}
+// CHECK-DAG: !dx.rootsignatures = !{![[#FIRST_ENTRY]], ![[#SECOND_ENTRY]]}
diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
index f999a0b5eef33..d1c39b720d213 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -14,10 +14,16 @@
 #ifndef LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
 #define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
 
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/Support/DXILABI.h"
 #include <variant>
 
 namespace llvm {
+class LLVMContext;
+class MDNode;
+class Metadata;
+
 namespace hlsl {
 namespace rootsig {
 
@@ -122,6 +128,27 @@ using RootElement = std::variant<DescriptorTable, DescriptorTableClause>;
 using ParamType = std::variant<uint32_t *, DescriptorRangeOffset *,
                                DescriptorRangeFlags *, ShaderVisibility *>;
 
+class MetadataBuilder {
+public:
+  MetadataBuilder(llvm::LLVMContext &Ctx, ArrayRef<RootElement> Elements)
+      : Ctx(Ctx), Elements(Elements) {}
+
+  /// Iterates through the elements and dispatches onto the correct Build method
+  ///
+  /// Accumulates the root signature and returns the Metadata node that is just
+  /// a list of all the elements
+  MDNode *BuildRootSignature();
+
+private:
+  /// Define the various builders for the different metadata types
+  MDNode *BuildDescriptorTable(const DescriptorTable &Table);
+  MDNode *BuildDescriptorTableClause(const DescriptorTableClause &Clause);
+
+  llvm::LLVMContext &Ctx;
+  ArrayRef<RootElement> Elements;
+  SmallVector<Metadata *> GeneratedMetadata;
+};
+
 } // namespace rootsig
 } // namespace hlsl
 } // namespace llvm
diff --git a/llvm/lib/Frontend/HLSL/CMakeLists.txt b/llvm/lib/Frontend/HLSL/CMakeLists.txt
index eda6cb8e69a49..739bfef8dbc37 100644
--- a/llvm/lib/Frontend/HLSL/CMakeLists.txt
+++ b/llvm/lib/Frontend/HLSL/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_llvm_component_library(LLVMFrontendHLSL
   HLSLResource.cpp
+  HLSLRootSignature.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
new file mode 100644
index 0000000000000..fb1a2ddc72640
--- /dev/null
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -0,0 +1,108 @@
+//===- HLSLRootSignature.cpp - HLSL Root Signature helper objects
+//----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file This file contains helpers for working with HLSL Root Signatures.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
+
+namespace llvm {
+namespace hlsl {
+namespace rootsig {
+
+// Static helper functions
+
+static MDString *ClauseTypeToName(LLVMContext &Ctx, ClauseType Type) {
+  StringRef Name;
+  switch (Type) {
+  case ClauseType::CBuffer:
+    Name = "CBV";
+    break;
+  case ClauseType::SRV:
+    Name = "SRV";
+    break;
+  case ClauseType::UAV:
+    Name = "UAV";
+    break;
+  case ClauseType::Sampler:
+    Name = "Sampler";
+    break;
+  }
+  return MDString::get(Ctx, Name);
+}
+
+// Helper struct so that we can use the overloaded notation of std::visit
+template <class... Ts> struct OverloadBuilds : Ts... {
+  using Ts::operator()...;
+};
+template <class... Ts> OverloadBuilds(Ts...) -> OverloadBuilds<Ts...>;
+
+MDNode *MetadataBuilder::BuildRootSignature() {
+  for (const RootElement &Element : Elements) {
+    MDNode *ElementMD =
+        std::visit(OverloadBuilds{
+                       [&](DescriptorTable Table) -> MDNode * {
+                         return BuildDescriptorTable(Table);
+                       },
+                       [&](DescriptorTableClause Clause) -> MDNode * {
+                         return BuildDescriptorTableClause(Clause);
+                       },
+                   },
+                   Element);
+    GeneratedMetadata.push_back(ElementMD);
+  }
+
+  return MDNode::get(Ctx, GeneratedMetadata);
+}
+
+MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) {
+  IRBuilder<> B(Ctx);
+  SmallVector<Metadata *> TableOperands;
+  // Set the mandatory arguments
+  TableOperands.push_back(MDString::get(Ctx, "DescriptorTable"));
+  TableOperands.push_back(ConstantAsMetadata::get(
+      B.getInt32(llvm::to_underlying(Table.Visibility))));
+
+  // Remaining operands are references to the table's clauses. The in-memory
+  // representation of the Root Elements created from parsing will ensure that
+  // the previous N elements are the clauses for this table.
+  assert(Table.NumClauses <= GeneratedMetadata.size() &&
+         "Table expected all owned clauses to be generated already");
+  // So, add a refence to each clause to our operands
+  TableOperands.append(GeneratedMetadata.end() - Table.NumClauses,
+                       GeneratedMetadata.end());
+  // Then, remove those clauses from the general list of Root Elements
+  GeneratedMetadata.pop_back_n(Table.NumClauses);
+
+  return MDNode::get(Ctx, TableOperands);
+}
+
+MDNode *MetadataBuilder::BuildDescriptorTableClause(
+    const DescriptorTableClause &Clause) {
+  IRBuilder<> B(Ctx);
+  return MDNode::get(
+      Ctx, {
+               ClauseTypeToName(Ctx, Clause.Type),
+               ConstantAsMetadata::get(B.getInt32(Clause.NumDescriptors)),
+               ConstantAsMetadata::get(B.getInt32(Clause.Register.Number)),
+               ConstantAsMetadata::get(B.getInt32(Clause.Space)),
+               ConstantAsMetadata::get(
+                   B.getInt32(llvm::to_underlying(Clause.Offset))),
+               ConstantAsMetadata::get(
+                   B.getInt32(llvm::to_underlying(Clause.Flags))),
+           });
+}
+
+} // namespace rootsig
+} // namespace hlsl
+} // namespace llvm

@llvmbot
Copy link
Member

llvmbot commented Feb 13, 2025

@llvm/pr-subscribers-clang-codegen

Author: Finn Plummer (inbelic)

Changes
  • Define and implement MetadataBuilder in HLSLRootSignature
  • Integrate and invoke the builder in CGHLSLRuntime.cpp to generate the Root Signature for any associated entry functions
  • Add tests to demonstrate functionality in RootSignature.hlsl

Resolves #126584


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

5 Files Affected:

  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (+20)
  • (added) clang/test/CodeGenHLSL/RootSignature.hlsl (+29)
  • (modified) llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h (+27)
  • (modified) llvm/lib/Frontend/HLSL/CMakeLists.txt (+1)
  • (added) llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp (+108)
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index c354e58e15f4b..62d062be91046 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -119,6 +119,20 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {
   return CBGV;
 }
 
+void addRootSignature(ArrayRef<llvm::hlsl::rootsig::RootElement> Elements,
+                      llvm::Function *Fn, llvm::Module &M) {
+  auto &Ctx = M.getContext();
+
+  llvm::hlsl::rootsig::MetadataBuilder Builder(Ctx, Elements);
+  MDNode *RootSignature = Builder.BuildRootSignature();
+  MDNode *FnPairing =
+      MDNode::get(Ctx, {ValueAsMetadata::get(Fn), RootSignature});
+
+  StringRef RootSignatureValKey = "dx.rootsignatures";
+  auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey);
+  RootSignatureValMD->addOperand(FnPairing);
+}
+
 } // namespace
 
 llvm::Type *CGHLSLRuntime::convertHLSLSpecificType(const Type *T) {
@@ -453,6 +467,12 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD,
   // FIXME: Handle codegen for return type semantics.
   // See: https://github.com/llvm/llvm-project/issues/57875
   B.CreateRetVoid();
+
+  // Add and identify root signature to function, if applicable
+  const AttrVec &Attrs = FD->getAttrs();
+  for (const Attr *Attr : Attrs)
+    if (const auto *RSAttr = dyn_cast<HLSLRootSignatureAttr>(Attr))
+      addRootSignature(RSAttr->getElements(), EntryFn, M);
 }
 
 void CGHLSLRuntime::setHLSLFunctionAttributes(const FunctionDecl *FD,
diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl
new file mode 100644
index 0000000000000..76aa2690b96a7
--- /dev/null
+++ b/clang/test/CodeGenHLSL/RootSignature.hlsl
@@ -0,0 +1,29 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s
+
+// CHECK-DAG: ![[#EMPTY:]] = !{}
+[shader("compute"), RootSignature("")]
+[numthreads(1,1,1)]
+void FirstEntry() {}
+
+// CHECK-DAG: ![[#CBV:]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4}
+// CHECK-DAG: ![[#SRV:]] = !{!"SRV", i32 4, i32 42, i32 3, i32 32, i32 0}
+// CHECK-DAG: ![[#TABLE:]] = !{!"DescriptorTable", i32 0, ![[#CBV]], ![[#SRV]]}
+// CHECK-DAG: ![[#SECOND_RS:]] = !{![[#TABLE]]}
+
+#define SampleDescriptorTable \
+  "DescriptorTable( " \
+  "  CBV(b0), " \
+  "  SRV(t42, space = 3, offset = 32, numDescriptors = 4, flags = 0) " \
+  ")"
+[shader("compute"), RootSignature(SampleDescriptorTable)]
+[numthreads(1,1,1)]
+void SecondEntry() {}
+
+// Sanity test to ensure no root is added for this function
+[shader("compute")]
+[numthreads(1,1,1)]
+void ThirdEntry() {}
+
+// CHECK-DAG: ![[#FIRST_ENTRY:]] = !{ptr @FirstEntry, ![[#EMPTY]]}
+// CHECK-DAG: ![[#SECOND_ENTRY:]] = !{ptr @SecondEntry, ![[#SECOND_RS]]}
+// CHECK-DAG: !dx.rootsignatures = !{![[#FIRST_ENTRY]], ![[#SECOND_ENTRY]]}
diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
index f999a0b5eef33..d1c39b720d213 100644
--- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
+++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h
@@ -14,10 +14,16 @@
 #ifndef LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
 #define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H
 
+#include "llvm/ADT/ArrayRef.h"
+#include "llvm/ADT/STLForwardCompat.h"
 #include "llvm/Support/DXILABI.h"
 #include <variant>
 
 namespace llvm {
+class LLVMContext;
+class MDNode;
+class Metadata;
+
 namespace hlsl {
 namespace rootsig {
 
@@ -122,6 +128,27 @@ using RootElement = std::variant<DescriptorTable, DescriptorTableClause>;
 using ParamType = std::variant<uint32_t *, DescriptorRangeOffset *,
                                DescriptorRangeFlags *, ShaderVisibility *>;
 
+class MetadataBuilder {
+public:
+  MetadataBuilder(llvm::LLVMContext &Ctx, ArrayRef<RootElement> Elements)
+      : Ctx(Ctx), Elements(Elements) {}
+
+  /// Iterates through the elements and dispatches onto the correct Build method
+  ///
+  /// Accumulates the root signature and returns the Metadata node that is just
+  /// a list of all the elements
+  MDNode *BuildRootSignature();
+
+private:
+  /// Define the various builders for the different metadata types
+  MDNode *BuildDescriptorTable(const DescriptorTable &Table);
+  MDNode *BuildDescriptorTableClause(const DescriptorTableClause &Clause);
+
+  llvm::LLVMContext &Ctx;
+  ArrayRef<RootElement> Elements;
+  SmallVector<Metadata *> GeneratedMetadata;
+};
+
 } // namespace rootsig
 } // namespace hlsl
 } // namespace llvm
diff --git a/llvm/lib/Frontend/HLSL/CMakeLists.txt b/llvm/lib/Frontend/HLSL/CMakeLists.txt
index eda6cb8e69a49..739bfef8dbc37 100644
--- a/llvm/lib/Frontend/HLSL/CMakeLists.txt
+++ b/llvm/lib/Frontend/HLSL/CMakeLists.txt
@@ -1,5 +1,6 @@
 add_llvm_component_library(LLVMFrontendHLSL
   HLSLResource.cpp
+  HLSLRootSignature.cpp
 
   ADDITIONAL_HEADER_DIRS
   ${LLVM_MAIN_INCLUDE_DIR}/llvm/Frontend
diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
new file mode 100644
index 0000000000000..fb1a2ddc72640
--- /dev/null
+++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp
@@ -0,0 +1,108 @@
+//===- HLSLRootSignature.cpp - HLSL Root Signature helper objects
+//----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+///
+/// \file This file contains helpers for working with HLSL Root Signatures.
+///
+//===----------------------------------------------------------------------===//
+
+#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
+#include "llvm/IR/IRBuilder.h"
+#include "llvm/IR/Metadata.h"
+#include "llvm/IR/Module.h"
+
+namespace llvm {
+namespace hlsl {
+namespace rootsig {
+
+// Static helper functions
+
+static MDString *ClauseTypeToName(LLVMContext &Ctx, ClauseType Type) {
+  StringRef Name;
+  switch (Type) {
+  case ClauseType::CBuffer:
+    Name = "CBV";
+    break;
+  case ClauseType::SRV:
+    Name = "SRV";
+    break;
+  case ClauseType::UAV:
+    Name = "UAV";
+    break;
+  case ClauseType::Sampler:
+    Name = "Sampler";
+    break;
+  }
+  return MDString::get(Ctx, Name);
+}
+
+// Helper struct so that we can use the overloaded notation of std::visit
+template <class... Ts> struct OverloadBuilds : Ts... {
+  using Ts::operator()...;
+};
+template <class... Ts> OverloadBuilds(Ts...) -> OverloadBuilds<Ts...>;
+
+MDNode *MetadataBuilder::BuildRootSignature() {
+  for (const RootElement &Element : Elements) {
+    MDNode *ElementMD =
+        std::visit(OverloadBuilds{
+                       [&](DescriptorTable Table) -> MDNode * {
+                         return BuildDescriptorTable(Table);
+                       },
+                       [&](DescriptorTableClause Clause) -> MDNode * {
+                         return BuildDescriptorTableClause(Clause);
+                       },
+                   },
+                   Element);
+    GeneratedMetadata.push_back(ElementMD);
+  }
+
+  return MDNode::get(Ctx, GeneratedMetadata);
+}
+
+MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) {
+  IRBuilder<> B(Ctx);
+  SmallVector<Metadata *> TableOperands;
+  // Set the mandatory arguments
+  TableOperands.push_back(MDString::get(Ctx, "DescriptorTable"));
+  TableOperands.push_back(ConstantAsMetadata::get(
+      B.getInt32(llvm::to_underlying(Table.Visibility))));
+
+  // Remaining operands are references to the table's clauses. The in-memory
+  // representation of the Root Elements created from parsing will ensure that
+  // the previous N elements are the clauses for this table.
+  assert(Table.NumClauses <= GeneratedMetadata.size() &&
+         "Table expected all owned clauses to be generated already");
+  // So, add a refence to each clause to our operands
+  TableOperands.append(GeneratedMetadata.end() - Table.NumClauses,
+                       GeneratedMetadata.end());
+  // Then, remove those clauses from the general list of Root Elements
+  GeneratedMetadata.pop_back_n(Table.NumClauses);
+
+  return MDNode::get(Ctx, TableOperands);
+}
+
+MDNode *MetadataBuilder::BuildDescriptorTableClause(
+    const DescriptorTableClause &Clause) {
+  IRBuilder<> B(Ctx);
+  return MDNode::get(
+      Ctx, {
+               ClauseTypeToName(Ctx, Clause.Type),
+               ConstantAsMetadata::get(B.getInt32(Clause.NumDescriptors)),
+               ConstantAsMetadata::get(B.getInt32(Clause.Register.Number)),
+               ConstantAsMetadata::get(B.getInt32(Clause.Space)),
+               ConstantAsMetadata::get(
+                   B.getInt32(llvm::to_underlying(Clause.Offset))),
+               ConstantAsMetadata::get(
+                   B.getInt32(llvm::to_underlying(Clause.Flags))),
+           });
+}
+
+} // namespace rootsig
+} // namespace hlsl
+} // namespace llvm

TableOperands.push_back(ConstantAsMetadata::get(
B.getInt32(llvm::to_underlying(Table.Visibility))));

// Remaining operands are references to the table's clauses. The in-memory
Copy link
Contributor

Choose a reason for hiding this comment

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

Very helpful 👍

Copy link
Contributor

@bob80905 bob80905 left a comment

Choose a reason for hiding this comment

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

Just a nit but this looks good to me

@inbelic inbelic deleted the branch llvm:users/inbelic/pr-123985 March 31, 2025 21:05
@inbelic inbelic closed this Mar 31, 2025
inbelic added a commit that referenced this pull request May 15, 2025
…139633)

- prereq: Modify `RootSignatureAttr` to hold a reference to the owned
declaration
- Define and implement `MetadataBuilder` in `HLSLRootSignature`
- Integrate and invoke the builder in `CGHLSLRuntime.cpp` to generate
the Root Signature for any associated entry functions
- Add tests to demonstrate functionality in `RootSignature.hlsl`

Resolves #126584

Note: this is essentially just
#125131 rebased onto the new
approach of constructing a root signature decl, instead of holding the
elements in `AdditionalMembers`.
llvm-sync bot pushed a commit to arm/arm-toolchain that referenced this pull request May 15, 2025
…or tables (#139633)

- prereq: Modify `RootSignatureAttr` to hold a reference to the owned
declaration
- Define and implement `MetadataBuilder` in `HLSLRootSignature`
- Integrate and invoke the builder in `CGHLSLRuntime.cpp` to generate
the Root Signature for any associated entry functions
- Add tests to demonstrate functionality in `RootSignature.hlsl`

Resolves llvm/llvm-project#126584

Note: this is essentially just
llvm/llvm-project#125131 rebased onto the new
approach of constructing a root signature decl, instead of holding the
elements in `AdditionalMembers`.
@inbelic inbelic deleted the inbelic/gen-ast-dt branch May 16, 2025 18:07
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
Status: Closed
Development

Successfully merging this pull request may close these issues.

[HLSL] Generate Root Signature Descriptor Table Metadata from AST
4 participants