Skip to content

[HLSL] Desugar ConstantArrayType when calculating cbuffer field layout #134683

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Apr 7, 2025

Conversation

spall
Copy link
Contributor

@spall spall commented Apr 7, 2025

When calculating the layout for a cbuffer field, if that field is a ConstantArrayType, desguar it before casting it to a ConstantArrayType.
Closes #134668

@spall spall requested a review from hekota April 7, 2025 16:39
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:codegen IR generation bugs: mangling, exceptions, etc. HLSL HLSL Language Support labels Apr 7, 2025
@llvmbot
Copy link
Member

llvmbot commented Apr 7, 2025

@llvm/pr-subscribers-clang-codegen

Author: Sarah Spall (spall)

Changes

When calculating the layout for a cbuffer field, if that field is a ConstantArrayType, desguar it before casting it to a ConstantArrayType.
Closes #134668


Full diff: https://github.com/llvm/llvm-project/pull/134683.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp (+2-1)
  • (modified) clang/test/CodeGenHLSL/cbuffer.hlsl (+16-1)
diff --git a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
index b546b6dd574ff..20d311f3609e0 100644
--- a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
@@ -195,7 +195,8 @@ bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD,
     // Unwrap array to find the element type and get combined array size.
     QualType Ty = FieldTy;
     while (Ty->isConstantArrayType()) {
-      const ConstantArrayType *ArrayTy = cast<ConstantArrayType>(Ty);
+      const ConstantArrayType *ArrayTy =
+          cast<ConstantArrayType>(Ty.getDesugaredType(CGM.getContext()));
       ArrayCount *= ArrayTy->getSExtSize();
       Ty = ArrayTy->getElementType();
     }
diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl b/clang/test/CodeGenHLSL/cbuffer.hlsl
index db06cea808b62..0a0465cc44e91 100644
--- a/clang/test/CodeGenHLSL/cbuffer.hlsl
+++ b/clang/test/CodeGenHLSL/cbuffer.hlsl
@@ -99,6 +99,19 @@ cbuffer CBArrays : register(b2) {
 // CHECK: @c7 = external addrspace(2) global [2 x i64], align 8
 // CHECK: @c8 = external addrspace(2) global [4 x i32], align 4
 
+typedef uint32_t4 uint32_t8[2];
+typedef uint4 T1;
+typedef T1 T2[2]; // check a double typedef
+
+cbuffer CBTypedefArray {
+  uint32_t8 t1[2];
+  T2 t2[2];
+}
+
+// CHECK: @CBTypedefArray.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CBTypedefArray,
+// CHECK-SAME: 128, 0, 64))
+// CHECK: @t1 = external addrspace(2) global [2 x [2 x <4 x i32>]], align 16
+// CHECK: @t2 = external addrspace(2) global [2 x [2 x <4 x i32>]], align 16
 struct Empty {};
 
 struct A {
@@ -278,7 +291,7 @@ void main() {
 // CHECK-NEXT: call void @_init_resource_CBScalars.cb()
 // CHECK-NEXT: call void @_init_resource_CBArrays.cb()
 
-// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBCLASSES:[0-9]+]],
+// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBTYPEDEFARRAY:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBCLASSES:[0-9]+]],
 // CHECK-SAME: ![[CBMIX:[0-9]+]], ![[CB_A:[0-9]+]], ![[CB_B:[0-9]+]], ![[CB_C:[0-9]+]]}
 
 // CHECK: ![[CBSCALARS]] = !{ptr @CBScalars.cb, ptr addrspace(2) @a1, ptr addrspace(2) @a2, ptr addrspace(2) @a3, ptr addrspace(2) @a4,
@@ -290,6 +303,8 @@ void main() {
 // CHECK: ![[CBARRAYS]] = !{ptr @CBArrays.cb, ptr addrspace(2) @c1, ptr addrspace(2) @c2, ptr addrspace(2) @c3, ptr addrspace(2) @c4,
 // CHECK-SAME: ptr addrspace(2) @c5, ptr addrspace(2) @c6, ptr addrspace(2) @c7, ptr addrspace(2) @c8}
 
+// CHECK: ![[CBTYPEDEFARRAY]] = !{ptr @CBTypedefArray.cb, ptr addrspace(2) @t1, ptr addrspace(2) @t2}
+
 // CHECK: ![[CBSTRUCTS]] = !{ptr @CBStructs.cb, ptr addrspace(2) @a, ptr addrspace(2) @b, ptr addrspace(2) @c, ptr addrspace(2) @array_of_A,
 // CHECK-SAME: ptr addrspace(2) @d, ptr addrspace(2) @e, ptr addrspace(2) @f}
 

@llvmbot
Copy link
Member

llvmbot commented Apr 7, 2025

@llvm/pr-subscribers-clang

Author: Sarah Spall (spall)

Changes

When calculating the layout for a cbuffer field, if that field is a ConstantArrayType, desguar it before casting it to a ConstantArrayType.
Closes #134668


Full diff: https://github.com/llvm/llvm-project/pull/134683.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp (+2-1)
  • (modified) clang/test/CodeGenHLSL/cbuffer.hlsl (+16-1)
diff --git a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
index b546b6dd574ff..20d311f3609e0 100644
--- a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
@@ -195,7 +195,8 @@ bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD,
     // Unwrap array to find the element type and get combined array size.
     QualType Ty = FieldTy;
     while (Ty->isConstantArrayType()) {
-      const ConstantArrayType *ArrayTy = cast<ConstantArrayType>(Ty);
+      const ConstantArrayType *ArrayTy =
+          cast<ConstantArrayType>(Ty.getDesugaredType(CGM.getContext()));
       ArrayCount *= ArrayTy->getSExtSize();
       Ty = ArrayTy->getElementType();
     }
diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl b/clang/test/CodeGenHLSL/cbuffer.hlsl
index db06cea808b62..0a0465cc44e91 100644
--- a/clang/test/CodeGenHLSL/cbuffer.hlsl
+++ b/clang/test/CodeGenHLSL/cbuffer.hlsl
@@ -99,6 +99,19 @@ cbuffer CBArrays : register(b2) {
 // CHECK: @c7 = external addrspace(2) global [2 x i64], align 8
 // CHECK: @c8 = external addrspace(2) global [4 x i32], align 4
 
+typedef uint32_t4 uint32_t8[2];
+typedef uint4 T1;
+typedef T1 T2[2]; // check a double typedef
+
+cbuffer CBTypedefArray {
+  uint32_t8 t1[2];
+  T2 t2[2];
+}
+
+// CHECK: @CBTypedefArray.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CBTypedefArray,
+// CHECK-SAME: 128, 0, 64))
+// CHECK: @t1 = external addrspace(2) global [2 x [2 x <4 x i32>]], align 16
+// CHECK: @t2 = external addrspace(2) global [2 x [2 x <4 x i32>]], align 16
 struct Empty {};
 
 struct A {
@@ -278,7 +291,7 @@ void main() {
 // CHECK-NEXT: call void @_init_resource_CBScalars.cb()
 // CHECK-NEXT: call void @_init_resource_CBArrays.cb()
 
-// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBCLASSES:[0-9]+]],
+// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBTYPEDEFARRAY:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBCLASSES:[0-9]+]],
 // CHECK-SAME: ![[CBMIX:[0-9]+]], ![[CB_A:[0-9]+]], ![[CB_B:[0-9]+]], ![[CB_C:[0-9]+]]}
 
 // CHECK: ![[CBSCALARS]] = !{ptr @CBScalars.cb, ptr addrspace(2) @a1, ptr addrspace(2) @a2, ptr addrspace(2) @a3, ptr addrspace(2) @a4,
@@ -290,6 +303,8 @@ void main() {
 // CHECK: ![[CBARRAYS]] = !{ptr @CBArrays.cb, ptr addrspace(2) @c1, ptr addrspace(2) @c2, ptr addrspace(2) @c3, ptr addrspace(2) @c4,
 // CHECK-SAME: ptr addrspace(2) @c5, ptr addrspace(2) @c6, ptr addrspace(2) @c7, ptr addrspace(2) @c8}
 
+// CHECK: ![[CBTYPEDEFARRAY]] = !{ptr @CBTypedefArray.cb, ptr addrspace(2) @t1, ptr addrspace(2) @t2}
+
 // CHECK: ![[CBSTRUCTS]] = !{ptr @CBStructs.cb, ptr addrspace(2) @a, ptr addrspace(2) @b, ptr addrspace(2) @c, ptr addrspace(2) @array_of_A,
 // CHECK-SAME: ptr addrspace(2) @d, ptr addrspace(2) @e, ptr addrspace(2) @f}
 

@llvmbot
Copy link
Member

llvmbot commented Apr 7, 2025

@llvm/pr-subscribers-hlsl

Author: Sarah Spall (spall)

Changes

When calculating the layout for a cbuffer field, if that field is a ConstantArrayType, desguar it before casting it to a ConstantArrayType.
Closes #134668


Full diff: https://github.com/llvm/llvm-project/pull/134683.diff

2 Files Affected:

  • (modified) clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp (+2-1)
  • (modified) clang/test/CodeGenHLSL/cbuffer.hlsl (+16-1)
diff --git a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
index b546b6dd574ff..20d311f3609e0 100644
--- a/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
+++ b/clang/lib/CodeGen/HLSLBufferLayoutBuilder.cpp
@@ -195,7 +195,8 @@ bool HLSLBufferLayoutBuilder::layoutField(const FieldDecl *FD,
     // Unwrap array to find the element type and get combined array size.
     QualType Ty = FieldTy;
     while (Ty->isConstantArrayType()) {
-      const ConstantArrayType *ArrayTy = cast<ConstantArrayType>(Ty);
+      const ConstantArrayType *ArrayTy =
+          cast<ConstantArrayType>(Ty.getDesugaredType(CGM.getContext()));
       ArrayCount *= ArrayTy->getSExtSize();
       Ty = ArrayTy->getElementType();
     }
diff --git a/clang/test/CodeGenHLSL/cbuffer.hlsl b/clang/test/CodeGenHLSL/cbuffer.hlsl
index db06cea808b62..0a0465cc44e91 100644
--- a/clang/test/CodeGenHLSL/cbuffer.hlsl
+++ b/clang/test/CodeGenHLSL/cbuffer.hlsl
@@ -99,6 +99,19 @@ cbuffer CBArrays : register(b2) {
 // CHECK: @c7 = external addrspace(2) global [2 x i64], align 8
 // CHECK: @c8 = external addrspace(2) global [4 x i32], align 4
 
+typedef uint32_t4 uint32_t8[2];
+typedef uint4 T1;
+typedef T1 T2[2]; // check a double typedef
+
+cbuffer CBTypedefArray {
+  uint32_t8 t1[2];
+  T2 t2[2];
+}
+
+// CHECK: @CBTypedefArray.cb = global target("dx.CBuffer", target("dx.Layout", %__cblayout_CBTypedefArray,
+// CHECK-SAME: 128, 0, 64))
+// CHECK: @t1 = external addrspace(2) global [2 x [2 x <4 x i32>]], align 16
+// CHECK: @t2 = external addrspace(2) global [2 x [2 x <4 x i32>]], align 16
 struct Empty {};
 
 struct A {
@@ -278,7 +291,7 @@ void main() {
 // CHECK-NEXT: call void @_init_resource_CBScalars.cb()
 // CHECK-NEXT: call void @_init_resource_CBArrays.cb()
 
-// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBCLASSES:[0-9]+]],
+// CHECK: !hlsl.cbs = !{![[CBSCALARS:[0-9]+]], ![[CBVECTORS:[0-9]+]], ![[CBARRAYS:[0-9]+]], ![[CBTYPEDEFARRAY:[0-9]+]], ![[CBSTRUCTS:[0-9]+]], ![[CBCLASSES:[0-9]+]],
 // CHECK-SAME: ![[CBMIX:[0-9]+]], ![[CB_A:[0-9]+]], ![[CB_B:[0-9]+]], ![[CB_C:[0-9]+]]}
 
 // CHECK: ![[CBSCALARS]] = !{ptr @CBScalars.cb, ptr addrspace(2) @a1, ptr addrspace(2) @a2, ptr addrspace(2) @a3, ptr addrspace(2) @a4,
@@ -290,6 +303,8 @@ void main() {
 // CHECK: ![[CBARRAYS]] = !{ptr @CBArrays.cb, ptr addrspace(2) @c1, ptr addrspace(2) @c2, ptr addrspace(2) @c3, ptr addrspace(2) @c4,
 // CHECK-SAME: ptr addrspace(2) @c5, ptr addrspace(2) @c6, ptr addrspace(2) @c7, ptr addrspace(2) @c8}
 
+// CHECK: ![[CBTYPEDEFARRAY]] = !{ptr @CBTypedefArray.cb, ptr addrspace(2) @t1, ptr addrspace(2) @t2}
+
 // CHECK: ![[CBSTRUCTS]] = !{ptr @CBStructs.cb, ptr addrspace(2) @a, ptr addrspace(2) @b, ptr addrspace(2) @c, ptr addrspace(2) @array_of_A,
 // CHECK-SAME: ptr addrspace(2) @d, ptr addrspace(2) @e, ptr addrspace(2) @f}
 

Copy link
Member

@hekota hekota left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM! One suggestion to use getUnqualifiedDesugaredType instead of getDesugaredType that requires a context.

@spall spall merged commit 01bc672 into llvm:main Apr 7, 2025
12 checks passed
@damyanp damyanp moved this to Closed in HLSL Support Apr 25, 2025
qiaojbao pushed a commit to GPUOpen-Drivers/llvm-project that referenced this pull request Apr 29, 2025
Local branch origin/amd-gfx 9191a26 Merged main:3382aef944ef into origin/amd-gfx:1058b0887612
Remote branch main 01bc672 [HLSL] Desugar ConstantArrayType when calculating cbuffer field layout (llvm#134683)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:codegen IR generation bugs: mangling, exceptions, etc. clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
Status: Closed
Development

Successfully merging this pull request may close these issues.

[HLSL] Cbuffer declaration with array typedef crashes
6 participants