Author: Joshua Batista
Date: 2024-07-12T13:10:34-07:00
New Revision: 5dc371e289584928345f74f560a18a805226b5f8

URL: 
https://github.com/llvm/llvm-project/commit/5dc371e289584928345f74f560a18a805226b5f8
DIFF: 
https://github.com/llvm/llvm-project/commit/5dc371e289584928345f74f560a18a805226b5f8.diff

LOG: [HLSL] Split out resource class data from resource attribute (#98419)

The ability to spell out and specify the resource class is necessary for
testing various resource binding behaviors. Though it is not intended
for users to use this in customized HLSL source code, the ability to
specify the resource class via an attribute is immensely helpful for
writing thorough tests.
This PR introduces a new attribute, hlsl::resource_attribute, that can
only be applied on structs. This attribute only has 1 required argument,
and must be one of:
```
SRV
UAV
CBuffer
Sampler
```
By applying this attribute to a struct, the struct will have the
`HLSLResourceClassAttr` attribute attached to it in the AST
representation, which provides information on the type of resource class
the struct is meant to be.

The resource class data that was originally contained within the
`HLSLResourceAttr` attribute has been removed in favor of this new
attribute, and so certain ast-dump tests need to be modified so that the
same information can be represented via 2 attributes instead of one.

Fixes #98193

---------

Co-authored-by: Damyan Pepper <damy...@microsoft.com>

Added: 
    clang/test/ParserHLSL/hlsl_resource_class_attr.hlsl
    clang/test/ParserHLSL/hlsl_resource_class_attr_error.hlsl

Modified: 
    clang/include/clang/Basic/Attr.td
    clang/include/clang/Sema/SemaHLSL.h
    clang/lib/CodeGen/CGHLSLRuntime.cpp
    clang/lib/Sema/HLSLExternalSemaSource.cpp
    clang/lib/Sema/SemaDeclAttr.cpp
    clang/lib/Sema/SemaHLSL.cpp
    clang/test/AST/HLSL/RWBuffer-AST.hlsl
    clang/test/Misc/pragma-attribute-supported-attributes-list.test

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/Attr.td 
b/clang/include/clang/Basic/Attr.td
index 6d80f0a0a6586..1293d0ddbc117 100644
--- a/clang/include/clang/Basic/Attr.td
+++ b/clang/include/clang/Basic/Attr.td
@@ -4561,11 +4561,7 @@ def HLSLResource : InheritableAttr {
   let Spellings = [];
   let Subjects = SubjectList<[Struct]>;
   let LangOpts = [HLSL];
-  let Args = [
-    EnumArgument<"ResourceClass", "llvm::hlsl::ResourceClass",
-                 /*is_string=*/0, ["SRV", "UAV", "CBuffer", "Sampler"],
-                 ["SRV", "UAV", "CBuffer", "Sampler"],
-                 /*opt=*/0, /*fake=*/0, /*isExternalType=*/1>,
+  let Args = [    
     EnumArgument<
         "ResourceKind", "llvm::hlsl::ResourceKind",
         /*is_string=*/0,
@@ -4589,6 +4585,19 @@ def HLSLResource : InheritableAttr {
   let Documentation = [InternalOnly];
 }
 
+def HLSLResourceClass : InheritableAttr {
+  let Spellings = [CXX11<"hlsl", "resource_class">];
+  let Subjects = SubjectList<[Struct]>;
+  let LangOpts = [HLSL];
+  let Args = [
+       EnumArgument<"ResourceClass", "llvm::hlsl::ResourceClass",
+                                /*is_string=*/true, ["SRV", "UAV", "CBuffer", 
"Sampler"],
+                                ["SRV", "UAV", "CBuffer", "Sampler"],
+                                /*opt=*/0, /*fake=*/0, /*isExternalType=*/1>
+  ];
+  let Documentation = [InternalOnly];
+}
+
 def HLSLGroupSharedAddressSpace : TypeAttr {
   let Spellings = [CustomKeyword<"groupshared">];
   let Subjects = SubjectList<[Var]>;

diff  --git a/clang/include/clang/Sema/SemaHLSL.h 
b/clang/include/clang/Sema/SemaHLSL.h
index 4d6958a1be3e5..2ddbee67c414b 100644
--- a/clang/include/clang/Sema/SemaHLSL.h
+++ b/clang/include/clang/Sema/SemaHLSL.h
@@ -56,6 +56,7 @@ class SemaHLSL : public SemaBase {
   void handleSV_DispatchThreadIDAttr(Decl *D, const ParsedAttr &AL);
   void handlePackOffsetAttr(Decl *D, const ParsedAttr &AL);
   void handleShaderAttr(Decl *D, const ParsedAttr &AL);
+  void handleResourceClassAttr(Decl *D, const ParsedAttr &AL);
   void handleResourceBindingAttr(Decl *D, const ParsedAttr &AL);
   void handleParamModifierAttr(Decl *D, const ParsedAttr &AL);
 

diff  --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp 
b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 55ba21ae2ba69..6a6aff594fb0f 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -280,13 +280,14 @@ void CGHLSLRuntime::annotateHLSLResource(const VarDecl 
*D, GlobalVariable *GV) {
   const auto *RD = Ty->getAsCXXRecordDecl();
   if (!RD)
     return;
-  const auto *Attr = RD->getAttr<HLSLResourceAttr>();
-  if (!Attr)
+  const auto *HLSLResAttr = RD->getAttr<HLSLResourceAttr>();
+  const auto *HLSLResClassAttr = RD->getAttr<HLSLResourceClassAttr>();
+  if (!HLSLResAttr || !HLSLResClassAttr)
     return;
 
-  llvm::hlsl::ResourceClass RC = Attr->getResourceClass();
-  llvm::hlsl::ResourceKind RK = Attr->getResourceKind();
-  bool IsROV = Attr->getIsROV();
+  llvm::hlsl::ResourceClass RC = HLSLResClassAttr->getResourceClass();
+  llvm::hlsl::ResourceKind RK = HLSLResAttr->getResourceKind();
+  bool IsROV = HLSLResAttr->getIsROV();
   llvm::hlsl::ElementType ET = calculateElementType(CGM.getContext(), Ty);
 
   BufferResBinding Binding(D->getAttr<HLSLResourceBindingAttr>());

diff  --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp 
b/clang/lib/Sema/HLSLExternalSemaSource.cpp
index a2b29a7bdf505..7fcf5754f9dd7 100644
--- a/clang/lib/Sema/HLSLExternalSemaSource.cpp
+++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp
@@ -115,12 +115,14 @@ struct BuiltinTypeDeclBuilder {
     return addMemberVariable("h", Ty, Access);
   }
 
-  BuiltinTypeDeclBuilder &annotateResourceClass(ResourceClass RC,
-                                                ResourceKind RK, bool IsROV) {
+  BuiltinTypeDeclBuilder &annotateHLSLResource(ResourceClass RC,
+                                               ResourceKind RK, bool IsROV) {
     if (Record->isCompleteDefinition())
       return *this;
-    Record->addAttr(HLSLResourceAttr::CreateImplicit(Record->getASTContext(),
-                                                     RC, RK, IsROV));
+    Record->addAttr(
+        HLSLResourceClassAttr::CreateImplicit(Record->getASTContext(), RC));
+    Record->addAttr(
+        HLSLResourceAttr::CreateImplicit(Record->getASTContext(), RK, IsROV));
     return *this;
   }
 
@@ -171,7 +173,6 @@ struct BuiltinTypeDeclBuilder {
 
     DeclRefExpr *Fn =
         lookupBuiltinFunction(AST, S, "__builtin_hlsl_create_handle");
-
     Expr *RCExpr = emitResourceClassExpr(AST, RC);
     Expr *Call = CallExpr::Create(AST, Fn, {RCExpr}, AST.VoidPtrTy, VK_PRValue,
                                   SourceLocation(), FPOptionsOverride());
@@ -496,7 +497,7 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl 
*Decl, Sema &S,
   return BuiltinTypeDeclBuilder(Decl)
       .addHandleMember()
       .addDefaultHandleConstructor(S, RC)
-      .annotateResourceClass(RC, RK, IsROV);
+      .annotateHLSLResource(RC, RK, IsROV);
 }
 
 void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() {

diff  --git a/clang/lib/Sema/SemaDeclAttr.cpp b/clang/lib/Sema/SemaDeclAttr.cpp
index f2cd46d1e7c93..20f46c003a464 100644
--- a/clang/lib/Sema/SemaDeclAttr.cpp
+++ b/clang/lib/Sema/SemaDeclAttr.cpp
@@ -7053,6 +7053,9 @@ ProcessDeclAttribute(Sema &S, Scope *scope, Decl *D, 
const ParsedAttr &AL,
   case ParsedAttr::AT_HLSLResourceBinding:
     S.HLSL().handleResourceBindingAttr(D, AL);
     break;
+  case ParsedAttr::AT_HLSLResourceClass:
+    S.HLSL().handleResourceClassAttr(D, AL);
+    break;
   case ParsedAttr::AT_HLSLParamModifier:
     S.HLSL().handleParamModifierAttr(D, AL);
     break;

diff  --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index babb984995f13..9940bc5b4a606 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -437,6 +437,28 @@ void SemaHLSL::handleShaderAttr(Decl *D, const ParsedAttr 
&AL) {
     D->addAttr(NewAttr);
 }
 
+void SemaHLSL::handleResourceClassAttr(Decl *D, const ParsedAttr &AL) {
+  if (!AL.isArgIdent(0)) {
+    Diag(AL.getLoc(), diag::err_attribute_argument_type)
+        << AL << AANT_ArgumentIdentifier;
+    return;
+  }
+
+  IdentifierLoc *Loc = AL.getArgAsIdent(0);
+  StringRef Identifier = Loc->Ident->getName();
+  SourceLocation ArgLoc = Loc->Loc;
+
+  // Validate.
+  llvm::dxil::ResourceClass RC;
+  if (!HLSLResourceClassAttr::ConvertStrToResourceClass(Identifier, RC)) {
+    Diag(ArgLoc, diag::warn_attribute_type_not_supported)
+        << "ResourceClass" << Identifier;
+    return;
+  }
+
+  D->addAttr(HLSLResourceClassAttr::Create(getASTContext(), RC, ArgLoc));
+}
+
 void SemaHLSL::handleResourceBindingAttr(Decl *D, const ParsedAttr &AL) {
   StringRef Space = "space0";
   StringRef Slot = "";

diff  --git a/clang/test/AST/HLSL/RWBuffer-AST.hlsl 
b/clang/test/AST/HLSL/RWBuffer-AST.hlsl
index ac54194be7f0d..cb66a703a4ec9 100644
--- a/clang/test/AST/HLSL/RWBuffer-AST.hlsl
+++ b/clang/test/AST/HLSL/RWBuffer-AST.hlsl
@@ -34,7 +34,8 @@ RWBuffer<float> Buffer;
 // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid 
sloc> implicit class RWBuffer definition
 
 // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
-// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit 
UAV TypedBuffer
+// CHECK-NEXT: HLSLResourceClassAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 
Implicit UAV
+// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit 
TypedBuffer
 // CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> 
implicit h 'element_type *'
 
 // CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc> 
operator[] 'element_type &const (unsigned int) const'
@@ -62,5 +63,6 @@ RWBuffer<float> Buffer;
 // CHECK: TemplateArgument type 'float'
 // CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float'
 // CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit final
-// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit 
UAV TypedBuffer
+// CHECK-NEXT: HLSLResourceClassAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> 
Implicit UAV
+// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> Implicit 
TypedBuffer
 // CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <<invalid sloc>> <invalid sloc>  
implicit referenced h 'float *'

diff  --git a/clang/test/Misc/pragma-attribute-supported-attributes-list.test 
b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
index 28df04c5e33ef..33f9c2f51363c 100644
--- a/clang/test/Misc/pragma-attribute-supported-attributes-list.test
+++ b/clang/test/Misc/pragma-attribute-supported-attributes-list.test
@@ -81,6 +81,7 @@
 // CHECK-NEXT: FunctionReturnThunks (SubjectMatchRule_function)
 // CHECK-NEXT: GNUInline (SubjectMatchRule_function)
 // CHECK-NEXT: HIPManaged (SubjectMatchRule_variable)
+// CHECK-NEXT: HLSLResourceClass (SubjectMatchRule_record_not_is_union)
 // CHECK-NEXT: Hot (SubjectMatchRule_function)
 // CHECK-NEXT: IBAction (SubjectMatchRule_objc_method_is_instance)
 // CHECK-NEXT: IFunc (SubjectMatchRule_function)

diff  --git a/clang/test/ParserHLSL/hlsl_resource_class_attr.hlsl 
b/clang/test/ParserHLSL/hlsl_resource_class_attr.hlsl
new file mode 100644
index 0000000000000..410b4524f1c3d
--- /dev/null
+++ b/clang/test/ParserHLSL/hlsl_resource_class_attr.hlsl
@@ -0,0 +1,32 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o 
- %s | FileCheck %s
+
+
+// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} <col:31> SRV
+struct [[hlsl::resource_class(SRV)]] Eg1 {
+  int i;  
+};
+
+Eg1 e1;
+
+// CHECK: -CXXRecordDecl 0x{{[0-9a-f]+}} <line:13:1, line:15:1> line:13:38 
referenced struct Eg2 definition
+// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} <col:31> UAV
+struct [[hlsl::resource_class(UAV)]] Eg2 {
+  int i;
+};
+Eg2 e2;
+
+// CHECK: -CXXRecordDecl 0x{{[0-9a-f]+}} <line:20:1, line:22:1> line:20:42 
referenced struct Eg3 definition
+// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} <col:31> CBuffer
+struct [[hlsl::resource_class(CBuffer)]] Eg3 {
+  int i;
+}; 
+Eg3 e3;
+
+// CHECK: -CXXRecordDecl 0x{{[0-9a-f]+}} <line:27:1, line:29:1> line:27:42 
referenced struct Eg4 definition
+// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} <col:31> Sampler
+struct [[hlsl::resource_class(Sampler)]] Eg4 {
+  int i;
+};
+Eg4 e4;
+
+RWBuffer<int> In : register(u1);

diff  --git a/clang/test/ParserHLSL/hlsl_resource_class_attr_error.hlsl 
b/clang/test/ParserHLSL/hlsl_resource_class_attr_error.hlsl
new file mode 100644
index 0000000000000..00fcd769760bb
--- /dev/null
+++ b/clang/test/ParserHLSL/hlsl_resource_class_attr_error.hlsl
@@ -0,0 +1,15 @@
+// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.0-compute -x hlsl -ast-dump -o 
- %s -verify
+
+// expected-error@+1{{'resource_class' attribute takes one argument}}
+struct [[hlsl::resource_class()]] Eg1 {
+  int i;  
+};
+
+Eg1 e1;
+
+// expected-warning@+1{{ResourceClass attribute argument not supported: 
gibberish}}
+struct [[hlsl::resource_class(gibberish)]] Eg2 {
+  int i;  
+};
+
+Eg2 e2;


        
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to