Skip to content
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

[HLSL] Introduce address space hlsl_constant(2) for constant buffer declarations #123411

Merged
merged 4 commits into from
Jan 25, 2025

Conversation

hekota
Copy link
Member

@hekota hekota commented Jan 17, 2025

Introduces a new address space hlsl_constant(2) for constant buffer declarations.

This address space is applied to declarations inside cbuffer block. Later on, it will also be applied to ConstantBuffer<T> syntax and the default $Globals constant buffer.

Clang codegen translates constant buffer declarations to global variables and loads from hlsl_constant(2) address space. More work coming soon will include addition of metadata that will map these globals to individual constant buffers and enable their transformation to appropriate constant buffer load intrinsics later on in an LLVM pass.

Fixes #123406

@hekota hekota changed the title [HLSL] Add address space hlsl_constant(2) for constant buffer declarations [HLSL] Introduce address space hlsl_constant(2) for constant buffer declarations Jan 17, 2025
@hekota hekota marked this pull request as ready for review January 17, 2025 22:14
@llvmbot llvmbot added clang Clang issues not falling into any other category backend:AArch64 backend:AMDGPU backend:SystemZ backend:WebAssembly clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:codegen backend:DirectX HLSL HLSL Language Support labels Jan 17, 2025
@llvmbot
Copy link
Member

llvmbot commented Jan 17, 2025

@llvm/pr-subscribers-backend-aarch64
@llvm/pr-subscribers-clang
@llvm/pr-subscribers-backend-webassembly

@llvm/pr-subscribers-clang-codegen

Author: Helena Kotas (hekota)

Changes

Introduces a new address space hlsl_constant(2) for constant buffer declarations.

This address space is applied to declarations inside cbuffer block. Later on, it will also be applied to ConstantBuffer&lt;T&gt; syntax and the default $Globals constant buffer.

Clang codegen translates constant buffer declarations to global variables and loads from hlsl_constant(2) address space. More work coming soon will include addition of metadata that will map these globals to individual constant buffers and enable their transformation to appropriate constant buffer load intrinsics later on in an LLVM pass.

Fixes #123406


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

21 Files Affected:

  • (modified) clang/include/clang/Basic/AddressSpaces.h (+1)
  • (modified) clang/lib/AST/TypePrinter.cpp (+2)
  • (modified) clang/lib/Basic/Targets/AArch64.h (+1)
  • (modified) clang/lib/Basic/Targets/AMDGPU.cpp (+1)
  • (modified) clang/lib/Basic/Targets/DirectX.h (+1)
  • (modified) clang/lib/Basic/Targets/NVPTX.h (+1)
  • (modified) clang/lib/Basic/Targets/SPIR.h (+2)
  • (modified) clang/lib/Basic/Targets/SystemZ.h (+1)
  • (modified) clang/lib/Basic/Targets/TCE.h (+1)
  • (modified) clang/lib/Basic/Targets/WebAssembly.h (+1)
  • (modified) clang/lib/Basic/Targets/X86.h (+1)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (-16)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+12-3)
  • (modified) clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl (+8-8)
  • (modified) clang/test/AST/HLSL/cbuffer.hlsl (+12-12)
  • (modified) clang/test/AST/HLSL/packoffset.hlsl (+19-19)
  • (modified) clang/test/AST/HLSL/pch_hlsl_buffer.hlsl (+6-6)
  • (modified) clang/test/AST/HLSL/resource_binding_attr.hlsl (+4-4)
  • (modified) clang/test/CodeGenHLSL/cbuf.hlsl (+9-4)
  • (modified) clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl (+6-2)
  • (modified) clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl (+8-6)
diff --git a/clang/include/clang/Basic/AddressSpaces.h b/clang/include/clang/Basic/AddressSpaces.h
index 7b723d508fff17..d18bfe54931f93 100644
--- a/clang/include/clang/Basic/AddressSpaces.h
+++ b/clang/include/clang/Basic/AddressSpaces.h
@@ -58,6 +58,7 @@ enum class LangAS : unsigned {
 
   // HLSL specific address spaces.
   hlsl_groupshared,
+  hlsl_constant,
 
   // Wasm specific address spaces.
   wasm_funcref,
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index a850410ffc8468..6cad74fef3fe33 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2556,6 +2556,8 @@ std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
     return "__funcref";
   case LangAS::hlsl_groupshared:
     return "groupshared";
+  case LangAS::hlsl_constant:
+    return "hlsl_constant";
   default:
     return std::to_string(toTargetAddressSpace(AS));
   }
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index ecf80b23a508c9..600940f5e4e23c 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -44,6 +44,7 @@ static const unsigned ARM64AddrSpaceMap[] = {
     static_cast<unsigned>(AArch64AddrSpace::ptr32_uptr),
     static_cast<unsigned>(AArch64AddrSpace::ptr64),
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp
index 99f8f2944e2796..824134d52ec139 100644
--- a/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -83,6 +83,7 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
     llvm::AMDGPUAS::FLAT_ADDRESS, // ptr32_uptr
     llvm::AMDGPUAS::FLAT_ADDRESS, // ptr64
     llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_groupshared
+    llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_constant
 
 };
 } // namespace targets
diff --git a/clang/lib/Basic/Targets/DirectX.h b/clang/lib/Basic/Targets/DirectX.h
index ab22d1281a4df7..4e6bc0e040398b 100644
--- a/clang/lib/Basic/Targets/DirectX.h
+++ b/clang/lib/Basic/Targets/DirectX.h
@@ -42,6 +42,7 @@ static const unsigned DirectXAddrSpaceMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     3, // hlsl_groupshared
+    2, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h
index d81b89a7f24ac0..c6531148fe30ce 100644
--- a/clang/lib/Basic/Targets/NVPTX.h
+++ b/clang/lib/Basic/Targets/NVPTX.h
@@ -46,6 +46,7 @@ static const unsigned NVPTXAddrSpaceMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index 5a328b9ceeb1d1..c0849b69dcdb32 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -47,6 +47,7 @@ static const unsigned SPIRDefIsPrivMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    2, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
@@ -80,6 +81,7 @@ static const unsigned SPIRDefIsGenMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index e6405f174f660f..66a1bf6a38b51b 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -42,6 +42,7 @@ static const unsigned ZOSAddressMap[] = {
     1, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     0  // wasm_funcref
 };
 
diff --git a/clang/lib/Basic/Targets/TCE.h b/clang/lib/Basic/Targets/TCE.h
index d6280b02f07b25..edec30bf69de0c 100644
--- a/clang/lib/Basic/Targets/TCE.h
+++ b/clang/lib/Basic/Targets/TCE.h
@@ -51,6 +51,7 @@ static const unsigned TCEOpenCLAddrSpaceMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h
index 0a14da6a277b8e..cfecc59ac75fd9 100644
--- a/clang/lib/Basic/Targets/WebAssembly.h
+++ b/clang/lib/Basic/Targets/WebAssembly.h
@@ -42,6 +42,7 @@ static const unsigned WebAssemblyAddrSpaceMap[] = {
     0,  // ptr32_uptr
     0,  // ptr64
     0,  // hlsl_groupshared
+    0,  // hlsl_constant
     20, // wasm_funcref
 };
 
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index 2c200e64a3d84d..8bd54e362526fb 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -46,6 +46,7 @@ static const unsigned X86AddrSpaceMap[] = {
     271, // ptr32_uptr
     272, // ptr64
     0,   // hlsl_groupshared
+    0,   // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 5679bd71581795..127bd4a7fc27f0 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -100,22 +100,6 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {
       llvm::formatv("{0}{1}", Buf.Name, Buf.IsCBuffer ? ".cb." : ".tb."),
       GlobalValue::NotThreadLocal);
 
-  IRBuilder<> B(CBGV->getContext());
-  Value *ZeroIdx = B.getInt32(0);
-  // Replace Const use with CB use.
-  for (auto &[GV, Offset] : Buf.Constants) {
-    Value *GEP =
-        B.CreateGEP(Buf.LayoutStruct, CBGV, {ZeroIdx, B.getInt32(Offset)});
-
-    assert(Buf.LayoutStruct->getElementType(Offset) == GV->getValueType() &&
-           "constant type mismatch");
-
-    // Replace.
-    GV->replaceAllUsesWith(GEP);
-    // Erase GV.
-    GV->removeDeadConstantUsers();
-    GV->eraseFromParent();
-  }
   return CBGV;
 }
 
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 9bbd0ad1eb4a64..372db586f8d8ea 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -24,6 +24,7 @@
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
@@ -455,14 +456,22 @@ void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl) {
   LS->setImplicit(true);
   LS->startDefinition();
 
-  for (const Decl *D : BufDecl->decls()) {
-    const VarDecl *VD = dyn_cast<VarDecl>(D);
+  for (Decl *D : BufDecl->decls()) {
+    VarDecl *VD = dyn_cast<VarDecl>(D);
     if (!VD || VD->getStorageClass() == SC_Static)
       continue;
     const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
     if (FieldDecl *FD = createFieldForHostLayoutStruct(
-            S, Ty, VD->getIdentifier(), LS, BufDecl))
+            S, Ty, VD->getIdentifier(), LS, BufDecl)) {
+      // add the field decl to the layout struct
       LS->addDecl(FD);
+      // update address space of the original decl to hlsl_constant
+      // and disable initialization
+      QualType NewTy =
+          AST.getAddrSpaceQualType(VD->getType(), LangAS::hlsl_constant);
+      VD->setType(NewTy);
+      VD->setInit(nullptr);
+    }
   }
   LS->completeDefinition();
   BufDecl->addDecl(LS);
diff --git a/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl b/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl
index aebb7c0e8da334..3cca808ae75b63 100644
--- a/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl
+++ b/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl
@@ -11,11 +11,11 @@
 cbuffer A {
     // JSON: "kind": "VarDecl",
     // JSON: "name": "a",
-    // JSON: "qualType": "float"
+    // JSON: "qualType": "hlsl_constant float"
     float a;
     // JSON: "kind": "VarDecl",
     // JSON: "name": "b",
-    // JSON: "qualType": "int"
+    // JSON: "qualType": "hlsl_constant int"
     int b;
 }
 
@@ -29,11 +29,11 @@ cbuffer A {
 tbuffer B {
     // JSON: "kind": "VarDecl",
     // JSON: "name": "c",
-    // JSON: "qualType": "float"
+    // JSON: "qualType": "hlsl_constant float"
     float c;
     // JSON: "kind": "VarDecl",
     // JSON: "name": "d",
-    // JSON: "qualType": "int"
+    // JSON: "qualType": "hlsl_constant int"
     int d;
 }
 
@@ -43,8 +43,8 @@ tbuffer B {
 // AST-NEXT: FullComment
 // AST-NEXT: ParagraphComment
 // AST-NEXT: TextComment {{.*}} Text=" CBuffer decl."
-// AST-NEXT: VarDecl {{.*}} a 'float'
-// AST-NEXT: VarDecl {{.*}} b 'int'
+// 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'
@@ -55,8 +55,8 @@ tbuffer B {
 // AST-NEXT: FullComment
 // AST-NEXT: ParagraphComment
 // AST-NEXT: TextComment {{.*}} Text=" TBuffer decl."
-// AST-NEXT: VarDecl {{.*}} c 'float'
-// AST-NEXT: VarDecl {{.*}} d 'int'
+// AST-NEXT: VarDecl {{.*}} c 'hlsl_constant float'
+// AST-NEXT: VarDecl {{.*}} d 'hlsl_constant int'
 // AST-NEXT: CXXRecordDecl {{.*}} implicit class __layout.B definition
 // AST: FieldDecl {{.*}} c 'float'
 // AST-NEXT: FieldDecl {{.*}} d 'int'
diff --git a/clang/test/AST/HLSL/cbuffer.hlsl b/clang/test/AST/HLSL/cbuffer.hlsl
index a20485606a79d0..1d933fcb1adebd 100644
--- a/clang/test/AST/HLSL/cbuffer.hlsl
+++ b/clang/test/AST/HLSL/cbuffer.hlsl
@@ -39,7 +39,7 @@ typedef float EmptyArrayTypedef[10][0];
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} col:9 used a1 'float'
+  // CHECK: VarDecl {{.*}} col:9 used a1 'hlsl_constant float'
   float a1;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.CB definition
   // CHECK: FieldDecl {{.*}} a1 'float'
@@ -50,7 +50,7 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} col:9 used a2 'float'
+  // CHECK: VarDecl {{.*}} col:9 used a2 'hlsl_constant float'
   float a2;
   // CHECK: VarDecl {{.*}} col:19 b2 'RWBuffer<float>':'hlsl::RWBuffer<float>'
   RWBuffer<float> b2; 
@@ -58,7 +58,7 @@ cbuffer CB {
   EmptyStruct c2;
   // CHECK: VarDecl {{.*}} col:9 d2 'float[0]'
   float d2[0];
-  // CHECK: VarDecl {{.*}} col:9 e2 'float'
+  // CHECK: VarDecl {{.*}} col:9 e2 'hlsl_constant float'
   float e2;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.CB.1 definition
   // CHECK: FieldDecl {{.*}} a2 'float'
@@ -70,11 +70,11 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} col:5 used s1 'A'
+  // CHECK: VarDecl {{.*}} col:5 used s1 'hlsl_constant A'
   A s1;
-  // CHECK: VarDecl {{.*}} col:5 s2 'B'
+  // CHECK: VarDecl {{.*}} col:5 s2 'hlsl_constant B'
   B s2;
-  // CHECK: VarDecl {{.*}} col:12 s3 'CTypedef':'C
+  // CHECK: VarDecl {{.*}} col:12 s3 'CTypedef':'C'
   CTypedef s3;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.B definition
   // CHECK: FieldDecl {{.*}} a 'float'
@@ -88,7 +88,7 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} s4 'D'
+  // CHECK: VarDecl {{.*}} s4 'hlsl_constant D'
   D s4;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.D definition
   // CHECK: FieldDecl {{.*}} b 'float'
@@ -103,9 +103,9 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}}  s5 'E'
+  // CHECK: VarDecl {{.*}}  s5 'hlsl_constant E'
   E s5;
-  // CHECK: VarDecl {{.*}} s6 'BTypedef':'B'
+  // CHECK: VarDecl {{.*}} s6 'hlsl_constant BTypedef':'hlsl_constant B'
   BTypedef s6;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.E definition
   // CHECK: FieldDecl {{.*}} c 'float'
@@ -139,7 +139,7 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} s8 'F'
+  // CHECK: VarDecl {{.*}} s8 'hlsl_constant F'
   F s8;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.F definition
   // CHECK: public 'A'
@@ -161,7 +161,7 @@ cbuffer CB {
     // CHECK: FieldDecl {{.*}} f 'RWBuffer<float>':'hlsl::RWBuffer<float>'
     RWBuffer<float> f;
   } s9;
-  // CHECK: VarDecl {{.*}} s9 'struct (unnamed struct at {{.*}}cbuffer.hlsl:156:3
+  // CHECK: VarDecl {{.*}} s9 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:156:3
   // CHECK: CXXRecordDecl {{.*}} struct definition
   struct {
     // CHECK: FieldDecl {{.*}} g 'int'
@@ -169,7 +169,7 @@ cbuffer CB {
     // CHECK: FieldDecl {{.*}} f 'RWBuffer<float>':'hlsl::RWBuffer<float>'
     RWBuffer<float> f;
   } s10;
-  // CHECK: VarDecl {{.*}} s10 'struct (unnamed struct at {{.*}}cbuffer.hlsl:166:3
+  // CHECK: VarDecl {{.*}} s10 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:166:3
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.anon definition
   // CHECK: FieldDecl {{.*}} e 'float'
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.anon.1 definition
diff --git a/clang/test/AST/HLSL/packoffset.hlsl b/clang/test/AST/HLSL/packoffset.hlsl
index 9c928bd6d922ed..a9bb90bb386f9c 100644
--- a/clang/test/AST/HLSL/packoffset.hlsl
+++ b/clang/test/AST/HLSL/packoffset.hlsl
@@ -6,13 +6,13 @@ cbuffer A
 {
     // CHECK-NEXT:-HLSLResourceClassAttr {{.*}} <<invalid sloc>> Implicit CBuffer
     // CHECK-NEXT:-HLSLResourceAttr {{.*}} <<invalid sloc>> Implicit CBuffer
-    // CHECK-NEXT: VarDecl {{.*}} A1 'float4'
+    // CHECK-NEXT: VarDecl {{.*}} A1 'hlsl_constant float4'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 0
     float4 A1 : packoffset(c);
-    // CHECK-NEXT: VarDecl {{.*}} col:11 A2 'float'
+    // CHECK-NEXT: VarDecl {{.*}} col:11 A2 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1 0
     float A2 : packoffset(c1);
-    // CHECK-NEXT: VarDecl {{.*}} col:11 A3 'float'
+    // CHECK-NEXT: VarDecl {{.*}} col:11 A3 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1 1
     float A3 : packoffset(c1.y);
 }
@@ -20,13 +20,13 @@ cbuffer A
 // CHECK: HLSLBufferDecl {{.*}} cbuffer B
 cbuffer B
 {
-    // CHECK: VarDecl {{.*}} B0 'float'
+    // CHECK: VarDecl {{.*}} B0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 1
     float B0 : packoffset(c0.g);
-    // CHECK-NEXT: VarDecl {{.*}} B1 'double'
+    // CHECK-NEXT: VarDecl {{.*}} B1 'hlsl_constant double'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 2
 	double B1 : packoffset(c0.b);
-    // CHECK-NEXT: VarDecl {{.*}} B2 'half'
+    // CHECK-NEXT: VarDecl {{.*}} B2 'hlsl_constant half'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 0
 	half B2 : packoffset(c0.r);
 }
@@ -34,13 +34,13 @@ cbuffer B
 // CHECK: HLSLBufferDecl {{.*}} cbuffer C
 cbuffer C
 {
-    // CHECK: VarDecl {{.*}} C0 'float'
+    // CHECK: VarDecl {{.*}} C0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1
     float C0 : packoffset(c0.y);
-    // CHECK-NEXT: VarDecl {{.*}} C1 'float2'
+    // CHECK-NEXT: VarDecl {{.*}} C1 'hlsl_constant float2'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 2
 	float2 C1 : packoffset(c0.z);
-    // CHECK-NEXT: VarDecl {{.*}} C2 'half'
+    // CHECK-NEXT: VarDecl {{.*}} C2 'hlsl_constant half'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0
 	half C2 : packoffset(c0.x);
 }
@@ -49,16 +49,16 @@ cbuffer C
 // CHECK: HLSLBufferDecl {{.*}} cbuffer D
 cbuffer D
 {
-    // CHECK: VarDecl {{.*}} D0 'float'
+    // CHECK: VarDecl {{.*}} D0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 1
     float D0 : packoffset(c0.y);
-    // CHECK-NEXT: VarDecl {{.*}} D1 'float[2]'
+    // CHECK-NEXT: VarDecl {{.*}} D1 'hlsl_constant float[2]'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1 0
 	float D1[2] : packoffset(c1.x);
-    // CHECK-NEXT: VarDecl {{.*}} D2 'half3'
+    // CHECK-NEXT: VarDecl {{.*}} D2 'hlsl_constant half3'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 2 1
 	half3 D2 : packoffset(c2.y);
-    // CHECK-NEXT: VarDecl {{.*}} D3 'double'
+    // CHECK-NEXT: VarDecl {{.*}} D3 'hlsl_constant double'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 2
 	double D3 : packoffset(c0.z);
 }
@@ -71,13 +71,13 @@ struct ST {
 
 // CHECK: HLSLBufferDecl {{.*}} cbuffer S
 cbuffer S {
-    // CHECK: VarDecl {{.*}} S0 'float'
+    // CHECK: VarDecl {{.*}} S0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 1
   float S0 : packoffset(c0.y);
-    // CHECK: VarDecl {{.*}} S1 'ST'
+    // CHECK: VarDecl {{.*}} S1 'hlsl_constant ST'
     // CHECK: HLSLPackOffsetAttr {{.*}} 1 0
   ST S1 : packoffset(c1);
-    // CHECK: VarDecl {{.*}} S2 'double2'
+    // CHECK: VarDecl {{.*}} S2 'hlsl_constant double2'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 2 0
   double2 S2 : packoffset(c2);
 }
@@ -90,13 +90,13 @@ struct ST2 {
 
 // CHECK: HLSLBufferDecl {{.*}} cbuffer S2
 cbuffer S2 {
-    // CHECK: VarDecl {{.*}} S20 'float'
+    // CHECK: VarDecl {{.*}} S20 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 3
   float S20 : packoffset(c0.a);
-    // CHECK: VarDecl {{.*}} S21 'ST2'
+    // CHECK: VarDecl {{.*}} S21 'hlsl_constant ST2'
     // CHECK: HLSLPackOffsetAttr {{.*}} 1 0
   ST2 S21 : packoffset(c1);
-    // CHECK: VarDecl {{.*}} S22 'half'
+    // CHECK: VarDecl {{.*}} S22 'hlsl_constant half'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 3 1
   half S22 : packoffset(c3.y);
 }
diff --git a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
index 02310c068c166e..3bfe8467544928 100644
--- a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
+++ b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
@@ -20,22 +20,22 @@ float foo() {
 // CHECK: HLSLBufferDecl {{.*}} line:7:9 imported <undeserialized declarations> cbuffer A
 // CHECK-NEXT: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK-NEXT: HLSLResourceAttr {{.*}} Implicit CBuffer
-// CHECK-NEXT: VarDecl 0x[[A:[0-9a-f]+]] {{.*}} imported used a 'float'
+// 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: 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 'float'
-// CHECK-NEXT: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} imported implicit <undeserialized declarations> class __layout.B definition
-// CHECK: FieldDecl 0x{{[0-9a-f]+}} {{.*}} imported b 'float'
+// CHECK-NEXT: VarDecl 0x[[B:[0-9a-f]+]] {{.*}} imported used b 'hlsl_constant float'
+// CHECK-NEXT: CXXRecordDecl {{.*}} imported implicit <undeserialized declarations> class __layout.B definition
+// CHECK: FieldDecl {{.*}} imported b 'float'
 
 // CHECK-NEXT: FunctionDecl {{.*}} line:15:7 imported foo 'float ()'
 // CHECK-NEXT: CompoundStmt {{.*}}
 // CHECK-NEXT: ReturnStmt {{.*}}
 // CHECK-NEXT: BinaryOperator {{.*}} 'float' '+'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
-// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue Var 0x[[A]] 'a' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl_constant float' lvalue Var 0x[[A]] 'a' 'hlsl_constant float'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
-// CHECK-NEXT: DeclRefExpr {{.*}} 'f...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Jan 17, 2025

@llvm/pr-subscribers-backend-systemz

Author: Helena Kotas (hekota)

Changes

Introduces a new address space hlsl_constant(2) for constant buffer declarations.

This address space is applied to declarations inside cbuffer block. Later on, it will also be applied to ConstantBuffer&lt;T&gt; syntax and the default $Globals constant buffer.

Clang codegen translates constant buffer declarations to global variables and loads from hlsl_constant(2) address space. More work coming soon will include addition of metadata that will map these globals to individual constant buffers and enable their transformation to appropriate constant buffer load intrinsics later on in an LLVM pass.

Fixes #123406


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

21 Files Affected:

  • (modified) clang/include/clang/Basic/AddressSpaces.h (+1)
  • (modified) clang/lib/AST/TypePrinter.cpp (+2)
  • (modified) clang/lib/Basic/Targets/AArch64.h (+1)
  • (modified) clang/lib/Basic/Targets/AMDGPU.cpp (+1)
  • (modified) clang/lib/Basic/Targets/DirectX.h (+1)
  • (modified) clang/lib/Basic/Targets/NVPTX.h (+1)
  • (modified) clang/lib/Basic/Targets/SPIR.h (+2)
  • (modified) clang/lib/Basic/Targets/SystemZ.h (+1)
  • (modified) clang/lib/Basic/Targets/TCE.h (+1)
  • (modified) clang/lib/Basic/Targets/WebAssembly.h (+1)
  • (modified) clang/lib/Basic/Targets/X86.h (+1)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (-16)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+12-3)
  • (modified) clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl (+8-8)
  • (modified) clang/test/AST/HLSL/cbuffer.hlsl (+12-12)
  • (modified) clang/test/AST/HLSL/packoffset.hlsl (+19-19)
  • (modified) clang/test/AST/HLSL/pch_hlsl_buffer.hlsl (+6-6)
  • (modified) clang/test/AST/HLSL/resource_binding_attr.hlsl (+4-4)
  • (modified) clang/test/CodeGenHLSL/cbuf.hlsl (+9-4)
  • (modified) clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl (+6-2)
  • (modified) clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl (+8-6)
diff --git a/clang/include/clang/Basic/AddressSpaces.h b/clang/include/clang/Basic/AddressSpaces.h
index 7b723d508fff17..d18bfe54931f93 100644
--- a/clang/include/clang/Basic/AddressSpaces.h
+++ b/clang/include/clang/Basic/AddressSpaces.h
@@ -58,6 +58,7 @@ enum class LangAS : unsigned {
 
   // HLSL specific address spaces.
   hlsl_groupshared,
+  hlsl_constant,
 
   // Wasm specific address spaces.
   wasm_funcref,
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index a850410ffc8468..6cad74fef3fe33 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2556,6 +2556,8 @@ std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
     return "__funcref";
   case LangAS::hlsl_groupshared:
     return "groupshared";
+  case LangAS::hlsl_constant:
+    return "hlsl_constant";
   default:
     return std::to_string(toTargetAddressSpace(AS));
   }
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index ecf80b23a508c9..600940f5e4e23c 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -44,6 +44,7 @@ static const unsigned ARM64AddrSpaceMap[] = {
     static_cast<unsigned>(AArch64AddrSpace::ptr32_uptr),
     static_cast<unsigned>(AArch64AddrSpace::ptr64),
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp
index 99f8f2944e2796..824134d52ec139 100644
--- a/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -83,6 +83,7 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
     llvm::AMDGPUAS::FLAT_ADDRESS, // ptr32_uptr
     llvm::AMDGPUAS::FLAT_ADDRESS, // ptr64
     llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_groupshared
+    llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_constant
 
 };
 } // namespace targets
diff --git a/clang/lib/Basic/Targets/DirectX.h b/clang/lib/Basic/Targets/DirectX.h
index ab22d1281a4df7..4e6bc0e040398b 100644
--- a/clang/lib/Basic/Targets/DirectX.h
+++ b/clang/lib/Basic/Targets/DirectX.h
@@ -42,6 +42,7 @@ static const unsigned DirectXAddrSpaceMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     3, // hlsl_groupshared
+    2, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h
index d81b89a7f24ac0..c6531148fe30ce 100644
--- a/clang/lib/Basic/Targets/NVPTX.h
+++ b/clang/lib/Basic/Targets/NVPTX.h
@@ -46,6 +46,7 @@ static const unsigned NVPTXAddrSpaceMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index 5a328b9ceeb1d1..c0849b69dcdb32 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -47,6 +47,7 @@ static const unsigned SPIRDefIsPrivMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    2, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
@@ -80,6 +81,7 @@ static const unsigned SPIRDefIsGenMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index e6405f174f660f..66a1bf6a38b51b 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -42,6 +42,7 @@ static const unsigned ZOSAddressMap[] = {
     1, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     0  // wasm_funcref
 };
 
diff --git a/clang/lib/Basic/Targets/TCE.h b/clang/lib/Basic/Targets/TCE.h
index d6280b02f07b25..edec30bf69de0c 100644
--- a/clang/lib/Basic/Targets/TCE.h
+++ b/clang/lib/Basic/Targets/TCE.h
@@ -51,6 +51,7 @@ static const unsigned TCEOpenCLAddrSpaceMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h
index 0a14da6a277b8e..cfecc59ac75fd9 100644
--- a/clang/lib/Basic/Targets/WebAssembly.h
+++ b/clang/lib/Basic/Targets/WebAssembly.h
@@ -42,6 +42,7 @@ static const unsigned WebAssemblyAddrSpaceMap[] = {
     0,  // ptr32_uptr
     0,  // ptr64
     0,  // hlsl_groupshared
+    0,  // hlsl_constant
     20, // wasm_funcref
 };
 
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index 2c200e64a3d84d..8bd54e362526fb 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -46,6 +46,7 @@ static const unsigned X86AddrSpaceMap[] = {
     271, // ptr32_uptr
     272, // ptr64
     0,   // hlsl_groupshared
+    0,   // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 5679bd71581795..127bd4a7fc27f0 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -100,22 +100,6 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {
       llvm::formatv("{0}{1}", Buf.Name, Buf.IsCBuffer ? ".cb." : ".tb."),
       GlobalValue::NotThreadLocal);
 
-  IRBuilder<> B(CBGV->getContext());
-  Value *ZeroIdx = B.getInt32(0);
-  // Replace Const use with CB use.
-  for (auto &[GV, Offset] : Buf.Constants) {
-    Value *GEP =
-        B.CreateGEP(Buf.LayoutStruct, CBGV, {ZeroIdx, B.getInt32(Offset)});
-
-    assert(Buf.LayoutStruct->getElementType(Offset) == GV->getValueType() &&
-           "constant type mismatch");
-
-    // Replace.
-    GV->replaceAllUsesWith(GEP);
-    // Erase GV.
-    GV->removeDeadConstantUsers();
-    GV->eraseFromParent();
-  }
   return CBGV;
 }
 
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 9bbd0ad1eb4a64..372db586f8d8ea 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -24,6 +24,7 @@
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
@@ -455,14 +456,22 @@ void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl) {
   LS->setImplicit(true);
   LS->startDefinition();
 
-  for (const Decl *D : BufDecl->decls()) {
-    const VarDecl *VD = dyn_cast<VarDecl>(D);
+  for (Decl *D : BufDecl->decls()) {
+    VarDecl *VD = dyn_cast<VarDecl>(D);
     if (!VD || VD->getStorageClass() == SC_Static)
       continue;
     const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
     if (FieldDecl *FD = createFieldForHostLayoutStruct(
-            S, Ty, VD->getIdentifier(), LS, BufDecl))
+            S, Ty, VD->getIdentifier(), LS, BufDecl)) {
+      // add the field decl to the layout struct
       LS->addDecl(FD);
+      // update address space of the original decl to hlsl_constant
+      // and disable initialization
+      QualType NewTy =
+          AST.getAddrSpaceQualType(VD->getType(), LangAS::hlsl_constant);
+      VD->setType(NewTy);
+      VD->setInit(nullptr);
+    }
   }
   LS->completeDefinition();
   BufDecl->addDecl(LS);
diff --git a/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl b/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl
index aebb7c0e8da334..3cca808ae75b63 100644
--- a/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl
+++ b/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl
@@ -11,11 +11,11 @@
 cbuffer A {
     // JSON: "kind": "VarDecl",
     // JSON: "name": "a",
-    // JSON: "qualType": "float"
+    // JSON: "qualType": "hlsl_constant float"
     float a;
     // JSON: "kind": "VarDecl",
     // JSON: "name": "b",
-    // JSON: "qualType": "int"
+    // JSON: "qualType": "hlsl_constant int"
     int b;
 }
 
@@ -29,11 +29,11 @@ cbuffer A {
 tbuffer B {
     // JSON: "kind": "VarDecl",
     // JSON: "name": "c",
-    // JSON: "qualType": "float"
+    // JSON: "qualType": "hlsl_constant float"
     float c;
     // JSON: "kind": "VarDecl",
     // JSON: "name": "d",
-    // JSON: "qualType": "int"
+    // JSON: "qualType": "hlsl_constant int"
     int d;
 }
 
@@ -43,8 +43,8 @@ tbuffer B {
 // AST-NEXT: FullComment
 // AST-NEXT: ParagraphComment
 // AST-NEXT: TextComment {{.*}} Text=" CBuffer decl."
-// AST-NEXT: VarDecl {{.*}} a 'float'
-// AST-NEXT: VarDecl {{.*}} b 'int'
+// 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'
@@ -55,8 +55,8 @@ tbuffer B {
 // AST-NEXT: FullComment
 // AST-NEXT: ParagraphComment
 // AST-NEXT: TextComment {{.*}} Text=" TBuffer decl."
-// AST-NEXT: VarDecl {{.*}} c 'float'
-// AST-NEXT: VarDecl {{.*}} d 'int'
+// AST-NEXT: VarDecl {{.*}} c 'hlsl_constant float'
+// AST-NEXT: VarDecl {{.*}} d 'hlsl_constant int'
 // AST-NEXT: CXXRecordDecl {{.*}} implicit class __layout.B definition
 // AST: FieldDecl {{.*}} c 'float'
 // AST-NEXT: FieldDecl {{.*}} d 'int'
diff --git a/clang/test/AST/HLSL/cbuffer.hlsl b/clang/test/AST/HLSL/cbuffer.hlsl
index a20485606a79d0..1d933fcb1adebd 100644
--- a/clang/test/AST/HLSL/cbuffer.hlsl
+++ b/clang/test/AST/HLSL/cbuffer.hlsl
@@ -39,7 +39,7 @@ typedef float EmptyArrayTypedef[10][0];
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} col:9 used a1 'float'
+  // CHECK: VarDecl {{.*}} col:9 used a1 'hlsl_constant float'
   float a1;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.CB definition
   // CHECK: FieldDecl {{.*}} a1 'float'
@@ -50,7 +50,7 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} col:9 used a2 'float'
+  // CHECK: VarDecl {{.*}} col:9 used a2 'hlsl_constant float'
   float a2;
   // CHECK: VarDecl {{.*}} col:19 b2 'RWBuffer<float>':'hlsl::RWBuffer<float>'
   RWBuffer<float> b2; 
@@ -58,7 +58,7 @@ cbuffer CB {
   EmptyStruct c2;
   // CHECK: VarDecl {{.*}} col:9 d2 'float[0]'
   float d2[0];
-  // CHECK: VarDecl {{.*}} col:9 e2 'float'
+  // CHECK: VarDecl {{.*}} col:9 e2 'hlsl_constant float'
   float e2;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.CB.1 definition
   // CHECK: FieldDecl {{.*}} a2 'float'
@@ -70,11 +70,11 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} col:5 used s1 'A'
+  // CHECK: VarDecl {{.*}} col:5 used s1 'hlsl_constant A'
   A s1;
-  // CHECK: VarDecl {{.*}} col:5 s2 'B'
+  // CHECK: VarDecl {{.*}} col:5 s2 'hlsl_constant B'
   B s2;
-  // CHECK: VarDecl {{.*}} col:12 s3 'CTypedef':'C
+  // CHECK: VarDecl {{.*}} col:12 s3 'CTypedef':'C'
   CTypedef s3;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.B definition
   // CHECK: FieldDecl {{.*}} a 'float'
@@ -88,7 +88,7 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} s4 'D'
+  // CHECK: VarDecl {{.*}} s4 'hlsl_constant D'
   D s4;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.D definition
   // CHECK: FieldDecl {{.*}} b 'float'
@@ -103,9 +103,9 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}}  s5 'E'
+  // CHECK: VarDecl {{.*}}  s5 'hlsl_constant E'
   E s5;
-  // CHECK: VarDecl {{.*}} s6 'BTypedef':'B'
+  // CHECK: VarDecl {{.*}} s6 'hlsl_constant BTypedef':'hlsl_constant B'
   BTypedef s6;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.E definition
   // CHECK: FieldDecl {{.*}} c 'float'
@@ -139,7 +139,7 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} s8 'F'
+  // CHECK: VarDecl {{.*}} s8 'hlsl_constant F'
   F s8;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.F definition
   // CHECK: public 'A'
@@ -161,7 +161,7 @@ cbuffer CB {
     // CHECK: FieldDecl {{.*}} f 'RWBuffer<float>':'hlsl::RWBuffer<float>'
     RWBuffer<float> f;
   } s9;
-  // CHECK: VarDecl {{.*}} s9 'struct (unnamed struct at {{.*}}cbuffer.hlsl:156:3
+  // CHECK: VarDecl {{.*}} s9 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:156:3
   // CHECK: CXXRecordDecl {{.*}} struct definition
   struct {
     // CHECK: FieldDecl {{.*}} g 'int'
@@ -169,7 +169,7 @@ cbuffer CB {
     // CHECK: FieldDecl {{.*}} f 'RWBuffer<float>':'hlsl::RWBuffer<float>'
     RWBuffer<float> f;
   } s10;
-  // CHECK: VarDecl {{.*}} s10 'struct (unnamed struct at {{.*}}cbuffer.hlsl:166:3
+  // CHECK: VarDecl {{.*}} s10 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:166:3
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.anon definition
   // CHECK: FieldDecl {{.*}} e 'float'
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.anon.1 definition
diff --git a/clang/test/AST/HLSL/packoffset.hlsl b/clang/test/AST/HLSL/packoffset.hlsl
index 9c928bd6d922ed..a9bb90bb386f9c 100644
--- a/clang/test/AST/HLSL/packoffset.hlsl
+++ b/clang/test/AST/HLSL/packoffset.hlsl
@@ -6,13 +6,13 @@ cbuffer A
 {
     // CHECK-NEXT:-HLSLResourceClassAttr {{.*}} <<invalid sloc>> Implicit CBuffer
     // CHECK-NEXT:-HLSLResourceAttr {{.*}} <<invalid sloc>> Implicit CBuffer
-    // CHECK-NEXT: VarDecl {{.*}} A1 'float4'
+    // CHECK-NEXT: VarDecl {{.*}} A1 'hlsl_constant float4'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 0
     float4 A1 : packoffset(c);
-    // CHECK-NEXT: VarDecl {{.*}} col:11 A2 'float'
+    // CHECK-NEXT: VarDecl {{.*}} col:11 A2 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1 0
     float A2 : packoffset(c1);
-    // CHECK-NEXT: VarDecl {{.*}} col:11 A3 'float'
+    // CHECK-NEXT: VarDecl {{.*}} col:11 A3 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1 1
     float A3 : packoffset(c1.y);
 }
@@ -20,13 +20,13 @@ cbuffer A
 // CHECK: HLSLBufferDecl {{.*}} cbuffer B
 cbuffer B
 {
-    // CHECK: VarDecl {{.*}} B0 'float'
+    // CHECK: VarDecl {{.*}} B0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 1
     float B0 : packoffset(c0.g);
-    // CHECK-NEXT: VarDecl {{.*}} B1 'double'
+    // CHECK-NEXT: VarDecl {{.*}} B1 'hlsl_constant double'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 2
 	double B1 : packoffset(c0.b);
-    // CHECK-NEXT: VarDecl {{.*}} B2 'half'
+    // CHECK-NEXT: VarDecl {{.*}} B2 'hlsl_constant half'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 0
 	half B2 : packoffset(c0.r);
 }
@@ -34,13 +34,13 @@ cbuffer B
 // CHECK: HLSLBufferDecl {{.*}} cbuffer C
 cbuffer C
 {
-    // CHECK: VarDecl {{.*}} C0 'float'
+    // CHECK: VarDecl {{.*}} C0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1
     float C0 : packoffset(c0.y);
-    // CHECK-NEXT: VarDecl {{.*}} C1 'float2'
+    // CHECK-NEXT: VarDecl {{.*}} C1 'hlsl_constant float2'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 2
 	float2 C1 : packoffset(c0.z);
-    // CHECK-NEXT: VarDecl {{.*}} C2 'half'
+    // CHECK-NEXT: VarDecl {{.*}} C2 'hlsl_constant half'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0
 	half C2 : packoffset(c0.x);
 }
@@ -49,16 +49,16 @@ cbuffer C
 // CHECK: HLSLBufferDecl {{.*}} cbuffer D
 cbuffer D
 {
-    // CHECK: VarDecl {{.*}} D0 'float'
+    // CHECK: VarDecl {{.*}} D0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 1
     float D0 : packoffset(c0.y);
-    // CHECK-NEXT: VarDecl {{.*}} D1 'float[2]'
+    // CHECK-NEXT: VarDecl {{.*}} D1 'hlsl_constant float[2]'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1 0
 	float D1[2] : packoffset(c1.x);
-    // CHECK-NEXT: VarDecl {{.*}} D2 'half3'
+    // CHECK-NEXT: VarDecl {{.*}} D2 'hlsl_constant half3'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 2 1
 	half3 D2 : packoffset(c2.y);
-    // CHECK-NEXT: VarDecl {{.*}} D3 'double'
+    // CHECK-NEXT: VarDecl {{.*}} D3 'hlsl_constant double'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 2
 	double D3 : packoffset(c0.z);
 }
@@ -71,13 +71,13 @@ struct ST {
 
 // CHECK: HLSLBufferDecl {{.*}} cbuffer S
 cbuffer S {
-    // CHECK: VarDecl {{.*}} S0 'float'
+    // CHECK: VarDecl {{.*}} S0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 1
   float S0 : packoffset(c0.y);
-    // CHECK: VarDecl {{.*}} S1 'ST'
+    // CHECK: VarDecl {{.*}} S1 'hlsl_constant ST'
     // CHECK: HLSLPackOffsetAttr {{.*}} 1 0
   ST S1 : packoffset(c1);
-    // CHECK: VarDecl {{.*}} S2 'double2'
+    // CHECK: VarDecl {{.*}} S2 'hlsl_constant double2'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 2 0
   double2 S2 : packoffset(c2);
 }
@@ -90,13 +90,13 @@ struct ST2 {
 
 // CHECK: HLSLBufferDecl {{.*}} cbuffer S2
 cbuffer S2 {
-    // CHECK: VarDecl {{.*}} S20 'float'
+    // CHECK: VarDecl {{.*}} S20 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 3
   float S20 : packoffset(c0.a);
-    // CHECK: VarDecl {{.*}} S21 'ST2'
+    // CHECK: VarDecl {{.*}} S21 'hlsl_constant ST2'
     // CHECK: HLSLPackOffsetAttr {{.*}} 1 0
   ST2 S21 : packoffset(c1);
-    // CHECK: VarDecl {{.*}} S22 'half'
+    // CHECK: VarDecl {{.*}} S22 'hlsl_constant half'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 3 1
   half S22 : packoffset(c3.y);
 }
diff --git a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
index 02310c068c166e..3bfe8467544928 100644
--- a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
+++ b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
@@ -20,22 +20,22 @@ float foo() {
 // CHECK: HLSLBufferDecl {{.*}} line:7:9 imported <undeserialized declarations> cbuffer A
 // CHECK-NEXT: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK-NEXT: HLSLResourceAttr {{.*}} Implicit CBuffer
-// CHECK-NEXT: VarDecl 0x[[A:[0-9a-f]+]] {{.*}} imported used a 'float'
+// 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: 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 'float'
-// CHECK-NEXT: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} imported implicit <undeserialized declarations> class __layout.B definition
-// CHECK: FieldDecl 0x{{[0-9a-f]+}} {{.*}} imported b 'float'
+// CHECK-NEXT: VarDecl 0x[[B:[0-9a-f]+]] {{.*}} imported used b 'hlsl_constant float'
+// CHECK-NEXT: CXXRecordDecl {{.*}} imported implicit <undeserialized declarations> class __layout.B definition
+// CHECK: FieldDecl {{.*}} imported b 'float'
 
 // CHECK-NEXT: FunctionDecl {{.*}} line:15:7 imported foo 'float ()'
 // CHECK-NEXT: CompoundStmt {{.*}}
 // CHECK-NEXT: ReturnStmt {{.*}}
 // CHECK-NEXT: BinaryOperator {{.*}} 'float' '+'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
-// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue Var 0x[[A]] 'a' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl_constant float' lvalue Var 0x[[A]] 'a' 'hlsl_constant float'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
-// CHECK-NEXT: DeclRefExpr {{.*}} 'f...
[truncated]

@llvmbot
Copy link
Member

llvmbot commented Jan 17, 2025

@llvm/pr-subscribers-backend-directx

Author: Helena Kotas (hekota)

Changes

Introduces a new address space hlsl_constant(2) for constant buffer declarations.

This address space is applied to declarations inside cbuffer block. Later on, it will also be applied to ConstantBuffer&lt;T&gt; syntax and the default $Globals constant buffer.

Clang codegen translates constant buffer declarations to global variables and loads from hlsl_constant(2) address space. More work coming soon will include addition of metadata that will map these globals to individual constant buffers and enable their transformation to appropriate constant buffer load intrinsics later on in an LLVM pass.

Fixes #123406


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

21 Files Affected:

  • (modified) clang/include/clang/Basic/AddressSpaces.h (+1)
  • (modified) clang/lib/AST/TypePrinter.cpp (+2)
  • (modified) clang/lib/Basic/Targets/AArch64.h (+1)
  • (modified) clang/lib/Basic/Targets/AMDGPU.cpp (+1)
  • (modified) clang/lib/Basic/Targets/DirectX.h (+1)
  • (modified) clang/lib/Basic/Targets/NVPTX.h (+1)
  • (modified) clang/lib/Basic/Targets/SPIR.h (+2)
  • (modified) clang/lib/Basic/Targets/SystemZ.h (+1)
  • (modified) clang/lib/Basic/Targets/TCE.h (+1)
  • (modified) clang/lib/Basic/Targets/WebAssembly.h (+1)
  • (modified) clang/lib/Basic/Targets/X86.h (+1)
  • (modified) clang/lib/CodeGen/CGHLSLRuntime.cpp (-16)
  • (modified) clang/lib/Sema/SemaHLSL.cpp (+12-3)
  • (modified) clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl (+8-8)
  • (modified) clang/test/AST/HLSL/cbuffer.hlsl (+12-12)
  • (modified) clang/test/AST/HLSL/packoffset.hlsl (+19-19)
  • (modified) clang/test/AST/HLSL/pch_hlsl_buffer.hlsl (+6-6)
  • (modified) clang/test/AST/HLSL/resource_binding_attr.hlsl (+4-4)
  • (modified) clang/test/CodeGenHLSL/cbuf.hlsl (+9-4)
  • (modified) clang/test/CodeGenHLSL/cbuf_in_namespace.hlsl (+6-2)
  • (modified) clang/test/CodeGenHLSL/static_global_and_function_in_cb.hlsl (+8-6)
diff --git a/clang/include/clang/Basic/AddressSpaces.h b/clang/include/clang/Basic/AddressSpaces.h
index 7b723d508fff17..d18bfe54931f93 100644
--- a/clang/include/clang/Basic/AddressSpaces.h
+++ b/clang/include/clang/Basic/AddressSpaces.h
@@ -58,6 +58,7 @@ enum class LangAS : unsigned {
 
   // HLSL specific address spaces.
   hlsl_groupshared,
+  hlsl_constant,
 
   // Wasm specific address spaces.
   wasm_funcref,
diff --git a/clang/lib/AST/TypePrinter.cpp b/clang/lib/AST/TypePrinter.cpp
index a850410ffc8468..6cad74fef3fe33 100644
--- a/clang/lib/AST/TypePrinter.cpp
+++ b/clang/lib/AST/TypePrinter.cpp
@@ -2556,6 +2556,8 @@ std::string Qualifiers::getAddrSpaceAsString(LangAS AS) {
     return "__funcref";
   case LangAS::hlsl_groupshared:
     return "groupshared";
+  case LangAS::hlsl_constant:
+    return "hlsl_constant";
   default:
     return std::to_string(toTargetAddressSpace(AS));
   }
diff --git a/clang/lib/Basic/Targets/AArch64.h b/clang/lib/Basic/Targets/AArch64.h
index ecf80b23a508c9..600940f5e4e23c 100644
--- a/clang/lib/Basic/Targets/AArch64.h
+++ b/clang/lib/Basic/Targets/AArch64.h
@@ -44,6 +44,7 @@ static const unsigned ARM64AddrSpaceMap[] = {
     static_cast<unsigned>(AArch64AddrSpace::ptr32_uptr),
     static_cast<unsigned>(AArch64AddrSpace::ptr64),
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/AMDGPU.cpp b/clang/lib/Basic/Targets/AMDGPU.cpp
index 99f8f2944e2796..824134d52ec139 100644
--- a/clang/lib/Basic/Targets/AMDGPU.cpp
+++ b/clang/lib/Basic/Targets/AMDGPU.cpp
@@ -83,6 +83,7 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
     llvm::AMDGPUAS::FLAT_ADDRESS, // ptr32_uptr
     llvm::AMDGPUAS::FLAT_ADDRESS, // ptr64
     llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_groupshared
+    llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_constant
 
 };
 } // namespace targets
diff --git a/clang/lib/Basic/Targets/DirectX.h b/clang/lib/Basic/Targets/DirectX.h
index ab22d1281a4df7..4e6bc0e040398b 100644
--- a/clang/lib/Basic/Targets/DirectX.h
+++ b/clang/lib/Basic/Targets/DirectX.h
@@ -42,6 +42,7 @@ static const unsigned DirectXAddrSpaceMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     3, // hlsl_groupshared
+    2, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/NVPTX.h b/clang/lib/Basic/Targets/NVPTX.h
index d81b89a7f24ac0..c6531148fe30ce 100644
--- a/clang/lib/Basic/Targets/NVPTX.h
+++ b/clang/lib/Basic/Targets/NVPTX.h
@@ -46,6 +46,7 @@ static const unsigned NVPTXAddrSpaceMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/SPIR.h b/clang/lib/Basic/Targets/SPIR.h
index 5a328b9ceeb1d1..c0849b69dcdb32 100644
--- a/clang/lib/Basic/Targets/SPIR.h
+++ b/clang/lib/Basic/Targets/SPIR.h
@@ -47,6 +47,7 @@ static const unsigned SPIRDefIsPrivMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    2, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
@@ -80,6 +81,7 @@ static const unsigned SPIRDefIsGenMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/SystemZ.h b/clang/lib/Basic/Targets/SystemZ.h
index e6405f174f660f..66a1bf6a38b51b 100644
--- a/clang/lib/Basic/Targets/SystemZ.h
+++ b/clang/lib/Basic/Targets/SystemZ.h
@@ -42,6 +42,7 @@ static const unsigned ZOSAddressMap[] = {
     1, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     0  // wasm_funcref
 };
 
diff --git a/clang/lib/Basic/Targets/TCE.h b/clang/lib/Basic/Targets/TCE.h
index d6280b02f07b25..edec30bf69de0c 100644
--- a/clang/lib/Basic/Targets/TCE.h
+++ b/clang/lib/Basic/Targets/TCE.h
@@ -51,6 +51,7 @@ static const unsigned TCEOpenCLAddrSpaceMap[] = {
     0, // ptr32_uptr
     0, // ptr64
     0, // hlsl_groupshared
+    0, // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/Basic/Targets/WebAssembly.h b/clang/lib/Basic/Targets/WebAssembly.h
index 0a14da6a277b8e..cfecc59ac75fd9 100644
--- a/clang/lib/Basic/Targets/WebAssembly.h
+++ b/clang/lib/Basic/Targets/WebAssembly.h
@@ -42,6 +42,7 @@ static const unsigned WebAssemblyAddrSpaceMap[] = {
     0,  // ptr32_uptr
     0,  // ptr64
     0,  // hlsl_groupshared
+    0,  // hlsl_constant
     20, // wasm_funcref
 };
 
diff --git a/clang/lib/Basic/Targets/X86.h b/clang/lib/Basic/Targets/X86.h
index 2c200e64a3d84d..8bd54e362526fb 100644
--- a/clang/lib/Basic/Targets/X86.h
+++ b/clang/lib/Basic/Targets/X86.h
@@ -46,6 +46,7 @@ static const unsigned X86AddrSpaceMap[] = {
     271, // ptr32_uptr
     272, // ptr64
     0,   // hlsl_groupshared
+    0,   // hlsl_constant
     // Wasm address space values for this target are dummy values,
     // as it is only enabled for Wasm targets.
     20, // wasm_funcref
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 5679bd71581795..127bd4a7fc27f0 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -100,22 +100,6 @@ GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {
       llvm::formatv("{0}{1}", Buf.Name, Buf.IsCBuffer ? ".cb." : ".tb."),
       GlobalValue::NotThreadLocal);
 
-  IRBuilder<> B(CBGV->getContext());
-  Value *ZeroIdx = B.getInt32(0);
-  // Replace Const use with CB use.
-  for (auto &[GV, Offset] : Buf.Constants) {
-    Value *GEP =
-        B.CreateGEP(Buf.LayoutStruct, CBGV, {ZeroIdx, B.getInt32(Offset)});
-
-    assert(Buf.LayoutStruct->getElementType(Offset) == GV->getValueType() &&
-           "constant type mismatch");
-
-    // Replace.
-    GV->replaceAllUsesWith(GEP);
-    // Erase GV.
-    GV->removeDeadConstantUsers();
-    GV->eraseFromParent();
-  }
   return CBGV;
 }
 
diff --git a/clang/lib/Sema/SemaHLSL.cpp b/clang/lib/Sema/SemaHLSL.cpp
index 9bbd0ad1eb4a64..372db586f8d8ea 100644
--- a/clang/lib/Sema/SemaHLSL.cpp
+++ b/clang/lib/Sema/SemaHLSL.cpp
@@ -24,6 +24,7 @@
 #include "clang/Basic/IdentifierTable.h"
 #include "clang/Basic/LLVM.h"
 #include "clang/Basic/SourceLocation.h"
+#include "clang/Basic/Specifiers.h"
 #include "clang/Basic/TargetInfo.h"
 #include "clang/Sema/Initialization.h"
 #include "clang/Sema/Lookup.h"
@@ -455,14 +456,22 @@ void createHostLayoutStructForBuffer(Sema &S, HLSLBufferDecl *BufDecl) {
   LS->setImplicit(true);
   LS->startDefinition();
 
-  for (const Decl *D : BufDecl->decls()) {
-    const VarDecl *VD = dyn_cast<VarDecl>(D);
+  for (Decl *D : BufDecl->decls()) {
+    VarDecl *VD = dyn_cast<VarDecl>(D);
     if (!VD || VD->getStorageClass() == SC_Static)
       continue;
     const Type *Ty = VD->getType()->getUnqualifiedDesugaredType();
     if (FieldDecl *FD = createFieldForHostLayoutStruct(
-            S, Ty, VD->getIdentifier(), LS, BufDecl))
+            S, Ty, VD->getIdentifier(), LS, BufDecl)) {
+      // add the field decl to the layout struct
       LS->addDecl(FD);
+      // update address space of the original decl to hlsl_constant
+      // and disable initialization
+      QualType NewTy =
+          AST.getAddrSpaceQualType(VD->getType(), LangAS::hlsl_constant);
+      VD->setType(NewTy);
+      VD->setInit(nullptr);
+    }
   }
   LS->completeDefinition();
   BufDecl->addDecl(LS);
diff --git a/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl b/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl
index aebb7c0e8da334..3cca808ae75b63 100644
--- a/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl
+++ b/clang/test/AST/HLSL/ast-dump-comment-cbuffer-tbuffer.hlsl
@@ -11,11 +11,11 @@
 cbuffer A {
     // JSON: "kind": "VarDecl",
     // JSON: "name": "a",
-    // JSON: "qualType": "float"
+    // JSON: "qualType": "hlsl_constant float"
     float a;
     // JSON: "kind": "VarDecl",
     // JSON: "name": "b",
-    // JSON: "qualType": "int"
+    // JSON: "qualType": "hlsl_constant int"
     int b;
 }
 
@@ -29,11 +29,11 @@ cbuffer A {
 tbuffer B {
     // JSON: "kind": "VarDecl",
     // JSON: "name": "c",
-    // JSON: "qualType": "float"
+    // JSON: "qualType": "hlsl_constant float"
     float c;
     // JSON: "kind": "VarDecl",
     // JSON: "name": "d",
-    // JSON: "qualType": "int"
+    // JSON: "qualType": "hlsl_constant int"
     int d;
 }
 
@@ -43,8 +43,8 @@ tbuffer B {
 // AST-NEXT: FullComment
 // AST-NEXT: ParagraphComment
 // AST-NEXT: TextComment {{.*}} Text=" CBuffer decl."
-// AST-NEXT: VarDecl {{.*}} a 'float'
-// AST-NEXT: VarDecl {{.*}} b 'int'
+// 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'
@@ -55,8 +55,8 @@ tbuffer B {
 // AST-NEXT: FullComment
 // AST-NEXT: ParagraphComment
 // AST-NEXT: TextComment {{.*}} Text=" TBuffer decl."
-// AST-NEXT: VarDecl {{.*}} c 'float'
-// AST-NEXT: VarDecl {{.*}} d 'int'
+// AST-NEXT: VarDecl {{.*}} c 'hlsl_constant float'
+// AST-NEXT: VarDecl {{.*}} d 'hlsl_constant int'
 // AST-NEXT: CXXRecordDecl {{.*}} implicit class __layout.B definition
 // AST: FieldDecl {{.*}} c 'float'
 // AST-NEXT: FieldDecl {{.*}} d 'int'
diff --git a/clang/test/AST/HLSL/cbuffer.hlsl b/clang/test/AST/HLSL/cbuffer.hlsl
index a20485606a79d0..1d933fcb1adebd 100644
--- a/clang/test/AST/HLSL/cbuffer.hlsl
+++ b/clang/test/AST/HLSL/cbuffer.hlsl
@@ -39,7 +39,7 @@ typedef float EmptyArrayTypedef[10][0];
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} col:9 used a1 'float'
+  // CHECK: VarDecl {{.*}} col:9 used a1 'hlsl_constant float'
   float a1;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.CB definition
   // CHECK: FieldDecl {{.*}} a1 'float'
@@ -50,7 +50,7 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} col:9 used a2 'float'
+  // CHECK: VarDecl {{.*}} col:9 used a2 'hlsl_constant float'
   float a2;
   // CHECK: VarDecl {{.*}} col:19 b2 'RWBuffer<float>':'hlsl::RWBuffer<float>'
   RWBuffer<float> b2; 
@@ -58,7 +58,7 @@ cbuffer CB {
   EmptyStruct c2;
   // CHECK: VarDecl {{.*}} col:9 d2 'float[0]'
   float d2[0];
-  // CHECK: VarDecl {{.*}} col:9 e2 'float'
+  // CHECK: VarDecl {{.*}} col:9 e2 'hlsl_constant float'
   float e2;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.CB.1 definition
   // CHECK: FieldDecl {{.*}} a2 'float'
@@ -70,11 +70,11 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} col:5 used s1 'A'
+  // CHECK: VarDecl {{.*}} col:5 used s1 'hlsl_constant A'
   A s1;
-  // CHECK: VarDecl {{.*}} col:5 s2 'B'
+  // CHECK: VarDecl {{.*}} col:5 s2 'hlsl_constant B'
   B s2;
-  // CHECK: VarDecl {{.*}} col:12 s3 'CTypedef':'C
+  // CHECK: VarDecl {{.*}} col:12 s3 'CTypedef':'C'
   CTypedef s3;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.B definition
   // CHECK: FieldDecl {{.*}} a 'float'
@@ -88,7 +88,7 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} s4 'D'
+  // CHECK: VarDecl {{.*}} s4 'hlsl_constant D'
   D s4;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.D definition
   // CHECK: FieldDecl {{.*}} b 'float'
@@ -103,9 +103,9 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}}  s5 'E'
+  // CHECK: VarDecl {{.*}}  s5 'hlsl_constant E'
   E s5;
-  // CHECK: VarDecl {{.*}} s6 'BTypedef':'B'
+  // CHECK: VarDecl {{.*}} s6 'hlsl_constant BTypedef':'hlsl_constant B'
   BTypedef s6;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.E definition
   // CHECK: FieldDecl {{.*}} c 'float'
@@ -139,7 +139,7 @@ cbuffer CB {
 // CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
 cbuffer CB {
-  // CHECK: VarDecl {{.*}} s8 'F'
+  // CHECK: VarDecl {{.*}} s8 'hlsl_constant F'
   F s8;
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.F definition
   // CHECK: public 'A'
@@ -161,7 +161,7 @@ cbuffer CB {
     // CHECK: FieldDecl {{.*}} f 'RWBuffer<float>':'hlsl::RWBuffer<float>'
     RWBuffer<float> f;
   } s9;
-  // CHECK: VarDecl {{.*}} s9 'struct (unnamed struct at {{.*}}cbuffer.hlsl:156:3
+  // CHECK: VarDecl {{.*}} s9 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:156:3
   // CHECK: CXXRecordDecl {{.*}} struct definition
   struct {
     // CHECK: FieldDecl {{.*}} g 'int'
@@ -169,7 +169,7 @@ cbuffer CB {
     // CHECK: FieldDecl {{.*}} f 'RWBuffer<float>':'hlsl::RWBuffer<float>'
     RWBuffer<float> f;
   } s10;
-  // CHECK: VarDecl {{.*}} s10 'struct (unnamed struct at {{.*}}cbuffer.hlsl:166:3
+  // CHECK: VarDecl {{.*}} s10 'hlsl_constant struct (unnamed struct at {{.*}}cbuffer.hlsl:166:3
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.anon definition
   // CHECK: FieldDecl {{.*}} e 'float'
   // CHECK: CXXRecordDecl {{.*}} implicit class __layout.anon.1 definition
diff --git a/clang/test/AST/HLSL/packoffset.hlsl b/clang/test/AST/HLSL/packoffset.hlsl
index 9c928bd6d922ed..a9bb90bb386f9c 100644
--- a/clang/test/AST/HLSL/packoffset.hlsl
+++ b/clang/test/AST/HLSL/packoffset.hlsl
@@ -6,13 +6,13 @@ cbuffer A
 {
     // CHECK-NEXT:-HLSLResourceClassAttr {{.*}} <<invalid sloc>> Implicit CBuffer
     // CHECK-NEXT:-HLSLResourceAttr {{.*}} <<invalid sloc>> Implicit CBuffer
-    // CHECK-NEXT: VarDecl {{.*}} A1 'float4'
+    // CHECK-NEXT: VarDecl {{.*}} A1 'hlsl_constant float4'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 0
     float4 A1 : packoffset(c);
-    // CHECK-NEXT: VarDecl {{.*}} col:11 A2 'float'
+    // CHECK-NEXT: VarDecl {{.*}} col:11 A2 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1 0
     float A2 : packoffset(c1);
-    // CHECK-NEXT: VarDecl {{.*}} col:11 A3 'float'
+    // CHECK-NEXT: VarDecl {{.*}} col:11 A3 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1 1
     float A3 : packoffset(c1.y);
 }
@@ -20,13 +20,13 @@ cbuffer A
 // CHECK: HLSLBufferDecl {{.*}} cbuffer B
 cbuffer B
 {
-    // CHECK: VarDecl {{.*}} B0 'float'
+    // CHECK: VarDecl {{.*}} B0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 1
     float B0 : packoffset(c0.g);
-    // CHECK-NEXT: VarDecl {{.*}} B1 'double'
+    // CHECK-NEXT: VarDecl {{.*}} B1 'hlsl_constant double'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 2
 	double B1 : packoffset(c0.b);
-    // CHECK-NEXT: VarDecl {{.*}} B2 'half'
+    // CHECK-NEXT: VarDecl {{.*}} B2 'hlsl_constant half'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 0
 	half B2 : packoffset(c0.r);
 }
@@ -34,13 +34,13 @@ cbuffer B
 // CHECK: HLSLBufferDecl {{.*}} cbuffer C
 cbuffer C
 {
-    // CHECK: VarDecl {{.*}} C0 'float'
+    // CHECK: VarDecl {{.*}} C0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1
     float C0 : packoffset(c0.y);
-    // CHECK-NEXT: VarDecl {{.*}} C1 'float2'
+    // CHECK-NEXT: VarDecl {{.*}} C1 'hlsl_constant float2'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 2
 	float2 C1 : packoffset(c0.z);
-    // CHECK-NEXT: VarDecl {{.*}} C2 'half'
+    // CHECK-NEXT: VarDecl {{.*}} C2 'hlsl_constant half'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0
 	half C2 : packoffset(c0.x);
 }
@@ -49,16 +49,16 @@ cbuffer C
 // CHECK: HLSLBufferDecl {{.*}} cbuffer D
 cbuffer D
 {
-    // CHECK: VarDecl {{.*}} D0 'float'
+    // CHECK: VarDecl {{.*}} D0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 1
     float D0 : packoffset(c0.y);
-    // CHECK-NEXT: VarDecl {{.*}} D1 'float[2]'
+    // CHECK-NEXT: VarDecl {{.*}} D1 'hlsl_constant float[2]'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 1 0
 	float D1[2] : packoffset(c1.x);
-    // CHECK-NEXT: VarDecl {{.*}} D2 'half3'
+    // CHECK-NEXT: VarDecl {{.*}} D2 'hlsl_constant half3'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 2 1
 	half3 D2 : packoffset(c2.y);
-    // CHECK-NEXT: VarDecl {{.*}} D3 'double'
+    // CHECK-NEXT: VarDecl {{.*}} D3 'hlsl_constant double'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 2
 	double D3 : packoffset(c0.z);
 }
@@ -71,13 +71,13 @@ struct ST {
 
 // CHECK: HLSLBufferDecl {{.*}} cbuffer S
 cbuffer S {
-    // CHECK: VarDecl {{.*}} S0 'float'
+    // CHECK: VarDecl {{.*}} S0 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 1
   float S0 : packoffset(c0.y);
-    // CHECK: VarDecl {{.*}} S1 'ST'
+    // CHECK: VarDecl {{.*}} S1 'hlsl_constant ST'
     // CHECK: HLSLPackOffsetAttr {{.*}} 1 0
   ST S1 : packoffset(c1);
-    // CHECK: VarDecl {{.*}} S2 'double2'
+    // CHECK: VarDecl {{.*}} S2 'hlsl_constant double2'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 2 0
   double2 S2 : packoffset(c2);
 }
@@ -90,13 +90,13 @@ struct ST2 {
 
 // CHECK: HLSLBufferDecl {{.*}} cbuffer S2
 cbuffer S2 {
-    // CHECK: VarDecl {{.*}} S20 'float'
+    // CHECK: VarDecl {{.*}} S20 'hlsl_constant float'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 0 3
   float S20 : packoffset(c0.a);
-    // CHECK: VarDecl {{.*}} S21 'ST2'
+    // CHECK: VarDecl {{.*}} S21 'hlsl_constant ST2'
     // CHECK: HLSLPackOffsetAttr {{.*}} 1 0
   ST2 S21 : packoffset(c1);
-    // CHECK: VarDecl {{.*}} S22 'half'
+    // CHECK: VarDecl {{.*}} S22 'hlsl_constant half'
     // CHECK-NEXT: HLSLPackOffsetAttr {{.*}} 3 1
   half S22 : packoffset(c3.y);
 }
diff --git a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
index 02310c068c166e..3bfe8467544928 100644
--- a/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
+++ b/clang/test/AST/HLSL/pch_hlsl_buffer.hlsl
@@ -20,22 +20,22 @@ float foo() {
 // CHECK: HLSLBufferDecl {{.*}} line:7:9 imported <undeserialized declarations> cbuffer A
 // CHECK-NEXT: HLSLResourceClassAttr {{.*}} Implicit CBuffer
 // CHECK-NEXT: HLSLResourceAttr {{.*}} Implicit CBuffer
-// CHECK-NEXT: VarDecl 0x[[A:[0-9a-f]+]] {{.*}} imported used a 'float'
+// 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: 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 'float'
-// CHECK-NEXT: CXXRecordDecl 0x{{[0-9a-f]+}} {{.*}} imported implicit <undeserialized declarations> class __layout.B definition
-// CHECK: FieldDecl 0x{{[0-9a-f]+}} {{.*}} imported b 'float'
+// CHECK-NEXT: VarDecl 0x[[B:[0-9a-f]+]] {{.*}} imported used b 'hlsl_constant float'
+// CHECK-NEXT: CXXRecordDecl {{.*}} imported implicit <undeserialized declarations> class __layout.B definition
+// CHECK: FieldDecl {{.*}} imported b 'float'
 
 // CHECK-NEXT: FunctionDecl {{.*}} line:15:7 imported foo 'float ()'
 // CHECK-NEXT: CompoundStmt {{.*}}
 // CHECK-NEXT: ReturnStmt {{.*}}
 // CHECK-NEXT: BinaryOperator {{.*}} 'float' '+'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
-// CHECK-NEXT: DeclRefExpr {{.*}} 'float' lvalue Var 0x[[A]] 'a' 'float'
+// CHECK-NEXT: DeclRefExpr {{.*}} 'hlsl_constant float' lvalue Var 0x[[A]] 'a' 'hlsl_constant float'
 // CHECK-NEXT: ImplicitCastExpr {{.*}} 'float' <LValueToRValue>
-// CHECK-NEXT: DeclRefExpr {{.*}} 'f...
[truncated]

@hekota hekota requested a review from llvm-beanz January 17, 2025 22:17
Copy link
Contributor

@tex3d tex3d left a comment

Choose a reason for hiding this comment

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

I think this looks good, though I had some questions.

Looks like a test update is needed:

error: 'expected-error' diagnostics expected but not seen: 
  File /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-q72qr-1/llvm-project/github-pull-requests/clang/test/SemaTemplate/address_space-dependent.cpp Line 46: address space is larger than the maximum supported (8388586)
error: 'expected-error' diagnostics seen but not expected: 
  File /var/lib/buildkite-agent/builds/linux-56-59b8f5d88-q72qr-1/llvm-project/github-pull-requests/clang/test/SemaTemplate/address_space-dependent.cpp Line 46: address space is larger than the maximum supported (8388585)

@@ -42,6 +42,7 @@ static const unsigned DirectXAddrSpaceMap[] = {
0, // ptr32_uptr
0, // ptr64
3, // hlsl_groupshared
2, // hlsl_constant
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm surprised we neither use the LangASMap type for this array, nor static_assert that the size is the same, to prevent these from getting out-of-sync. Does the assignment of this array pointer to LangASMap * cause a compilation failure which can be used to enforce map updates when address spaces are added?

Copy link
Member Author

Choose a reason for hiding this comment

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

Yes, not updating all of the maps produces a compile error.

@@ -83,6 +83,7 @@ const LangASMap AMDGPUTargetInfo::AMDGPUDefIsPrivMap = {
llvm::AMDGPUAS::FLAT_ADDRESS, // ptr32_uptr
llvm::AMDGPUAS::FLAT_ADDRESS, // ptr64
llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_groupshared
llvm::AMDGPUAS::FLAT_ADDRESS, // hlsl_constant
Copy link
Contributor

Choose a reason for hiding this comment

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

Note: I noticed this uses LangASMap, but doesn't specify a value for wasm_funcref, which will invisibly initialize it to 0 (initializer shorter than array type LangASMap) and that maps to the dummy value of FLAT_ADDRESS likely desired anyway. It doesn't rely on this auto-initialization for sycl_global and beyond though, even though it could.

Copy link
Member Author

Choose a reason for hiding this comment

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

Interesting. Sounds like it is useful to use static const unsigned[] then instead of LangASMap since it gives you a compile error when the dimension does not match.

QualType NewTy =
AST.getAddrSpaceQualType(VD->getType(), LangAS::hlsl_constant);
VD->setType(NewTy);
VD->setInit(nullptr);
Copy link
Contributor

Choose a reason for hiding this comment

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

Does this VD->setInit(nullptr); silently get rid of an initializer if there was one? This feels a bit sketchy, unless I'm missing something. I know we don't currently support capturing initializers for constant buffer values, but it is part of HLSL syntax and could in theory be captured. Silently erasing it from the AST node at this point seems weird.

Copy link
Member Author

Choose a reason for hiding this comment

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

If we need to preserve the initializers in the AST even though they are not used, we could mark the generated global variable as externally_initialized. The global gets removed in the final DXIL after all.

// AST-NEXT: VarDecl {{.*}} a 'float'
// AST-NEXT: VarDecl {{.*}} b 'int'
// AST-NEXT: VarDecl {{.*}} a 'hlsl_constant float'
// AST-NEXT: VarDecl {{.*}} b 'hlsl_constant int'
Copy link
Contributor

Choose a reason for hiding this comment

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

Might we want a different address space for tbuffer, potentially?

Copy link
Member Author

Choose a reason for hiding this comment

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

Correct. I will update this test to be just for cbuffer and will handle tbuffer separately.

@@ -39,7 +39,7 @@ typedef float EmptyArrayTypedef[10][0];
// CHECK: HLSLResourceClassAttr {{.*}} Implicit CBuffer
// CHECK: HLSLResourceAttr {{.*}} Implicit CBuffer
cbuffer CB {
// CHECK: VarDecl {{.*}} col:9 used a1 'float'
// CHECK: VarDecl {{.*}} col:9 used a1 'hlsl_constant float'
Copy link
Contributor

Choose a reason for hiding this comment

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

Will this also impact type names in diagnostics?

Copy link
Member Author

Choose a reason for hiding this comment

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

Probably, the address space is attached to QualType.

Copy link
Contributor

@s-perron s-perron left a comment

Choose a reason for hiding this comment

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

LGTM. The SPIR-V code seems correct. It would be useful to have a SPIR-V specific test.

Copy link
Contributor

@Keenuts Keenuts left a comment

Choose a reason for hiding this comment

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

Thanks! Just some questions, otherwise LGTM.
For the AMDGPU address space, shouldn't this be CONSTANT_ADDRESS ? (Might want to double check this with Matt?)

// CHECK-DAG:@_ZL1b = internal global float 3.000000e+00, align 4
// CHECK: @a = external addrspace(2) externally_initialized global float, align 4
float a;
// CHECK: @_ZL1b = internal global float 3.000000e+00, align 4
static float b = 3;
Copy link
Contributor

Choose a reason for hiding this comment

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

This shouldn't be legal no?
(#117715 )

Copy link
Member Author

Choose a reason for hiding this comment

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

Ideally no, but DXC currently allows it (https://godbolt.org/z/G6G4eob7b) and at this point Clang does as well.
We have an issue tracking it here: #118524

Copy link
Contributor

Choose a reason for hiding this comment

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

If the end-goal is not to support this, but we "do" because we just inherit the behavior for now, I'd be in favor of checking that this is disallowed and mark as XFAIL with this issued referenced

Copy link
Member Author

Choose a reason for hiding this comment

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

At this point it is not clear what is the end goal. The static decl here tests that is does not get added to the cbuffer layout struct or the new address space. When/if we prohibit static decls in cbuffers this test will surely flare up and will be fixed up.

@hekota hekota changed the base branch from users/hekota/pr-122820 to main January 24, 2025 20:03
- preserve init and use externally_initialized
- update tests and add SPIRV variant
- reorder switch in TypePrinter.cpp
@hekota hekota force-pushed the cbuffer-addressspace branch from 3e44af9 to 404de38 Compare January 24, 2025 20:44
@hekota hekota merged commit d92bac8 into llvm:main Jan 25, 2025
9 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented Jan 25, 2025

LLVM Buildbot has detected a new failure on builder flang-aarch64-dylib running on linaro-flang-aarch64-dylib while building clang at step 5 "build-unified-tree".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/50/builds/9388

Here is the relevant piece of the build log for the reference
Step 5 (build-unified-tree) failure: build (failure)
...
690.015 [1977/1/4844] Building CXX object tools/mlir/lib/Dialect/Linalg/Transforms/CMakeFiles/obj.MLIRLinalgTransforms.dir/BubbleUpExtractSlice.cpp.o
690.101 [1976/1/4845] Building CXX object tools/mlir/lib/Conversion/FuncToSPIRV/CMakeFiles/obj.MLIRFuncToSPIRV.dir/FuncToSPIRVPass.cpp.o
690.149 [1975/1/4846] Building CXX object tools/mlir/lib/Dialect/Transform/Transforms/CMakeFiles/obj.MLIRTransformDialectTransforms.dir/CheckUses.cpp.o
690.204 [1974/1/4847] Building CXX object tools/mlir/lib/CAPI/IR/CMakeFiles/obj.MLIRCAPIIR.dir/AffineMap.cpp.o
690.299 [1973/1/4848] Building CXX object tools/mlir/lib/CAPI/IR/CMakeFiles/obj.MLIRCAPIIR.dir/BuiltinAttributes.cpp.o
690.369 [1972/1/4849] Building CXX object tools/mlir/lib/CAPI/Transforms/CMakeFiles/obj.MLIRCAPITransforms.dir/Rewrite.cpp.o
690.433 [1971/1/4850] Building CXX object tools/mlir/test/lib/Conversion/VectorToSPIRV/CMakeFiles/MLIRTestVectorToSPIRV.dir/TestVectorReductionToSPIRVDotProd.cpp.o
690.485 [1970/1/4851] Building CXX object tools/mlir/tools/mlir-parser-fuzzer/bytecode/CMakeFiles/mlir-bytecode-parser-fuzzer.dir/DummyParserFuzzer.cpp.o
690.553 [1969/1/4852] Building CXX object tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitors.cpp.o
706.363 [1968/1/4853] Building CXX object tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitorsGeneric.cpp.o
FAILED: tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitorsGeneric.cpp.o 
/usr/local/bin/c++ -DGTEST_HAS_RTTI=0 -DMLIR_INCLUDE_TESTS -D_DEBUG -D_GLIBCXX_ASSERTIONS -D_GNU_SOURCE -D__STDC_CONSTANT_MACROS -D__STDC_FORMAT_MACROS -D__STDC_LIMIT_MACROS -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/test/lib/IR -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/llvm/include -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/../Dialect/Test -I/home/tcwg-buildbot/worker/flang-aarch64-dylib/build/tools/mlir/test/lib/IR/../Dialect/Test -fPIC -fno-semantic-interposition -fvisibility-inlines-hidden -Werror=date-time -Werror=unguarded-availability-new -Wall -Wextra -Wno-unused-parameter -Wwrite-strings -Wcast-qual -Wmissing-field-initializers -pedantic -Wno-long-long -Wc++98-compat-extra-semi -Wimplicit-fallthrough -Wcovered-switch-default -Wno-noexcept-type -Wnon-virtual-dtor -Wdelete-non-virtual-dtor -Wsuggest-override -Wstring-conversion -Wmisleading-indentation -Wctad-maybe-unsupported -fdiagnostics-color -ffunction-sections -fdata-sections -Wundef -Werror=mismatched-tags -O3 -DNDEBUG -std=c++17  -fno-exceptions -funwind-tables -fno-rtti -UNDEBUG -MD -MT tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitorsGeneric.cpp.o -MF tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitorsGeneric.cpp.o.d -o tools/mlir/test/lib/IR/CMakeFiles/MLIRTestIR.dir/TestVisitorsGeneric.cpp.o -c /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/TestVisitorsGeneric.cpp
In file included from /home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/TestVisitorsGeneric.cpp:9:
/home/tcwg-buildbot/worker/flang-aarch64-dylib/llvm-project/mlir/test/lib/IR/../Dialect/Test/TestOps.h:148:10: fatal error: 'TestOps.h.inc' file not found
  148 | #include "TestOps.h.inc"
      |          ^~~~~~~~~~~~~~~
1 error generated.
ninja: build stopped: subcommand failed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
backend:AArch64 backend:AMDGPU backend:DirectX backend:SystemZ backend:WebAssembly clang:codegen clang:frontend Language frontend issues, e.g. anything involving "Sema" clang Clang issues not falling into any other category HLSL HLSL Language Support
Projects
Status: No status
Development

Successfully merging this pull request may close these issues.

[HLSL] Introduce a new address space for constant buffer declarations
6 participants