diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index d2d9dd24536cb..74efff54254c1 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4549,11 +4549,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, @@ -4577,6 +4573,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(); - if (!Attr) + const auto *HLSLResAttr = RD->getAttr(); + const auto *HLSLResClassAttr = RD->getAttr(); + 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()); 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 Buffer; // CHECK-NEXT: CXXRecordDecl 0x{{[0-9A-Fa-f]+}} <> implicit class RWBuffer definition // CHECK: FinalAttr 0x{{[0-9A-Fa-f]+}} <> Implicit final -// CHECK-NEXT: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit UAV TypedBuffer +// 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' @@ -62,5 +63,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: HLSLResourceAttr 0x{{[0-9A-Fa-f]+}} <> Implicit UAV TypedBuffer +// 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/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]+}} SRV +struct [[hlsl::resource_class(SRV)]] Eg1 { + int i; +}; + +Eg1 e1; + +// CHECK: -CXXRecordDecl 0x{{[0-9a-f]+}} line:13:38 referenced struct Eg2 definition +// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} UAV +struct [[hlsl::resource_class(UAV)]] Eg2 { + int i; +}; +Eg2 e2; + +// CHECK: -CXXRecordDecl 0x{{[0-9a-f]+}} line:20:42 referenced struct Eg3 definition +// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} CBuffer +struct [[hlsl::resource_class(CBuffer)]] Eg3 { + int i; +}; +Eg3 e3; + +// CHECK: -CXXRecordDecl 0x{{[0-9a-f]+}} line:27:42 referenced struct Eg4 definition +// CHECK: -HLSLResourceClassAttr 0x{{[0-9a-f]+}} Sampler +struct [[hlsl::resource_class(Sampler)]] Eg4 { + int i; +}; +Eg4 e4; + +RWBuffer 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;