Skip to content

[HLSL] Constant buffer layout struct update #124840

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 7 commits into from
Feb 11, 2025

Conversation

hekota
Copy link
Member

@hekota hekota commented Jan 28, 2025

Updates layout struct to be struct with public fields instead of class with private fields and chang the name prefix to __cblayout_. Also adds Packed attribute to prevent struct padding and filters additional types from the layout that were missed previously (arrays of resources and groupshared declarations).

- 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
@hekota hekota marked this pull request as ready for review January 28, 2025 21:53
@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" HLSL HLSL Language Support labels Jan 28, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 28, 2025

@llvm/pr-subscribers-hlsl

@llvm/pr-subscribers-clang

Author: Helena Kotas (hekota)

Changes
  • 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

Patch is 21.09 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/124840.diff

6 Files Affected:

  • (modified) clang/lib/Sema/SemaDecl.cpp (+7)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+17-12)
  • (modified) clang/test/AST/HLSL/ast-dump-comment-cbuffer.hlsl (-3)
  • (modified) clang/test/AST/HLSL/cbuffer.hlsl (+80-64)
  • (modified) clang/test/AST/HLSL/cbuffer_and_namespaces.hlsl (+15-15)
  • (modified) clang/test/AST/HLSL/pch_hlsl_buffer.hlsl (+2-2)
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 CBu...
[truncated]

@hekota hekota requested a review from bogner February 3, 2025 18:55
Copy link
Contributor

@bogner bogner left a comment

Choose a reason for hiding this comment

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

This all looks reasonable, though it is kind of a mess of random fixes. It's generally best to commit unrelated things individually, and it would be nice to have commit messages that are full sentences of what and why rather than a bulleted list of various things that changed.

@hekota
Copy link
Member Author

hekota commented Feb 4, 2025

All of these changes except one are related to layout structs. I will update the PR description to make it clearer and move that one unrelated change about synthetizing initializers to the constant buffer codegen PR.

@hekota hekota merged commit 1a0de96 into llvm:main Feb 11, 2025
9 checks passed
Icohedron pushed a commit to Icohedron/llvm-project that referenced this pull request Feb 11, 2025
Updates layout struct to be `struct` with public fields instead of
`class` with private fields and chang the name prefix to `__cblayout_`.
Also adds Packed attribute to prevent struct padding and filters
additional types from the layout that were missed previously (arrays of
resources and groupshared declarations).
joaosaffran pushed a commit to joaosaffran/llvm-project that referenced this pull request Feb 14, 2025
Updates layout struct to be `struct` with public fields instead of
`class` with private fields and chang the name prefix to `__cblayout_`.
Also adds Packed attribute to prevent struct padding and filters
additional types from the layout that were missed previously (arrays of
resources and groupshared declarations).
sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Feb 24, 2025
Updates layout struct to be `struct` with public fields instead of
`class` with private fields and chang the name prefix to `__cblayout_`.
Also adds Packed attribute to prevent struct padding and filters
additional types from the layout that were missed previously (arrays of
resources and groupshared declarations).
@damyanp damyanp moved this to Closed in HLSL Support Apr 25, 2025
@damyanp damyanp removed this from HLSL Support Jun 25, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants