[clang] 2a2324a - [HLSL] Do not remove `HLSLVkBindingAttr` if the target is not SPIR-V (#161752)
via cfe-commits
cfe-commits at lists.llvm.org
Tue Oct 7 14:48:32 PDT 2025
Author: Helena Kotas
Date: 2025-10-07T14:48:29-07:00
New Revision: 2a2324a6eae7447be07ed95a24d5b335c9513450
URL: https://github.com/llvm/llvm-project/commit/2a2324a6eae7447be07ed95a24d5b335c9513450
DIFF: https://github.com/llvm/llvm-project/commit/2a2324a6eae7447be07ed95a24d5b335c9513450.diff
LOG: [HLSL] Do not remove `HLSLVkBindingAttr` if the target is not SPIR-V (#161752)
The attribute needs to be preserved for rewriter scenarios. Two places were updated to use the `ResourceBindingAttrs` helper struct to make sure the `HLSLVkBindingAttr` is ignored when the target is DirectX.
Added:
Modified:
clang/include/clang/AST/HLSLResource.h
clang/lib/Sema/SemaHLSL.cpp
clang/test/AST/HLSL/resource_binding_attr.hlsl
clang/test/AST/HLSL/vk_binding_attr.hlsl
Removed:
################################################################################
diff --git a/clang/include/clang/AST/HLSLResource.h b/clang/include/clang/AST/HLSLResource.h
index 9cdd81b2d8dab..7440050c7b2b9 100644
--- a/clang/include/clang/AST/HLSLResource.h
+++ b/clang/include/clang/AST/HLSLResource.h
@@ -69,6 +69,11 @@ struct ResourceBindingAttrs {
assert(hasImplicitOrderID());
return RegBinding->getImplicitBindingOrderID();
}
+
+ void setImplicitOrderID(unsigned Value) const {
+ assert(hasBinding() && !isExplicit() && !hasImplicitOrderID());
+ RegBinding->setImplicitBindingOrderID(Value);
+ }
};
} // namespace hlsl
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index a662b72c2a362..09e5d69b39329 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -598,18 +598,17 @@ void SemaHLSL::ActOnFinishBuffer(Decl *Dcl, SourceLocation RBrace) {
validatePackoffset(SemaRef, BufDecl);
- // create buffer layout struct
createHostLayoutStructForBuffer(SemaRef, BufDecl);
- HLSLVkBindingAttr *VkBinding = Dcl->getAttr<HLSLVkBindingAttr>();
- HLSLResourceBindingAttr *RBA = Dcl->getAttr<HLSLResourceBindingAttr>();
- if (!VkBinding && (!RBA || !RBA->hasRegisterSlot())) {
+ // Handle implicit binding if needed.
+ ResourceBindingAttrs ResourceAttrs(Dcl);
+ if (!ResourceAttrs.isExplicit()) {
SemaRef.Diag(Dcl->getLocation(), diag::warn_hlsl_implicit_binding);
// Use HLSLResourceBindingAttr to transfer implicit binding order_ID
// to codegen. If it does not exist, create an implicit attribute.
uint32_t OrderID = getNextImplicitBindingOrderID();
- if (RBA)
- RBA->setImplicitBindingOrderID(OrderID);
+ if (ResourceAttrs.hasBinding())
+ ResourceAttrs.setImplicitOrderID(OrderID);
else
addImplicitBindingAttrToDecl(SemaRef, BufDecl,
BufDecl->isCBuffer() ? RegisterType::CBuffer
@@ -1590,10 +1589,6 @@ void SemaHLSL::handleVkConstantIdAttr(Decl *D, const ParsedAttr &AL) {
}
void SemaHLSL::handleVkBindingAttr(Decl *D, const ParsedAttr &AL) {
- // The vk::binding attribute only applies to SPIR-V.
- if (!getASTContext().getTargetInfo().getTriple().isSPIRV())
- return;
-
uint32_t Binding = 0;
if (!SemaRef.checkUInt32Argument(AL, AL.getArgAsExpr(0), Binding))
return;
@@ -3780,17 +3775,15 @@ void SemaHLSL::ActOnVariableDeclarator(VarDecl *VD) {
// If the resource array does not have an explicit binding attribute,
// create an implicit one. It will be used to transfer implicit binding
// order_ID to codegen.
- if (!VD->hasAttr<HLSLVkBindingAttr>()) {
- HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
- if (!RBA || !RBA->hasRegisterSlot()) {
- uint32_t OrderID = getNextImplicitBindingOrderID();
- if (RBA)
- RBA->setImplicitBindingOrderID(OrderID);
- else
- addImplicitBindingAttrToDecl(
- SemaRef, VD, getRegisterType(getResourceArrayHandleType(VD)),
- OrderID);
- }
+ ResourceBindingAttrs Binding(VD);
+ if (!Binding.isExplicit()) {
+ uint32_t OrderID = getNextImplicitBindingOrderID();
+ if (Binding.hasBinding())
+ Binding.setImplicitOrderID(OrderID);
+ else
+ addImplicitBindingAttrToDecl(
+ SemaRef, VD, getRegisterType(getResourceArrayHandleType(VD)),
+ OrderID);
}
}
}
diff --git a/clang/test/AST/HLSL/resource_binding_attr.hlsl b/clang/test/AST/HLSL/resource_binding_attr.hlsl
index c6d93b991fbfc..2de06741cfd46 100644
--- a/clang/test/AST/HLSL/resource_binding_attr.hlsl
+++ b/clang/test/AST/HLSL/resource_binding_attr.hlsl
@@ -92,9 +92,8 @@ cbuffer CB3 {
StructuredBuffer<float> SB[10];
// CHECK: VarDecl {{.*}} SB2 'StructuredBuffer<float>[10]'
+// CHECK: HLSLVkBindingAttr {{.*}} 2 0
// DXIL: HLSLResourceBindingAttr {{.*}} Implicit
-// DXIL-NOT: HLSLVkBindingAttr
-// SPV: HLSLVkBindingAttr {{.*}} 2 0
// SPV-NOT: HLSLResourceBindingAttr {{.*}} Implicit
[[vk::binding(2)]]
StructuredBuffer<float> SB2[10];
diff --git a/clang/test/AST/HLSL/vk_binding_attr.hlsl b/clang/test/AST/HLSL/vk_binding_attr.hlsl
index d08165d7c593d..13e7544eb672c 100644
--- a/clang/test/AST/HLSL/vk_binding_attr.hlsl
+++ b/clang/test/AST/HLSL/vk_binding_attr.hlsl
@@ -10,8 +10,7 @@
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 102
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
-// SPV: HLSLVkBindingAttr {{.*}} 23 102
-// DXIL-NOT: HLSLVkBindingAttr
+// CHECK: HLSLVkBindingAttr {{.*}} 23 102
[[vk::binding(23, 102)]] StructuredBuffer<float> Buf;
// CHECK: VarDecl {{.*}} Buf2 'StructuredBuffer<float>':'hlsl::StructuredBuffer<float>'
@@ -23,8 +22,7 @@
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 1
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 102
-// SPV: HLSLVkBindingAttr {{.*}} 14 1
-// DXIL-NOT: HLSLVkBindingAttr
+// CHECK: HLSLVkBindingAttr {{.*}} 14 1
// CHECK: HLSLResourceBindingAttr {{.*}} "t23" "space102"
[[vk::binding(14, 1)]] StructuredBuffer<float> Buf2 : register(t23, space102);
@@ -37,15 +35,13 @@
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 23
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 102
-// SPV: HLSLVkBindingAttr {{.*}} 14 0
-// DXIL-NOT: HLSLVkBindingAttr
+// CHECK: HLSLVkBindingAttr {{.*}} 14 0
// CHECK: HLSLResourceBindingAttr {{.*}} "t23" "space102"
[[vk::binding(14)]] StructuredBuffer<float> Buf3 : register(t23, space102);
// CHECK: HLSLBufferDecl {{.*}} cbuffer CB
// CHECK-NEXT: HLSLResourceClassAttr {{.*}} Implicit CBuffer
-// SPV-NEXT: HLSLVkBindingAttr {{.*}} 1 2
-// DXIL-NOT: HLSLVkBindingAttr
+// CHECK: HLSLVkBindingAttr {{.*}} 1 2
[[vk::binding(1, 2)]] cbuffer CB {
float a;
}
@@ -54,15 +50,14 @@
// CHECK-NEXT: CallExpr {{.*}} 'Buffer<int>':'hlsl::Buffer<int>'
// CHECK-NEXT: ImplicitCastExpr {{.*}} 'hlsl::Buffer<int> (*)(unsigned int, unsigned int, int, unsigned int, const char *)' <FunctionToPointerDecay>
// SPV-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
-// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// SPV-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 24
// SPV-NEXT: IntegerLiteral {{.*}} 'unsigned int' 103
-// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
-// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// DXIL-NEXT: DeclRefExpr {{.*}} 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
+// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'hlsl::Buffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 2
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
-// SPV: HLSLVkBindingAttr {{.*}} 24 103
-// DXIL-NOT: HLSLVkBindingAttr
+// CHECK: HLSLVkBindingAttr {{.*}} 24 103
[[vk::binding(24, 103)]] Buffer<int> Buf4;
// CHECK: VarDecl {{.*}} Buf5 'RWBuffer<int2>':'hlsl::RWBuffer<vector<int, 2>>'
@@ -76,8 +71,7 @@
// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromImplicitBinding' 'Buffer<int2> (unsigned int, unsigned int, int, unsigned int, const char *)'
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 3
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
-// SPV: HLSLVkBindingAttr {{.*}} 25 104
-// DXIL-NOT: HLSLVkBindingAttr
+// CHECK: HLSLVkBindingAttr {{.*}} 25 104
[[vk::binding(25, 104)]] RWBuffer<int2> Buf5;
// CHECK: VarDecl {{.*}} Buf6 'RWStructuredBuffer<int>':'hlsl::RWStructuredBuffer<int>'
@@ -91,6 +85,5 @@
// DXIL-NEXT-SAME: CXXMethod {{.*}} '__createFromBinding' 'hlsl::RWStructuredBuffer<int> (unsigned int, unsigned int, int, unsigned int, const char *)'
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 4
// DXIL-NEXT: IntegerLiteral {{.*}} 'unsigned int' 0
-// SPV: HLSLVkBindingAttr {{.*}} 26 105
-// DXIL-NOT: HLSLVkBindingAttr
+// CHECK: HLSLVkBindingAttr {{.*}} 26 105
[[vk::binding(26, 105)]] RWStructuredBuffer<int> Buf6;
More information about the cfe-commits
mailing list