[clang] [HLSL] Constant buffer layout struct update (PR #124840)
Helena Kotas via cfe-commits
cfe-commits at lists.llvm.org
Tue Jan 28 16:55:19 PST 2025
https://github.com/hekota updated https://github.com/llvm/llvm-project/pull/124840
>From 63c465b40512ad4c5fff84c0b2b022b49d46eaa7 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 28 Jan 2025 13:20:30 -0800
Subject: [PATCH 1/2] [HLSL] Constant buffer layout struct update
- create structs with public fields instead of classes with private fields
- add Packed attribute to prevent struct padding
- use __cblayout_ prefix in name
- filter out arrays of resources (bug fix)
- don't create implicit initializer for constant buffer decls
- update tests
---
clang/lib/Sema/SemaDecl.cpp | 7 +
clang/lib/Sema/SemaHLSL.cpp | 29 ++--
.../AST/HLSL/ast-dump-comment-cbuffer.hlsl | 3 -
clang/test/AST/HLSL/cbuffer.hlsl | 144 ++++++++++--------
.../test/AST/HLSL/cbuffer_and_namespaces.hlsl | 30 ++--
clang/test/AST/HLSL/pch_hlsl_buffer.hlsl | 4 +-
6 files changed, 121 insertions(+), 96 deletions(-)
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index fe68eadc951b5f..ba424567b23e0b 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -14183,6 +14183,13 @@ void Sema::ActOnUninitializedDecl(Decl *RealDecl) {
if (getLangOpts().OpenCL &&
Var->getType().getAddressSpace() == LangAS::opencl_local)
return;
+
+ // In HLSL, objects in the hlsl_constat address space are initialized
+ // externaly, so don't synthesize an implicit initializer.
+ if (getLangOpts().HLSL &&
+ Var->getType().getAddressSpace() == LangAS::hlsl_constant)
+ return;
+
// C++03 [dcl.init]p9:
// If no initializer is specified for an object, and the
// object is of (possibly cv-qualified) non-POD class type (or
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index aa99b44958eafd..97df01a5dd3074 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -269,8 +269,11 @@ static bool isZeroSizedArray(const ConstantArrayType *CAT) {
return CAT != nullptr;
}
-// Returns true if the record type is an HLSL resource class
-static bool isResourceRecordType(const Type *Ty) {
+// Returns true if the record type is an HLSL resource class or an array of
+// HLSL resource classes
+static bool isResourceRecordTypeOrArrayOf(const Type *Ty) {
+ while (const ConstantArrayType *CAT = dyn_cast<ConstantArrayType>(Ty))
+ Ty = CAT->getArrayElementTypeNoTypeQual();
return HLSLAttributedResourceType::findHandleTypeOnResource(Ty) != nullptr;
}
@@ -279,11 +282,10 @@ static bool isResourceRecordType(const Type *Ty) {
// array, or a builtin intangible type. Returns false it is a valid leaf element
// type or if it is a record type that needs to be inspected further.
static bool isInvalidConstantBufferLeafElementType(const Type *Ty) {
- if (Ty->isRecordType()) {
- if (isResourceRecordType(Ty) || Ty->getAsCXXRecordDecl()->isEmpty())
- return true;
- return false;
- }
+ if (isResourceRecordTypeOrArrayOf(Ty))
+ return true;
+ if (Ty->isRecordType())
+ return Ty->getAsCXXRecordDecl()->isEmpty();
if (Ty->isConstantArrayType() &&
isZeroSizedArray(cast<ConstantArrayType>(Ty)))
return true;
@@ -339,7 +341,7 @@ static IdentifierInfo *getHostLayoutStructName(Sema &S, NamedDecl *BaseDecl,
ASTContext &AST = S.getASTContext();
IdentifierInfo *NameBaseII = BaseDecl->getIdentifier();
- llvm::SmallString<64> Name("__layout_");
+ llvm::SmallString<64> Name("__cblayout_");
if (NameBaseII) {
Name.append(NameBaseII->getName());
} else {
@@ -393,7 +395,7 @@ static FieldDecl *createFieldForHostLayoutStruct(Sema &S, const Type *Ty,
auto *Field = FieldDecl::Create(AST, LayoutStruct, SourceLocation(),
SourceLocation(), II, QT, TSI, nullptr, false,
InClassInitStyle::ICIS_NoInit);
- Field->setAccess(AccessSpecifier::AS_private);
+ Field->setAccess(AccessSpecifier::AS_public);
return Field;
}
@@ -417,9 +419,11 @@ static CXXRecordDecl *createHostLayoutStruct(Sema &S,
if (CXXRecordDecl *RD = findRecordDeclInContext(II, DC))
return RD;
- CXXRecordDecl *LS = CXXRecordDecl::Create(
- AST, TagDecl::TagKind::Class, DC, SourceLocation(), SourceLocation(), II);
+ CXXRecordDecl *LS =
+ CXXRecordDecl::Create(AST, TagDecl::TagKind::Struct, DC, SourceLocation(),
+ SourceLocation(), II);
LS->setImplicit(true);
+ LS->addAttr(PackedAttr::CreateImplicit(AST));
LS->startDefinition();
// copy base struct, create HLSL Buffer compatible version if needed
@@ -472,8 +476,9 @@ void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl) {
IdentifierInfo *II = getHostLayoutStructName(S, BufDecl, true);
CXXRecordDecl *LS =
- CXXRecordDecl::Create(AST, TagDecl::TagKind::Class, BufDecl,
+ CXXRecordDecl::Create(AST, TagDecl::TagKind::Struct, BufDecl,
SourceLocation(), SourceLocation(), II);
+ LS->addAttr(PackedAttr::CreateImplicit(AST));
LS->setImplicit(true);
LS->startDefinition();
diff --git a/clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl b/clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl
index b2b3e13308da3f..eca2ed0211d1b7 100644
--- a/clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl
+++ b/clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl
@@ -27,6 +27,3 @@ cbuffer A {
// AST-NEXT: TextComment {{.*}} Text=" CBuffer decl."
// AST-NEXT: VarDecl {{.*}} a 'hlsl_constant float'
// AST-NEXT: VarDecl {{.*}} b 'hlsl_constant int'
-// AST-NEXT: CXXRecordDecl {{.*}} implicit class __layout_A definition
-// AST: FieldDecl {{.*}} a 'float'
-// AST-NEXT: FieldDecl {{.*}} b 'int'
diff --git a/clang/test/AST/HLSL/cbuffer.hlsl b/clang/test/AST/HLSL/cbuffer.hlsl
index f516cf5099e82d..8254f0ee00b140 100644
--- a/clang/test/AST/HLSL/cbuffer.hlsl
+++ b/clang/test/AST/HLSL/cbuffer.hlsl
@@ -48,75 +48,83 @@ struct TwoFloats {
// CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
// CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
cbuffer CB {
- // CHECK: VarDecl {{.*}} col:9 used a1 'hlsl_constant float'
+ // CHECK: VarDecl {{.*}} used a1 'hlsl_constant float'
float a1;
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_CB definition
- // CHECK: FieldDecl {{.*}} a1 'float'
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_CB definition
+ // CHECK: PackedAttr
+ // CHECK-NEXT: FieldDecl {{.*}} a1 'float'
}
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __layout_CB), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __cblayout_CB), "");
// Check that buffer layout struct does not include resources or empty types
-// CHECK: HLSLBufferDecl {{.*}} line:62:9 cbuffer CB
+// CHECK: HLSLBufferDecl {{.*}} line:[[# @LINE + 3]]:9 cbuffer CB
// CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
// CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
cbuffer CB {
- // CHECK: VarDecl {{.*}} col:9 used a2 'hlsl_constant float'
+ // CHECK: VarDecl {{.*}} used a2 'hlsl_constant float'
float a2;
- // CHECK: VarDecl {{.*}} col:19 b2 'RWBuffer<float>':'hlsl::RWBuffer<float>'
+ // CHECK: VarDecl {{.*}} b2 'RWBuffer<float>':'hlsl::RWBuffer<float>'
RWBuffer<float> b2;
- // CHECK: VarDecl {{.*}} col:15 c2 'EmptyStruct'
+ // CHECK: VarDecl {{.*}} c2 'EmptyStruct'
EmptyStruct c2;
- // CHECK: VarDecl {{.*}} col:9 d2 'float[0]'
+ // CHECK: VarDecl {{.*}} d2 'float[0]'
float d2[0];
- // CHECK: VarDecl {{.*}} col:9 e2 'hlsl_constant float'
+ // CHECK: VarDecl {{.*}} f2 'RWBuffer<float>[2]'
+ RWBuffer<float> f2[2];
+ // CHECK: VarDecl {{.*}} e2 'hlsl_constant float'
float e2;
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_CB_1 definition
- // CHECK: FieldDecl {{.*}} a2 'float'
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_CB_1 definition
+ // CHECK: PackedAttr
+ // CHECK-NEXT: FieldDecl {{.*}} a2 'float'
// CHECK-NEXT: FieldDecl {{.*}} e2 'float'
}
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __layout_CB_1), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __cblayout_CB_1), "");
// Check that layout struct is created for B and the empty struct C is removed
-// CHECK: HLSLBufferDecl {{.*}} line:83:9 cbuffer CB
+// CHECK: HLSLBufferDecl {{.*}} line:[[# @LINE + 3]]:9 cbuffer CB
// CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
// CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
cbuffer CB {
- // CHECK: VarDecl {{.*}} col:5 used s1 'hlsl_constant A'
+ // CHECK: VarDecl {{.*}} used s1 'hlsl_constant A'
A s1;
- // CHECK: VarDecl {{.*}} col:5 s2 'hlsl_constant B'
+ // CHECK: VarDecl {{.*}} s2 'hlsl_constant B'
B s2;
- // CHECK: VarDecl {{.*}} col:12 s3 'CTypedef':'C'
+ // CHECK: VarDecl {{.*}} s3 'CTypedef':'C'
CTypedef s3;
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_CB_2 definition
- // CHECK: FieldDecl {{.*}} s1 'A'
- // CHECK: FieldDecl {{.*}} s2 '__layout_B'
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_CB_2 definition
+ // CHECK: PackedAttr
+ // CHECK-NEXT: FieldDecl {{.*}} s1 'A'
+ // CHECK-NEXT: FieldDecl {{.*}} s2 '__cblayout_B'
}
-// CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_B definition
-// CHECK: FieldDecl {{.*}} a 'float'
+// CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_B definition
+// CHECK: PackedAttr
+// CHECK-NEXT: FieldDecl {{.*}} a 'float'
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __layout_B), "");
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __layout_CB_2), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __cblayout_B), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __cblayout_CB_2), "");
// check that layout struct is created for D because of its base struct
-// CHECK: HLSLBufferDecl {{.*}} line:104:9 cbuffer CB
+// CHECK: HLSLBufferDecl {{.*}} line:[[# @LINE + 3]]:9 cbuffer CB
// CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
// CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
cbuffer CB {
// CHECK: VarDecl {{.*}} s4 'hlsl_constant D'
D s4;
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_CB_3 definition
- // CHECK: FieldDecl {{.*}} s4 '__layout_D'
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_CB_3 definition
+ // CHECK: PackedAttr
+ // CHECK-NEXT: FieldDecl {{.*}} s4 '__cblayout_D'
}
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_D definition
- // CHECK: public '__layout_B'
- // CHECK: FieldDecl {{.*}} b 'float'
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __layout_D), "");
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __layout_CB_3), "");
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_D definition
+ // CHECK: public '__cblayout_B'
+ // CHECK: PackedAttr
+ // CHECK-NEXT: FieldDecl {{.*}} b 'float'
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __cblayout_D), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __cblayout_CB_3), "");
// check that layout struct is created for E because because its base struct
// is empty and should be eliminated, and BTypedef should reuse the previously
-// defined '__layout_B'
-// CHECK: HLSLBufferDecl {{.*}} line:122:9 cbuffer CB
+// defined '__cblayout_B'
+// CHECK: HLSLBufferDecl {{.*}} line:[[# @LINE + 3]]:9 cbuffer CB
// CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
// CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
cbuffer CB {
@@ -124,18 +132,20 @@ cbuffer CB {
E s5;
// CHECK: VarDecl {{.*}} s6 'hlsl_constant BTypedef':'hlsl_constant B'
BTypedef s6;
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_CB_4 definition
- // CHECK: FieldDecl {{.*}} s5 '__layout_E'
- // CHECK: FieldDecl {{.*}} s6 '__layout_B'
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_CB_4 definition
+ // CHECK: PackedAttr
+ // CHECK-NEXT: FieldDecl {{.*}} s5 '__cblayout_E'
+ // CHECK-NEXT: FieldDecl {{.*}} s6 '__cblayout_B'
}
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_E definition
- // CHECK: FieldDecl {{.*}} c 'float'
- // CHECK-NOT: CXXRecordDecl {{.*}} class __layout_B definition
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __layout_E), "");
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __layout_CB_4), "");
+// CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_E definition
+// CHECK: PackedAttr
+// CHECK-NEXT: FieldDecl {{.*}} c 'float'
+// CHECK-NOT: CXXRecordDecl {{.*}} struct __cblayout_B definition
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __cblayout_E), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __cblayout_CB_4), "");
// check that this produces empty layout struct
-// CHECK: HLSLBufferDecl {{.*}} line:141:9 cbuffer CB
+// CHECK: HLSLBufferDecl {{.*}} line:[[# @LINE + 3]]:9 cbuffer CB
// CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
// CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
cbuffer CB {
@@ -149,27 +159,30 @@ cbuffer CB {
RWBuffer<float> Buf;
// CHECK: VarDecl {{.*}} ea 'EmptyArrayTypedef':'float[10][0]'
EmptyArrayTypedef ea;
- // CHECK: CXXRecordDecl {{.*}} implicit class __layout_CB_5 definition
+ // CHECK: CXXRecordDecl {{.*}} implicit struct __cblayout_CB_5 definition
+ // CHECK: PackedAttr
// CHECK-NOT: FieldDecl
}
// check host layout struct with compatible base struct
-// CHECK: HLSLBufferDecl {{.*}} line:160:9 cbuffer CB
+// CHECK: HLSLBufferDecl {{.*}} line:[[# @LINE + 3]]:9 cbuffer CB
// CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
// CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
cbuffer CB {
// CHECK: VarDecl {{.*}} s8 'hlsl_constant F'
F s8;
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_CB_6 definition
- // CHECK: FieldDecl {{.*}} s8 '__layout_F'
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_CB_6 definition
+ // CHECK: PackedAttr
+ // CHECK-NEXT: FieldDecl {{.*}} s8 '__cblayout_F'
}
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_F definition
- // CHECK: public 'A'
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __layout_F), "");
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __layout_CB_6), "");
+// CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_F definition
+// CHECK: public 'A'
+// CHECK: PackedAttr
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __cblayout_F), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __cblayout_CB_6), "");
// anonymous structs
-// CHECK: HLSLBufferDecl {{.*}} line:175:9 cbuffer CB
+// CHECK: HLSLBufferDecl {{.*}} line:[[# @LINE + 3]]:9 cbuffer CB
// CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
// CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
cbuffer CB {
@@ -182,7 +195,7 @@ cbuffer CB {
// CHECK: FieldDecl {{.*}} f 'RWBuffer<float>':'hlsl::RWBuffer<float>'
RWBuffer<float> f;
} s9;
- // CHECK: VarDecl {{.*}} s9 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:177:3
+ // CHECK: VarDecl {{.*}} s9 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:[[# @LINE - 8]]:3
// CHECK: CXXRecordDecl {{.*}} struct definition
struct {
// CHECK: FieldDecl {{.*}} g 'float'
@@ -190,18 +203,21 @@ cbuffer CB {
// CHECK: FieldDecl {{.*}} f 'RWBuffer<float>':'hlsl::RWBuffer<float>'
RWBuffer<float> f;
} s10;
- // CHECK: VarDecl {{.*}} s10 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:187:3
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_anon definition
- // CHECK: FieldDecl {{.*}} e 'float'
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_anon_1 definition
- // CHECK: FieldDecl {{.*}} g 'float'
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_CB_7 definition
- // CHECK: FieldDecl {{.*}} s9 '__layout_anon'
- // CHECK: FieldDecl {{.*}} s10 '__layout_anon_1'
+ // CHECK: VarDecl {{.*}} s10 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:[[# @LINE - 6]]:3
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_anon definition
+ // CHECK: PackedAttr
+ // CHECK-NEXT: FieldDecl {{.*}} e 'float'
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_anon_1 definition
+ // CHECK: PackedAttr
+ // CHECK-NEXT: FieldDecl {{.*}} g 'float'
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_CB_7 definition
+ // CHECK: PackedAttr
+ // CHECK-NEXT: FieldDecl {{.*}} s9 '__cblayout_anon'
+ // CHECK-NEXT: FieldDecl {{.*}} s10 '__cblayout_anon_1'
}
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __layout_anon), "");
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __layout_anon_1), "");
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __layout_CB_7), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __cblayout_anon), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(OneFloat, __cblayout_anon_1), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(TwoFloats, __cblayout_CB_7), "");
// Add uses for the constant buffer declarations so they are not optimized away
export float foo() {
diff --git a/clang/test/AST/HLSL/cbuffer_and_namespaces.hlsl b/clang/test/AST/HLSL/cbuffer_and_namespaces.hlsl
index 12ce327d8be022..09596eda90b6ae 100644
--- a/clang/test/AST/HLSL/cbuffer_and_namespaces.hlsl
+++ b/clang/test/AST/HLSL/cbuffer_and_namespaces.hlsl
@@ -19,10 +19,10 @@ namespace NS1 {
int b;
EmptyStruct es;
};
- // CHECK: CXXRecordDecl {{.*}} implicit class __layout_Foo definition
+ // CHECK: CXXRecordDecl {{.*}} implicit struct __cblayout_Foo definition
// CHECK: FieldDecl {{.*}} b 'int'
};
- // CHECK: CXXRecordDecl {{.*}} implicit class __layout_Foo definition
+ // CHECK: CXXRecordDecl {{.*}} implicit struct __cblayout_Foo definition
// CHECK: FieldDecl {{.*}} a 'float'
}
@@ -41,12 +41,12 @@ cbuffer CB1 {
NS1::Foo foo2;
// CHECK: VarDecl {{.*}} foo3 'hlsl_constant NS1::Bar::Foo'
NS1::Bar::Foo foo3;
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_CB1 definition
- // CHECK: FieldDecl {{.*}} foo1 '__layout_Foo'
- // CHECK: FieldDecl {{.*}} foo2 'NS1::__layout_Foo'
- // CHECK: FieldDecl {{.*}} foo3 'NS1::Bar::__layout_Foo'
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_CB1 definition
+ // CHECK: FieldDecl {{.*}} foo1 '__cblayout_Foo'
+ // CHECK: FieldDecl {{.*}} foo2 'NS1::__cblayout_Foo'
+ // CHECK: FieldDecl {{.*}} foo3 'NS1::Bar::__cblayout_Foo'
}
-// CHECK: CXXRecordDecl {{.*}} implicit class __layout_Foo definition
+// CHECK: CXXRecordDecl {{.*}} implicit struct __cblayout_Foo definition
// CHECK: FieldDecl {{.*}} c 'double'
struct CB1ExpectedShape {
@@ -54,7 +54,7 @@ struct CB1ExpectedShape {
float a2;
int a;
};
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(CB1ExpectedShape, __layout_CB1), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(CB1ExpectedShape, __cblayout_CB1), "");
namespace NS2 {
struct Foo {
@@ -73,13 +73,13 @@ namespace NS2 {
NS1::Foo foo2;
// CHECK: VarDecl {{.*}} foo3 'hlsl_constant NS1::Bar::Foo'
NS1::Bar::Foo foo3;
- // CHECK: CXXRecordDecl {{.*}} implicit referenced class __layout_CB2 definition
- // CHECK: FieldDecl {{.*}} foo0 '__layout_Foo'
- // CHECK: FieldDecl {{.*}} foo1 'NS2::__layout_Foo'
- // CHECK: FieldDecl {{.*}} foo2 'NS1::__layout_Foo'
- // CHECK: FieldDecl {{.*}} foo3 'NS1::Bar::__layout_Foo'
+ // CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_CB2 definition
+ // CHECK: FieldDecl {{.*}} foo0 '__cblayout_Foo'
+ // CHECK: FieldDecl {{.*}} foo1 'NS2::__cblayout_Foo'
+ // CHECK: FieldDecl {{.*}} foo2 'NS1::__cblayout_Foo'
+ // CHECK: FieldDecl {{.*}} foo3 'NS1::Bar::__cblayout_Foo'
}
- // CHECK: CXXRecordDecl {{.*}} implicit class __layout_Foo definition
+ // CHECK: CXXRecordDecl {{.*}} implicit struct __cblayout_Foo definition
// CHECK: FieldDecl {{.*}} d 'float[4]'
}
@@ -89,7 +89,7 @@ struct CB2ExpectedShape {
float a2;
int a;
};
-_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(CB2ExpectedShape, NS2::__layout_CB2), "");
+_Static_assert(__builtin_hlsl_is_scalarized_layout_compatible(CB2ExpectedShape, NS2::__cblayout_CB2), "");
// Add uses for the constant buffer declarations so they are not optimized away
// CHECK: ExportDecl
diff --git a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
index 98d7aba3978528..754948931ee538 100644
--- a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
+++ b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
@@ -21,14 +21,14 @@ float foo() {
// CHECK-NEXT: HLSLResourceClassAttr {{.*}} Implicit CBuffer
// CHECK-NEXT: HLSLResourceAttr {{.*}} Implicit CBuffer
// CHECK-NEXT: VarDecl 0x[[A:[0-9a-f]+]] {{.*}} imported used a 'hlsl_constant float'
-// CHECK-NEXT: CXXRecordDecl {{.*}} imported implicit <undeserialized declarations> class __layout_A definition
+// CHECK-NEXT: CXXRecordDecl {{.*}} imported implicit <undeserialized declarations> struct __cblayout_A definition
// CHECK: FieldDecl {{.*}} imported a 'float'
// CHECK: HLSLBufferDecl {{.*}} line:11:9 imported <undeserialized declarations> tbuffer B
// CHECK-NEXT: HLSLResourceClassAttr {{.*}} Implicit SRV
// CHECK-NEXT: HLSLResourceAttr {{.*}} Implicit TBuffer
// CHECK-NEXT: VarDecl 0x[[B:[0-9a-f]+]] {{.*}} imported used b 'hlsl_constant float'
-// CHECK-NEXT: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} imported implicit <undeserialized declarations> class __layout_B definition
+// CHECK-NEXT: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} imported implicit <undeserialized declarations> struct __cblayout_B definition
// CHECK: FieldDecl 0x{{[0-9a-f]+}} {{.*}} imported b 'float'
// CHECK-NEXT: FunctionDecl {{.*}} line:15:7 imported foo 'float ()'
>From c80415a22bf9b1e06928e84d8d0efa646fbaa5f9 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Tue, 28 Jan 2025 16:52:45 -0800
Subject: [PATCH 2/2] filter groupshared var decls
---
clang/lib/Sema/SemaHLSL.cpp | 3 ++-
clang/test/AST/HLSL/cbuffer.hlsl | 2 ++
2 files changed, 4 insertions(+), 1 deletion(-)
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 97df01a5dd3074..b71dd2b273a1c6 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -484,7 +484,8 @@ void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl) {
for (Decl *D : BufDecl->decls()) {
VarDecl *VD = dyn_cast<VarDecl>(D);
- if (!VD || VD->getStorageClass() == SC_Static)
+ if (!VD || VD->getStorageClass() == SC_Static ||
+ VD->getType().getAddressSpace() == LangAS::hlsl_groupshared)
continue;
const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
if (FieldDecl *FD =
diff --git a/clang/test/AST/HLSL/cbuffer.hlsl b/clang/test/AST/HLSL/cbuffer.hlsl
index 8254f0ee00b140..865db1201baa5b 100644
--- a/clang/test/AST/HLSL/cbuffer.hlsl
+++ b/clang/test/AST/HLSL/cbuffer.hlsl
@@ -71,6 +71,8 @@ cbuffer CB {
float d2[0];
// CHECK: VarDecl {{.*}} f2 'RWBuffer<float>[2]'
RWBuffer<float> f2[2];
+ // CHECK: VarDecl {{.*}} g2 'groupshared float'
+ groupshared float g2;
// CHECK: VarDecl {{.*}} e2 'hlsl_constant float'
float e2;
// CHECK: CXXRecordDecl {{.*}} implicit referenced struct __cblayout_CB_1 definition
More information about the cfe-commits
mailing list