https://github.com/bob80905 updated https://github.com/llvm/llvm-project/pull/97103
>From c784272b3f66ca06be4ab8e72a0963e5ebb6a869 Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Fri, 28 Jun 2024 12:40:56 -0700 Subject: [PATCH 1/7] update tests, update code --- clang/include/clang/Basic/Attr.td | 2 +- .../clang/Basic/DiagnosticSemaKinds.td | 5 +- clang/include/clang/Sema/SemaHLSL.h | 2 + clang/lib/Sema/HLSLExternalSemaSource.cpp | 26 +- clang/lib/Sema/SemaHLSL.cpp | 232 +++++++++++++++++- .../ast-dump-comment-cbuffe-tbufferr.hlsl | 2 + clang/test/AST/HLSL/cbuffer_tbuffer.hlsl | 6 +- clang/test/AST/HLSL/packoffset.hlsl | 1 + clang/test/AST/HLSL/pch_hlsl_buffer.hlsl | 2 + .../test/AST/HLSL/resource_binding_attr.hlsl | 6 +- .../SemaHLSL/resource_binding_attr_error.hlsl | 21 +- .../resource_binding_attr_error_mismatch.hlsl | 74 ++++++ 12 files changed, 346 insertions(+), 33 deletions(-) create mode 100644 clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl diff --git a/clang/include/clang/Basic/Attr.td b/clang/include/clang/Basic/Attr.td index 452cd1810f653..c3d67e19656da 100644 --- a/clang/include/clang/Basic/Attr.td +++ b/clang/include/clang/Basic/Attr.td @@ -4467,7 +4467,7 @@ def HLSLSV_GroupIndex: HLSLAnnotationAttr { def HLSLResourceBinding: InheritableAttr { let Spellings = [HLSLAnnotation<"register">]; - let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar]>; + let Subjects = SubjectList<[HLSLBufferObj, ExternalGlobalVar], ErrorDiag>; let LangOpts = [HLSL]; let Args = [StringArgument<"Slot">, StringArgument<"Space", 1>]; let Documentation = [HLSLResourceBindingDocs]; diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 96f0c0f0205c2..3bf15ff5f2657 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12303,7 +12303,10 @@ def err_hlsl_missing_semantic_annotation : Error< def err_hlsl_init_priority_unsupported : Error< "initializer priorities are not supported in HLSL">; -def err_hlsl_unsupported_register_type : Error<"invalid resource class specifier '%0' used; expected 'b', 's', 't', or 'u'">; +def err_hlsl_mismatching_register_resource_type_and_name: Error<"invalid register name prefix '%0' for register resource type '%1' (expected %select{'t'|'u'|'b'|'s'}2)">; +def err_hlsl_mismatching_register_builtin_type_and_name: Error<"invalid register name prefix '%0' for '%1' (expected %2)">; +def err_hlsl_unsupported_register_prefix : Error<"invalid resource class specifier '%0' used; expected 't', 'u', 'b', or 's'">; +def err_hlsl_unsupported_register_resource_type : Error<"invalid resource '%0' used">; def err_hlsl_unsupported_register_number : Error<"register number should be an integer">; def err_hlsl_expected_space : Error<"invalid space specifier '%0' used; expected 'space' followed by an integer, like space1">; def warn_hlsl_packoffset_mix : Warning<"cannot mix packoffset elements with nonpackoffset elements in a cbuffer">, diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 4d6958a1be3e5..d3d36d04d1019 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -22,6 +22,7 @@ #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Scope.h" #include "clang/Sema/SemaBase.h" +#include "clang/Sema/Sema.h" #include <initializer_list> namespace clang { @@ -31,6 +32,7 @@ class SemaHLSL : public SemaBase { public: SemaHLSL(Sema &S); + HLSLResourceAttr *mergeHLSLResourceAttr(bool CBuffer); Decl *ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, SourceLocation LBrace); diff --git a/clang/lib/Sema/HLSLExternalSemaSource.cpp b/clang/lib/Sema/HLSLExternalSemaSource.cpp index a2b29a7bdf505..b82cd8373403a 100644 --- a/clang/lib/Sema/HLSLExternalSemaSource.cpp +++ b/clang/lib/Sema/HLSLExternalSemaSource.cpp @@ -490,23 +490,24 @@ void HLSLExternalSemaSource::defineTrivialHLSLTypes() { } /// Set up common members and attributes for buffer types -static BuiltinTypeDeclBuilder setupBufferType(CXXRecordDecl *Decl, Sema &S, - ResourceClass RC, ResourceKind RK, - bool IsROV) { +static BuiltinTypeDeclBuilder setupBufferHandle(CXXRecordDecl *Decl, Sema &S, + ResourceClass RC) { return BuiltinTypeDeclBuilder(Decl) .addHandleMember() - .addDefaultHandleConstructor(S, RC) - .annotateResourceClass(RC, RK, IsROV); + .addDefaultHandleConstructor(S, RC); } void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { CXXRecordDecl *Decl; - Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer") - .addSimpleTemplateParams(*SemaPtr, {"element_type"}) - .Record; + Decl = + BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RWBuffer") + .addSimpleTemplateParams(*SemaPtr, {"element_type"}) + .annotateResourceClass(ResourceClass::UAV, ResourceKind::TypedBuffer, + /*IsROV=*/false) + .Record; + onCompletion(Decl, [this](CXXRecordDecl *Decl) { - setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, - ResourceKind::TypedBuffer, /*IsROV=*/false) + setupBufferHandle(Decl, *SemaPtr, ResourceClass::UAV) .addArraySubscriptOperators() .completeDefinition(); }); @@ -514,10 +515,11 @@ void HLSLExternalSemaSource::defineHLSLTypesWithForwardDeclarations() { Decl = BuiltinTypeDeclBuilder(*SemaPtr, HLSLNamespace, "RasterizerOrderedBuffer") .addSimpleTemplateParams(*SemaPtr, {"element_type"}) + .annotateResourceClass(ResourceClass::UAV, ResourceKind::TypedBuffer, + /*IsROV=*/true) .Record; onCompletion(Decl, [this](CXXRecordDecl *Decl) { - setupBufferType(Decl, *SemaPtr, ResourceClass::UAV, - ResourceKind::TypedBuffer, /*IsROV=*/true) + setupBufferHandle(Decl, *SemaPtr, ResourceClass::UAV) .addArraySubscriptOperators() .completeDefinition(); }); diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index eebe17a5b4bf7..d2b2f163231c9 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -29,6 +29,25 @@ using namespace clang; SemaHLSL::SemaHLSL(Sema &S) : SemaBase(S) {} +HLSLResourceAttr *SemaHLSL::mergeHLSLResourceAttr(bool CBuffer) { + // cbuffer case + if (CBuffer) { + HLSLResourceAttr *attr = HLSLResourceAttr::CreateImplicit( + getASTContext(), llvm::hlsl::ResourceClass::CBuffer, + llvm::hlsl::ResourceKind::CBuffer, + /*IsROV=*/false); + return attr; + } + // tbuffer case + else { + HLSLResourceAttr *attr = HLSLResourceAttr::CreateImplicit( + getASTContext(), llvm::hlsl::ResourceClass::SRV, + llvm::hlsl::ResourceKind::TBuffer, + /*IsROV=*/false); + return attr; + } +} + Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer, SourceLocation KwLoc, IdentifierInfo *Ident, SourceLocation IdentLoc, @@ -38,6 +57,10 @@ Decl *SemaHLSL::ActOnStartBuffer(Scope *BufferScope, bool CBuffer, HLSLBufferDecl *Result = HLSLBufferDecl::Create( getASTContext(), LexicalParent, CBuffer, KwLoc, Ident, IdentLoc, LBrace); + HLSLResourceAttr *NewAttr = mergeHLSLResourceAttr(CBuffer); + if (NewAttr) + Result->addAttr(NewAttr); + SemaRef.PushOnScopeChains(Result, BufferScope); SemaRef.PushDeclContext(BufferScope, Result); @@ -437,7 +460,206 @@ void SemaHLSL::handleShaderAttr(Decl *D, const ParsedAttr &AL) { D->addAttr(NewAttr); } +struct register_binding_flags { + bool resource = false; + bool udt = false; + bool other = false; + bool basic = false; + + bool srv = false; + bool uav = false; + bool cbv = false; + bool sampler = false; + + bool contains_numeric = false; + bool default_globals = false; +}; + +bool isDeclaredWithinCOrTBuffer(const Decl *decl) { + if (!decl) + return false; + + // Traverse up the parent contexts + const DeclContext *context = decl->getDeclContext(); + while (context) { + if (isa<HLSLBufferDecl>(context)) { + return true; + } + context = context->getParent(); + } + + return false; +} + +const HLSLResourceAttr * +getHLSLResourceAttrFromVarDecl(VarDecl *SamplerUAVOrSRV) { + const Type *Ty = SamplerUAVOrSRV->getType()->getPointeeOrArrayElementType(); + if (!Ty) + llvm_unreachable("Resource class must have an element type."); + + if (const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty)) { + /* QualType QT = SamplerUAVOrSRV->getType(); + PrintingPolicy PP = S.getPrintingPolicy(); + std::string typestr = QualType::getAsString(QT.split(), PP); + + S.Diag(ArgLoc, diag::err_hlsl_unsupported_register_resource_type) + << typestr; + return; */ + return nullptr; + } + + const CXXRecordDecl *TheRecordDecl = Ty->getAsCXXRecordDecl(); + if (!TheRecordDecl) + llvm_unreachable("Resource class should have a resource type declaration."); + + if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(TheRecordDecl)) + TheRecordDecl = TDecl->getSpecializedTemplate()->getTemplatedDecl(); + TheRecordDecl = TheRecordDecl->getCanonicalDecl(); + const auto *Attr = TheRecordDecl->getAttr<HLSLResourceAttr>(); + return Attr; +} + +void traverseType(QualType T, register_binding_flags &r) { + if (T->isIntegralOrEnumerationType() || T->isFloatingType()) { + r.contains_numeric = true; + return; + } else if (const RecordType *RT = T->getAs<RecordType>()) { + RecordDecl *SubRD = RT->getDecl(); + if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(SubRD)) { + auto TheRecordDecl = TDecl->getSpecializedTemplate()->getTemplatedDecl(); + TheRecordDecl = TheRecordDecl->getCanonicalDecl(); + const auto *Attr = TheRecordDecl->getAttr<HLSLResourceAttr>(); + llvm::hlsl::ResourceClass DeclResourceClass = Attr->getResourceClass(); + switch (DeclResourceClass) { + case llvm::hlsl::ResourceClass::SRV: { + r.srv = true; + break; + } + case llvm::hlsl::ResourceClass::UAV: { + r.uav = true; + break; + } + case llvm::hlsl::ResourceClass::CBuffer: { + r.cbv = true; + break; + } + case llvm::hlsl::ResourceClass::Sampler: { + r.sampler = true; + break; + } + } + } + + else if (SubRD->isCompleteDefinition()) { + for (auto Field : SubRD->fields()) { + QualType T = Field->getType(); + traverseType(T, r); + } + } + } +} + +void setResourceClassFlagsFromRecordDecl(register_binding_flags &r, + const RecordDecl *RD) { + if (!RD) + return; + + if (RD->isCompleteDefinition()) { + for (auto Field : RD->fields()) { + QualType T = Field->getType(); + traverseType(T, r); + } + } +} + +register_binding_flags HLSLFillRegisterBindingFlags(Sema &S, Decl *D) { + register_binding_flags r; + if (!isDeclaredWithinCOrTBuffer(D)) { + // make sure the type is a basic / numeric type + if (VarDecl *v = dyn_cast<VarDecl>(D)) { + QualType t = v->getType(); + // a numeric variable will inevitably end up in $Globals buffer + if (t->isIntegralType(S.getASTContext()) || t->isFloatingType()) + r.default_globals = true; + } + } + // Cbuffers and Tbuffers are HLSLBufferDecl types + HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D); + // Samplers, UAVs, and SRVs are VarDecl types + VarDecl *SamplerUAVOrSRV = dyn_cast<VarDecl>(D); + + if (CBufferOrTBuffer) { + r.resource = true; + if (CBufferOrTBuffer->isCBuffer()) + r.cbv = true; + else + r.srv = true; + } else if (SamplerUAVOrSRV) { + const HLSLResourceAttr *res_attr = + getHLSLResourceAttrFromVarDecl(SamplerUAVOrSRV); + if (res_attr) { + llvm::hlsl::ResourceClass DeclResourceClass = + res_attr->getResourceClass(); + r.resource = true; + switch (DeclResourceClass) { + case llvm::hlsl::ResourceClass::SRV: { + r.srv = true; + break; + } + case llvm::hlsl::ResourceClass::UAV: { + r.uav = true; + break; + } + case llvm::hlsl::ResourceClass::CBuffer: { + r.cbv = true; + break; + } + case llvm::hlsl::ResourceClass::Sampler: { + r.sampler = true; + break; + } + } + } else { + if (SamplerUAVOrSRV->getType()->isBuiltinType()) + r.basic = true; + else if (SamplerUAVOrSRV->getType()->isAggregateType()) { + r.udt = true; + QualType VarType = SamplerUAVOrSRV->getType(); + if (const RecordType *RT = VarType->getAs<RecordType>()) { + const RecordDecl *RD = RT->getDecl(); + // recurse through members, set appropriate resource class flags. + setResourceClassFlagsFromRecordDecl(r, RD); + } + } else + r.other = true; + } + } else { + llvm_unreachable("unknown decl type"); + } + return r; +} + +static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, + Decl *D, StringRef &Slot) { + + register_binding_flags f = HLSLFillRegisterBindingFlags(S, D); + // Samplers, UAVs, and SRVs are VarDecl types + VarDecl *SamplerUAVOrSRV = dyn_cast<VarDecl>(D); + // Cbuffers and Tbuffers are HLSLBufferDecl types + HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D); + if (!SamplerUAVOrSRV && !CBufferOrTBuffer) + return; + + // TODO: emit diagnostic code based on the flags set in f. +} + + void SemaHLSL::handleResourceBindingAttr(Decl *D, const ParsedAttr &AL) { + if (dyn_cast<VarDecl>(D)) { + if (SemaRef.RequireCompleteType(D->getBeginLoc(), cast<ValueDecl>(D)->getType(), + diag::err_incomplete_type)) + return; + } StringRef Space = "space0"; StringRef Slot = ""; @@ -470,13 +692,15 @@ void SemaHLSL::handleResourceBindingAttr(Decl *D, const ParsedAttr &AL) { // Validate. if (!Slot.empty()) { switch (Slot[0]) { + case 't': case 'u': case 'b': case 's': - case 't': + case 'c': + case 'i': break; default: - Diag(ArgLoc, diag::err_hlsl_unsupported_register_type) + Diag(ArgLoc, diag::err_hlsl_unsupported_register_prefix) << Slot.substr(0, 1); return; } @@ -500,8 +724,8 @@ void SemaHLSL::handleResourceBindingAttr(Decl *D, const ParsedAttr &AL) { return; } - // FIXME: check reg type match decl. Issue - // https://github.com/llvm/llvm-project/issues/57886. + DiagnoseHLSLResourceRegType(SemaRef, ArgLoc, D, Slot); + HLSLResourceBindingAttr *NewAttr = HLSLResourceBindingAttr::Create(getASTContext(), Slot, Space, AL); if (NewAttr) diff --git a/clang/test/AST/HLSL/ast-dump-comment-cbuffe-tbufferr.hlsl b/clang/test/AST/HLSL/ast-dump-comment-cbuffe-tbufferr.hlsl index a98dc0f4ce431..727d505471bcb 100644 --- a/clang/test/AST/HLSL/ast-dump-comment-cbuffe-tbufferr.hlsl +++ b/clang/test/AST/HLSL/ast-dump-comment-cbuffe-tbufferr.hlsl @@ -38,12 +38,14 @@ tbuffer B { } // AST:HLSLBufferDecl {{.*}}:11:1, line:20:1> line:11:9 cbuffer A +// AST-NEXT:-HLSLResourceAttr {{.*}} <<invalid sloc>> Implicit CBuffer CBuffer // AST-NEXT:FullComment {{.*}}<line:10:4, col:17> // AST-NEXT:`-ParagraphComment {{.*}}<col:4, col:17> // AST-NEXT:`-TextComment {{.*}}<col:4, col:17> Text=" CBuffer decl." // AST-NEXT:-VarDecl {{.*}}<line:15:5, col:11> col:11 a 'float' // AST-NEXT:`-VarDecl {{.*}}<line:19:5, col:9> col:9 b 'int' // AST-NEXT:HLSLBufferDecl {{.*}}<line:29:1, line:38:1> line:29:9 tbuffer B +// AST-NEXT:-HLSLResourceAttr {{.*}} <<invalid sloc>> Implicit SRV TBuffer // AST-NEXT:-FullComment {{.*}}<line:28:4, col:17> // AST-NEXT: `-ParagraphComment {{.*}}<col:4, col:17> // AST-NEXT: `-TextComment {{.*}}<col:4, col:17> Text=" TBuffer decl." diff --git a/clang/test/AST/HLSL/cbuffer_tbuffer.hlsl b/clang/test/AST/HLSL/cbuffer_tbuffer.hlsl index 7204dcd16e0a9..a67688d510ea6 100644 --- a/clang/test/AST/HLSL/cbuffer_tbuffer.hlsl +++ b/clang/test/AST/HLSL/cbuffer_tbuffer.hlsl @@ -1,12 +1,14 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s | FileCheck %s -// CHECK:HLSLBufferDecl 0x[[CB:[0-9a-f]+]] {{.*}} line:5:9 cbuffer CB +// CHECK:HLSLBufferDecl 0x[[CB:[0-9a-f]+]] {{.*}} line:6:9 cbuffer CB +// CHECK-NEXT:HLSLResourceAttr {{.*}} <<invalid sloc>> Implicit CBuffer CBuffer // CHECK-NEXT:VarDecl 0x[[A:[0-9a-f]+]] {{.*}} col:9 used a 'float' cbuffer CB { float a; } -// CHECK:HLSLBufferDecl 0x[[TB:[0-9a-f]+]] {{.*}} line:11:9 tbuffer TB +// CHECK:HLSLBufferDecl 0x[[TB:[0-9a-f]+]] {{.*}} line:13:9 tbuffer TB +// CHECK-NEXT:HLSLResourceAttr {{.*}} <<invalid sloc>> Implicit SRV TBuffer // CHECK-NEXT:VarDecl 0x[[B:[0-9a-f]+]] {{.*}} col:9 used b 'float' tbuffer TB { float b; diff --git a/clang/test/AST/HLSL/packoffset.hlsl b/clang/test/AST/HLSL/packoffset.hlsl index 060288c2f7f76..1dc99620c55c4 100644 --- a/clang/test/AST/HLSL/packoffset.hlsl +++ b/clang/test/AST/HLSL/packoffset.hlsl @@ -4,6 +4,7 @@ // CHECK: HLSLBufferDecl {{.*}} cbuffer A cbuffer A { + // CHECK-NEXT:-HLSLResourceAttr {{.*}} <<invalid sloc>> line:5:9 cbuffer A // CHECK-NEXT: VarDecl {{.*}} A1 'float4' // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 0 float4 A1 : packoffset(c); diff --git a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl index e9a6ea1a16312..e264241e62e92 100644 --- a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl +++ b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl @@ -17,8 +17,10 @@ float foo() { } // Make sure cbuffer/tbuffer works for PCH. // CHECK:HLSLBufferDecl 0x{{[0-9a-f]+}} <{{.*}}:7:1, line:9:1> line:7:9 imported <undeserialized declarations> cbuffer A +// CHECK-NEXT:HLSLResourceAttr {{.*}} <<invalid sloc>> Implicit CBuffer CBuffer // CHECK-NEXT:`-VarDecl 0x[[A:[0-9a-f]+]] <line:8:3, col:9> col:9 imported used a 'float' // CHECK-NEXT:HLSLBufferDecl 0x{{[0-9a-f]+}} <line:11:1, line:13:1> line:11:9 imported <undeserialized declarations> tbuffer B +// CHECK-NEXT:HLSLResourceAttr {{.*}} <<invalid sloc>> Implicit SRV TBuffer // CHECK-NEXT:`-VarDecl 0x[[B:[0-9a-f]+]] <line:12:3, col:9> col:9 imported used b 'float' // CHECK-NEXT:FunctionDecl 0x{{[0-9a-f]+}} <line:15:1, line:17:1> line:15:7 imported foo 'float ()' // CHECK-NEXT:CompoundStmt 0x{{[0-9a-f]+}} <col:13, line:17:1> diff --git a/clang/test/AST/HLSL/resource_binding_attr.hlsl b/clang/test/AST/HLSL/resource_binding_attr.hlsl index 71900f2dbda55..9752494f5adc9 100644 --- a/clang/test/AST/HLSL/resource_binding_attr.hlsl +++ b/clang/test/AST/HLSL/resource_binding_attr.hlsl @@ -1,13 +1,15 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -ast-dump -o - %s | FileCheck %s -// CHECK:HLSLBufferDecl 0x[[CB:[0-9a-f]+]] {{.*}} line:6:9 cbuffer CB +// CHECK:HLSLBufferDecl 0x[[CB:[0-9a-f]+]] {{.*}} line:7:9 cbuffer CB +// CHECK-NEXT:HLSLResourceAttr 0x[[CB:[0-9a-f]+]] {{.*}} Implicit CBuffer CBuffer // CHECK-NEXT:HLSLResourceBindingAttr 0x{{[0-9a-f]+}} <col:14> "b3" "space2" // CHECK-NEXT:VarDecl 0x[[A:[0-9a-f]+]] {{.*}} col:9 used a 'float' cbuffer CB : register(b3, space2) { float a; } -// CHECK:HLSLBufferDecl 0x[[TB:[0-9a-f]+]] {{.*}} line:13:9 tbuffer TB +// CHECK:HLSLBufferDecl 0x[[TB:[0-9a-f]+]] {{.*}} line:15:9 tbuffer TB +// CHECK-NEXT:HLSLResourceAttr 0x[[CB:[0-9a-f]+]] {{.*}} Implicit SRV TBuffer // CHECK-NEXT:HLSLResourceBindingAttr 0x{{[0-9a-f]+}} <col:14> "t2" "space1" // CHECK-NEXT:VarDecl 0x[[B:[0-9a-f]+]] {{.*}} col:9 used b 'float' tbuffer TB : register(t2, space1) { diff --git a/clang/test/SemaHLSL/resource_binding_attr_error.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error.hlsl index 2f8aa098db701..58a1f3f1f64d7 100644 --- a/clang/test/SemaHLSL/resource_binding_attr_error.hlsl +++ b/clang/test/SemaHLSL/resource_binding_attr_error.hlsl @@ -1,9 +1,9 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify -// expected-error@+1 {{invalid resource class specifier 'c' used; expected 'b', 's', 't', or 'u'}} +// FIXME: emit a diagnostic because float doesn't match the 'c' register type float a : register(c0, space1); -// expected-error@+1 {{invalid resource class specifier 'i' used; expected 'b', 's', 't', or 'u'}} +// FIXME: emit a diagnostic because cbuffer doesn't match the 'i' register type cbuffer b : register(i0) { } @@ -33,28 +33,27 @@ cbuffer C : register(b 2) {} // expected-error@+1 {{wrong argument format for hlsl attribute, use space3 instead}} cbuffer D : register(b 2, space 3) {} -// expected-warning@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} +// expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} static RWBuffer<float> U : register(u5); void foo() { - // expected-warning@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} + // expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} RWBuffer<float> U : register(u3); } void foo2() { - // expected-warning@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} + // expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} extern RWBuffer<float> U2 : register(u5); } -// FIXME: expect-error once fix https://github.com/llvm/llvm-project/issues/57886. + +// FIXME: emit a diagnostic because float doesn't match the 'u' register type float b : register(u0, space1); -// expected-warning@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} +// expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} void bar(RWBuffer<float> U : register(u3)) { } -struct S { - // FIXME: generate better error when support semantic on struct field. - // See https://github.com/llvm/llvm-project/issues/57889. - // expected-warning@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} +struct S { + // expected-error@+1 {{'register' attribute only applies to cbuffer/tbuffer and external global variables}} RWBuffer<float> U : register(u3); }; diff --git a/clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl new file mode 100644 index 0000000000000..b47171f878436 --- /dev/null +++ b/clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify + + +// expected-error@+1 {{invalid register name prefix 'b' for register resource type 'RWBuffer' (expected 'u')}} +RWBuffer<int> a : register(b2, space1); + +// expected-error@+1 {{invalid register name prefix 't' for register resource type 'RWBuffer' (expected 'u')}} +RWBuffer<int> b : register(t2, space1); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'Texture1D' (expected 't')}} +// NOT YET IMPLEMENTED Texture1D<float> tex : register(u3); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 's' for register type 'Texture2D' (expected 't')}} +// NOT YET IMPLEMENTED Texture2D<float> Texture : register(s0); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'Texture2DMS' (expected 't')}} +// NOT YET IMPLEMENTED Texture2DMS<float4, 4> T2DMS_t2 : register(u2) + +// NOT YET IMPLEMENTED : {{invalid register name prefix 't' for register type 'RWTexture3D' (expected 'u')}} +// NOT YET IMPLEMENTED RWTexture3D<float4> RWT3D_u1 : register(t1) + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'b' for register type 'TextureCube' (expected 't')}} +// NOT YET IMPLEMENTED TextureCube <float> t8 : register(b8); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'b' for register type 'TextureCubeArray' (expected 't')}} +// NOT YET IMPLEMENTED TextureCubeArray TCubeArray_t2 : register(b2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'b' for register type 'Texture1DArray' (expected 't')}} +// NOT YET IMPLEMENTED Texture1DArray T1DArray_t2 : register(b2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'B' for register type 'Texture2DArray' (expected 't')}} +// NOT YET IMPLEMENTED Texture2DArray T2DArray_b2 : register(B2); + + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'Texture2DMSArray' (expected 't')}} +// NOT YET IMPLEMENTED Texture2DMSArray<float4> msTextureArray : register(u2, space2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'TextureCubeArray' (expected 't')}} +// NOT YET IMPLEMENTED TextureCubeArray TCubeArray_f2 : register(u2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'TypedBuffer' (expected 't')}} +// NOT YET IMPLEMENTED TypedBuffer tbuf : register(u2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'RawBuffer' (expected 't')}} +// NOT YET IMPLEMENTED RawBuffer rbuf : register(u2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 't' for register type 'StructuredBuffer' (expected 'u')}} +// NOT YET IMPLEMENTED StructuredBuffer ROVStructuredBuff_t2 : register(T2); + +// expected-error@+1 {{invalid register name prefix 's' for register resource type 'cbuffer' (expected 'b')}} +cbuffer f : register(s2, space1) {} + +// NOT YET IMPLEMENTED : {{invalid register name prefix 't' for register type 'Sampler' (expected 's')}} +// Can this type just be Sampler instead of SamplerState? +// NOT YET IMPLEMENTED SamplerState MySampler : register(t3, space1); + +// expected-error@+1 {{invalid register name prefix 's' for register resource type 'tbuffer' (expected 't')}} +tbuffer f : register(s2, space1) {} + +// NOT YET IMPLEMENTED : RTAccelerationStructure doesn't have any example tests in DXC + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'FeedbackTexture2D' (expected 't')}} +// NOT YET IMPLEMENTED FeedbackTexture2D<float> FBTex2D[3][] : register(u0, space26); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'FeedbackTexture2DArray' (expected 't')}} +// NOT YET IMPLEMENTED FeedbackTexture2DArray<float> FBTex2DArr[3][2][] : register(u0, space27); + + +// empty binding prefix cases: +// expected-error@+1 {{expected identifier}} +RWBuffer<int> c: register(); + +// expected-error@+1 {{expected identifier}} +RWBuffer<int> d: register(""); >From 8e20fce2dbb0e88bc6c286815d36339f37d34d80 Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Fri, 28 Jun 2024 16:18:43 -0700 Subject: [PATCH 2/7] remove mismatch test, will be applied in step 2 PR. update packoffset --- clang/test/AST/HLSL/packoffset.hlsl | 2 +- .../resource_binding_attr_error_mismatch.hlsl | 74 ------------------- 2 files changed, 1 insertion(+), 75 deletions(-) delete mode 100644 clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl diff --git a/clang/test/AST/HLSL/packoffset.hlsl b/clang/test/AST/HLSL/packoffset.hlsl index 1dc99620c55c4..9deb63caa500a 100644 --- a/clang/test/AST/HLSL/packoffset.hlsl +++ b/clang/test/AST/HLSL/packoffset.hlsl @@ -4,7 +4,7 @@ // CHECK: HLSLBufferDecl {{.*}} cbuffer A cbuffer A { - // CHECK-NEXT:-HLSLResourceAttr {{.*}} <<invalid sloc>> line:5:9 cbuffer A + // CHECK-NEXT:-HLSLResourceAttr {{.*}} <<invalid sloc>> Implicit CBuffer CBuffer // CHECK-NEXT: VarDecl {{.*}} A1 'float4' // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 0 float4 A1 : packoffset(c); diff --git a/clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl deleted file mode 100644 index b47171f878436..0000000000000 --- a/clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl +++ /dev/null @@ -1,74 +0,0 @@ -// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify - - -// expected-error@+1 {{invalid register name prefix 'b' for register resource type 'RWBuffer' (expected 'u')}} -RWBuffer<int> a : register(b2, space1); - -// expected-error@+1 {{invalid register name prefix 't' for register resource type 'RWBuffer' (expected 'u')}} -RWBuffer<int> b : register(t2, space1); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'Texture1D' (expected 't')}} -// NOT YET IMPLEMENTED Texture1D<float> tex : register(u3); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 's' for register type 'Texture2D' (expected 't')}} -// NOT YET IMPLEMENTED Texture2D<float> Texture : register(s0); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'Texture2DMS' (expected 't')}} -// NOT YET IMPLEMENTED Texture2DMS<float4, 4> T2DMS_t2 : register(u2) - -// NOT YET IMPLEMENTED : {{invalid register name prefix 't' for register type 'RWTexture3D' (expected 'u')}} -// NOT YET IMPLEMENTED RWTexture3D<float4> RWT3D_u1 : register(t1) - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'b' for register type 'TextureCube' (expected 't')}} -// NOT YET IMPLEMENTED TextureCube <float> t8 : register(b8); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'b' for register type 'TextureCubeArray' (expected 't')}} -// NOT YET IMPLEMENTED TextureCubeArray TCubeArray_t2 : register(b2); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'b' for register type 'Texture1DArray' (expected 't')}} -// NOT YET IMPLEMENTED Texture1DArray T1DArray_t2 : register(b2); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'B' for register type 'Texture2DArray' (expected 't')}} -// NOT YET IMPLEMENTED Texture2DArray T2DArray_b2 : register(B2); - - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'Texture2DMSArray' (expected 't')}} -// NOT YET IMPLEMENTED Texture2DMSArray<float4> msTextureArray : register(u2, space2); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'TextureCubeArray' (expected 't')}} -// NOT YET IMPLEMENTED TextureCubeArray TCubeArray_f2 : register(u2); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'TypedBuffer' (expected 't')}} -// NOT YET IMPLEMENTED TypedBuffer tbuf : register(u2); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'RawBuffer' (expected 't')}} -// NOT YET IMPLEMENTED RawBuffer rbuf : register(u2); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 't' for register type 'StructuredBuffer' (expected 'u')}} -// NOT YET IMPLEMENTED StructuredBuffer ROVStructuredBuff_t2 : register(T2); - -// expected-error@+1 {{invalid register name prefix 's' for register resource type 'cbuffer' (expected 'b')}} -cbuffer f : register(s2, space1) {} - -// NOT YET IMPLEMENTED : {{invalid register name prefix 't' for register type 'Sampler' (expected 's')}} -// Can this type just be Sampler instead of SamplerState? -// NOT YET IMPLEMENTED SamplerState MySampler : register(t3, space1); - -// expected-error@+1 {{invalid register name prefix 's' for register resource type 'tbuffer' (expected 't')}} -tbuffer f : register(s2, space1) {} - -// NOT YET IMPLEMENTED : RTAccelerationStructure doesn't have any example tests in DXC - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'FeedbackTexture2D' (expected 't')}} -// NOT YET IMPLEMENTED FeedbackTexture2D<float> FBTex2D[3][] : register(u0, space26); - -// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'FeedbackTexture2DArray' (expected 't')}} -// NOT YET IMPLEMENTED FeedbackTexture2DArray<float> FBTex2DArr[3][2][] : register(u0, space27); - - -// empty binding prefix cases: -// expected-error@+1 {{expected identifier}} -RWBuffer<int> c: register(); - -// expected-error@+1 {{expected identifier}} -RWBuffer<int> d: register(""); >From 8e19f3dd702e0e65b991b2a741405c224a066ba0 Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Fri, 28 Jun 2024 16:29:20 -0700 Subject: [PATCH 3/7] clang-format --- clang/include/clang/Sema/SemaHLSL.h | 2 +- clang/lib/Sema/SemaHLSL.cpp | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index d3d36d04d1019..4e2a93209386e 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -21,8 +21,8 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Scope.h" -#include "clang/Sema/SemaBase.h" #include "clang/Sema/Sema.h" +#include "clang/Sema/SemaBase.h" #include <initializer_list> namespace clang { diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index d2b2f163231c9..8b6ecc6b7d992 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -546,7 +546,7 @@ void traverseType(QualType T, register_binding_flags &r) { case llvm::hlsl::ResourceClass::Sampler: { r.sampler = true; break; - } + } } } @@ -617,7 +617,7 @@ register_binding_flags HLSLFillRegisterBindingFlags(Sema &S, Decl *D) { case llvm::hlsl::ResourceClass::Sampler: { r.sampler = true; break; - } + } } } else { if (SamplerUAVOrSRV->getType()->isBuiltinType()) @@ -653,11 +653,11 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, // TODO: emit diagnostic code based on the flags set in f. } - void SemaHLSL::handleResourceBindingAttr(Decl *D, const ParsedAttr &AL) { - if (dyn_cast<VarDecl>(D)) { - if (SemaRef.RequireCompleteType(D->getBeginLoc(), cast<ValueDecl>(D)->getType(), - diag::err_incomplete_type)) + if (dyn_cast<VarDecl>(D)) { + if (SemaRef.RequireCompleteType(D->getBeginLoc(), + cast<ValueDecl>(D)->getType(), + diag::err_incomplete_type)) return; } StringRef Space = "space0"; >From ba058afa3c79185396351cfe9d80ff6aa6ac3318 Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Mon, 1 Jul 2024 10:36:02 -0700 Subject: [PATCH 4/7] remove unnecessary header --- clang/include/clang/Sema/SemaHLSL.h | 1 - 1 file changed, 1 deletion(-) diff --git a/clang/include/clang/Sema/SemaHLSL.h b/clang/include/clang/Sema/SemaHLSL.h index 4e2a93209386e..d72e136bd5457 100644 --- a/clang/include/clang/Sema/SemaHLSL.h +++ b/clang/include/clang/Sema/SemaHLSL.h @@ -21,7 +21,6 @@ #include "clang/Basic/IdentifierTable.h" #include "clang/Basic/SourceLocation.h" #include "clang/Sema/Scope.h" -#include "clang/Sema/Sema.h" #include "clang/Sema/SemaBase.h" #include <initializer_list> >From c02869d8be071354dd26d3bb8af62056a0f3a2ee Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Mon, 1 Jul 2024 17:55:03 -0700 Subject: [PATCH 5/7] full implementation --- .../clang/Basic/DiagnosticSemaKinds.td | 10 ++ clang/lib/Sema/SemaHLSL.cpp | 162 +++++++++++++++++- 2 files changed, 170 insertions(+), 2 deletions(-) diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index 3bf15ff5f2657..a4994922b15c9 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -12303,6 +12303,16 @@ def err_hlsl_missing_semantic_annotation : Error< def err_hlsl_init_priority_unsupported : Error< "initializer priorities are not supported in HLSL">; +def err_hlsl_mismatching_register_type_and_variable_type: Error<"unsupported resource register binding '%select{t|u|b|s}1' on variable of type '%0'">; +def err_hlsl_unsupported_register_type_and_variable_type: Error<"register binding type '%1' not supported for variable of type '%0'">; +def err_hlsl_mismatching_register_type_and_resource_type: Error<"%select{srv|uav|cbv|sampler}2 type '%0' requires register type '%select{t|u|b|s}2', but register type '%1' was used">; +def err_hlsl_unsupported_register_type_and_resource_type: Error<"invalid register type '%0' used; expected 't', 'u', 'b', or 's'">; +def err_hlsl_conflicting_register_annotations: Error<"conflicting register annotations: %0 and %0">; +def warn_hlsl_deprecated_register_type_b: Warning<"deprecated legacy bool constant register binding 'b' used. 'b' is only used for constant buffer resource binding">; +def warn_hlsl_deprecated_register_type_i: Warning<"deprecated legacy int constant register binding 'i' used">; +def warn_hlsl_register_type_c_not_in_global_scope: Warning<"register binding 'c' ignored inside cbuffer/tbuffer declarations; use pack_offset instead">; +def warn_hlsl_UDT_missing_resource_type_member: Warning<"variable of type '%0' bound to register type '%1' does not contain a matching '%select{srv|uav|cbv|sampler}2' resource">; +def warn_hlsl_UDT_missing_basic_type: Warning<"register 'c' used on type with no contents to allocate in a constant buffer">; def err_hlsl_mismatching_register_resource_type_and_name: Error<"invalid register name prefix '%0' for register resource type '%1' (expected %select{'t'|'u'|'b'|'s'}2)">; def err_hlsl_mismatching_register_builtin_type_and_name: Error<"invalid register name prefix '%0' for '%1' (expected %2)">; def err_hlsl_unsupported_register_prefix : Error<"invalid resource class specifier '%0' used; expected 't', 'u', 'b', or 's'">; diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 8b6ecc6b7d992..0cdce9e53bd93 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -639,10 +639,26 @@ register_binding_flags HLSLFillRegisterBindingFlags(Sema &S, Decl *D) { return r; } +static void ValidateMultipleRegisterAnnotations(Sema &S, Decl *D, + StringRef &Slot) { + std::set<std::string> s; // store unique register type + numbers + for (auto it = D->attr_begin(); it != D->attr_end(); ++it) { + + if (HLSLResourceBindingAttr *attr = + dyn_cast<HLSLResourceBindingAttr>(*it)) { + std::string regInfo(Slot); + auto p = s.insert(regInfo); + if (!p.second) { + S.Diag(attr->getLoc(), diag::err_hlsl_conflicting_register_annotations) + << Slot.substr(0, 1); + } + } + } +} + static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, Decl *D, StringRef &Slot) { - register_binding_flags f = HLSLFillRegisterBindingFlags(S, D); // Samplers, UAVs, and SRVs are VarDecl types VarDecl *SamplerUAVOrSRV = dyn_cast<VarDecl>(D); // Cbuffers and Tbuffers are HLSLBufferDecl types @@ -650,7 +666,149 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, if (!SamplerUAVOrSRV && !CBufferOrTBuffer) return; - // TODO: emit diagnostic code based on the flags set in f. + register_binding_flags f = HLSLFillRegisterBindingFlags(S, D); + assert((int)f.other + (int)f.resource + (int)f.basic + (int)f.udt == 1 && "only one resource analysis result should be expected"); + + // get the variable type + std::string typestr; + if (SamplerUAVOrSRV) { + QualType QT = SamplerUAVOrSRV->getType(); + PrintingPolicy PP = S.getPrintingPolicy(); + typestr = QualType::getAsString(QT.split(), PP); + } else + typestr = CBufferOrTBuffer->isCBuffer() ? "cbuffer" : "tbuffer"; + + + // first, if "other" is set, emit an error + if (f.other) { + S.Diag(ArgLoc, diag::err_hlsl_unsupported_register_type_and_variable_type) + << Slot << typestr; + } + + // next, if multiple register annotations exist, check that none conflict. + ValidateMultipleRegisterAnnotations(S, D, Slot); + + // next, if resource is set, make sure the register type in the register annotation + // is compatible with the variable's resource type. + if (f.resource) { + VarDecl *VD = dyn_cast<VarDecl>(D); + + const HLSLResourceAttr *res_attr = + getHLSLResourceAttrFromVarDecl(VD); + assert(res_attr && "any decl that set the resource flag on analysis should have a resource attribute attached."); + llvm::hlsl::ResourceClass DeclResourceClass = res_attr->getResourceClass(); + switch (DeclResourceClass) { + case llvm::hlsl::ResourceClass::SRV: { + if (!f.srv) { + S.Diag( + res_attr->getLoc(), diag::err_hlsl_mismatching_register_type_and_resource_type) + << typestr << Slot[0] << 0 /*srv*/; + } + break; + } + case llvm::hlsl::ResourceClass::UAV: { + if (!f.uav) { + S.Diag(res_attr->getLoc(), + diag::err_hlsl_mismatching_register_type_and_resource_type) + << typestr << Slot[0] << 1 /*uav*/; + } + break; + } + case llvm::hlsl::ResourceClass::CBuffer: { + if (!f.cbv) { + S.Diag(res_attr->getLoc(), + diag::err_hlsl_mismatching_register_type_and_resource_type) + << typestr << Slot[0] << 2 /*cbv*/; + } + break; + } + case llvm::hlsl::ResourceClass::Sampler: { + if (!f.sampler) { + S.Diag(res_attr->getLoc(), + diag::err_hlsl_mismatching_register_type_and_resource_type) + << typestr << Slot[0] << 3 /*sampler*/; + } + break; + } + } + } + + // next, handle diagnostics for when the "basic" flag is set, + // including the legacy "i" and "b" register types. + if (f.basic) { + if (f.default_globals) { + if (Slot[0] == 'b') + S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b); + if (Slot[0] == 'i') + S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i); + } + + else if (Slot[0] == 'c') { + if (!f.default_globals){ + S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_not_in_global_scope); + } + } + else if (Slot[0] == 't') + S.Diag(ArgLoc, diag::err_hlsl_mismatching_register_type_and_variable_type) << 0 << typestr; + else if (Slot[0] == 'u') + S.Diag(ArgLoc, + diag::err_hlsl_mismatching_register_type_and_variable_type) + << 1 << typestr; + else if (Slot[0] == 's') + S.Diag(ArgLoc, + diag::err_hlsl_mismatching_register_type_and_variable_type) + << 3 << typestr; + // any other register type should emit err_hlsl_unsupported_register_type_and_variable_type + else { + S.Diag(ArgLoc, diag::err_hlsl_unsupported_register_type_and_variable_type) + << Slot[0] << typestr; + } + } + + // finally, we handle the udt case + + if (f.udt) { + for (auto it = D->attr_begin(); it != D->attr_end(); ++it) { + if (HLSLResourceBindingAttr *attr = + dyn_cast<HLSLResourceBindingAttr>(*it)) { + llvm::StringRef registerTypeSlotRef = attr->getSlot(); + std::string registerTypeSlot( + registerTypeSlotRef); + if (registerTypeSlot[0] == 't') { + if (!f.srv) { + S.Diag(attr->getLoc(), + diag::warn_hlsl_UDT_missing_resource_type_member) + << typestr << "t" + << 0; + } + } else if (registerTypeSlot[0] == 'u') { + if (!f.uav) { + S.Diag(attr->getLoc(), + diag::warn_hlsl_UDT_missing_resource_type_member) + << typestr << "u" << 1; + } + } else if (registerTypeSlot[0] == 'b') { + if (!f.cbv) { + S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_resource_type_member) + << typestr << "b" << 2; + } + } else if (registerTypeSlot[0] == 's') { + if (!f.sampler) { + S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_resource_type_member) + << typestr << "s" << 3; + } + } else if (registerTypeSlot[0] == 'c') { + if (!f.srv) + S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_basic_type); + } + else { + S.Diag(attr->getLoc(), + diag::err_hlsl_unsupported_register_type_and_variable_type) + << registerTypeSlot[0] << typestr; + } + } + } + } } void SemaHLSL::handleResourceBindingAttr(Decl *D, const ParsedAttr &AL) { >From b75f9fb7356b9c4539cad609957b4f2773c42216 Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Mon, 1 Jul 2024 17:55:33 -0700 Subject: [PATCH 6/7] clang format --- clang/lib/Sema/SemaHLSL.cpp | 74 ++++++++++++++++++------------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 0cdce9e53bd93..8cd793ceff4c9 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -667,7 +667,8 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, return; register_binding_flags f = HLSLFillRegisterBindingFlags(S, D); - assert((int)f.other + (int)f.resource + (int)f.basic + (int)f.udt == 1 && "only one resource analysis result should be expected"); + assert((int)f.other + (int)f.resource + (int)f.basic + (int)f.udt == 1 && + "only one resource analysis result should be expected"); // get the variable type std::string typestr; @@ -675,33 +676,32 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, QualType QT = SamplerUAVOrSRV->getType(); PrintingPolicy PP = S.getPrintingPolicy(); typestr = QualType::getAsString(QT.split(), PP); - } else + } else typestr = CBufferOrTBuffer->isCBuffer() ? "cbuffer" : "tbuffer"; - // first, if "other" is set, emit an error - if (f.other) { + if (f.other) { S.Diag(ArgLoc, diag::err_hlsl_unsupported_register_type_and_variable_type) << Slot << typestr; } // next, if multiple register annotations exist, check that none conflict. ValidateMultipleRegisterAnnotations(S, D, Slot); - - // next, if resource is set, make sure the register type in the register annotation - // is compatible with the variable's resource type. + + // next, if resource is set, make sure the register type in the register + // annotation is compatible with the variable's resource type. if (f.resource) { VarDecl *VD = dyn_cast<VarDecl>(D); - const HLSLResourceAttr *res_attr = - getHLSLResourceAttrFromVarDecl(VD); - assert(res_attr && "any decl that set the resource flag on analysis should have a resource attribute attached."); + const HLSLResourceAttr *res_attr = getHLSLResourceAttrFromVarDecl(VD); + assert(res_attr && "any decl that set the resource flag on analysis should " + "have a resource attribute attached."); llvm::hlsl::ResourceClass DeclResourceClass = res_attr->getResourceClass(); switch (DeclResourceClass) { case llvm::hlsl::ResourceClass::SRV: { if (!f.srv) { - S.Diag( - res_attr->getLoc(), diag::err_hlsl_mismatching_register_type_and_resource_type) + S.Diag(res_attr->getLoc(), + diag::err_hlsl_mismatching_register_type_and_resource_type) << typestr << Slot[0] << 0 /*srv*/; } break; @@ -732,54 +732,51 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, } } } - + // next, handle diagnostics for when the "basic" flag is set, // including the legacy "i" and "b" register types. if (f.basic) { if (f.default_globals) { if (Slot[0] == 'b') - S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b); + S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_b); if (Slot[0] == 'i') - S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i); + S.Diag(ArgLoc, diag::warn_hlsl_deprecated_register_type_i); } else if (Slot[0] == 'c') { - if (!f.default_globals){ + if (!f.default_globals) { S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_not_in_global_scope); - } - } - else if (Slot[0] == 't') - S.Diag(ArgLoc, diag::err_hlsl_mismatching_register_type_and_variable_type) << 0 << typestr; + } + } else if (Slot[0] == 't') + S.Diag(ArgLoc, diag::err_hlsl_mismatching_register_type_and_variable_type) + << 0 << typestr; else if (Slot[0] == 'u') - S.Diag(ArgLoc, - diag::err_hlsl_mismatching_register_type_and_variable_type) + S.Diag(ArgLoc, diag::err_hlsl_mismatching_register_type_and_variable_type) << 1 << typestr; else if (Slot[0] == 's') - S.Diag(ArgLoc, - diag::err_hlsl_mismatching_register_type_and_variable_type) + S.Diag(ArgLoc, diag::err_hlsl_mismatching_register_type_and_variable_type) << 3 << typestr; - // any other register type should emit err_hlsl_unsupported_register_type_and_variable_type + // any other register type should emit + // err_hlsl_unsupported_register_type_and_variable_type else { S.Diag(ArgLoc, diag::err_hlsl_unsupported_register_type_and_variable_type) << Slot[0] << typestr; - } + } } // finally, we handle the udt case - + if (f.udt) { for (auto it = D->attr_begin(); it != D->attr_end(); ++it) { if (HLSLResourceBindingAttr *attr = dyn_cast<HLSLResourceBindingAttr>(*it)) { llvm::StringRef registerTypeSlotRef = attr->getSlot(); - std::string registerTypeSlot( - registerTypeSlotRef); - if (registerTypeSlot[0] == 't') { + std::string registerTypeSlot(registerTypeSlotRef); + if (registerTypeSlot[0] == 't') { if (!f.srv) { S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_resource_type_member) - << typestr << "t" - << 0; + << typestr << "t" << 0; } } else if (registerTypeSlot[0] == 'u') { if (!f.uav) { @@ -789,26 +786,27 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, } } else if (registerTypeSlot[0] == 'b') { if (!f.cbv) { - S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_resource_type_member) + S.Diag(attr->getLoc(), + diag::warn_hlsl_UDT_missing_resource_type_member) << typestr << "b" << 2; } } else if (registerTypeSlot[0] == 's') { if (!f.sampler) { - S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_resource_type_member) + S.Diag(attr->getLoc(), + diag::warn_hlsl_UDT_missing_resource_type_member) << typestr << "s" << 3; } } else if (registerTypeSlot[0] == 'c') { if (!f.srv) - S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_basic_type); - } - else { + S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_basic_type); + } else { S.Diag(attr->getLoc(), diag::err_hlsl_unsupported_register_type_and_variable_type) << registerTypeSlot[0] << typestr; } } } - } + } } void SemaHLSL::handleResourceBindingAttr(Decl *D, const ParsedAttr &AL) { >From a2bf4416ed91cf9ab408b6fb773fcc2e5c528696 Mon Sep 17 00:00:00 2001 From: Joshua Batista <jbati...@microsoft.com> Date: Tue, 2 Jul 2024 16:41:39 -0700 Subject: [PATCH 7/7] fix mismatching register type diagnostic logic --- clang/lib/Sema/SemaHLSL.cpp | 113 ++++++++++-------- .../SemaHLSL/resource_binding_attr_error.hlsl | 7 +- .../resource_binding_attr_error_mismatch.hlsl | 74 ++++++++++++ 3 files changed, 142 insertions(+), 52 deletions(-) create mode 100644 clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp index 8cd793ceff4c9..1d1ced083b1d3 100644 --- a/clang/lib/Sema/SemaHLSL.cpp +++ b/clang/lib/Sema/SemaHLSL.cpp @@ -492,31 +492,39 @@ bool isDeclaredWithinCOrTBuffer(const Decl *decl) { } const HLSLResourceAttr * -getHLSLResourceAttrFromVarDecl(VarDecl *SamplerUAVOrSRV) { - const Type *Ty = SamplerUAVOrSRV->getType()->getPointeeOrArrayElementType(); - if (!Ty) - llvm_unreachable("Resource class must have an element type."); +getHLSLResourceAttrFromEitherDecl(VarDecl *SamplerUAVOrSRV, + HLSLBufferDecl *CBufferOrTBuffer) { - if (const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty)) { - /* QualType QT = SamplerUAVOrSRV->getType(); - PrintingPolicy PP = S.getPrintingPolicy(); - std::string typestr = QualType::getAsString(QT.split(), PP); - - S.Diag(ArgLoc, diag::err_hlsl_unsupported_register_resource_type) - << typestr; - return; */ - return nullptr; - } + if (SamplerUAVOrSRV) { + const Type *Ty = SamplerUAVOrSRV->getType()->getPointeeOrArrayElementType(); + if (!Ty) + llvm_unreachable("Resource class must have an element type."); + + if (const BuiltinType *BTy = dyn_cast<BuiltinType>(Ty)) { + /* QualType QT = SamplerUAVOrSRV->getType(); + PrintingPolicy PP = S.getPrintingPolicy(); + std::string typestr = QualType::getAsString(QT.split(), PP); + + S.Diag(ArgLoc, diag::err_hlsl_unsupported_register_resource_type) + << typestr; + return; */ + return nullptr; + } - const CXXRecordDecl *TheRecordDecl = Ty->getAsCXXRecordDecl(); - if (!TheRecordDecl) - llvm_unreachable("Resource class should have a resource type declaration."); + const CXXRecordDecl *TheRecordDecl = Ty->getAsCXXRecordDecl(); + if (!TheRecordDecl) + llvm_unreachable( + "Resource class should have a resource type declaration."); - if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(TheRecordDecl)) - TheRecordDecl = TDecl->getSpecializedTemplate()->getTemplatedDecl(); - TheRecordDecl = TheRecordDecl->getCanonicalDecl(); - const auto *Attr = TheRecordDecl->getAttr<HLSLResourceAttr>(); - return Attr; + if (auto TDecl = dyn_cast<ClassTemplateSpecializationDecl>(TheRecordDecl)) + TheRecordDecl = TDecl->getSpecializedTemplate()->getTemplatedDecl(); + TheRecordDecl = TheRecordDecl->getCanonicalDecl(); + const auto *Attr = TheRecordDecl->getAttr<HLSLResourceAttr>(); + return Attr; + } else if (CBufferOrTBuffer) { + const auto *Attr = CBufferOrTBuffer->getAttr<HLSLResourceAttr>(); + return Attr; + } } void traverseType(QualType T, register_binding_flags &r) { @@ -596,7 +604,7 @@ register_binding_flags HLSLFillRegisterBindingFlags(Sema &S, Decl *D) { r.srv = true; } else if (SamplerUAVOrSRV) { const HLSLResourceAttr *res_attr = - getHLSLResourceAttrFromVarDecl(SamplerUAVOrSRV); + getHLSLResourceAttrFromEitherDecl(SamplerUAVOrSRV, CBufferOrTBuffer); if (res_attr) { llvm::hlsl::ResourceClass DeclResourceClass = res_attr->getResourceClass(); @@ -663,8 +671,12 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, VarDecl *SamplerUAVOrSRV = dyn_cast<VarDecl>(D); // Cbuffers and Tbuffers are HLSLBufferDecl types HLSLBufferDecl *CBufferOrTBuffer = dyn_cast<HLSLBufferDecl>(D); + + // exactly one of these two types should be set if (!SamplerUAVOrSRV && !CBufferOrTBuffer) return; + if (SamplerUAVOrSRV && CBufferOrTBuffer) + return; register_binding_flags f = HLSLFillRegisterBindingFlags(S, D); assert((int)f.other + (int)f.resource + (int)f.basic + (int)f.udt == 1 && @@ -679,6 +691,8 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, } else typestr = CBufferOrTBuffer->isCBuffer() ? "cbuffer" : "tbuffer"; + std::string registerType(Slot.substr(0, 1)); + // first, if "other" is set, emit an error if (f.other) { S.Diag(ArgLoc, diag::err_hlsl_unsupported_register_type_and_variable_type) @@ -691,42 +705,43 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, // next, if resource is set, make sure the register type in the register // annotation is compatible with the variable's resource type. if (f.resource) { - VarDecl *VD = dyn_cast<VarDecl>(D); - - const HLSLResourceAttr *res_attr = getHLSLResourceAttrFromVarDecl(VD); + const HLSLResourceAttr *res_attr = + getHLSLResourceAttrFromEitherDecl(SamplerUAVOrSRV, CBufferOrTBuffer); assert(res_attr && "any decl that set the resource flag on analysis should " "have a resource attribute attached."); - llvm::hlsl::ResourceClass DeclResourceClass = res_attr->getResourceClass(); + const llvm::hlsl::ResourceClass DeclResourceClass = + res_attr->getResourceClass(); + switch (DeclResourceClass) { case llvm::hlsl::ResourceClass::SRV: { - if (!f.srv) { - S.Diag(res_attr->getLoc(), + if (registerType != "t") { + S.Diag(D->getLocation(), diag::err_hlsl_mismatching_register_type_and_resource_type) - << typestr << Slot[0] << 0 /*srv*/; + << typestr << registerType << 0 /*srv*/; } break; } case llvm::hlsl::ResourceClass::UAV: { - if (!f.uav) { - S.Diag(res_attr->getLoc(), + if (registerType != "u") { + S.Diag(D->getLocation(), diag::err_hlsl_mismatching_register_type_and_resource_type) - << typestr << Slot[0] << 1 /*uav*/; + << typestr << registerType << 1 /*uav*/; } break; } case llvm::hlsl::ResourceClass::CBuffer: { - if (!f.cbv) { - S.Diag(res_attr->getLoc(), + if (registerType != "b") { + S.Diag(D->getLocation(), diag::err_hlsl_mismatching_register_type_and_resource_type) - << typestr << Slot[0] << 2 /*cbv*/; + << typestr << registerType << 2 /*cbv*/; } break; } case llvm::hlsl::ResourceClass::Sampler: { - if (!f.sampler) { - S.Diag(res_attr->getLoc(), + if (registerType != "s") { + S.Diag(D->getLocation(), diag::err_hlsl_mismatching_register_type_and_resource_type) - << typestr << Slot[0] << 3 /*sampler*/; + << typestr << registerType << 3 /*sampler*/; } break; } @@ -747,18 +762,18 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, if (!f.default_globals) { S.Diag(ArgLoc, diag::warn_hlsl_register_type_c_not_in_global_scope); } - } else if (Slot[0] == 't') + } else if (Slot[0] == 't') { S.Diag(ArgLoc, diag::err_hlsl_mismatching_register_type_and_variable_type) << 0 << typestr; - else if (Slot[0] == 'u') + } else if (Slot[0] == 'u') { S.Diag(ArgLoc, diag::err_hlsl_mismatching_register_type_and_variable_type) << 1 << typestr; - else if (Slot[0] == 's') + } else if (Slot[0] == 's') { S.Diag(ArgLoc, diag::err_hlsl_mismatching_register_type_and_variable_type) << 3 << typestr; // any other register type should emit // err_hlsl_unsupported_register_type_and_variable_type - else { + } else { S.Diag(ArgLoc, diag::err_hlsl_unsupported_register_type_and_variable_type) << Slot[0] << typestr; } @@ -772,37 +787,37 @@ static void DiagnoseHLSLResourceRegType(Sema &S, SourceLocation &ArgLoc, dyn_cast<HLSLResourceBindingAttr>(*it)) { llvm::StringRef registerTypeSlotRef = attr->getSlot(); std::string registerTypeSlot(registerTypeSlotRef); - if (registerTypeSlot[0] == 't') { + if (registerTypeSlot.front() == 't') { if (!f.srv) { S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_resource_type_member) << typestr << "t" << 0; } - } else if (registerTypeSlot[0] == 'u') { + } else if (registerTypeSlot.front() == 'u') { if (!f.uav) { S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_resource_type_member) << typestr << "u" << 1; } - } else if (registerTypeSlot[0] == 'b') { + } else if (registerTypeSlot.front() == 'b') { if (!f.cbv) { S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_resource_type_member) << typestr << "b" << 2; } - } else if (registerTypeSlot[0] == 's') { + } else if (registerTypeSlot.front() == 's') { if (!f.sampler) { S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_resource_type_member) << typestr << "s" << 3; } - } else if (registerTypeSlot[0] == 'c') { + } else if (registerTypeSlot.front() == 'c') { if (!f.srv) S.Diag(attr->getLoc(), diag::warn_hlsl_UDT_missing_basic_type); } else { S.Diag(attr->getLoc(), diag::err_hlsl_unsupported_register_type_and_variable_type) - << registerTypeSlot[0] << typestr; + << registerTypeSlot.front() << typestr; } } } diff --git a/clang/test/SemaHLSL/resource_binding_attr_error.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error.hlsl index 58a1f3f1f64d7..ce81574a79608 100644 --- a/clang/test/SemaHLSL/resource_binding_attr_error.hlsl +++ b/clang/test/SemaHLSL/resource_binding_attr_error.hlsl @@ -1,9 +1,10 @@ // RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify -// FIXME: emit a diagnostic because float doesn't match the 'c' register type -float a : register(c0, space1); +// valid, The register keyword in this statement isn't binding a resource, rather it is +// specifying a constant register binding offset within the $Globals cbuffer, which is legacy behavior from DX9. +float a : register(c0); -// FIXME: emit a diagnostic because cbuffer doesn't match the 'i' register type +// expected-error@+1 {{cbv type 'cbuffer' requires register type 'b', but register type 'i' was used}} cbuffer b : register(i0) { } diff --git a/clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl b/clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl new file mode 100644 index 0000000000000..54e852483f832 --- /dev/null +++ b/clang/test/SemaHLSL/resource_binding_attr_error_mismatch.hlsl @@ -0,0 +1,74 @@ +// RUN: %clang_cc1 -triple dxil-pc-shadermodel6.3-library -x hlsl -o - -fsyntax-only %s -verify + + +// expected-error@+1 {{uav type 'RWBuffer<int>' requires register type 'u', but register type 'b' was used}} +RWBuffer<int> a : register(b2, space1); + +// expected-error@+1 {{uav type 'RWBuffer<int>' requires register type 'u', but register type 't' was used}} +RWBuffer<int> b : register(t2, space1); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'Texture1D' (expected 't')}} +// NOT YET IMPLEMENTED Texture1D<float> tex : register(u3); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 's' for register type 'Texture2D' (expected 't')}} +// NOT YET IMPLEMENTED Texture2D<float> Texture : register(s0); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'Texture2DMS' (expected 't')}} +// NOT YET IMPLEMENTED Texture2DMS<float4, 4> T2DMS_t2 : register(u2) + +// NOT YET IMPLEMENTED : {{invalid register name prefix 't' for register type 'RWTexture3D' (expected 'u')}} +// NOT YET IMPLEMENTED RWTexture3D<float4> RWT3D_u1 : register(t1) + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'b' for register type 'TextureCube' (expected 't')}} +// NOT YET IMPLEMENTED TextureCube <float> t8 : register(b8); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'b' for register type 'TextureCubeArray' (expected 't')}} +// NOT YET IMPLEMENTED TextureCubeArray TCubeArray_t2 : register(b2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'b' for register type 'Texture1DArray' (expected 't')}} +// NOT YET IMPLEMENTED Texture1DArray T1DArray_t2 : register(b2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'B' for register type 'Texture2DArray' (expected 't')}} +// NOT YET IMPLEMENTED Texture2DArray T2DArray_b2 : register(B2); + + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'Texture2DMSArray' (expected 't')}} +// NOT YET IMPLEMENTED Texture2DMSArray<float4> msTextureArray : register(u2, space2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'TextureCubeArray' (expected 't')}} +// NOT YET IMPLEMENTED TextureCubeArray TCubeArray_f2 : register(u2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'TypedBuffer' (expected 't')}} +// NOT YET IMPLEMENTED TypedBuffer tbuf : register(u2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'RawBuffer' (expected 't')}} +// NOT YET IMPLEMENTED RawBuffer rbuf : register(u2); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 't' for register type 'StructuredBuffer' (expected 'u')}} +// NOT YET IMPLEMENTED StructuredBuffer ROVStructuredBuff_t2 : register(T2); + +// expected-error@+1 {{cbv type 'cbuffer' requires register type 'b', but register type 's' was used}} +cbuffer f : register(s2, space1) {} + +// NOT YET IMPLEMENTED : {{invalid register name prefix 't' for register type 'Sampler' (expected 's')}} +// Can this type just be Sampler instead of SamplerState? +// NOT YET IMPLEMENTED SamplerState MySampler : register(t3, space1); + +// expected-error@+1 {{srv type 'tbuffer' requires register type 't', but register type 's' was used}} +tbuffer f : register(s2, space1) {} + +// NOT YET IMPLEMENTED : RTAccelerationStructure doesn't have any example tests in DXC + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'FeedbackTexture2D' (expected 't')}} +// NOT YET IMPLEMENTED FeedbackTexture2D<float> FBTex2D[3][] : register(u0, space26); + +// NOT YET IMPLEMENTED : {{invalid register name prefix 'u' for register type 'FeedbackTexture2DArray' (expected 't')}} +// NOT YET IMPLEMENTED FeedbackTexture2DArray<float> FBTex2DArr[3][2][] : register(u0, space27); + + +// empty binding prefix cases: +// expected-error@+1 {{expected identifier}} +RWBuffer<int> c: register(); + +// expected-error@+1 {{expected identifier}} +RWBuffer<int> d: register(""); _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits