python3kgae updated this revision to Diff 468047.
python3kgae added a comment.
Herald added a project: clang.
Herald added a subscriber: cfe-commits.

arc diff `git merge-base HEAD origin` --update D136031 
<https://reviews.llvm.org/D136031> to fix the apply patch issue


Repository:
  rG LLVM Github Monorepo

CHANGES SINCE LAST ACTION
  https://reviews.llvm.org/D136031/new/

https://reviews.llvm.org/D136031

Files:
  clang/lib/CodeGen/CGHLSLRuntime.cpp
  clang/lib/CodeGen/CGHLSLRuntime.h
  clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl
  clang/test/CodeGenHLSL/cbuf.hlsl
  llvm/include/llvm/Frontend/HLSL/HLSLResource.h
  llvm/lib/Frontend/HLSL/HLSLResource.cpp
  llvm/lib/Target/DirectX/CBufferDataLayout.cpp
  llvm/lib/Target/DirectX/CBufferDataLayout.h
  llvm/lib/Target/DirectX/CMakeLists.txt
  llvm/lib/Target/DirectX/DXILResource.cpp
  llvm/lib/Target/DirectX/DXILResource.h
  llvm/test/CodeGen/DirectX/UAVMetadata.ll
  llvm/test/CodeGen/DirectX/cbuf.ll
  llvm/test/CodeGen/DirectX/legacy_cb_layout_0.ll
  llvm/test/CodeGen/DirectX/legacy_cb_layout_1.ll
  llvm/test/CodeGen/DirectX/legacy_cb_layout_2.ll
  llvm/test/CodeGen/DirectX/legacy_cb_layout_3.ll

Index: llvm/test/CodeGen/DirectX/legacy_cb_layout_3.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/DirectX/legacy_cb_layout_3.ll
@@ -0,0 +1,81 @@
+; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD
+
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-unknown-shadermodel6.7-library"
+
+; cbuffer D
+; {
+;
+;   struct D
+;   {
+;
+;       int D0;                                       ; Offset:    0
+;       struct struct.B
+;       {
+;
+;           double B0;                                ; Offset:   16
+;           float3 B1;                                ; Offset:   32
+;           float B2;                                 ; Offset:   44
+;           double3 B3;                               ; Offset:   48
+;           half B4;                                  ; Offset:   72
+;           double2 B5;                               ; Offset:   80
+;           float B6;                                 ; Offset:   96
+;           half3 B7;                                 ; Offset:  100
+;           half3 B8;                                 ; Offset:  106
+;       
+;       } D1;                                         ; Offset:   16
+;
+;       half D2;                                      ; Offset:  112
+;       struct struct.C
+;       {
+;
+;           struct struct.A
+;           {
+;
+;               float A0;                             ; Offset:  128
+;               double A1;                            ; Offset:  136
+;               float A2;                             ; Offset:  144
+;               half A3;                              ; Offset:  148
+;               int16_t A4;                           ; Offset:  150
+;               int64_t A5;                           ; Offset:  152
+;               int A6;                               ; Offset:  160
+;           
+;           } C0;                                     ; Offset:  128
+;
+;           float C1[1];                              ; Offset:  176
+;           struct struct.B
+;           {
+;
+;               double B0;                            ; Offset:  192
+;               float3 B1;                            ; Offset:  208
+;               float B2;                             ; Offset:  220
+;               double3 B3;                           ; Offset:  224
+;               half B4;                              ; Offset:  248
+;               double2 B5;                           ; Offset:  256
+;               float B6;                             ; Offset:  272
+;               half3 B7;                             ; Offset:  276
+;               half3 B8;                             ; Offset:  282
+;           
+;           } C2[2];;                                 ; Offset:  192
+;
+;           half C3;                                  ; Offset:  384
+;       
+;       } D3;                                         ; Offset:  128
+;
+;       double D4;                                    ; Offset:  392
+;   
+;   } D;                                              ; Offset:    0 Size:   400
+
+
+; Make sure the size is 400
+; DXILMD:!{i32 0, ptr @D.cb., !"", i32 0, i32 1, i32 1, i32 400}
+
+
+%struct.B = type <{ double, <3 x float>, float, <3 x double>, half, <2 x double>, float, <3 x half>, <3 x half> }>
+%struct.C = type <{ %struct.A, [1 x float], [2 x %struct.B], half }>
+%struct.A = type <{ float, double, float, half, i16, i64, i32 }>
+
+@D.cb. = external local_unnamed_addr constant { i32, %struct.B, half, %struct.C, double }
+
+!hlsl.cbufs = !{!0}
+!0 = !{ptr @D.cb., !"D.cb.ty", i32 0, i32 13, i32 1, i32 0}
Index: llvm/test/CodeGen/DirectX/legacy_cb_layout_2.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/DirectX/legacy_cb_layout_2.ll
@@ -0,0 +1,51 @@
+; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD
+
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-unknown-shadermodel6.7-library"
+
+; cbuffer B
+; {
+;
+;   struct B
+;   {
+;
+;       double B0[2];                                 ; Offset:    0
+;       float3 B1[3];                                 ; Offset:   32
+;       float B2;                                     ; Offset:   76
+;       double B3[3];                                 ; Offset:   80
+;       half B4;                                      ; Offset:  120
+;       double2 B5[1];                                ; Offset:  128
+;       float B6;                                     ; Offset:  144
+;       half3 B7[2];                                  ; Offset:  160
+;       half3 B8;                                     ; Offset:  182
+;   
+;   } B;                                              ; Offset:    0 Size:   188
+;
+; }
+;
+; cbuffer B
+; {
+;
+;   struct B.0
+;   {
+;
+;       double3 B9[3];                                ; Offset:    0
+;       half3 B10;                                    ; Offset:   88
+;   
+;   } B;                                              ; Offset:    0 Size:    94
+;
+; }
+
+
+; Make sure the size is 188.
+; DXILMD:!{i32 0, ptr @B.cb., !"", i32 0, i32 1, i32 1, i32 188}
+; Make sure the size is 94.
+; DXILMD:!{i32 1, ptr @B.cb..1, !"", i32 0, i32 2, i32 1, i32 94}
+
+@B.cb. = external local_unnamed_addr constant { [2 x double], [3 x <3 x float>], float, [3 x double], half, [1 x <2 x double>], float, [2 x <3 x half>], <3 x half> }
+@B.cb..1 = external local_unnamed_addr constant { [3 x <3 x double>], <3 x half> }
+
+!hlsl.cbufs = !{!0, !1}
+
+!0 = !{ptr @B.cb., !"B.cb.ty", i32 0, i32 13, i32 1, i32 0}
+!1 = !{ptr @B.cb..1, !"B.cb.ty", i32 1, i32 13, i32 2, i32 0}
Index: llvm/test/CodeGen/DirectX/legacy_cb_layout_1.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/DirectX/legacy_cb_layout_1.ll
@@ -0,0 +1,37 @@
+; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD
+
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-unknown-shadermodel6.7-library"
+
+;
+; cbuffer B
+; {
+;
+;   struct B
+;   {
+;
+;       double B0;                                    ; Offset:    0
+;       float3 B1;                                    ; Offset:   16
+;       float B2;                                     ; Offset:   28
+;       double3 B3;                                   ; Offset:   32
+;       half B4;                                      ; Offset:   56
+;       double2 B5;                                   ; Offset:   64
+;       float B6;                                     ; Offset:   80
+;       half3 B7;                                     ; Offset:   84
+;       half3 B8;                                     ; Offset:   90
+;   
+;   } B;                                              ; Offset:    0 Size:    96
+;
+; }
+;
+
+
+; Make sure the size is 96
+; DXILMD:!{i32 0, ptr @B.cb., !"", i32 0, i32 1, i32 1, i32 96}
+
+@B.cb. = external local_unnamed_addr constant { double, <3 x float>, float, <3 x double>, half, <2 x double>, float, <3 x half>, <3 x half> }
+
+
+!hlsl.cbufs = !{!0}
+
+!0 = !{ptr @B.cb., !"B.cb.ty", i32 0, i32 13, i32 1, i32 0}
Index: llvm/test/CodeGen/DirectX/legacy_cb_layout_0.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/DirectX/legacy_cb_layout_0.ll
@@ -0,0 +1,14 @@
+; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD
+
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-unknown-shadermodel6.7-library"
+
+; Make sure the size is 36 = 16 + 16 + 4 (float, double -> 16, float, half, i16, i64 -> 16 and int -> 4)
+; DXILMD:!{i32 0, ptr @A.cb., !"", i32 0, i32 2, i32 1, i32 36}
+
+@A.cb. = external local_unnamed_addr constant { float, double, float, half, i16, i64, i32 }
+
+
+!hlsl.cbufs = !{!1}
+
+!1 = !{ptr @A.cb., !"A.cb.ty", i32 0, i32 13, i32 2, i32 0}
Index: llvm/test/CodeGen/DirectX/cbuf.ll
===================================================================
--- /dev/null
+++ llvm/test/CodeGen/DirectX/cbuf.ll
@@ -0,0 +1,37 @@
+; RUN: opt -S -dxil-metadata-emit < %s | FileCheck %s --check-prefix=DXILMD
+; RUN: opt -S --passes="print-dxil-resource" < %s 2>&1 | FileCheck %s --check-prefix=PRINT
+
+target datalayout = "e-m:e-p:32:32-i1:32-i8:8-i16:16-i32:32-i64:64-f16:16-f32:32-f64:64-n8:16:32:64"
+target triple = "dxil-unknown-shadermodel6.7-library"
+
+; Make sure the size is 24 = 16 + 8 (float,i32,double -> 16 and int2 -> 8)
+; DXILMD:!{i32 0, ptr @A.cb., !"", i32 1, i32 2, i32 1, i32 24}
+
+; Make sure match register(b2, space1) with ID 0.
+; PRINT:cbuffer      NA          NA     CB0     cb2,space1     1
+
+@A.cb. = external constant { float, i32, double, <2 x i32> }
+
+; Function Attrs: noinline nounwind optnone
+define noundef float @"?foo@@YAMXZ"() #0 {
+entry:
+  %0 = load float, ptr @A.cb., align 4
+  %conv = fpext float %0 to double
+  %1 = load double, ptr getelementptr inbounds ({ float, i32, double, <2 x i32> }, ptr @A.cb., i32 0, i32 2), align 8
+  %2 = load <2 x i32>, ptr getelementptr inbounds ({ float, i32, double, <2 x i32> }, ptr @A.cb., i32 0, i32 3), align 8
+  %3 = extractelement <2 x i32> %2, i32 1
+  %conv1 = sitofp i32 %3 to double
+  %4 = call double @llvm.fmuladd.f64(double %1, double %conv1, double %conv)
+  %conv2 = fptrunc double %4 to float
+  ret float %conv2
+}
+
+; Function Attrs: nocallback nofree nosync nounwind readnone speculatable willreturn
+declare double @llvm.fmuladd.f64(double, double, double) #1
+
+attributes #0 = { noinline nounwind }
+attributes #1 = { nocallback nofree nosync nounwind readnone speculatable willreturn }
+
+!hlsl.cbufs = !{!1}
+
+!1 = !{ptr @A.cb., !"A.cb.ty", i32 0, i32 13, i32 2, i32 1}
Index: llvm/test/CodeGen/DirectX/UAVMetadata.ll
===================================================================
--- llvm/test/CodeGen/DirectX/UAVMetadata.ll
+++ llvm/test/CodeGen/DirectX/UAVMetadata.ll
@@ -13,15 +13,15 @@
 ; PRINT-NEXT:; Name                                 Type  Format         Dim      ID      HLSL Bind  Count
 ; PRINT-NEXT:; ------------------------------ ---------- ------- ----------- ------- -------------- ------
 ; PRINT-NEXT:;                                       UAV     f16         buf      U0             u0     1
-; PRINT-NEXT:;                                       UAV     f32         buf      U1             u0     1
-; PRINT-NEXT:;                                       UAV     f64         buf      U2             u0     1
-; PRINT-NEXT:;                                       UAV      i1         buf      U3             u0     2
-; PRINT-NEXT:;                                       UAV    byte         r/w      U4             u0     1
-; PRINT-NEXT:;                                       UAV  struct         r/w      U5             u0     1
-; PRINT-NEXT:;                                       UAV     i32         buf      U6             u0     1
-; PRINT-NEXT:;                                       UAV  struct         r/w      U7             u0     1
-; PRINT-NEXT:;                                       UAV    byte         r/w      U8             u0     1
-; PRINT-NEXT:;                                       UAV     u64         buf      U9             u0     1
+; PRINT-NEXT:;                                       UAV     f32         buf      U1             u1     1
+; PRINT-NEXT:;                                       UAV     f64         buf      U2             u2     1
+; PRINT-NEXT:;                                       UAV      i1         buf      U3             u3     2
+; PRINT-NEXT:;                                       UAV    byte         r/w      U4             u5     1
+; PRINT-NEXT:;                                       UAV  struct         r/w      U5             u6     1
+; PRINT-NEXT:;                                       UAV     i32         buf      U6             u7     1
+; PRINT-NEXT:;                                       UAV  struct         r/w      U7             u8     1
+; PRINT-NEXT:;                                       UAV    byte         r/w      U8             u9     1
+; PRINT-NEXT:;                                       UAV     u64         buf      U9     u10,space2     1
 
 @Zero = local_unnamed_addr global %"class.hlsl::RWBuffer" zeroinitializer, align 4
 @One = local_unnamed_addr global %"class.hlsl::RWBuffer" zeroinitializer, align 4
@@ -37,16 +37,16 @@
 
 !hlsl.uavs = !{!0, !1, !2, !3, !4, !5, !6, !7, !8, !9}
 
-!0 = !{ptr @Zero, !"RWBuffer<half>", i32 0}
-!1 = !{ptr @One, !"Buffer<vector<float,4>>", i32 1}
-!2 = !{ptr @Two, !"Buffer<double>", i32 2}
-!3 = !{ptr @Three, !"Buffer<bool>", i32 3}
-!4 = !{ptr @Four, !"ByteAddressBuffer<int16_t>", i32 4}
-!5 = !{ptr @Five, !"StructuredBuffer<uint16_t>", i32 5}
-!6 = !{ptr @Six, !"RasterizerOrderedBuffer<int32_t>", i32 6}
-!7 = !{ptr @Seven, !"RasterizerOrderedStructuredBuffer<uint32_t>", i32 7}
-!8 = !{ptr @Eight, !"RasterizerOrderedByteAddressBuffer<int64_t>", i32 8}
-!9 = !{ptr @Nine, !"RWBuffer<uint64_t>", i32 9}
+!0 = !{ptr @Zero, !"RWBuffer<half>", i32 0, i32 10, i32 0, i32 0}
+!1 = !{ptr @One, !"Buffer<vector<float,4>>", i32 1, i32 10, i32 1, i32 0}
+!2 = !{ptr @Two, !"Buffer<double>", i32 2, i32 10, i32 2, i32 0}
+!3 = !{ptr @Three, !"Buffer<bool>", i32 3, i32 10, i32 3, i32 0}
+!4 = !{ptr @Four, !"ByteAddressBuffer<int16_t>", i32 4, i32 11, i32 5, i32 0}
+!5 = !{ptr @Five, !"StructuredBuffer<uint16_t>", i32 5, i32 12, i32 6, i32 0}
+!6 = !{ptr @Six, !"RasterizerOrderedBuffer<int32_t>", i32 6, i32 10, i32 7, i32 0}
+!7 = !{ptr @Seven, !"RasterizerOrderedStructuredBuffer<uint32_t>", i32 7, i32 12, i32 8, i32 0}
+!8 = !{ptr @Eight, !"RasterizerOrderedByteAddressBuffer<int64_t>", i32 8, i32 11, i32 9, i32 0}
+!9 = !{ptr @Nine, !"RWBuffer<uint64_t>", i32 9, i32 10, i32 10, i32 2}
 
 ; CHECK: !dx.resources = !{[[ResList:[!][0-9]+]]}
 
@@ -57,21 +57,21 @@
 ; CHECK-SAME: [[Eight:[!][0-9]+]], [[Nine:[!][0-9]+]]}
 ; CHECK: [[Zero]] = !{i32 0, ptr @Zero, !"", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, [[Half:[!][0-9]+]]}
 ; CHECK: [[Half]] = !{i32 0, i32 8}
-; CHECK: [[One]] = !{i32 1, ptr @One, !"", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, [[Float:[!][0-9]+]]}
+; CHECK: [[One]] = !{i32 1, ptr @One, !"", i32 0, i32 1, i32 1, i32 10, i1 false, i1 false, i1 false, [[Float:[!][0-9]+]]}
 ; CHECK: [[Float]] = !{i32 0, i32 9}
-; CHECK: [[Two]] = !{i32 2, ptr @Two, !"", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, [[Double:[!][0-9]+]]}
+; CHECK: [[Two]] = !{i32 2, ptr @Two, !"", i32 0, i32 2, i32 1, i32 10, i1 false, i1 false, i1 false, [[Double:[!][0-9]+]]}
 ; CHECK: [[Double]] = !{i32 0, i32 10}
-; CHECK: [[Three]] = !{i32 3, ptr @Three, !"", i32 0, i32 0, i32 2, i32 10, i1 false, i1 false, i1 false, [[Bool:[!][0-9]+]]}
+; CHECK: [[Three]] = !{i32 3, ptr @Three, !"", i32 0, i32 3, i32 2, i32 10, i1 false, i1 false, i1 false, [[Bool:[!][0-9]+]]}
 ; CHECK: [[Bool]] = !{i32 0, i32 1}
-; CHECK: [[Four]] = !{i32 4, ptr @Four, !"", i32 0, i32 0, i32 1, i32 11, i1 false, i1 false, i1 false, [[I16:[!][0-9]+]]}
+; CHECK: [[Four]] = !{i32 4, ptr @Four, !"", i32 0, i32 5, i32 1, i32 11, i1 false, i1 false, i1 false, [[I16:[!][0-9]+]]}
 ; CHECK: [[I16]] = !{i32 0, i32 2}
-; CHECK: [[Five]] = !{i32 5, ptr @Five, !"", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 false, [[U16:[!][0-9]+]]}
+; CHECK: [[Five]] = !{i32 5, ptr @Five, !"", i32 0, i32 6, i32 1, i32 12, i1 false, i1 false, i1 false, [[U16:[!][0-9]+]]}
 ; CHECK: [[U16]] = !{i32 0, i32 3}
-; CHECK: [[Six]] = !{i32 6, ptr @Six, !"", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 true, [[I32:[!][0-9]+]]}
+; CHECK: [[Six]] = !{i32 6, ptr @Six, !"", i32 0, i32 7, i32 1, i32 10, i1 false, i1 false, i1 true, [[I32:[!][0-9]+]]}
 ; CHECK: [[I32]] = !{i32 0, i32 4}
-; CHECK: [[Seven]] = !{i32 7, ptr @Seven, !"", i32 0, i32 0, i32 1, i32 12, i1 false, i1 false, i1 true, [[U32:[!][0-9]+]]}
+; CHECK: [[Seven]] = !{i32 7, ptr @Seven, !"", i32 0, i32 8, i32 1, i32 12, i1 false, i1 false, i1 true, [[U32:[!][0-9]+]]}
 ; CHECK: [[U32]] = !{i32 0, i32 5}
-; CHECK: [[Eight]] = !{i32 8, ptr @Eight, !"", i32 0, i32 0, i32 1, i32 11, i1 false, i1 false, i1 true, [[I64:[!][0-9]+]]}
+; CHECK: [[Eight]] = !{i32 8, ptr @Eight, !"", i32 0, i32 9, i32 1, i32 11, i1 false, i1 false, i1 true, [[I64:[!][0-9]+]]}
 ; CHECK: [[I64]] = !{i32 0, i32 6}
-; CHECK: [[Nine]] = !{i32 9, ptr @Nine, !"", i32 0, i32 0, i32 1, i32 10, i1 false, i1 false, i1 false, [[U64:[!][0-9]+]]}
+; CHECK: [[Nine]] = !{i32 9, ptr @Nine, !"", i32 2, i32 10, i32 1, i32 10, i1 false, i1 false, i1 false, [[U64:[!][0-9]+]]}
 ; CHECK: [[U64]] = !{i32 0, i32 7}
Index: llvm/lib/Target/DirectX/DXILResource.h
===================================================================
--- llvm/lib/Target/DirectX/DXILResource.h
+++ llvm/lib/Target/DirectX/DXILResource.h
@@ -26,6 +26,7 @@
 class GlobalVariable;
 
 namespace dxil {
+class CBufferDataLayout;
 
 class ResourceBase {
 protected:
@@ -40,32 +41,7 @@
   void write(LLVMContext &Ctx, MutableArrayRef<Metadata *> Entries) const;
 
   void print(raw_ostream &O, StringRef IDPrefix, StringRef BindingPrefix) const;
-
-  // The value ordering of this enumeration is part of the DXIL ABI. Elements
-  // can only be added to the end, and not removed.
-  enum class Kinds : uint32_t {
-    Invalid = 0,
-    Texture1D,
-    Texture2D,
-    Texture2DMS,
-    Texture3D,
-    TextureCube,
-    Texture1DArray,
-    Texture2DArray,
-    Texture2DMSArray,
-    TextureCubeArray,
-    TypedBuffer,
-    RawBuffer,
-    StructuredBuffer,
-    CBuffer,
-    Sampler,
-    TBuffer,
-    RTAccelerationStructure,
-    FeedbackTexture2D,
-    FeedbackTexture2DArray,
-    NumEntries,
-  };
-
+  using Kinds = hlsl::ResourceKind;
   static StringRef getKindName(Kinds Kind);
   static void printKind(Kinds Kind, unsigned Alignment, raw_ostream &OS,
                         bool SRV = false, bool HasCounter = false,
@@ -133,14 +109,34 @@
   void print(raw_ostream &O) const;
 };
 
+class ConstantBuffer : public ResourceBase {
+  uint32_t CBufferSizeInBytes = 0; // Cbuffer used size in bytes.
+public:
+  ConstantBuffer(uint32_t I, hlsl::FrontendResource R);
+  void setSize(CBufferDataLayout &DL);
+  MDNode *write() const;
+  void print(raw_ostream &O) const;
+};
+
+template <typename T> class ResourceTable {
+  StringRef MDName;
+
+  llvm::SmallVector<T> Data;
+
+public:
+  ResourceTable(StringRef Name) : MDName(Name) {}
+  void collect(Module &M);
+  MDNode *write(Module &M) const;
+  void print(raw_ostream &O) const;
+};
+
 // FIXME: Fully computing the resource structures requires analyzing the IR
 // because some flags are set based on what operations are performed on the
 // resource. This partial patch handles some of the leg work, but not all of it.
 // See issue https://github.com/llvm/llvm-project/issues/57936.
 class Resources {
-  llvm::SmallVector<UAVResource> UAVs;
-
-  void collectUAVs(Module &M);
+  ResourceTable<UAVResource> UAVs = {"hlsl.uavs"};
+  ResourceTable<ConstantBuffer> CBuffers = {"hlsl.cbufs"};
 
 public:
   void collect(Module &M);
Index: llvm/lib/Target/DirectX/DXILResource.cpp
===================================================================
--- llvm/lib/Target/DirectX/DXILResource.cpp
+++ llvm/lib/Target/DirectX/DXILResource.cpp
@@ -11,6 +11,7 @@
 //===----------------------------------------------------------------------===//
 
 #include "DXILResource.h"
+#include "CBufferDataLayout.h"
 #include "llvm/ADT/StringSwitch.h"
 #include "llvm/IR/IRBuilder.h"
 #include "llvm/IR/Metadata.h"
@@ -22,23 +23,43 @@
 using namespace llvm::dxil;
 using namespace llvm::hlsl;
 
-void Resources::collectUAVs(Module &M) {
-  NamedMDNode *Entry = M.getNamedMetadata("hlsl.uavs");
+template <typename T> void ResourceTable<T>::collect(Module &M) {
+  NamedMDNode *Entry = M.getNamedMetadata(MDName);
   if (!Entry || Entry->getNumOperands() == 0)
     return;
 
   uint32_t Counter = 0;
-  for (auto *UAV : Entry->operands()) {
-    UAVs.push_back(UAVResource(Counter++, FrontendResource(cast<MDNode>(UAV))));
+  for (auto *Res : Entry->operands()) {
+    Data.push_back(T(Counter++, FrontendResource(cast<MDNode>(Res))));
   }
 }
 
-void Resources::collect(Module &M) { collectUAVs(M); }
+template <> void ResourceTable<ConstantBuffer>::collect(Module &M) {
+  NamedMDNode *Entry = M.getNamedMetadata(MDName);
+  if (!Entry || Entry->getNumOperands() == 0)
+    return;
+
+  uint32_t Counter = 0;
+  for (auto *Res : Entry->operands()) {
+    Data.push_back(
+        ConstantBuffer(Counter++, FrontendResource(cast<MDNode>(Res))));
+  }
+  // FIXME: share CBufferDataLayout with CBuffer load lowering.
+  //   See https://github.com/llvm/llvm-project/issues/58381
+  CBufferDataLayout CBDL(M.getDataLayout(), /*IsLegacy*/ true);
+  for (auto &CB : Data)
+    CB.setSize(CBDL);
+}
+
+void Resources::collect(Module &M) {
+  UAVs.collect(M);
+  CBuffers.collect(M);
+}
 
 ResourceBase::ResourceBase(uint32_t I, FrontendResource R)
-    : ID(I), GV(R.getGlobalVariable()), Name(""), Space(0), LowerBound(0),
-      RangeSize(1) {
-  if (auto *ArrTy = dyn_cast<ArrayType>(GV->getInitializer()->getType()))
+    : ID(I), GV(R.getGlobalVariable()), Name(""), Space(R.getSpace()),
+      LowerBound(R.getResourceIndex()), RangeSize(1) {
+  if (auto *ArrTy = dyn_cast<ArrayType>(GV->getValueType()))
     RangeSize = ArrTy->getNumElements();
 }
 
@@ -210,8 +231,9 @@
 }
 
 UAVResource::UAVResource(uint32_t I, FrontendResource R)
-    : ResourceBase(I, R), Shape(Kinds::Invalid), GloballyCoherent(false),
-      HasCounter(false), IsROV(false), ExtProps() {
+    : ResourceBase(I, R),
+      Shape(static_cast<ResourceBase::Kinds>(R.getResourceKind())),
+      GloballyCoherent(false), HasCounter(false), IsROV(false), ExtProps() {
   parseSourceType(R.getSourceType());
 }
 
@@ -275,6 +297,30 @@
     ExtProps.ElementType = ElTy;
 }
 
+ConstantBuffer::ConstantBuffer(uint32_t I, hlsl::FrontendResource R)
+    : ResourceBase(I, R) {}
+
+void ConstantBuffer::setSize(CBufferDataLayout &DL) {
+  CBufferSizeInBytes = DL.getTypeAllocSizeInBytes(GV->getValueType());
+}
+
+void ConstantBuffer::print(raw_ostream &OS) const {
+  OS << "; " << left_justify(Name, 31);
+
+  OS << right_justify("cbuffer", 10);
+
+  printComponentType(Kinds::CBuffer, ComponentType::Invalid, 8, OS);
+
+  printKind(Kinds::CBuffer, 12, OS, /*SRV*/ false, /*HasCounter*/ false);
+  // Print the binding part.
+  ResourceBase::print(OS, "CB", "cb");
+}
+
+template <typename T> void ResourceTable<T>::print(raw_ostream &OS) const {
+  for (auto &Res : Data)
+    Res.print(OS);
+}
+
 MDNode *ResourceBase::ExtendedProperties::write(LLVMContext &Ctx) const {
   IRBuilder<> B(Ctx);
   SmallVector<Metadata *> Entries;
@@ -314,21 +360,39 @@
   return MDNode::get(Ctx, Entries);
 }
 
+MDNode *ConstantBuffer::write() const {
+  auto &Ctx = GV->getContext();
+  IRBuilder<> B(Ctx);
+  Metadata *Entries[7];
+  ResourceBase::write(Ctx, Entries);
+
+  Entries[6] = ConstantAsMetadata::get(B.getInt32(CBufferSizeInBytes));
+  return MDNode::get(Ctx, Entries);
+}
+
+template <typename T> MDNode *ResourceTable<T>::write(Module &M) const {
+  if (Data.empty())
+    return nullptr;
+  SmallVector<Metadata *> MDs;
+  for (auto &Res : Data)
+    MDs.emplace_back(Res.write());
+
+  NamedMDNode *Entry = M.getNamedMetadata(MDName);
+  if (Entry)
+    Entry->eraseFromParent();
+
+  return MDNode::get(M.getContext(), MDs);
+}
+
 void Resources::write(Module &M) const {
   Metadata *ResourceMDs[4] = {nullptr, nullptr, nullptr, nullptr};
-  SmallVector<Metadata *> UAVMDs;
-  for (auto &UAV : UAVs)
-    UAVMDs.emplace_back(UAV.write());
 
-  if (!UAVMDs.empty())
-    ResourceMDs[1] = MDNode::get(M.getContext(), UAVMDs);
+  ResourceMDs[1] = UAVs.write(M);
+
+  ResourceMDs[2] = CBuffers.write(M);
 
   NamedMDNode *DXResMD = M.getOrInsertNamedMetadata("dx.resources");
   DXResMD->addOperand(MDNode::get(M.getContext(), ResourceMDs));
-
-  NamedMDNode *Entry = M.getNamedMetadata("hlsl.uavs");
-  if (Entry)
-    Entry->eraseFromParent();
 }
 
 void Resources::print(raw_ostream &O) const {
@@ -340,8 +404,8 @@
     << "; ------------------------------ ---------- ------- ----------- "
        "------- -------------- ------\n";
 
-  for (auto &UAV : UAVs)
-    UAV.print(O);
+  CBuffers.print(O);
+  UAVs.print(O);
 }
 
 void Resources::dump() const { print(dbgs()); }
Index: llvm/lib/Target/DirectX/CMakeLists.txt
===================================================================
--- llvm/lib/Target/DirectX/CMakeLists.txt
+++ llvm/lib/Target/DirectX/CMakeLists.txt
@@ -12,6 +12,7 @@
 add_public_tablegen_target(DirectXCommonTableGen)
 
 add_llvm_target(DirectXCodeGen
+  CBufferDataLayout.cpp
   DirectXAsmPrinter.cpp
   DirectXInstrInfo.cpp
   DirectXRegisterInfo.cpp
Index: llvm/lib/Target/DirectX/CBufferDataLayout.h
===================================================================
--- /dev/null
+++ llvm/lib/Target/DirectX/CBufferDataLayout.h
@@ -0,0 +1,41 @@
+//===- Target/DirectX/CBufferDataLayout.h - Cbuffer layout helper ---------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utils to help cbuffer layout.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_TARGET_DIRECTX_CBUFFERDATALAYOUT_H
+#define LLVM_TARGET_DIRECTX_CBUFFERDATALAYOUT_H
+
+#include <memory>
+#include <stdint.h>
+
+namespace llvm {
+class DataLayout;
+class Type;
+
+namespace dxil {
+
+class LegacyCBufferLayout;
+
+class CBufferDataLayout {
+  const DataLayout &DL;
+  const bool IsLegacyLayout;
+  std::unique_ptr<LegacyCBufferLayout> LegacyDL;
+
+public:
+  CBufferDataLayout(const DataLayout &DL, const bool IsLegacy);
+  ~CBufferDataLayout();
+  uint32_t getTypeAllocSizeInBytes(Type *Ty);
+};
+
+} // namespace dxil
+} // namespace llvm
+
+#endif
Index: llvm/lib/Target/DirectX/CBufferDataLayout.cpp
===================================================================
--- /dev/null
+++ llvm/lib/Target/DirectX/CBufferDataLayout.cpp
@@ -0,0 +1,132 @@
+//===- Target/DirectX/CBufferDataLayout.cpp - Cbuffer layout helper -------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Utils to help cbuffer layout.
+//
+//===----------------------------------------------------------------------===//
+
+#include "CBufferDataLayout.h"
+
+#include "llvm/IR/DerivedTypes.h"
+#include "llvm/IR/IRBuilder.h"
+
+namespace llvm {
+namespace dxil {
+
+// Implement cbuffer layout in
+// https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-packing-rules
+class LegacyCBufferLayout {
+  struct LegacyStructLayout {
+    StructType *ST;
+    SmallVector<unsigned> Offsets;
+    uint32_t Size;
+    std::pair<uint32_t, uint32_t> getElementLegacyOffset(unsigned Idx) const {
+      assert(Idx < Offsets.size() && "Invalid element idx!");
+      unsigned Offset = Offsets[Idx];
+      unsigned Ch = Offset & (RowAlign - 1);
+      return std::make_pair((Offset - Ch) / RowAlign, Ch);
+    }
+  };
+
+public:
+  LegacyCBufferLayout(const DataLayout &DL) : DL(DL) {}
+  uint32_t getTypeAllocSizeInBytes(Type *Ty);
+
+private:
+  unsigned applyRowAlign(unsigned Offset, Type *EltTy);
+  unsigned getTypeAllocSize(Type *Ty);
+  LegacyStructLayout &getStructLayout(StructType *ST);
+  const DataLayout &DL;
+  SmallDenseMap<StructType *, LegacyStructLayout> StructLayouts;
+  // 4 Dwords align.
+  static const unsigned RowAlign = 16;
+  static unsigned align(unsigned Offset, unsigned Alignment) {
+    return (Offset + Alignment - 1) / Alignment * Alignment;
+  }
+  static unsigned alignTo4Dwords(unsigned Offset) {
+    return align(Offset, RowAlign);
+  }
+};
+
+uint32_t LegacyCBufferLayout::getTypeAllocSizeInBytes(Type *Ty) {
+  return getTypeAllocSize(Ty);
+}
+
+unsigned LegacyCBufferLayout::applyRowAlign(unsigned Offset, Type *EltTy) {
+  unsigned AlignedOffset = alignTo4Dwords(Offset);
+
+  if (AlignedOffset == Offset)
+    return Offset;
+
+  if (isa<StructType>(EltTy) || isa<ArrayType>(EltTy))
+    return AlignedOffset;
+  unsigned Size = DL.getTypeStoreSize(EltTy);
+  if ((Offset + Size) > AlignedOffset)
+    return AlignedOffset;
+  else
+    return Offset;
+}
+
+unsigned LegacyCBufferLayout::getTypeAllocSize(Type *Ty) {
+  if (auto *ST = dyn_cast<StructType>(Ty)) {
+    LegacyStructLayout &Layout = getStructLayout(ST);
+    return Layout.Size;
+  } else if (auto *AT = dyn_cast<ArrayType>(Ty)) {
+    unsigned NumElts = AT->getNumElements();
+    if (NumElts == 0)
+      return 0;
+
+    unsigned EltSize = getTypeAllocSize(AT->getElementType());
+    unsigned AlignedEltSize = alignTo4Dwords(EltSize);
+    // Each new element start 4 dwords aligned.
+    return AlignedEltSize * (NumElts - 1) + EltSize;
+  } else {
+    // NOTE: Use type store size, not align to ABI on basic types for legacy
+    // layout.
+    return DL.getTypeStoreSize(Ty);
+  }
+}
+
+LegacyCBufferLayout::LegacyStructLayout &
+LegacyCBufferLayout::getStructLayout(StructType *ST) {
+  auto it = StructLayouts.find(ST);
+  if (it != StructLayouts.end())
+    return it->second;
+
+  unsigned Offset = 0;
+  LegacyStructLayout Layout;
+  Layout.ST = ST;
+  for (Type *EltTy : ST->elements()) {
+    unsigned EltSize = getTypeAllocSize(EltTy);
+    if (unsigned ScalarSize = EltTy->getScalarSizeInBits())
+      Offset = align(Offset, ScalarSize >> 3);
+    Offset = applyRowAlign(Offset, EltTy);
+    Layout.Offsets.emplace_back(Offset);
+    Offset += EltSize;
+  }
+  Layout.Size = Offset;
+  StructLayouts[ST] = Layout;
+  return StructLayouts[ST];
+}
+
+CBufferDataLayout::CBufferDataLayout(const DataLayout &DL, const bool IsLegacy)
+    : DL(DL), IsLegacyLayout(IsLegacy),
+      LegacyDL(IsLegacy ? std::make_unique<LegacyCBufferLayout>(DL) : nullptr) {
+}
+
+CBufferDataLayout::~CBufferDataLayout() = default;
+
+uint32_t CBufferDataLayout::getTypeAllocSizeInBytes(Type *Ty) {
+  if (IsLegacyLayout)
+    return LegacyDL->getTypeAllocSizeInBytes(Ty);
+  else
+    return DL.getTypeAllocSize(Ty);
+}
+
+} // namespace dxil
+} // namespace llvm
Index: llvm/lib/Frontend/HLSL/HLSLResource.cpp
===================================================================
--- llvm/lib/Frontend/HLSL/HLSLResource.cpp
+++ llvm/lib/Frontend/HLSL/HLSLResource.cpp
@@ -31,11 +31,31 @@
   return cast<ConstantAsMetadata>(Entry->getOperand(2))->getValue();
 }
 
+uint32_t FrontendResource::FrontendResource::getResourceKind() {
+  return cast<ConstantInt>(
+             cast<ConstantAsMetadata>(Entry->getOperand(3))->getValue())
+      ->getLimitedValue();
+}
+uint32_t FrontendResource::getResourceIndex() {
+  return cast<ConstantInt>(
+             cast<ConstantAsMetadata>(Entry->getOperand(4))->getValue())
+      ->getLimitedValue();
+}
+uint32_t FrontendResource::getSpace() {
+  return cast<ConstantInt>(
+             cast<ConstantAsMetadata>(Entry->getOperand(5))->getValue())
+      ->getLimitedValue();
+}
+
 FrontendResource::FrontendResource(GlobalVariable *GV, StringRef TypeStr,
-                                   uint32_t Counter) {
+                                   uint32_t Counter, ResourceKind RK,
+                                   uint32_t ResIndex, uint32_t Space) {
   auto &Ctx = GV->getContext();
   IRBuilder<> B(Ctx);
-  Entry =
-      MDNode::get(Ctx, {ValueAsMetadata::get(GV), MDString::get(Ctx, TypeStr),
-                        ConstantAsMetadata::get(B.getInt32(Counter))});
+  Entry = MDNode::get(
+      Ctx, {ValueAsMetadata::get(GV), MDString::get(Ctx, TypeStr),
+            ConstantAsMetadata::get(B.getInt32(Counter)),
+            ConstantAsMetadata::get(B.getInt32(static_cast<int>(RK))),
+            ConstantAsMetadata::get(B.getInt32(ResIndex)),
+            ConstantAsMetadata::get(B.getInt32(Space))});
 }
Index: llvm/include/llvm/Frontend/HLSL/HLSLResource.h
===================================================================
--- llvm/include/llvm/Frontend/HLSL/HLSLResource.h
+++ llvm/include/llvm/Frontend/HLSL/HLSLResource.h
@@ -21,20 +21,48 @@
 
 namespace hlsl {
 
+// The value ordering of this enumeration is part of the DXIL ABI. Elements
+// can only be added to the end, and not removed.
+enum class ResourceKind : uint32_t {
+  Invalid = 0,
+  Texture1D,
+  Texture2D,
+  Texture2DMS,
+  Texture3D,
+  TextureCube,
+  Texture1DArray,
+  Texture2DArray,
+  Texture2DMSArray,
+  TextureCubeArray,
+  TypedBuffer,
+  RawBuffer,
+  StructuredBuffer,
+  CBuffer,
+  Sampler,
+  TBuffer,
+  RTAccelerationStructure,
+  FeedbackTexture2D,
+  FeedbackTexture2DArray,
+  NumEntries,
+};
+
 class FrontendResource {
   MDNode *Entry;
 
 public:
   FrontendResource(MDNode *E) : Entry(E) {
-    assert(Entry->getNumOperands() == 3 && "Unexpected metadata shape");
+    assert(Entry->getNumOperands() == 6 && "Unexpected metadata shape");
   }
 
-  FrontendResource(GlobalVariable *GV, StringRef TypeStr, uint32_t Counter);
+  FrontendResource(GlobalVariable *GV, StringRef TypeStr, uint32_t Counter,
+                   ResourceKind RK, uint32_t ResIndex, uint32_t Space);
 
   GlobalVariable *getGlobalVariable();
   StringRef getSourceType();
   Constant *getID();
-
+  uint32_t getResourceKind();
+  uint32_t getResourceIndex();
+  uint32_t getSpace();
   MDNode *getMetadata() { return Entry; }
 };
 } // namespace hlsl
Index: clang/test/CodeGenHLSL/cbuf.hlsl
===================================================================
--- clang/test/CodeGenHLSL/cbuf.hlsl
+++ clang/test/CodeGenHLSL/cbuf.hlsl
@@ -3,7 +3,7 @@
 // RUN:   -emit-llvm -disable-llvm-passes -o - | FileCheck %s
 
 // CHECK: @[[CB:.+]] = external constant { float, double }
-cbuffer A : register(b0, space1) {
+cbuffer A : register(b0, space2) {
   float a;
   double b;
 }
@@ -21,3 +21,8 @@
 // CHECK: load double, ptr getelementptr inbounds ({ float, double }, ptr @[[TB]], i32 0, i32 1), align 8
   return a + b + c*d;
 }
+
+// CHECK: !hlsl.cbufs = !{![[CBMD:[0-9]+]]}
+// CHECK: !hlsl.srvs = !{![[TBMD:[0-9]+]]}
+// CHECK: ![[CBMD]] = !{ptr @[[CB]], !"A.cb.ty", i32 0, i32 13, i32 0, i32 2}
+// CHECK: ![[TBMD]] = !{ptr @[[TB]], !"A.tb.ty", i32 0, i32 15, i32 2, i32 1}
Index: clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl
===================================================================
--- clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl
+++ clang/test/CodeGenHLSL/builtins/RWBuffer-annotations.hlsl
@@ -3,10 +3,22 @@
 RWBuffer<float> Buffer1;
 RWBuffer<vector<float, 4> > BufferArray[4];
 
+RWBuffer<float> Buffer2 : register(u3);
+RWBuffer<vector<float, 4> > BufferArray2[4] : register(u4);
+
+RWBuffer<float> Buffer3 : register(u3, space1);
+RWBuffer<vector<float, 4> > BufferArray3[4] : register(u4, space1);
+
+
+
 [numthreads(1,1,1)]
 void main() {
 }
 
-// CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]]}
-// CHECK-DAG: ![[Single]] = !{ptr @"?Buffer1@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer<float>", i32 0}
-// CHECK-DAG: ![[Array]] = !{ptr @"?BufferArray@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer<vector<float, 4> >", i32 1}
+// CHECK: !hlsl.uavs = !{![[Single:[0-9]+]], ![[Array:[0-9]+]], ![[SingleAllocated:[0-9]+]], ![[ArrayAllocated:[0-9]+]], ![[SingleSpace:[0-9]+]], ![[ArraySpace:[0-9]+]]}
+// CHECK-DAG: ![[Single]] = !{ptr @"?Buffer1@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer<float>", i32 0, i32 10, i32 -1, i32 0}
+// CHECK-DAG: ![[Array]] = !{ptr @"?BufferArray@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer<vector<float, 4> >", i32 1, i32 10, i32 -1, i32 0}
+// CHECK-DAG: ![[SingleAllocated]] = !{ptr @"?Buffer2@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer<float>", i32 2, i32 10, i32 3, i32 0}
+// CHECK-DAG: ![[ArrayAllocated]] = !{ptr @"?BufferArray2@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer<vector<float, 4> >", i32 3, i32 10, i32 4, i32 0}
+// CHECK-DAG: ![[SingleSpace]] = !{ptr @"?Buffer3@@3V?$RWBuffer@M@hlsl@@A", !"RWBuffer<float>", i32 4, i32 10, i32 3, i32 1}
+// CHECK-DAG: ![[ArraySpace]] = !{ptr @"?BufferArray3@@3PAV?$RWBuffer@T?$__vector@M$03@__clang@@@hlsl@@A", !"RWBuffer<vector<float, 4> >", i32 5, i32 10, i32 4, i32 1}
Index: clang/lib/CodeGen/CGHLSLRuntime.h
===================================================================
--- clang/lib/CodeGen/CGHLSLRuntime.h
+++ clang/lib/CodeGen/CGHLSLRuntime.h
@@ -22,6 +22,7 @@
 #include "llvm/ADT/Optional.h"
 #include "llvm/ADT/SmallVector.h"
 #include "llvm/ADT/StringRef.h"
+#include "llvm/Frontend/HLSL/HLSLResource.h"
 
 #include <vector>
 
@@ -35,6 +36,7 @@
 class VarDecl;
 class ParmVarDecl;
 class HLSLBufferDecl;
+class HLSLResourceBindingAttr;
 class CallExpr;
 class Type;
 class DeclContext;
@@ -47,13 +49,20 @@
 
 class CGHLSLRuntime {
 public:
+  struct BufferResBinding {
+    // The ID like 2 in register(b2, space1).
+    llvm::Optional<unsigned> Reg;
+    // The Space like 1 is register(b2, space1).
+    // Default value is 0.
+    unsigned Space;
+    BufferResBinding(HLSLResourceBindingAttr *Attr);
+  };
   struct Buffer {
     Buffer(const HLSLBufferDecl *D);
     llvm::StringRef Name;
     // IsCBuffer - Whether the buffer is a cbuffer (and not a tbuffer).
     bool IsCBuffer;
-    llvm::Optional<unsigned> Reg;
-    unsigned Space;
+    BufferResBinding Binding;
     // Global variable and offset for each constant.
     std::vector<std::pair<llvm::GlobalVariable *, unsigned>> Constants;
     llvm::StructType *LayoutStruct = nullptr;
@@ -82,6 +91,11 @@
   void setHLSLFunctionAttributes(llvm::Function *, const FunctionDecl *);
 
 private:
+  void addBufferResourceAnnotation(llvm::GlobalVariable *GV,
+                                   llvm::StringRef TyName,
+                                   hlsl::ResourceClass RC,
+                                   llvm::hlsl::ResourceKind RK,
+                                   BufferResBinding &Binding);
   void addConstant(VarDecl *D, Buffer &CB);
   void addBufferDecls(const DeclContext *DC, Buffer &CB);
   llvm::SmallVector<Buffer> Buffers;
Index: clang/lib/CodeGen/CGHLSLRuntime.cpp
===================================================================
--- clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -17,7 +17,6 @@
 #include "CodeGenModule.h"
 #include "clang/AST/Decl.h"
 #include "clang/Basic/TargetOptions.h"
-#include "llvm/Frontend/HLSL/HLSLResource.h"
 #include "llvm/IR/IntrinsicsDirectX.h"
 #include "llvm/IR/Metadata.h"
 #include "llvm/IR/Module.h"
@@ -90,16 +89,16 @@
 
 GlobalVariable *replaceBuffer(CGHLSLRuntime::Buffer &Buf) {
   // Create global variable for CB.
-  GlobalVariable *CBGV =
-      new GlobalVariable(Buf.LayoutStruct, /*isConstant*/ true,
-                         GlobalValue::LinkageTypes::ExternalLinkage, nullptr,
-                         Buf.Name + (Buf.IsCBuffer ? ".cb." : ".tb."),
-                         GlobalValue::NotThreadLocal);
+  GlobalVariable *CBGV = new GlobalVariable(
+      Buf.LayoutStruct, /*isConstant*/ true,
+      GlobalValue::LinkageTypes::ExternalLinkage, nullptr,
+      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) {
+  for (auto &[GV, Offset] : Buf.Constants) {
     Value *GEP =
         B.CreateGEP(Buf.LayoutStruct, CBGV, {ZeroIdx, B.getInt32(Offset)});
 
@@ -177,25 +176,100 @@
     layoutBuffer(Buf, DL);
     GlobalVariable *GV = replaceBuffer(Buf);
     M.getGlobalList().push_back(GV);
-    // FIXME: generate resource binding.
-    // See https://github.com/llvm/llvm-project/issues/57915.
+    hlsl::ResourceClass RC =
+        Buf.IsCBuffer ? hlsl::ResourceClass::CBuffer : hlsl::ResourceClass::SRV;
+    llvm::hlsl::ResourceKind RK = Buf.IsCBuffer
+                                      ? llvm::hlsl::ResourceKind::CBuffer
+                                      : llvm::hlsl::ResourceKind::TBuffer;
+    std::string TyName =
+        Buf.Name.str() + (Buf.IsCBuffer ? ".cb." : ".tb.") + "ty";
+    addBufferResourceAnnotation(GV, TyName, RC, RK, Buf.Binding);
   }
 }
 
-CGHLSLRuntime::Buffer::Buffer(const HLSLBufferDecl *D) {
-  Name = D->getName();
-  IsCBuffer = D->isCBuffer();
-  if (auto *Binding = D->getAttr<HLSLResourceBindingAttr>()) {
-    llvm::APInt RegInt(64, 0);
-    Binding->getSlot().substr(1).getAsInteger(10, RegInt);
-    Reg = RegInt.getLimitedValue();
+CGHLSLRuntime::Buffer::Buffer(const HLSLBufferDecl *D)
+    : Name(D->getName()), IsCBuffer(D->isCBuffer()),
+      Binding(D->getAttr<HLSLResourceBindingAttr>()) {}
 
-    llvm::APInt SpaceInt(64, 0);
-    Binding->getSpace().substr(5).getAsInteger(10, RegInt);
-    Space = SpaceInt.getLimitedValue();
-  } else {
-    Space = 0;
+void CGHLSLRuntime::addBufferResourceAnnotation(llvm::GlobalVariable *GV,
+                                                llvm::StringRef TyName,
+                                                hlsl::ResourceClass RC,
+                                                llvm::hlsl::ResourceKind RK,
+                                                BufferResBinding &Binding) {
+  uint32_t Counter = ResourceCounters[static_cast<uint32_t>(RC)]++;
+  llvm::Module &M = CGM.getModule();
+
+  NamedMDNode *ResourceMD = nullptr;
+  switch (RC) {
+  case hlsl::ResourceClass::UAV:
+    ResourceMD = M.getOrInsertNamedMetadata("hlsl.uavs");
+    break;
+  case hlsl::ResourceClass::SRV:
+    ResourceMD = M.getOrInsertNamedMetadata("hlsl.srvs");
+    break;
+  case hlsl::ResourceClass::CBuffer:
+    ResourceMD = M.getOrInsertNamedMetadata("hlsl.cbufs");
+    break;
+  default:
+    assert(false && "Unsupported buffer type!");
+    return;
   }
+
+  assert(ResourceMD != nullptr &&
+         "ResourceMD must have been set by the switch above.");
+
+  llvm::hlsl::FrontendResource Res(
+      GV, TyName, Counter, RK, Binding.Reg.value_or(UINT_MAX), Binding.Space);
+  ResourceMD->addOperand(Res.getMetadata());
+}
+
+static llvm::hlsl::ResourceKind
+castResourceShapeToResourceKind(HLSLResourceAttr::ResourceKind RK) {
+  switch (RK) {
+  case HLSLResourceAttr::ResourceKind::Texture1D:
+    return llvm::hlsl::ResourceKind::Texture1D;
+  case HLSLResourceAttr::ResourceKind::Texture2D:
+    return llvm::hlsl::ResourceKind::Texture2D;
+  case HLSLResourceAttr::ResourceKind::Texture2DMS:
+    return llvm::hlsl::ResourceKind::Texture2DMS;
+  case HLSLResourceAttr::ResourceKind::Texture3D:
+    return llvm::hlsl::ResourceKind::Texture3D;
+  case HLSLResourceAttr::ResourceKind::TextureCube:
+    return llvm::hlsl::ResourceKind::TextureCube;
+  case HLSLResourceAttr::ResourceKind::Texture1DArray:
+    return llvm::hlsl::ResourceKind::Texture1DArray;
+  case HLSLResourceAttr::ResourceKind::Texture2DArray:
+    return llvm::hlsl::ResourceKind::Texture2DArray;
+  case HLSLResourceAttr::ResourceKind::Texture2DMSArray:
+    return llvm::hlsl::ResourceKind::Texture2DMSArray;
+  case HLSLResourceAttr::ResourceKind::TextureCubeArray:
+    return llvm::hlsl::ResourceKind::TextureCubeArray;
+  case HLSLResourceAttr::ResourceKind::TypedBuffer:
+    return llvm::hlsl::ResourceKind::TypedBuffer;
+  case HLSLResourceAttr::ResourceKind::RawBuffer:
+    return llvm::hlsl::ResourceKind::RawBuffer;
+  case HLSLResourceAttr::ResourceKind::StructuredBuffer:
+    return llvm::hlsl::ResourceKind::StructuredBuffer;
+  case HLSLResourceAttr::ResourceKind::CBufferKind:
+    return llvm::hlsl::ResourceKind::CBuffer;
+  case HLSLResourceAttr::ResourceKind::SamplerKind:
+    return llvm::hlsl::ResourceKind::Sampler;
+  case HLSLResourceAttr::ResourceKind::TBuffer:
+    return llvm::hlsl::ResourceKind::TBuffer;
+  case HLSLResourceAttr::ResourceKind::RTAccelerationStructure:
+    return llvm::hlsl::ResourceKind::RTAccelerationStructure;
+  case HLSLResourceAttr::ResourceKind::FeedbackTexture2D:
+    return llvm::hlsl::ResourceKind::FeedbackTexture2D;
+  case HLSLResourceAttr::ResourceKind::FeedbackTexture2DArray:
+    return llvm::hlsl::ResourceKind::FeedbackTexture2DArray;
+  }
+  // Make sure to update HLSLResourceAttr::ResourceKind when add new Kind to
+  // hlsl::ResourceKind. Assume FeedbackTexture2DArray is the last enum for
+  // HLSLResourceAttr::ResourceKind.
+  static_assert(
+      static_cast<uint32_t>(
+          HLSLResourceAttr::ResourceKind::FeedbackTexture2DArray) ==
+      (static_cast<uint32_t>(llvm::hlsl::ResourceKind::NumEntries) - 2));
 }
 
 void CGHLSLRuntime::annotateHLSLResource(const VarDecl *D, GlobalVariable *GV) {
@@ -210,26 +284,27 @@
     return;
 
   HLSLResourceAttr::ResourceClass RC = Attr->getResourceType();
-  uint32_t Counter = ResourceCounters[static_cast<uint32_t>(RC)]++;
-
-  NamedMDNode *ResourceMD = nullptr;
-  switch (RC) {
-  case HLSLResourceAttr::ResourceClass::UAV:
-    ResourceMD = CGM.getModule().getOrInsertNamedMetadata("hlsl.uavs");
-    break;
-  default:
-    assert(false && "Unsupported buffer type!");
-    return;
-  }
-
-  assert(ResourceMD != nullptr &&
-         "ResourceMD must have been set by the switch above.");
+  llvm::hlsl::ResourceKind RK =
+      castResourceShapeToResourceKind(Attr->getResourceShape());
 
-  auto &Ctx = CGM.getModule().getContext();
-  IRBuilder<> B(Ctx);
   QualType QT(Ty, 0);
-  llvm::hlsl::FrontendResource Res(GV, QT.getAsString(), Counter);
-  ResourceMD->addOperand(Res.getMetadata());
+  BufferResBinding Binding(D->getAttr<HLSLResourceBindingAttr>());
+  addBufferResourceAnnotation(
+      GV, QT.getAsString(), static_cast<hlsl::ResourceClass>(RC), RK, Binding);
+}
+
+CGHLSLRuntime::BufferResBinding::BufferResBinding(
+    HLSLResourceBindingAttr *Binding) {
+  if (Binding) {
+    llvm::APInt RegInt(64, 0);
+    Binding->getSlot().substr(1).getAsInteger(10, RegInt);
+    Reg = RegInt.getLimitedValue();
+    llvm::APInt SpaceInt(64, 0);
+    Binding->getSpace().substr(5).getAsInteger(10, SpaceInt);
+    Space = SpaceInt.getLimitedValue();
+  } else {
+    Space = 0;
+  }
 }
 
 void clang::CodeGen::CGHLSLRuntime::setHLSLEntryAttributes(
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to