https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/139633
>From 135e6c98f964daff5313c335fc38c5e857994366 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Mon, 12 May 2025 21:43:57 +0000 Subject: [PATCH 01/13] pre-req: update attr to store reference to root signature decl --- clang/include/clang/Basic/Attr.td | 3 ++- clang/lib/Sema/SemaHLSL.cpp | 9 +++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index ccd13a4cca4dd..dda62fdf03586 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4739,7 +4739,8 @@ def Error : InheritableAttr { def RootSignature : Attr { /// [RootSignature(Signature)] let Spellings = [Microsoft<"RootSignature">]; - let Args = [IdentifierArgument<"Signature">]; + let Args = [IdentifierArgument<"SignatureIdent">, + DeclArgument<HLSLRootSignature, "SignatureDecl", 0, /*fake=*/1>]; let Subjects = SubjectList<[Function], ErrorDiag, "'function'">; let LangOpts = [HLSL]; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 744ec439b2393..1b1b6573b7af3 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -959,7 +959,7 @@ void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) { IdentifierInfo *Ident = AL.getArgAsIdent(0)->getIdentifierInfo(); if (auto *RS = D->getAttr<RootSignatureAttr>()) { - if (RS->getSignature() != Ident) { + if (RS->getSignatureIdent() != Ident) { Diag(AL.getLoc(), diag::err_disallowed_duplicate_attribute) << RS; return; } @@ -970,10 +970,11 @@ void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) { LookupResult R(SemaRef, Ident, SourceLocation(), Sema::LookupOrdinaryName); if (SemaRef.LookupQualifiedName(R, D->getDeclContext())) - if (isa<HLSLRootSignatureDecl>(R.getFoundDecl())) { + if (auto *SignatureDecl = + dyn_cast<HLSLRootSignatureDecl>(R.getFoundDecl())) { // Perform validation of constructs here - D->addAttr(::new (getASTContext()) - RootSignatureAttr(getASTContext(), AL, Ident)); + D->addAttr(::new (getASTContext()) RootSignatureAttr( + getASTContext(), AL, Ident, SignatureDecl)); } } >From e1693ccb3a8e9a47013ab03bcdda5b6f37853070 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Wed, 29 Jan 2025 19:40:08 +0000 Subject: [PATCH 02/13] add basic empty root signature --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 21 +++++++++++++++++++++ clang/test/CodeGenHLSL/RootSignature.hlsl | 19 +++++++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 clang/test/CodeGenHLSL/RootSignature.hlsl diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 0eb4bb062e02e..3485bef397f64 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -68,6 +68,20 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) { DXILValMD->addOperand(Val); } +void addRootSignature(llvm::Function *Fn, llvm::Module &M) { + auto &Ctx = M.getContext(); + IRBuilder<> B(M.getContext()); + + MDNode *ExampleRootSignature = MDNode::get(Ctx, {}); + + MDNode *ExamplePairing = MDNode::get(Ctx, {ValueAsMetadata::get(Fn), + ExampleRootSignature}); + + StringRef RootSignatureValKey = "dx.rootsignatures"; + auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey); + RootSignatureValMD->addOperand(ExamplePairing); +} + } // namespace llvm::Type * @@ -423,6 +437,13 @@ 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 (isa<RootSignatureAttr>(Attr)) + addRootSignature(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..1ea9ab7aaa2c3 --- /dev/null +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -0,0 +1,19 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s + +// CHECK: !dx.rootsignatures = !{![[#FIRST_ENTRY:]], ![[#SECOND_ENTRY:]]} +// CHECK-DAG: ![[#FIRST_ENTRY]] = !{ptr @FirstEntry, ![[#RS:]]} +// CHECK-DAG: ![[#SECOND_ENTRY]] = !{ptr @SecondEntry, ![[#RS:]]} +// CHECK-DAG: ![[#RS]] = !{} + +[shader("compute"), RootSignature("")] +[numthreads(1,1,1)] +void FirstEntry() {} + +[shader("compute"), RootSignature("DescriptorTable()")] +[numthreads(1,1,1)] +void SecondEntry() {} + +// Sanity test to ensure to root is added for this function +[shader("compute")] +[numthreads(1,1,1)] +void ThirdEntry() {} >From 76e3b5e3220f7afc16f866c1cf4b272e8cde8d5e Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Wed, 29 Jan 2025 19:57:48 +0000 Subject: [PATCH 03/13] pass down the actual root elements - test that we have the correct number of elements --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 17 ++++++++++++----- clang/test/CodeGenHLSL/RootSignature.hlsl | 9 +++++---- 2 files changed, 17 insertions(+), 9 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 3485bef397f64..aeda2f3c9c272 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -68,11 +68,18 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) { DXILValMD->addOperand(Val); } -void addRootSignature(llvm::Function *Fn, llvm::Module &M) { +void addRootSignature( + ArrayRef<llvm::hlsl::rootsig::RootElement> Elements, + llvm::Function *Fn, llvm::Module &M) { auto &Ctx = M.getContext(); - IRBuilder<> B(M.getContext()); - MDNode *ExampleRootSignature = MDNode::get(Ctx, {}); + SmallVector<Metadata *> GeneratedMetadata; + for (auto Element : Elements) { + MDNode *ExampleRootElement = MDNode::get(Ctx, {}); + GeneratedMetadata.push_back(ExampleRootElement); + } + + MDNode *ExampleRootSignature = MDNode::get(Ctx, GeneratedMetadata); MDNode *ExamplePairing = MDNode::get(Ctx, {ValueAsMetadata::get(Fn), ExampleRootSignature}); @@ -441,8 +448,8 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, // Add and identify root signature to function, if applicable const AttrVec &Attrs = FD->getAttrs(); for (const Attr *Attr : Attrs) { - if (isa<RootSignatureAttr>(Attr)) - addRootSignature(EntryFn, M); + if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) + addRootSignature(RSAttr->getSignatureDecl()->getRootElements(), EntryFn, M); } } diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index 1ea9ab7aaa2c3..63c0505e224f0 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -1,9 +1,10 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s -// CHECK: !dx.rootsignatures = !{![[#FIRST_ENTRY:]], ![[#SECOND_ENTRY:]]} -// CHECK-DAG: ![[#FIRST_ENTRY]] = !{ptr @FirstEntry, ![[#RS:]]} -// CHECK-DAG: ![[#SECOND_ENTRY]] = !{ptr @SecondEntry, ![[#RS:]]} -// CHECK-DAG: ![[#RS]] = !{} +// CHECK-DAG: ![[#EMPTY:]] = !{} +// CHECK-DAG: ![[#SECOND_RS:]] = !{![[#EMPTY]]} +// CHECK-DAG: ![[#SECOND_ENTRY:]] = !{ptr @SecondEntry, ![[#SECOND_RS]]} +// CHECK-DAG: ![[#FIRST_ENTRY:]] = !{ptr @FirstEntry, ![[#EMPTY]]} +// CHECK-DAG: !dx.rootsignatures = !{![[#FIRST_ENTRY]], ![[#SECOND_ENTRY]]} [shader("compute"), RootSignature("")] [numthreads(1,1,1)] >From bdbf47c5e63407f911e7502552e3dfede6f3f367 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Wed, 29 Jan 2025 22:50:13 +0000 Subject: [PATCH 04/13] introduce a MetadataBuilder to handle the construction of nodes --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 16 +++---- clang/test/CodeGenHLSL/RootSignature.hlsl | 17 ++++--- .../llvm/Frontend/HLSL/HLSLRootSignature.h | 23 ++++++++++ llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 45 ++++++++++++++++++- 4 files changed, 83 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index aeda2f3c9c272..ec2520a1a090d 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -73,20 +73,14 @@ void addRootSignature( llvm::Function *Fn, llvm::Module &M) { auto &Ctx = M.getContext(); - SmallVector<Metadata *> GeneratedMetadata; - for (auto Element : Elements) { - MDNode *ExampleRootElement = MDNode::get(Ctx, {}); - GeneratedMetadata.push_back(ExampleRootElement); - } - - MDNode *ExampleRootSignature = MDNode::get(Ctx, GeneratedMetadata); - - MDNode *ExamplePairing = MDNode::get(Ctx, {ValueAsMetadata::get(Fn), - ExampleRootSignature}); + 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(ExamplePairing); + RootSignatureValMD->addOperand(FnPairing); } } // namespace diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index 63c0505e224f0..659631133ad9b 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -1,16 +1,17 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s // CHECK-DAG: ![[#EMPTY:]] = !{} -// CHECK-DAG: ![[#SECOND_RS:]] = !{![[#EMPTY]]} -// CHECK-DAG: ![[#SECOND_ENTRY:]] = !{ptr @SecondEntry, ![[#SECOND_RS]]} -// CHECK-DAG: ![[#FIRST_ENTRY:]] = !{ptr @FirstEntry, ![[#EMPTY]]} -// CHECK-DAG: !dx.rootsignatures = !{![[#FIRST_ENTRY]], ![[#SECOND_ENTRY]]} - [shader("compute"), RootSignature("")] [numthreads(1,1,1)] void FirstEntry() {} -[shader("compute"), RootSignature("DescriptorTable()")] +// CHECK-DAG: ![[#TABLE:]] = !{!"DescriptorTable"} +// CHECK-DAG: ![[#SECOND_RS:]] = !{![[#TABLE]]} + +#define SampleDescriptorTable \ + "DescriptorTable( " \ + ")" +[shader("compute"), RootSignature(SampleDescriptorTable)] [numthreads(1,1,1)] void SecondEntry() {} @@ -18,3 +19,7 @@ void SecondEntry() {} [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 37f3d9ad61d3e..915b3e2160bb0 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -15,11 +15,16 @@ #define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H #include "llvm/ADT/ArrayRef.h" +// #include "llvm/ADT/STLForwardCompat.h" #include "llvm/Support/DXILABI.h" #include "llvm/Support/raw_ostream.h" #include <variant> namespace llvm { +class LLVMContext; +class MDNode; +class Metadata; + namespace hlsl { namespace rootsig { @@ -125,6 +130,24 @@ using RootElement = std::variant<RootFlags, RootConstants, DescriptorTable, void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements); +class MetadataBuilder { + public: + MetadataBuilder(llvm::LLVMContext &Ctx, ArrayRef<RootElement> Elements) + : Ctx(Ctx), Elements(Elements) {} + + // Iterates through the elements and builds the respective nodes + 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/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index cd3c6f8dde8be..482856c1fb10d 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -10,8 +10,11 @@ /// //===----------------------------------------------------------------------===// -#include "llvm/Frontend/HLSL/HLSLRootSignature.h" #include "llvm/ADT/bit.h" +#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 { @@ -160,6 +163,46 @@ void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) { OS << "}"; } +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); +} + +MDNode *MetadataBuilder::BuildRootSignature() { + for (const RootElement &Element : Elements) { + MDNode *ElementMD = nullptr; + if (const auto &Clause = std::get_if<DescriptorTableClause>(&Element)) + ElementMD = BuildDescriptorTableClause(*Clause); + if (const auto &Table = std::get_if<DescriptorTable>(&Element)) + ElementMD = BuildDescriptorTable(*Table); + GeneratedMetadata.push_back(ElementMD); + } + + return MDNode::get(Ctx, GeneratedMetadata); +} + +MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) { + return MDNode::get(Ctx, {MDString::get(Ctx, "DescriptorTable")}); +} + +MDNode *MetadataBuilder::BuildDescriptorTableClause(const DescriptorTableClause &Clause) { + return MDNode::get(Ctx, {ClauseTypeToName(Ctx, Clause.Type)}); +} + } // namespace rootsig } // namespace hlsl } // namespace llvm >From a931947d82ab1eec862238f5a03eacbb9a041a7b Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Thu, 30 Jan 2025 22:45:58 +0000 Subject: [PATCH 05/13] add support for DescriptorTableClauses --- clang/test/CodeGenHLSL/RootSignature.hlsl | 2 ++ llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 11 ++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index 659631133ad9b..da8f2e5e24df1 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -5,11 +5,13 @@ [numthreads(1,1,1)] void FirstEntry() {} +// CHECK-DAG: ![[#CBV:]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4} // CHECK-DAG: ![[#TABLE:]] = !{!"DescriptorTable"} // CHECK-DAG: ![[#SECOND_RS:]] = !{![[#TABLE]]} #define SampleDescriptorTable \ "DescriptorTable( " \ + " CBV(b0) " \ ")" [shader("compute"), RootSignature(SampleDescriptorTable)] [numthreads(1,1,1)] diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index 482856c1fb10d..706fdced533b8 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -200,7 +200,16 @@ MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) { } MDNode *MetadataBuilder::BuildDescriptorTableClause(const DescriptorTableClause &Clause) { - return MDNode::get(Ctx, {ClauseTypeToName(Ctx, Clause.Type)}); + IRBuilder<> B(Ctx); + return MDNode::get(Ctx, { + ClauseTypeToName(Ctx, Clause.Type), + ConstantAsMetadata::get(B.getInt32(Clause.NumDescriptors)), + ConstantAsMetadata::get(B.getInt32(Clause.Reg.Number)), + ConstantAsMetadata::get(B.getInt32(Clause.Space)), + ConstantAsMetadata::get(B.getInt32(Clause.Offset)), + ConstantAsMetadata::get( + B.getInt32(llvm::to_underlying(Clause.Flags))), + }); } } // namespace rootsig >From 5ccbf463e67ded46d806eac9521e8f0cc8772265 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Thu, 30 Jan 2025 22:51:42 +0000 Subject: [PATCH 06/13] add support for associating DescriptorTables with their clauses --- clang/test/CodeGenHLSL/RootSignature.hlsl | 6 ++++-- llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 11 ++++++++++- 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index da8f2e5e24df1..2bbf4bf09093e 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -6,12 +6,14 @@ void FirstEntry() {} // CHECK-DAG: ![[#CBV:]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4} -// CHECK-DAG: ![[#TABLE:]] = !{!"DescriptorTable"} +// 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) " \ + " CBV(b0), " \ + " SRV(t42, space = 3, offset = 32, numDescriptors = 4, flags = 0) " \ ")" [shader("compute"), RootSignature(SampleDescriptorTable)] [numthreads(1,1,1)] diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index 706fdced533b8..f2c667729caac 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -196,7 +196,16 @@ MDNode *MetadataBuilder::BuildRootSignature() { } MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) { - return MDNode::get(Ctx, {MDString::get(Ctx, "DescriptorTable")}); + IRBuilder<> B(Ctx); + SmallVector<Metadata *> TableOperands; + TableOperands.push_back(MDString::get(Ctx, "DescriptorTable")); + TableOperands.push_back(ConstantAsMetadata::get(B.getInt32(llvm::to_underlying(Table.Visibility)))); + + assert(Table.NumClauses <= GeneratedMetadata.size() && "Table expected all owned clauses to be generated already"); + TableOperands.append(GeneratedMetadata.end() - Table.NumClauses, GeneratedMetadata.end()); + GeneratedMetadata.pop_back_n(Table.NumClauses); + + return MDNode::get(Ctx, TableOperands); } MDNode *MetadataBuilder::BuildDescriptorTableClause(const DescriptorTableClause &Clause) { >From 0ed0c09116ce96e7b7886e0f6826f485388ee211 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Thu, 30 Jan 2025 23:14:00 +0000 Subject: [PATCH 07/13] self-review: misc clean up --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 12 +++++----- clang/test/CodeGenHLSL/RootSignature.hlsl | 2 +- .../llvm/Frontend/HLSL/HLSLRootSignature.h | 13 ++++++----- llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 22 ++++++++++++++----- 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index ec2520a1a090d..61fc65863a12e 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -68,15 +68,14 @@ void addDxilValVersion(StringRef ValVersionStr, llvm::Module &M) { DXILValMD->addOperand(Val); } -void addRootSignature( - ArrayRef<llvm::hlsl::rootsig::RootElement> Elements, - llvm::Function *Fn, llvm::Module &M) { +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}); + MDNode *FnPairing = + MDNode::get(Ctx, {ValueAsMetadata::get(Fn), RootSignature}); StringRef RootSignatureValKey = "dx.rootsignatures"; auto *RootSignatureValMD = M.getOrInsertNamedMetadata(RootSignatureValKey); @@ -443,7 +442,8 @@ void CGHLSLRuntime::emitEntryFunction(const FunctionDecl *FD, const AttrVec &Attrs = FD->getAttrs(); for (const Attr *Attr : Attrs) { if (const auto *RSAttr = dyn_cast<RootSignatureAttr>(Attr)) - addRootSignature(RSAttr->getSignatureDecl()->getRootElements(), EntryFn, M); + addRootSignature(RSAttr->getSignatureDecl()->getRootElements(), EntryFn, + M); } } diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index 2bbf4bf09093e..76aa2690b96a7 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -19,7 +19,7 @@ void FirstEntry() {} [numthreads(1,1,1)] void SecondEntry() {} -// Sanity test to ensure to root is added for this function +// Sanity test to ensure no root is added for this function [shader("compute")] [numthreads(1,1,1)] void ThirdEntry() {} diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 915b3e2160bb0..585a1338fa4d0 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -131,15 +131,18 @@ using RootElement = std::variant<RootFlags, RootConstants, DescriptorTable, void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements); class MetadataBuilder { - public: +public: MetadataBuilder(llvm::LLVMContext &Ctx, ArrayRef<RootElement> Elements) - : Ctx(Ctx), Elements(Elements) {} + : Ctx(Ctx), Elements(Elements) {} - // Iterates through the elements and builds the respective nodes + /// 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 +private: + /// Define the various builders for the different metadata types MDNode *BuildDescriptorTable(const DescriptorTable &Table); MDNode *BuildDescriptorTableClause(const DescriptorTableClause &Clause); diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index f2c667729caac..fa341312b9668 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -10,8 +10,8 @@ /// //===----------------------------------------------------------------------===// -#include "llvm/ADT/bit.h" #include "llvm/Frontend/HLSL/HLSLRootSignature.h" +#include "llvm/ADT/bit.h" #include "llvm/IR/IRBuilder.h" #include "llvm/IR/Metadata.h" #include "llvm/IR/Module.h" @@ -198,17 +198,27 @@ MDNode *MetadataBuilder::BuildRootSignature() { 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)))); - - assert(Table.NumClauses <= GeneratedMetadata.size() && "Table expected all owned clauses to be generated already"); - TableOperands.append(GeneratedMetadata.end() - Table.NumClauses, GeneratedMetadata.end()); + 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) { +MDNode *MetadataBuilder::BuildDescriptorTableClause( + const DescriptorTableClause &Clause) { IRBuilder<> B(Ctx); return MDNode::get(Ctx, { ClauseTypeToName(Ctx, Clause.Type), >From 9e1e53017bab3d5e1aebaca37fbc73d075d2f624 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Mon, 12 May 2025 22:25:13 +0000 Subject: [PATCH 08/13] clang-format --- llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index fa341312b9668..301de33400349 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -220,15 +220,16 @@ MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) { 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.Reg.Number)), - ConstantAsMetadata::get(B.getInt32(Clause.Space)), - ConstantAsMetadata::get(B.getInt32(Clause.Offset)), - ConstantAsMetadata::get( - B.getInt32(llvm::to_underlying(Clause.Flags))), - }); + return MDNode::get( + Ctx, { + ClauseTypeToName(Ctx, Clause.Type), + ConstantAsMetadata::get(B.getInt32(Clause.NumDescriptors)), + ConstantAsMetadata::get(B.getInt32(Clause.Reg.Number)), + ConstantAsMetadata::get(B.getInt32(Clause.Space)), + ConstantAsMetadata::get(B.getInt32(Clause.Offset)), + ConstantAsMetadata::get( + B.getInt32(llvm::to_underlying(Clause.Flags))), + }); } } // namespace rootsig >From b613e2e448856fe37d525d856fa756cbe25419bb Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Wed, 5 Mar 2025 17:56:51 +0000 Subject: [PATCH 09/13] review: remove use of CHECK-DAG --- clang/test/CodeGenHLSL/RootSignature.hlsl | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/clang/test/CodeGenHLSL/RootSignature.hlsl b/clang/test/CodeGenHLSL/RootSignature.hlsl index 76aa2690b96a7..60e0dec175b8f 100644 --- a/clang/test/CodeGenHLSL/RootSignature.hlsl +++ b/clang/test/CodeGenHLSL/RootSignature.hlsl @@ -1,14 +1,19 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -emit-llvm -o - %s | FileCheck %s -// CHECK-DAG: ![[#EMPTY:]] = !{} +// CHECK: !dx.rootsignatures = !{![[#FIRST_ENTRY:]], ![[#SECOND_ENTRY:]]} + +// CHECK: ![[#FIRST_ENTRY]] = !{ptr @FirstEntry, ![[#EMPTY:]]} +// CHECK: ![[#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]]} +// CHECK: ![[#SECOND_ENTRY]] = !{ptr @SecondEntry, ![[#SECOND_RS:]]} +// CHECK: ![[#SECOND_RS]] = !{![[#TABLE:]]} +// CHECK: ![[#TABLE]] = !{!"DescriptorTable", i32 0, ![[#CBV:]], ![[#SRV:]]} +// CHECK: ![[#CBV]] = !{!"CBV", i32 1, i32 0, i32 0, i32 -1, i32 4} +// CHECK: ![[#SRV]] = !{!"SRV", i32 4, i32 42, i32 3, i32 32, i32 0} #define SampleDescriptorTable \ "DescriptorTable( " \ @@ -19,11 +24,8 @@ void FirstEntry() {} [numthreads(1,1,1)] void SecondEntry() {} -// Sanity test to ensure no root is added for this function +// Sanity test to ensure no root is added for this function as there is only +// two entries in !dx.roosignatures [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]]} >From 3da3df533ca0503444665f8b2997f7b0e5cc45f3 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Mon, 12 May 2025 22:37:39 +0000 Subject: [PATCH 10/13] self-review: remove commented header --- llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h | 1 - 1 file changed, 1 deletion(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 585a1338fa4d0..77c6bdc477cce 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -15,7 +15,6 @@ #define LLVM_FRONTEND_HLSL_HLSLROOTSIGNATURE_H #include "llvm/ADT/ArrayRef.h" -// #include "llvm/ADT/STLForwardCompat.h" #include "llvm/Support/DXILABI.h" #include "llvm/Support/raw_ostream.h" #include <variant> >From be9173c63b25ab279f856e4e94b1e25aa2d44bb9 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Thu, 15 May 2025 16:44:52 +0000 Subject: [PATCH 11/13] self-review: use << operator instead of redefining switch behaviour --- llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 24 ++++---------------- 1 file changed, 4 insertions(+), 20 deletions(-) diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index 301de33400349..c4561746f80f4 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -163,25 +163,6 @@ void dumpRootElements(raw_ostream &OS, ArrayRef<RootElement> Elements) { OS << "}"; } -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); -} - MDNode *MetadataBuilder::BuildRootSignature() { for (const RootElement &Element : Elements) { MDNode *ElementMD = nullptr; @@ -220,9 +201,12 @@ MDNode *MetadataBuilder::BuildDescriptorTable(const DescriptorTable &Table) { MDNode *MetadataBuilder::BuildDescriptorTableClause( const DescriptorTableClause &Clause) { IRBuilder<> B(Ctx); + std::string Name; + llvm::raw_string_ostream OS(Name); + OS << Clause.Type; return MDNode::get( Ctx, { - ClauseTypeToName(Ctx, Clause.Type), + MDString::get(Ctx, OS.str()), ConstantAsMetadata::get(B.getInt32(Clause.NumDescriptors)), ConstantAsMetadata::get(B.getInt32(Clause.Reg.Number)), ConstantAsMetadata::get(B.getInt32(Clause.Space)), >From dfe18c0f7d192492067c6a2b260369502b574720 Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Thu, 15 May 2025 16:56:25 +0000 Subject: [PATCH 12/13] self-review: mark to revisit get_if chain --- llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp index c4561746f80f4..e4e7b7720ae77 100644 --- a/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp +++ b/llvm/lib/Frontend/HLSL/HLSLRootSignature.cpp @@ -170,6 +170,12 @@ MDNode *MetadataBuilder::BuildRootSignature() { ElementMD = BuildDescriptorTableClause(*Clause); if (const auto &Table = std::get_if<DescriptorTable>(&Element)) ElementMD = BuildDescriptorTable(*Table); + + // FIXME(#126586): remove once all RootElemnt variants are handled in a + // visit or otherwise + assert(ElementMD != nullptr && + "Constructed an unhandled root element type."); + GeneratedMetadata.push_back(ElementMD); } >From 496ab5da473fed8608370f8e6aafd4574e6d9a5a Mon Sep 17 00:00:00 2001 From: Finn Plummer <canadienf...@gmail.com> Date: Thu, 15 May 2025 17:24:01 +0000 Subject: [PATCH 13/13] review: clarify the struct the in-memory representation - formally document the structure of the in-memory representation of a root signature as an array of the defined RootElements --- .../llvm/Frontend/HLSL/HLSLRootSignature.h | 20 +++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h index 77c6bdc477cce..9fdb40db9c23d 100644 --- a/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h +++ b/llvm/include/llvm/Frontend/HLSL/HLSLRootSignature.h @@ -88,7 +88,9 @@ struct RootConstants { // Models the end of a descriptor table and stores its visibility struct DescriptorTable { ShaderVisibility Visibility = ShaderVisibility::All; - uint32_t NumClauses = 0; // The number of clauses in the table + // Denotes that the previous NumClauses in the RootElement array + // are the clauses in the table. + uint32_t NumClauses = 0; void dump(raw_ostream &OS) const; }; @@ -123,7 +125,21 @@ struct DescriptorTableClause { void dump(raw_ostream &OS) const; }; -// Models RootElement : RootConstants | DescriptorTable | DescriptorTableClause +/// Models RootElement : RootFlags | RootConstants | DescriptorTable +/// | DescriptorTableClause +/// +/// A Root Signature is modeled in-memory by an array of RootElements. These +/// aim to map closely to their DSL grammar reprsentation defined in the spec. +/// +/// Each optional parameter has its default value defined in the struct, and, +/// each mandatory parameter does not have a default initialization. +/// +/// For the variants RootFlags, RootConstants and DescriptorTableClause: each +/// data member maps directly to a parameter in the grammar. +/// +/// The DescriptorTable is modelled by having its Clauses as the previous +/// RootElements in the array, and it holds a data member for the Visibility +/// parameter. using RootElement = std::variant<RootFlags, RootConstants, DescriptorTable, DescriptorTableClause>; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits