[llvm-branch-commits] [clang] [HLSL] Define the HLSLRootSignature Attr (PR #123985)

Finn Plummer via llvm-branch-commits llvm-branch-commits at lists.llvm.org
Fri Feb 7 10:25:21 PST 2025


https://github.com/inbelic updated https://github.com/llvm/llvm-project/pull/123985

>From 05c9523adaf9cc3e1585c02bed036ad83667b722 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 22 Jan 2025 17:53:59 +0000
Subject: [PATCH 1/6] [HLSL] Define the HLSLRootSignature Attr

- Defines HLSLRootSignature Attr in `Attr.td`
- Define and implement handleHLSLRootSignature in `SemaHLSL`
- Adds sample test case to show AST Node is generated in
`RootSignatures-AST.hlsl`

This commit will "hook-up" the seperately defined RootSignature parser
and invoke it to create the RootElements, then store them on the
ASTContext and finally store the reference to the Elements in
RootSignatureAttr
---
 clang/include/clang/AST/Attr.h              |  1 +
 clang/include/clang/Basic/Attr.td           | 20 ++++++++++++
 clang/include/clang/Basic/AttrDocs.td       |  4 +++
 clang/include/clang/Sema/SemaHLSL.h         |  1 +
 clang/lib/Sema/SemaDeclAttr.cpp             |  3 ++
 clang/lib/Sema/SemaHLSL.cpp                 | 36 +++++++++++++++++++++
 clang/test/AST/HLSL/RootSignatures-AST.hlsl | 28 ++++++++++++++++
 7 files changed, 93 insertions(+)
 create mode 100644 clang/test/AST/HLSL/RootSignatures-AST.hlsl

diff --git a/clang/include/clang/AST/Attr.h b/clang/include/clang/AST/Attr.h
index 3365ebe4d9012be..d45b8891cf1a72a 100644
--- a/clang/include/clang/AST/Attr.h
+++ b/clang/include/clang/AST/Attr.h
@@ -26,6 +26,7 @@
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Support/Compiler.h"
 #include "llvm/Frontend/HLSL/HLSLResource.h"
+#include "llvm/Frontend/HLSL/HLSLRootSignature.h"
 #include "llvm/Support/CodeGen.h"
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/VersionTuple.h"
diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 52ad72eb608c319..36ae98730db031c 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4643,6 +4643,26 @@ def Error : InheritableAttr {
   let Documentation = [ErrorAttrDocs];
 }
 
+/// HLSL Root Signature Attribute
+def HLSLRootSignature : Attr {
+  /// [RootSignature(Signature)]
+  let Spellings = [Microsoft<"RootSignature">];
+  let Args = [StringArgument<"Signature">];
+  let Subjects = SubjectList<[Function],
+                             ErrorDiag, "'function'">;
+  let LangOpts = [HLSL];
+  let Documentation = [HLSLRootSignatureDocs];
+  let AdditionalMembers = [{
+private:
+  ArrayRef<llvm::hlsl::root_signature::RootElement> RootElements;
+public:
+  void setElements(ArrayRef<llvm::hlsl::root_signature::RootElement> Elements) {
+    RootElements = Elements;
+  }
+  auto getElements() const { return RootElements; }
+}];
+}
+
 def HLSLNumThreads: InheritableAttr {
   let Spellings = [Microsoft<"numthreads">];
   let Args = [IntArgument<"X">, IntArgument<"Y">, IntArgument<"Z">];
diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index fdad4c9a3ea1910..bb0934a11f9f3f0 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7783,6 +7783,10 @@ and https://microsoft.github.io/hlsl-specs/proposals/0013-wave-size-range.html
   }];
 }
 
+def HLSLRootSignatureDocs : Documentation {
+  let Category = DocCatUndocumented;
+}
+
 def NumThreadsDocs : Documentation {
   let Category = DocCatFunction;
   let Content = [{
diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h
index f4cd11f423a84a0..df4a5c8d88ba9e2 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -116,6 +116,7 @@ class SemaHLSL : public SemaBase {
                                        bool IsCompAssign);
   void emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS, BinaryOperatorKind Opc);
 
+  void handleRootSignatureAttr(Decl *D, const ParsedAttr &AL);
   void handleNumThreadsAttr(Decl *D, const ParsedAttr &AL);
   void handleWaveSizeAttr(Decl *D, const ParsedAttr &AL);
   void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
diff --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index bb4d33560b93b8d..c594d6e54ddbcd2 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -7149,6 +7149,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, const ParsedAttr &AL,
     break;
 
   // HLSL attributes:
+  case ParsedAttr::AT_HLSLRootSignature:
+    S.HLSL().handleRootSignatureAttr(D, AL);
+    break;
   case ParsedAttr::AT_HLSLNumThreads:
     S.HLSL().handleNumThreadsAttr(D, AL);
     break;
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 600c800029fd05a..ab8aa6f5a351be6 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -24,6 +24,7 @@
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
 #include "clang/Basic/TargetInfo.h"
+#include "clang/Parse/ParseHLSLRootSignature.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/ParsedAttr.h"
 #include "clang/Sema/Sema.h"
@@ -647,6 +648,41 @@ void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS,
       << NewFnName << FixItHint::CreateReplacement(FullRange, OS.str());
 }
 
+void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {
+  using namespace llvm::hlsl::root_signature;
+
+  if (AL.getNumArgs() != 1)
+    return;
+
+  StringRef Signature;
+  if (!SemaRef.checkStringLiteralArgumentAttr(AL, 0, Signature))
+    return;
+
+  SourceLocation Loc = AL.getArgAsExpr(0)->getExprLoc();
+  // FIXME: pass down below to lexer when fp is supported
+  // llvm::RoundingMode RM = SemaRef.CurFPFeatures.getRoundingMode();
+  SmallVector<RootSignatureToken> Tokens;
+  RootSignatureLexer Lexer(Signature, Loc, SemaRef.getPreprocessor());
+  if (Lexer.Lex(Tokens))
+    return;
+
+  SmallVector<RootElement> Elements;
+  RootSignatureParser Parser(Elements, Tokens);
+  if (Parser.Parse())
+    return;
+
+  unsigned N = Elements.size();
+  auto RootElements =
+      MutableArrayRef<RootElement>(::new (getASTContext()) RootElement[N], N);
+  for (unsigned I = 0; I < N; ++I)
+    RootElements[I] = Elements[I];
+
+  auto *Result = ::new (getASTContext())
+      HLSLRootSignatureAttr(getASTContext(), AL, Signature);
+  Result->setElements(ArrayRef<RootElement>(RootElements));
+  D->addAttr(Result);
+}
+
 void SemaHLSL::handleNumThreadsAttr(Decl *D, const ParsedAttr &AL) {
   llvm::VersionTuple SMVersion =
       getASTContext().getTargetInfo().getTriple().getOSVersion();
diff --git a/clang/test/AST/HLSL/RootSignatures-AST.hlsl b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
new file mode 100644
index 000000000000000..dbc06b61cffebe9
--- /dev/null
+++ b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
@@ -0,0 +1,28 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-library -ast-dump \
+// RUN:  -disable-llvm-passes -o - %s | FileCheck %s
+
+// This test ensures that the sample root signature is parsed without error and
+// the Attr AST Node is created succesfully. If an invalid root signature was
+// passed in then we would exit out of Sema before the Attr is created.
+
+#define SampleRS \
+  "DescriptorTable( " \
+  "  CBV(b1), " \
+  "  SRV(t1, numDescriptors = 8, " \
+  "          flags = DESCRIPTORS_VOLATILE), " \
+  "  UAV(u1, numDescriptors = 0, " \
+  "          flags = DESCRIPTORS_VOLATILE) " \
+  "), " \
+  "DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
+
+// CHECK:      HLSLRootSignatureAttr 0x{{[0-9A-Fa-f]+}} <line:{{[0-9]+}}:{{[0-9]+}}, col:{{[0-9]+}}>
+// CHECK-SAME: "DescriptorTable(
+// CHECK-SAME:   CBV(b1),
+// CHECK-SAME:   SRV(t1, numDescriptors = 8,
+// CHECK-SAME:           flags = DESCRIPTORS_VOLATILE),
+// CHECK-SAME:   UAV(u1, numDescriptors = 0,
+// CHECK-SAME:           flags = DESCRIPTORS_VOLATILE)
+// CHECK-SAME: ),
+// CHECK-SAME: DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
+[RootSignature(SampleRS)]
+void main() {}

>From d1044fe020174b50bf548492cda669cd24dd6451 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 22 Jan 2025 19:08:16 +0000
Subject: [PATCH 2/6] add docs

---
 clang/include/clang/Basic/AttrDocs.td | 9 ++++++++-
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/clang/include/clang/Basic/AttrDocs.td b/clang/include/clang/Basic/AttrDocs.td
index bb0934a11f9f3f0..dc909cf0ae9b7d1 100644
--- a/clang/include/clang/Basic/AttrDocs.td
+++ b/clang/include/clang/Basic/AttrDocs.td
@@ -7784,7 +7784,14 @@ and https://microsoft.github.io/hlsl-specs/proposals/0013-wave-size-range.html
 }
 
 def HLSLRootSignatureDocs : Documentation {
-  let Category = DocCatUndocumented;
+  let Category = DocCatFunction;
+  let Content = [{
+The ``RootSignature`` attribute applies to HLSL entry functions to define what
+types of resources are bound to the graphics pipeline.
+
+For details about the use and specification of Root Signatures please see here:
+https://learn.microsoft.com/en-us/windows/win32/direct3d12/root-signatures
+  }];
 }
 
 def NumThreadsDocs : Documentation {

>From b7d30e9c9c4a8ce8a11f22dc150405b1164dbbfa Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Tue, 28 Jan 2025 23:36:55 +0000
Subject: [PATCH 3/6] rebase onto updated lex/parser prs

- we can now pass down the diagnostics for reporting
- update the namespace
---
 clang/lib/Sema/SemaHLSL.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index ab8aa6f5a351be6..a1db8e29fb85782 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -650,6 +650,7 @@ void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS,
 
 void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {
   using namespace llvm::hlsl::root_signature;
+  using namespace clang::hlsl;
 
   if (AL.getNumArgs() != 1)
     return;
@@ -667,7 +668,8 @@ void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {
     return;
 
   SmallVector<RootElement> Elements;
-  RootSignatureParser Parser(Elements, Tokens);
+  RootSignatureParser Parser(Elements, Tokens,
+                             SemaRef.getPreprocessor().getDiagnostics());
   if (Parser.Parse())
     return;
 

>From f1b7dc9f9af5c8df45e817f6cb67702fa4d3ec2f Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Wed, 29 Jan 2025 00:32:25 +0000
Subject: [PATCH 4/6] add some additional error testing

---
 clang/test/SemaHLSL/RootSignature-err.hlsl | 54 ++++++++++++++++++++++
 1 file changed, 54 insertions(+)
 create mode 100644 clang/test/SemaHLSL/RootSignature-err.hlsl

diff --git a/clang/test/SemaHLSL/RootSignature-err.hlsl b/clang/test/SemaHLSL/RootSignature-err.hlsl
new file mode 100644
index 000000000000000..6c72418d7a2db8a
--- /dev/null
+++ b/clang/test/SemaHLSL/RootSignature-err.hlsl
@@ -0,0 +1,54 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - %s -verify
+
+// This file mirrors the diagnostics testing in ParseHLSLRootSignatureTest.cpp
+// to verify that the correct diagnostics strings are output
+
+// Lexer related tests
+
+#define InvalidToken \
+  "DescriptorTable( " \
+  "  invalid " \
+  ")"
+
+[RootSignature(InvalidToken)] // expected-error {{unable to lex a valid Root Signature token}}
+void bad_root_signature_1() {}
+
+#define InvalidEmptyNumber \
+  "DescriptorTable( " \
+  "  CBV(t32, space = +) " \
+  ")"
+
+[RootSignature(InvalidEmptyNumber)] // expected-error {{expected number literal is not a supported number literal of unsigned integer or integer}}
+void bad_root_signature_2() {}
+
+#define InvalidOverflowNumber \
+  "DescriptorTable( " \
+  "  CBV(t32, space = 98273498327498273487) " \
+  ")"
+
+[RootSignature(InvalidOverflowNumber)] // expected-error {{provided unsigned integer literal '98273498327498273487' that overflows the maximum of 32 bits}}
+void bad_root_signature_3() {}
+
+#define InvalidEOS \
+  "DescriptorTable( "
+
+// Parser related tests
+
+[RootSignature(InvalidEOS)] // expected-error {{unexpected end to token stream}}
+void bad_root_signature_4() {}
+
+#define InvalidTokenKind \
+  "DescriptorTable( " \
+  "  DescriptorTable()" \
+  ")"
+
+[RootSignature(InvalidTokenKind)] // expected-error {{expected the one of the following token kinds 'CBV, SRV, UAV, Sampler'}}
+void bad_root_signature_5() {}
+
+#define InvalidRepeat \
+  "DescriptorTable( " \
+  "  CBV(t0, space = 1, space = 2)" \
+  ")"
+
+[RootSignature(InvalidRepeat)] // expected-error {{specified the same parameter 'space' multiple times}}
+void bad_root_signature_6() {}

>From 4f7a0e20b2c76c4681519b6eb51a8e9d3696ad35 Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 7 Feb 2025 18:02:23 +0000
Subject: [PATCH 5/6] review comments:

- remove bad use of namespaces
- simplify test case checking
---
 clang/lib/Sema/SemaHLSL.cpp                 | 15 ++++++---------
 clang/test/AST/HLSL/RootSignatures-AST.hlsl |  2 +-
 2 files changed, 7 insertions(+), 10 deletions(-)

diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index a1db8e29fb85782..b4ca5fa2aa62dae 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -649,9 +649,6 @@ void SemaHLSL::emitLogicalOperatorFixIt(Expr *LHS, Expr *RHS,
 }
 
 void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {
-  using namespace llvm::hlsl::root_signature;
-  using namespace clang::hlsl;
-
   if (AL.getNumArgs() != 1)
     return;
 
@@ -662,26 +659,26 @@ void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {
   SourceLocation Loc = AL.getArgAsExpr(0)->getExprLoc();
   // FIXME: pass down below to lexer when fp is supported
   // llvm::RoundingMode RM = SemaRef.CurFPFeatures.getRoundingMode();
-  SmallVector<RootSignatureToken> Tokens;
-  RootSignatureLexer Lexer(Signature, Loc, SemaRef.getPreprocessor());
+  SmallVector<hlsl::RootSignatureToken> Tokens;
+  hlsl::RootSignatureLexer Lexer(Signature, Loc, SemaRef.getPreprocessor());
   if (Lexer.Lex(Tokens))
     return;
 
-  SmallVector<RootElement> Elements;
-  RootSignatureParser Parser(Elements, Tokens,
+  SmallVector<llvm::hlsl::root_signature::RootElement> Elements;
+  hlsl::RootSignatureParser Parser(Elements, Tokens,
                              SemaRef.getPreprocessor().getDiagnostics());
   if (Parser.Parse())
     return;
 
   unsigned N = Elements.size();
   auto RootElements =
-      MutableArrayRef<RootElement>(::new (getASTContext()) RootElement[N], N);
+      MutableArrayRef<llvm::hlsl::root_signature::RootElement>(::new (getASTContext()) llvm::hlsl::root_signature::RootElement[N], N);
   for (unsigned I = 0; I < N; ++I)
     RootElements[I] = Elements[I];
 
   auto *Result = ::new (getASTContext())
       HLSLRootSignatureAttr(getASTContext(), AL, Signature);
-  Result->setElements(ArrayRef<RootElement>(RootElements));
+  Result->setElements(ArrayRef<llvm::hlsl::root_signature::RootElement>(RootElements));
   D->addAttr(Result);
 }
 
diff --git a/clang/test/AST/HLSL/RootSignatures-AST.hlsl b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
index dbc06b61cffebe9..9b0908c053254e3 100644
--- a/clang/test/AST/HLSL/RootSignatures-AST.hlsl
+++ b/clang/test/AST/HLSL/RootSignatures-AST.hlsl
@@ -15,7 +15,7 @@
   "), " \
   "DescriptorTable(Sampler(s0, numDescriptors = 4, space = 1))"
 
-// CHECK:      HLSLRootSignatureAttr 0x{{[0-9A-Fa-f]+}} <line:{{[0-9]+}}:{{[0-9]+}}, col:{{[0-9]+}}>
+// CHECK:      HLSLRootSignatureAttr
 // CHECK-SAME: "DescriptorTable(
 // CHECK-SAME:   CBV(b1),
 // CHECK-SAME:   SRV(t1, numDescriptors = 8,

>From 7fde9d9879cd76923fc874a07dd54608394d20bb Mon Sep 17 00:00:00 2001
From: Finn Plummer <canadienfinn at gmail.com>
Date: Fri, 7 Feb 2025 18:08:49 +0000
Subject: [PATCH 6/6] rebase changes

---
 clang/include/clang/Basic/Attr.td |  4 ++--
 clang/lib/Sema/SemaHLSL.cpp       | 10 +++++-----
 2 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td
index 36ae98730db031c..094aba5f6fadc19 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4654,9 +4654,9 @@ def HLSLRootSignature : Attr {
   let Documentation = [HLSLRootSignatureDocs];
   let AdditionalMembers = [{
 private:
-  ArrayRef<llvm::hlsl::root_signature::RootElement> RootElements;
+  ArrayRef<llvm::hlsl::rootsig::RootElement> RootElements;
 public:
-  void setElements(ArrayRef<llvm::hlsl::root_signature::RootElement> Elements) {
+  void setElements(ArrayRef<llvm::hlsl::rootsig::RootElement> Elements) {
     RootElements = Elements;
   }
   auto getElements() const { return RootElements; }
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index b4ca5fa2aa62dae..3b432998cf433af 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -664,21 +664,21 @@ void SemaHLSL::handleRootSignatureAttr(Decl *D, const ParsedAttr &AL) {
   if (Lexer.Lex(Tokens))
     return;
 
-  SmallVector<llvm::hlsl::root_signature::RootElement> Elements;
+  SmallVector<llvm::hlsl::rootsig::RootElement> Elements;
   hlsl::RootSignatureParser Parser(Elements, Tokens,
-                             SemaRef.getPreprocessor().getDiagnostics());
+                                   SemaRef.getPreprocessor().getDiagnostics());
   if (Parser.Parse())
     return;
 
   unsigned N = Elements.size();
-  auto RootElements =
-      MutableArrayRef<llvm::hlsl::root_signature::RootElement>(::new (getASTContext()) llvm::hlsl::root_signature::RootElement[N], N);
+  auto RootElements = MutableArrayRef<llvm::hlsl::rootsig::RootElement>(
+      ::new (getASTContext()) llvm::hlsl::rootsig::RootElement[N], N);
   for (unsigned I = 0; I < N; ++I)
     RootElements[I] = Elements[I];
 
   auto *Result = ::new (getASTContext())
       HLSLRootSignatureAttr(getASTContext(), AL, Signature);
-  Result->setElements(ArrayRef<llvm::hlsl::root_signature::RootElement>(RootElements));
+  Result->setElements(ArrayRef<llvm::hlsl::rootsig::RootElement>(RootElements));
   D->addAttr(Result);
 }
 



More information about the llvm-branch-commits mailing list