[clang] [HLSL] Fix global resource initialization (PR #123394)
Helena Kotas via cfe-commits
cfe-commits at lists.llvm.org
Fri Jan 17 12:44:36 PST 2025
https://github.com/hekota created https://github.com/llvm/llvm-project/pull/123394
Create separate resource initialization function for each resource and add them to CodeGenModule's `CXXGlobalInits` list. fixes Fixes #120636 and addresses this [comment ](https://github.com/llvm/llvm-project/pull/119755/files#r1894093603).
>From 1d04bfa8e1b138a13acf30c3fc46428d3b260569 Mon Sep 17 00:00:00 2001
From: Helena Kotas <hekotas at microsoft.com>
Date: Fri, 17 Jan 2025 12:40:21 -0800
Subject: [PATCH] [HLSL] Fix global resource initialization
Fixes #120636
---
clang/lib/CodeGen/CGDeclCXX.cpp | 8 --
clang/lib/CodeGen/CGHLSLRuntime.cpp | 128 +++++++++---------
clang/lib/CodeGen/CGHLSLRuntime.h | 5 -
clang/lib/CodeGen/CodeGenModule.h | 2 +
.../ByteAddressBuffers-constructors.hlsl | 26 ++--
.../builtins/RWBuffer-constructor.hlsl | 15 +-
.../StructuredBuffers-constructors.hlsl | 51 ++++---
clang/test/CodeGenHLSL/resource-bindings.hlsl | 15 +-
8 files changed, 122 insertions(+), 128 deletions(-)
diff --git a/clang/lib/CodeGen/CGDeclCXX.cpp b/clang/lib/CodeGen/CGDeclCXX.cpp
index 96517511b21114..1c2fecea1a6ac2 100644
--- a/clang/lib/CodeGen/CGDeclCXX.cpp
+++ b/clang/lib/CodeGen/CGDeclCXX.cpp
@@ -1131,14 +1131,6 @@ CodeGenFunction::GenerateCXXGlobalInitFunc(llvm::Function *Fn,
if (Decls[i])
EmitRuntimeCall(Decls[i]);
- if (getLangOpts().HLSL) {
- CGHLSLRuntime &CGHLSL = CGM.getHLSLRuntime();
- if (CGHLSL.needsResourceBindingInitFn()) {
- llvm::Function *ResInitFn = CGHLSL.createResourceBindingInitFn();
- Builder.CreateCall(llvm::FunctionCallee(ResInitFn), {});
- }
- }
-
Scope.ForceCleanup();
if (ExitBlock) {
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.cpp b/clang/lib/CodeGen/CGHLSLRuntime.cpp
index 5679bd71581795..c01416bcd36368 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.cpp
+++ b/clang/lib/CodeGen/CGHLSLRuntime.cpp
@@ -536,89 +536,83 @@ void CGHLSLRuntime::generateGlobalCtorDtorCalls() {
}
}
-void CGHLSLRuntime::handleGlobalVarDefinition(const VarDecl *VD,
- llvm::GlobalVariable *GV) {
- // If the global variable has resource binding, add it to the list of globals
- // that need resource binding initialization.
- const HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
- if (!RBA)
- return;
-
- if (!HLSLAttributedResourceType::findHandleTypeOnResource(
- VD->getType().getTypePtr()))
- // FIXME: Only simple declarations of resources are supported for now.
- // Arrays of resources or resources in user defined classes are
- // not implemented yet.
- return;
-
- ResourcesToBind.emplace_back(VD, GV);
-}
-
-bool CGHLSLRuntime::needsResourceBindingInitFn() {
- return !ResourcesToBind.empty();
+// Returns true if the record type is an HLSL resource class
+static bool isResourceRecordType(const clang::Type *Ty) {
+ return HLSLAttributedResourceType::findHandleTypeOnResource(Ty) != nullptr;
}
-llvm::Function *CGHLSLRuntime::createResourceBindingInitFn() {
- // No resources to bind
- assert(needsResourceBindingInitFn() && "no resources to bind");
-
+static void createResourceInitFn(CodeGenModule &CGM, const VarDecl *VD,
+ llvm::GlobalVariable *GV, unsigned Slot,
+ unsigned Space) {
LLVMContext &Ctx = CGM.getLLVMContext();
llvm::Type *Int1Ty = llvm::Type::getInt1Ty(Ctx);
- llvm::Function *InitResBindingsFunc =
- llvm::Function::Create(llvm::FunctionType::get(CGM.VoidTy, false),
- llvm::GlobalValue::InternalLinkage,
- "_init_resource_bindings", CGM.getModule());
+ llvm::Function *InitResFunc = llvm::Function::Create(
+ llvm::FunctionType::get(CGM.VoidTy, false),
+ llvm::GlobalValue::InternalLinkage,
+ ("_init_resource_" + VD->getName()).str(), CGM.getModule());
llvm::BasicBlock *EntryBB =
- llvm::BasicBlock::Create(Ctx, "entry", InitResBindingsFunc);
+ llvm::BasicBlock::Create(Ctx, "entry", InitResFunc);
CGBuilderTy Builder(CGM, Ctx);
const DataLayout &DL = CGM.getModule().getDataLayout();
Builder.SetInsertPoint(EntryBB);
- for (const auto &[VD, GV] : ResourcesToBind) {
- for (Attr *A : VD->getAttrs()) {
- HLSLResourceBindingAttr *RBA = dyn_cast<HLSLResourceBindingAttr>(A);
- if (!RBA)
- continue;
-
- const HLSLAttributedResourceType *AttrResType =
- HLSLAttributedResourceType::findHandleTypeOnResource(
- VD->getType().getTypePtr());
-
- // FIXME: Only simple declarations of resources are supported for now.
- // Arrays of resources or resources in user defined classes are
- // not implemented yet.
- assert(AttrResType != nullptr &&
- "Resource class must have a handle of HLSLAttributedResourceType");
-
- llvm::Type *TargetTy =
- CGM.getTargetCodeGenInfo().getHLSLType(CGM, AttrResType);
- assert(TargetTy != nullptr &&
- "Failed to convert resource handle to target type");
-
- auto *Space = llvm::ConstantInt::get(CGM.IntTy, RBA->getSpaceNumber());
- auto *Slot = llvm::ConstantInt::get(CGM.IntTy, RBA->getSlotNumber());
+ const HLSLAttributedResourceType *AttrResType =
+ HLSLAttributedResourceType::findHandleTypeOnResource(
+ VD->getType().getTypePtr());
+
+ // FIXME: Only simple declarations of resources are supported for now.
+ // Arrays of resources or resources in user defined classes are
+ // not implemented yet.
+ assert(AttrResType != nullptr &&
+ "Resource class must have a handle of HLSLAttributedResourceType");
+
+ llvm::Type *TargetTy =
+ CGM.getTargetCodeGenInfo().getHLSLType(CGM, AttrResType);
+ assert(TargetTy != nullptr &&
+ "Failed to convert resource handle to target type");
+
+ llvm::Value *Args[] = {
+ llvm::ConstantInt::get(CGM.IntTy, Space), /* reg_space */
+ llvm::ConstantInt::get(CGM.IntTy, Slot), /* lower_bound */
// FIXME: resource arrays are not yet implemented
- auto *Range = llvm::ConstantInt::get(CGM.IntTy, 1);
- auto *Index = llvm::ConstantInt::get(CGM.IntTy, 0);
+ llvm::ConstantInt::get(CGM.IntTy, 1), /* range_size */
+ llvm::ConstantInt::get(CGM.IntTy, 0), /* index */
// FIXME: NonUniformResourceIndex bit is not yet implemented
- auto *NonUniform = llvm::ConstantInt::get(Int1Ty, false);
- llvm::Value *Args[] = {Space, Slot, Range, Index, NonUniform};
+ llvm::ConstantInt::get(Int1Ty, false) /* non-uniform */
+ };
+ llvm::Value *CreateHandle = Builder.CreateIntrinsic(
+ /*ReturnType=*/TargetTy,
+ CGM.getHLSLRuntime().getCreateHandleFromBindingIntrinsic(), Args, nullptr,
+ Twine(VD->getName()).concat("_h"));
+
+ llvm::Value *HandleRef = Builder.CreateStructGEP(GV->getValueType(), GV, 0);
+ Builder.CreateAlignedStore(CreateHandle, HandleRef,
+ HandleRef->getPointerAlignment(DL));
+ Builder.CreateRetVoid();
- llvm::Value *CreateHandle = Builder.CreateIntrinsic(
- /*ReturnType=*/TargetTy, getCreateHandleFromBindingIntrinsic(), Args,
- nullptr, Twine(VD->getName()).concat("_h"));
+ CGM.AddCXXGlobalInit(InitResFunc);
+}
- llvm::Value *HandleRef =
- Builder.CreateStructGEP(GV->getValueType(), GV, 0);
- Builder.CreateAlignedStore(CreateHandle, HandleRef,
- HandleRef->getPointerAlignment(DL));
- }
- }
+void CGHLSLRuntime::handleGlobalVarDefinition(const VarDecl *VD,
+ llvm::GlobalVariable *GV) {
- Builder.CreateRetVoid();
- return InitResBindingsFunc;
+ // If the global variable has resource binding, create an init function
+ // for the resource
+ const HLSLResourceBindingAttr *RBA = VD->getAttr<HLSLResourceBindingAttr>();
+ if (!RBA)
+ // FIXME: collect unbound resources for implicit binding resolution later on?
+ return;
+
+ if (!isResourceRecordType(VD->getType().getTypePtr()))
+ // FIXME: Only simple declarations of resources are supported for now.
+ // Arrays of resources or resources in user defined classes are
+ // not implemented yet.
+ return;
+
+ createResourceInitFn(CGM, VD, GV, RBA->getSlotNumber(),
+ RBA->getSpaceNumber());
}
llvm::Instruction *CGHLSLRuntime::getConvergenceToken(BasicBlock &BB) {
diff --git a/clang/lib/CodeGen/CGHLSLRuntime.h b/clang/lib/CodeGen/CGHLSLRuntime.h
index f9dc7b87af0e34..032b2dee82f211 100644
--- a/clang/lib/CodeGen/CGHLSLRuntime.h
+++ b/clang/lib/CodeGen/CGHLSLRuntime.h
@@ -159,8 +159,6 @@ class CGHLSLRuntime {
void setHLSLFunctionAttributes(const FunctionDecl *FD, llvm::Function *Fn);
void handleGlobalVarDefinition(const VarDecl *VD, llvm::GlobalVariable *Var);
- bool needsResourceBindingInitFn();
- llvm::Function *createResourceBindingInitFn();
llvm::Instruction *getConvergenceToken(llvm::BasicBlock &BB);
private:
@@ -173,9 +171,6 @@ class CGHLSLRuntime {
void addBufferDecls(const DeclContext *DC, Buffer &CB);
llvm::Triple::ArchType getArch();
llvm::SmallVector<Buffer> Buffers;
-
- llvm::SmallVector<std::pair<const VarDecl *, llvm::GlobalVariable *>>
- ResourcesToBind;
};
} // namespace CodeGen
diff --git a/clang/lib/CodeGen/CodeGenModule.h b/clang/lib/CodeGen/CodeGenModule.h
index d5ef1a710eb403..1aa5d483d49c08 100644
--- a/clang/lib/CodeGen/CodeGenModule.h
+++ b/clang/lib/CodeGen/CodeGenModule.h
@@ -1226,6 +1226,8 @@ class CodeGenModule : public CodeGenTypeCache {
llvm::Function *getIntrinsic(unsigned IID, ArrayRef<llvm::Type *> Tys = {});
+ void AddCXXGlobalInit(llvm::Function *F) { CXXGlobalInits.push_back(F); }
+
/// Emit code for a single top level declaration.
void EmitTopLevelDecl(Decl *D);
diff --git a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
index 7507e741a9c9ba..0a90055b000f03 100644
--- a/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/ByteAddressBuffers-constructors.hlsl
@@ -15,15 +15,21 @@ RasterizerOrderedByteAddressBuffer Buffer2: register(u3, space4);
// CHECK: @Buffer1 = global %"class.hlsl::RWByteAddressBuffer" zeroinitializer, align 4
// CHECK: @Buffer2 = global %"class.hlsl::RasterizerOrderedByteAddressBuffer" zeroinitializer, align 4
+// CHECK; define internal void @_init_resource_Buffer0()
+// CHECK-DXIL: %Buffer0_h = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false)
+// CHECK-DXIL: store target("dx.RawBuffer", i8, 0, 0) %Buffer0_h, ptr @Buffer0, align 4
+
+// CHECK; define internal void @_init_resource_Buffer1()
+// CHECK-DXIL: %Buffer1_h = call target("dx.RawBuffer", i8, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_1_0t(i32 2, i32 1, i32 1, i32 0, i1 false)
+// CHECK-DXIL: store target("dx.RawBuffer", i8, 1, 0) %Buffer1_h, ptr @Buffer1, align 4
+
+// CHECK; define internal void @_init_resource_Buffer2()
+// CHECK-DXIL: %Buffer2_h = call target("dx.RawBuffer", i8, 1, 1) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_1_1t(i32 4, i32 3, i32 1, i32 0, i1 false)
+// CHECK-DXIL: store target("dx.RawBuffer", i8, 1, 1) %Buffer2_h, ptr @Buffer2, align 4
+
// CHECK: define internal void @_GLOBAL__sub_I_ByteAddressBuffers_constructors.hlsl()
// CHECK: entry:
-// CHECK: call void @_init_resource_bindings()
-
-// CHECK: define internal void @_init_resource_bindings() {
-// CHECK-NEXT: entry:
-// CHECK-DXIL-NEXT: %Buffer0_h = call target("dx.RawBuffer", i8, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false)
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 0, 0) %Buffer0_h, ptr @Buffer0, align 4
-// CHECK-DXIL-NEXT: %Buffer1_h = call target("dx.RawBuffer", i8, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_1_0t(i32 2, i32 1, i32 1, i32 0, i1 false)
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 0) %Buffer1_h, ptr @Buffer1, align 4
-// CHECK-DXIL-NEXT: %Buffer2_h = call target("dx.RawBuffer", i8, 1, 1) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i8_1_1t(i32 4, i32 3, i32 1, i32 0, i1 false)
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", i8, 1, 1) %Buffer2_h, ptr @Buffer2, align 4
+// CHECK: call void @_init_resource_Buffer0()
+// CHECK: call void @_init_resource_Buffer1()
+// CHECK: call void @_init_resource_Buffer2()
+
\ No newline at end of file
diff --git a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
index e4226abf71b8ec..f120a08adc61cc 100644
--- a/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/RWBuffer-constructor.hlsl
@@ -9,17 +9,12 @@ RWBuffer<float> Buf : register(u5, space3);
// CHECK: %"class.hlsl::RWBuffer" = type { target("dx.TypedBuffer", float, 1, 0, 0) }
// CHECK: @Buf = global %"class.hlsl::RWBuffer" zeroinitializer, align 4
+// CHECK: define internal void @_init_resource_Buf() {
+// CHECK-DXIL: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
+// CHECK-DXIL: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, ptr @Buf, align 4
+
// CHECK: define linkonce_odr void @_ZN4hlsl8RWBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
// CHECK-NEXT: entry:
// CHECK: define internal void @_GLOBAL__sub_I_RWBuffer_constructor.hlsl()
-// CHECK-NEXT: entry:
-// CHECK-NEXT: call void @__cxx_global_var_init()
-// CHECK-NEXT: call void @_init_resource_bindings()
-
-// CHECK: define internal void @_init_resource_bindings() {
-// CHECK-NEXT: entry:
-// CHECK-DXIL-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
-// CHECK-DXIL-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, ptr @Buf, align 4
-// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.spv.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
-// CHECK-SPIRV-NEXT: store target("dx.TypedBuffer", float, 1, 0, 0) %Buf_h, ptr @Buf, align 4
+// CHECK: call void @_init_resource_Buf()
diff --git a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
index 16f4f80231dae4..bd931181045ba5 100644
--- a/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
+++ b/clang/test/CodeGenHLSL/builtins/StructuredBuffers-constructors.hlsl
@@ -21,6 +21,26 @@ RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, space2);
// CHECK: @Buf4 = global %"class.hlsl::ConsumeStructuredBuffer" zeroinitializer, align 4
// CHECK: @Buf5 = global %"class.hlsl::RasterizerOrderedStructuredBuffer" zeroinitializer, align 4
+// CHECK: define internal void @_init_resource_Buf()
+// CHECK-DXIL: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false)
+// CHECK-DXIL: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf, align 4
+
+// CHECK: define internal void @_init_resource_Buf2()
+// CHECK-DXIL: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false)
+// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2, align 4
+
+// CHECK: define internal void @_init_resource_Buf3()
+// CHECK-DXIL: %Buf3_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false)
+// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) %Buf3_h, ptr @Buf3, align 4
+
+// CHECK: define internal void @_init_resource_Buf4()
+// CHECK-DXIL: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false)
+// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 0) %Buf4_h, ptr @Buf4, align 4
+
+// CHECK: define internal void @_init_resource_Buf5()
+// CHECK-DXIL: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false)
+// CHECK-DXIL: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4
+
// CHECK: define linkonce_odr void @_ZN4hlsl16StructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
// CHECK-NEXT: entry:
// CHECK: define linkonce_odr void @_ZN4hlsl18RWStructuredBufferIfEC2Ev(ptr noundef nonnull align 4 dereferenceable(4) %this)
@@ -32,29 +52,8 @@ RasterizerOrderedStructuredBuffer<float> Buf5 : register(u1, space2);
// CHECK-NEXT: entry:
// CHECK: define internal void @_GLOBAL__sub_I_StructuredBuffers_constructors.hlsl()
-// CHECK: entry:
-// CHECK: call void @_init_resource_bindings()
-
-// CHECK: define internal void @_init_resource_bindings() {
-// CHECK-NEXT: entry:
-// CHECK-DXIL-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false)
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf, align 4
-// CHECK-DXIL-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false)
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2, align 4
-// CHECK-DXIL-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false)
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf3_h, ptr @Buf3, align 4
-// CHECK-DXIL-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false)
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf4_h, ptr @Buf4, align 4
-// CHECK-DXIL-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false)
-// CHECK-DXIL-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4
-
-// CHECK-SPIRV-NEXT: %Buf_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.resource.handlefrombinding.tdx.RawBuffer_f32_0_0t(i32 0, i32 10, i32 1, i32 0, i1 false)
-// CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf_h, ptr @Buf", align 4
-// CHECK-SPIRV-NEXT: %Buf2_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 1, i32 5, i32 1, i32 0, i1 false)
-// CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf2_h, ptr @Buf2", align 4
-// CHECK-SPIRV-NEXT: %Buf3_h = call target("dx.RawBuffer", float, 0, 0) @llvm.spv.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 3, i32 1, i32 0, i1 false)
-// CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 0, 0) %Buf3_h, ptr @Buf3, align 4
-// CHECK-SPIRV-NEXT: %Buf4_h = call target("dx.RawBuffer", float, 1, 0) @llvm.spv.resource.handlefrombinding.tdx.RawBuffer_f32_1_0t(i32 0, i32 4, i32 1, i32 0, i1 false)
-// CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 0) %Buf4_h, ptr @Buf4, align 4
-// CHECK-SPIRV-NEXT: %Buf5_h = call target("dx.RawBuffer", float, 1, 1) @llvm.spv.resource.handlefrombinding.tdx.RawBuffer_f32_1_1t(i32 2, i32 1, i32 1, i32 0, i1 false)
-// CHECK-SPIRV-NEXT: store target("dx.RawBuffer", float, 1, 1) %Buf5_h, ptr @Buf5, align 4
+// CHECK: call void @_init_resource_Buf()
+// CHECK: call void @_init_resource_Buf2()
+// CHECK: call void @_init_resource_Buf3()
+// CHECK: call void @_init_resource_Buf4()
+// CHECK: call void @_init_resource_Buf5()
diff --git a/clang/test/CodeGenHLSL/resource-bindings.hlsl b/clang/test/CodeGenHLSL/resource-bindings.hlsl
index 4049a87a8ab712..a37c9548acd3fe 100644
--- a/clang/test/CodeGenHLSL/resource-bindings.hlsl
+++ b/clang/test/CodeGenHLSL/resource-bindings.hlsl
@@ -1,13 +1,14 @@
// RUN: %clang_cc1 -triple dxil--shadermodel6.6-compute -x hlsl -finclude-default-header -emit-llvm -o - %s | FileCheck %s
-// CHECK: define internal void @_init_resource_bindings() {
-
+// CHECK: define internal void @_init_resource_U0S0()
// CHECK: %U0S0_h = call target("dx.TypedBuffer", <4 x float>, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_v4f32_1_0_0t(i32 0, i32 0, i32 1, i32 0, i1 false)
RWBuffer<float4> U0S0 : register(u0);
+// CHECK: define internal void @_init_resource_U5S3()
// CHECK: %U5S3_h = call target("dx.TypedBuffer", float, 1, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.TypedBuffer_f32_1_0_0t(i32 3, i32 5, i32 1, i32 0, i1 false)
RWBuffer<float> U5S3 : register(u5, space3);
+// CHECK: define internal void @_init_resource_T2S2()
// CHECK: %T2S2_h = call target("dx.RawBuffer", i32, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_i32_0_0t(i32 2, i32 2, i32 1, i32 0, i1 false)
StructuredBuffer<int> T2S2 : register(t2, space2);
struct S {
@@ -15,5 +16,15 @@ struct S {
int i;
};
+// CHECK: define internal void @_init_resource_T3S0()
// CHECK: %T3S0_h = call target("dx.RawBuffer", %struct.S, 0, 0) @llvm.dx.resource.handlefrombinding.tdx.RawBuffer_s_struct.Ss_0_0t(i32 0, i32 3, i32 1, i32 0, i1 false)
StructuredBuffer<S> T3S0 : register(t3);
+
+// CHECK: define void @main()
+// CHECK: call void @_init_resource_U0S0()
+// CHECK: call void @_init_resource_U5S3()
+// CHECK: call void @_init_resource_T2S2()
+// CHECK: call void @_init_resource_T3S0()
+
+[numthreads(4,1,1)]
+void main() {}
More information about the cfe-commits
mailing list