From ac319a8dd8b7999ffa0342e50e02932c5c8f7a6a Mon Sep 17 00:00:00 2001 From: Joshua Batista Date: Fri, 2 Aug 2024 17:29:36 -0700 Subject: [PATCH] Attach resource attributes to handle within record, instead of record (#101433) This PR attaches the resource attributes, `HLSLResourceAttr` and `HLSLResourceClassAttr`, to the handle contained within such resource classes like `RWBuffer`. CodeGen will now search for fields within HLSL resource decls, and emit previous data based on attributes on the handle member. An AST-dump test was added to verify that the resource attribute is attached to the handle within the resource record decl. Fixes #98556 --------- Co-authored-by: Justin Bogner --- clang/lib/CodeGen/CGHLSLRuntime.cpp | 24 ++++++++------- clang/lib/Sema/HLSLExternalSemaSource.cpp | 30 +++++++++---------- clang/test/AST/HLSL/RWBuffer-AST.hlsl | 4 +-- .../hlsl_resource_handle_attrs.hlsl | 14 +++++++++ 4 files changed, 44 insertions(+), 28 deletions(-) create mode 100644 clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp index 6a6aff594fb0f..defc79683e61f 100644 --- a/clang/lib/CodeGen/CGHLSLRuntime.cpp +++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp @@ -280,18 +280,22 @@ void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) { const auto *RD = Ty->getAsCXXRecordDecl(); if (!RD) return; - const auto *HLSLResAttr = RD->getAttr(); - const auto *HLSLResClassAttr = RD->getAttr(); - if (!HLSLResAttr || !HLSLResClassAttr) - return; + // the resource related attributes are on the handle member + // inside the record decl + for (auto *FD : RD->fields()) { + const auto *HLSLResAttr = FD->getAttr(); + const auto *HLSLResClassAttr = FD->getAttr(); + if (!HLSLResAttr || !HLSLResClassAttr) + continue; - llvm::hlsl::ResourceClass RC = HLSLResClassAttr->getResourceClass(); - llvm::hlsl::ResourceKind RK = HLSLResAttr->getResourceKind(); - bool IsROV = HLSLResAttr->getIsROV(); - llvm::hlsl::ElementType ET = calculateElementType(CGM.getContext(), Ty); + 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()); - addBufferResourceAnnotation(GV, RC, RK, IsROV, ET, Binding); + BufferResBinding Binding(D->getAttr()); + addBufferResourceAnnotation(GV, RC, RK, IsROV, ET, Binding); + } } CGHLSLRuntime::BufferResBinding::BufferResBinding( diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index ca88d138aef5d..6ee90d15d7a6d 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -80,7 +80,7 @@ struct BuiltinTypeDeclBuilder { } BuiltinTypeDeclBuilder & - addMemberVariable(StringRef Name, QualType Type, + addMemberVariable(StringRef Name, QualType Type, llvm::ArrayRef Attrs, AccessSpecifier Access = AccessSpecifier::AS_private) { if (Record->isCompleteDefinition()) return *this; @@ -96,13 +96,16 @@ struct BuiltinTypeDeclBuilder { nullptr, false, InClassInitStyle::ICIS_NoInit); Field->setAccess(Access); Field->setImplicit(true); + for (Attr *A : Attrs) + Field->addAttr(A); Record->addDecl(Field); Fields[Name] = Field; return *this; } BuiltinTypeDeclBuilder & - addHandleMember(AccessSpecifier Access = AccessSpecifier::AS_private) { + addHandleMember(ResourceClass RC, ResourceKind RK, bool IsROV, + AccessSpecifier Access = AccessSpecifier::AS_private) { if (Record->isCompleteDefinition()) return *this; QualType Ty = Record->getASTContext().VoidPtrTy; @@ -112,17 +115,13 @@ struct BuiltinTypeDeclBuilder { Ty = Record->getASTContext().getPointerType( QualType(TTD->getTypeForDecl(), 0)); } - return addMemberVariable("h", Ty, Access); - } - - BuiltinTypeDeclBuilder &annotateHLSLResource(ResourceClass RC, - ResourceKind RK, bool IsROV) { - if (Record->isCompleteDefinition()) - return *this; - Record->addAttr( - HLSLResourceClassAttr::CreateImplicit(Record->getASTContext(), RC)); - Record->addAttr( - HLSLResourceAttr::CreateImplicit(Record->getASTContext(), RK, IsROV)); + // add handle member + llvm::SmallVector Attrs; + Attr *ResourceClassAttr = + HLSLResourceClassAttr::CreateImplicit(Record->getASTContext(), RC); + Attr *ResourceAttr = + HLSLResourceAttr::CreateImplicit(Record->getASTContext(), RK, IsROV); + addMemberVariable("h", Ty, {ResourceClassAttr, ResourceAttr}, Access); return *this; } @@ -489,9 +488,8 @@ static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S, ResourceClass RC, ResourceKind RK, bool IsROV) { return BuiltinTypeDeclBuilder(Decl) - .addHandleMember() - .addDefaultHandleConstructor(S, RC) - .annotateHLSLResource(RC, RK, IsROV); + .addHandleMember(RC, RK, IsROV) + .addDefaultHandleConstructor(S, RC); } void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { diff --git a/clang/test/AST/HLSL/RWBuffer-AST.hlsl b/clang/test/AST/HLSL/RWBuffer-AST.hlsl index e95acb8896ba4..1f6ef60e121ea 100644 --- a/clang/test/AST/HLSL/RWBuffer-AST.hlsl +++ b/clang/test/AST/HLSL/RWBuffer-AST.hlsl @@ -30,9 +30,9 @@ RWBuffer Buffer; // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h 'element_type *' // CHECK-NEXT: HLSLResourceClassAttr 0x{{[0-9A-Fa-f]+}} <> Implicit UAV // CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit TypedBuffer -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit h 'element_type *' // CHECK: CXXMethodDecl 0x{{[0-9A-Fa-f]+}} <> operator[] 'element_type &const (unsigned int) const' // CHECK-NEXT: ParmVarDecl 0x{{[0-9A-Fa-f]+}} <> Idx 'unsigned int' @@ -59,6 +59,6 @@ RWBuffer Buffer; // CHECK: TemplateArgument type 'float' // CHECK-NEXT: BuiltinType 0x{{[0-9A-Fa-f]+}} 'float' // CHECK-NEXT: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final +// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit referenced h 'float *' // CHECK-NEXT: HLSLResourceClassAttr 0x{{[0-9A-Fa-f]+}} <> Implicit UAV // CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit TypedBuffer -// CHECK-NEXT: FieldDecl 0x{{[0-9A-Fa-f]+}} <> implicit referenced h 'float *' diff --git a/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl b/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl new file mode 100644 index 0000000000000..6b7bcbc35b8f8 --- /dev/null +++ b/clang/test/ParserHLSL/hlsl_resource_handle_attrs.hlsl @@ -0,0 +1,14 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s | FileCheck %s + +// CHECK: -ClassTemplateDecl 0x{{[0-9a-f]+}} <> implicit RWBuffer +// CHECK: -CXXRecordDecl 0x{{[0-9a-f]+}} <> implicit class RWBuffer definition +// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <> implicit h 'element_type *' +// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} <> Implicit UAV +// CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <> Implicit TypedBuffer +RasterizerOrderedBuffer > BufferArray3[4] : register(u4, space1); + +// CHECK: -ClassTemplateSpecializationDecl 0x{{[0-9a-f]+}} <> class RWBuffer definition implicit_instantiation +// CHECK: -FieldDecl 0x{{[0-9a-f]+}} <> implicit referenced h 'float *' +// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} <> Implicit UAV +// CHECK: -HLSLResourceAttr 0x{{[0-9a-f]+}} <> Implicit TypedBuffer +RWBuffer Buffer1;